Commit 74ccb34e6b52d06d577b5e3695d86d7f440431df
1 parent
5ef54116
Sparc64 host support (Blue Swirl)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2064 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
84 additions
and
18 deletions
Makefile.target
... | ... | @@ -112,7 +112,7 @@ CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3 |
112 | 112 | LDFLAGS+=-m32 |
113 | 113 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0 |
114 | 114 | else |
115 | -CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 | |
115 | +CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 | |
116 | 116 | LDFLAGS+=-m32 |
117 | 117 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 |
118 | 118 | HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat |
... | ... | @@ -122,8 +122,9 @@ endif |
122 | 122 | endif |
123 | 123 | |
124 | 124 | ifeq ($(ARCH),sparc64) |
125 | -CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6 | |
125 | +CFLAGS+=-mcpu=ultrasparc -m64 -ffixed-g1 -ffixed-g4 -ffixed-g5 -ffixed-g7 | |
126 | 126 | LDFLAGS+=-m64 |
127 | +LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld | |
127 | 128 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 |
128 | 129 | endif |
129 | 130 | |
... | ... | @@ -415,6 +416,11 @@ ifeq ($(ARCH),ia64) |
415 | 416 | VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld |
416 | 417 | endif |
417 | 418 | |
419 | +ifeq ($(ARCH),sparc64) | |
420 | +VL_LDFLAGS+=-m64 | |
421 | +VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld | |
422 | +endif | |
423 | + | |
418 | 424 | ifdef CONFIG_WIN32 |
419 | 425 | SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole |
420 | 426 | endif | ... | ... |
cpu-all.h
dyngen-exec.h
... | ... | @@ -35,12 +35,15 @@ |
35 | 35 | typedef unsigned char uint8_t; |
36 | 36 | typedef unsigned short uint16_t; |
37 | 37 | typedef unsigned int uint32_t; |
38 | +// Linux/Sparc64 defines uint64_t | |
39 | +#if !(defined (__sparc_v9__) && defined(__linux__)) | |
38 | 40 | /* XXX may be done for all 64 bits targets ? */ |
39 | 41 | #if defined (__x86_64__) || defined(__ia64) |
40 | 42 | typedef unsigned long uint64_t; |
41 | 43 | #else |
42 | 44 | typedef unsigned long long uint64_t; |
43 | 45 | #endif |
46 | +#endif | |
44 | 47 | |
45 | 48 | /* if Solaris/__sun__, don't typedef int8_t, as it will be typedef'd |
46 | 49 | prior to this and will cause an error in compliation, conflicting |
... | ... | @@ -50,11 +53,14 @@ typedef signed char int8_t; |
50 | 53 | #endif |
51 | 54 | typedef signed short int16_t; |
52 | 55 | typedef signed int int32_t; |
56 | +// Linux/Sparc64 defines int64_t | |
57 | +#if !(defined (__sparc_v9__) && defined(__linux__)) | |
53 | 58 | #if defined (__x86_64__) || defined(__ia64) |
54 | 59 | typedef signed long int64_t; |
55 | 60 | #else |
56 | 61 | typedef signed long long int64_t; |
57 | 62 | #endif |
63 | +#endif | |
58 | 64 | |
59 | 65 | #define INT8_MIN (-128) |
60 | 66 | #define INT16_MIN (-32767-1) |
... | ... | @@ -128,6 +134,12 @@ extern int printf(const char *, ...); |
128 | 134 | #define AREG3 "g5" |
129 | 135 | #define AREG4 "g6" |
130 | 136 | #else |
137 | +#ifdef __sparc_v9__ | |
138 | +#define AREG0 "g1" | |
139 | +#define AREG1 "g4" | |
140 | +#define AREG2 "g5" | |
141 | +#define AREG3 "g7" | |
142 | +#else | |
131 | 143 | #define AREG0 "g6" |
132 | 144 | #define AREG1 "g1" |
133 | 145 | #define AREG2 "g2" |
... | ... | @@ -141,6 +153,7 @@ extern int printf(const char *, ...); |
141 | 153 | #define AREG10 "l6" |
142 | 154 | #define AREG11 "l7" |
143 | 155 | #endif |
156 | +#endif | |
144 | 157 | #define USE_FP_CONVERT |
145 | 158 | #endif |
146 | 159 | #ifdef __s390__ | ... | ... |
dyngen.c
... | ... | @@ -1442,9 +1442,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
1442 | 1442 | { |
1443 | 1443 | #define INSN_SAVE 0x9de3a000 |
1444 | 1444 | #define INSN_RET 0x81c7e008 |
1445 | +#define INSN_RETL 0x81c3e008 | |
1445 | 1446 | #define INSN_RESTORE 0x81e80000 |
1446 | 1447 | #define INSN_RETURN 0x81cfe008 |
1447 | 1448 | #define INSN_NOP 0x01000000 |
1449 | +#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp | |
1450 | +#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp | |
1448 | 1451 | |
1449 | 1452 | uint32_t start_insn, end_insn1, end_insn2; |
1450 | 1453 | uint8_t *p; |
... | ... | @@ -1454,18 +1457,21 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
1454 | 1457 | start_insn = get32((uint32_t *)(p_start + 0x0)); |
1455 | 1458 | end_insn1 = get32((uint32_t *)(p + 0x0)); |
1456 | 1459 | end_insn2 = get32((uint32_t *)(p + 0x4)); |
1457 | - if ((start_insn & ~0x1fff) == INSN_SAVE) { | |
1460 | + if (((start_insn & ~0x1fff) == INSN_SAVE) || | |
1461 | + (start_insn & ~0x1fff) == INSN_ADD_SP) { | |
1458 | 1462 | p_start += 0x4; |
1459 | 1463 | start_offset += 0x4; |
1460 | - if ((int)(start_insn | ~0x1fff) < -128) | |
1461 | - error("Found bogus save at the start of %s", name); | |
1462 | 1464 | if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) |
1463 | 1465 | /* SPARC v7: ret; restore; */ ; |
1464 | 1466 | else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) |
1465 | 1467 | /* SPARC v9: return; nop; */ ; |
1468 | + else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) | |
1469 | + /* SPARC v7: retl; sub %sp, nn, %sp; */ ; | |
1466 | 1470 | else |
1467 | 1471 | |
1468 | 1472 | error("ret; restore; not found at end of %s", name); |
1473 | + } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { | |
1474 | + ; | |
1469 | 1475 | } else { |
1470 | 1476 | error("No save at the beginning of %s", name); |
1471 | 1477 | } |
... | ... | @@ -1481,21 +1487,41 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
1481 | 1487 | } |
1482 | 1488 | #elif defined(HOST_SPARC64) |
1483 | 1489 | { |
1490 | +#define INSN_SAVE 0x9de3a000 | |
1491 | +#define INSN_RET 0x81c7e008 | |
1492 | +#define INSN_RETL 0x81c3e008 | |
1493 | +#define INSN_RESTORE 0x81e80000 | |
1494 | +#define INSN_RETURN 0x81cfe008 | |
1495 | +#define INSN_NOP 0x01000000 | |
1496 | +#define INSN_ADD_SP 0x9c03a000 // add %sp, nn, %sp | |
1497 | +#define INSN_SUB_SP 0x9c23a000 // sub %sp, nn, %sp | |
1498 | + | |
1484 | 1499 | uint32_t start_insn, end_insn1, end_insn2, skip_insn; |
1485 | 1500 | uint8_t *p; |
1486 | 1501 | p = (void *)(p_end - 8); |
1502 | +#if 0 | |
1503 | + /* XXX: check why it occurs */ | |
1487 | 1504 | if (p <= p_start) |
1488 | 1505 | error("empty code for %s", name); |
1506 | +#endif | |
1489 | 1507 | start_insn = get32((uint32_t *)(p_start + 0x0)); |
1490 | 1508 | end_insn1 = get32((uint32_t *)(p + 0x0)); |
1491 | 1509 | end_insn2 = get32((uint32_t *)(p + 0x4)); |
1492 | - if ((start_insn & ~0x1fff) == 0x9de3a000) { | |
1510 | + if (((start_insn & ~0x1fff) == INSN_SAVE) || | |
1511 | + (start_insn & ~0x1fff) == INSN_ADD_SP) { | |
1493 | 1512 | p_start += 0x4; |
1494 | 1513 | start_offset += 0x4; |
1495 | - if ((int)(start_insn | ~0x1fff) < -256) | |
1496 | - error("Found bogus save at the start of %s", name); | |
1497 | - if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000) | |
1514 | + if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) | |
1515 | + /* SPARC v7: ret; restore; */ ; | |
1516 | + else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) | |
1517 | + /* SPARC v9: return; nop; */ ; | |
1518 | + else if (end_insn1 == INSN_RETL && (end_insn2 & ~0x1fff) == INSN_SUB_SP) | |
1519 | + /* SPARC v7: retl; sub %sp, nn, %sp; */ ; | |
1520 | + else | |
1521 | + | |
1498 | 1522 | error("ret; restore; not found at end of %s", name); |
1523 | + } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { | |
1524 | + ; | |
1499 | 1525 | } else { |
1500 | 1526 | error("No save at the beginning of %s", name); |
1501 | 1527 | } |
... | ... | @@ -2191,7 +2217,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
2191 | 2217 | rel->r_offset < start_offset + copy_size) { |
2192 | 2218 | sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
2193 | 2219 | get_reloc_expr(name, sizeof(name), sym_name); |
2194 | - type = ELF64_R_TYPE(rel->r_info); | |
2220 | + type = ELF32_R_TYPE(rel->r_info); | |
2195 | 2221 | addend = rel->r_addend; |
2196 | 2222 | reloc_offset = rel->r_offset - start_offset; |
2197 | 2223 | switch(type) { |
... | ... | @@ -2215,6 +2241,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
2215 | 2241 | " | ((%s + %d) & 0x3ff);\n", |
2216 | 2242 | reloc_offset, reloc_offset, name, addend); |
2217 | 2243 | break; |
2244 | + case R_SPARC_OLO10: | |
2245 | + addend += ELF64_R_TYPE_DATA (rel->r_info); | |
2246 | + fprintf(outfile, | |
2247 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
2248 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
2249 | + " & ~0x3ff) " | |
2250 | + " | ((%s + %d) & 0x3ff);\n", | |
2251 | + reloc_offset, reloc_offset, name, addend); | |
2252 | + break; | |
2218 | 2253 | case R_SPARC_WDISP30: |
2219 | 2254 | fprintf(outfile, |
2220 | 2255 | " *(uint32_t *)(gen_code_ptr + %d) = " |
... | ... | @@ -2225,8 +2260,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, |
2225 | 2260 | reloc_offset, reloc_offset, name, addend, |
2226 | 2261 | reloc_offset); |
2227 | 2262 | break; |
2263 | + case R_SPARC_WDISP22: | |
2264 | + fprintf(outfile, | |
2265 | + " *(uint32_t *)(gen_code_ptr + %d) = " | |
2266 | + "((*(uint32_t *)(gen_code_ptr + %d)) " | |
2267 | + " & ~0x3fffff) " | |
2268 | + " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) " | |
2269 | + " & 0x3fffff);\n", | |
2270 | + reloc_offset, reloc_offset, name, addend, | |
2271 | + reloc_offset); | |
2272 | + break; | |
2228 | 2273 | default: |
2229 | - error("unsupported sparc64 relocation (%d)", type); | |
2274 | + error("unsupported sparc64 relocation (%d) for symbol %s", type, name); | |
2230 | 2275 | } |
2231 | 2276 | } |
2232 | 2277 | } | ... | ... |
elf.h
... | ... | @@ -227,6 +227,7 @@ typedef struct { |
227 | 227 | |
228 | 228 | #define ELF64_R_SYM(i) ((i) >> 32) |
229 | 229 | #define ELF64_R_TYPE(i) ((i) & 0xffffffff) |
230 | +#define ELF64_R_TYPE_DATA(i) (((ELF64_R_TYPE(i) >> 8) ^ 0x00800000) - 0x00800000) | |
230 | 231 | |
231 | 232 | #define R_386_NONE 0 |
232 | 233 | #define R_386_32 1 |
... | ... | @@ -326,6 +327,7 @@ typedef struct { |
326 | 327 | #define R_SPARC_10 30 |
327 | 328 | #define R_SPARC_11 31 |
328 | 329 | #define R_SPARC_64 32 |
330 | +#define R_SPARC_OLO10 33 | |
329 | 331 | #define R_SPARC_WDISP16 40 |
330 | 332 | #define R_SPARC_WDISP19 41 |
331 | 333 | #define R_SPARC_7 43 | ... | ... |
linux-user/signal.c
... | ... | @@ -1334,28 +1334,28 @@ typedef struct { |
1334 | 1334 | unsigned long *insn_addr; |
1335 | 1335 | unsigned long insn; |
1336 | 1336 | } si_fpqueue [16]; |
1337 | -} __siginfo_fpu_t; | |
1337 | +} qemu_siginfo_fpu_t; | |
1338 | 1338 | |
1339 | 1339 | |
1340 | 1340 | struct target_signal_frame { |
1341 | 1341 | struct sparc_stackf ss; |
1342 | 1342 | __siginfo_t info; |
1343 | - __siginfo_fpu_t *fpu_save; | |
1343 | + qemu_siginfo_fpu_t *fpu_save; | |
1344 | 1344 | target_ulong insns[2] __attribute__ ((aligned (8))); |
1345 | 1345 | target_ulong extramask[TARGET_NSIG_WORDS - 1]; |
1346 | 1346 | target_ulong extra_size; /* Should be 0 */ |
1347 | - __siginfo_fpu_t fpu_state; | |
1347 | + qemu_siginfo_fpu_t fpu_state; | |
1348 | 1348 | }; |
1349 | 1349 | struct target_rt_signal_frame { |
1350 | 1350 | struct sparc_stackf ss; |
1351 | 1351 | siginfo_t info; |
1352 | 1352 | target_ulong regs[20]; |
1353 | 1353 | sigset_t mask; |
1354 | - __siginfo_fpu_t *fpu_save; | |
1354 | + qemu_siginfo_fpu_t *fpu_save; | |
1355 | 1355 | unsigned int insns[2]; |
1356 | 1356 | stack_t stack; |
1357 | 1357 | unsigned int extra_size; /* Should be 0 */ |
1358 | - __siginfo_fpu_t fpu_state; | |
1358 | + qemu_siginfo_fpu_t fpu_state; | |
1359 | 1359 | }; |
1360 | 1360 | |
1361 | 1361 | #define UREG_O0 16 |
... | ... | @@ -1500,7 +1500,7 @@ sigsegv: |
1500 | 1500 | force_sig(TARGET_SIGSEGV); |
1501 | 1501 | } |
1502 | 1502 | static inline int |
1503 | -restore_fpu_state(CPUState *env, __siginfo_fpu_t *fpu) | |
1503 | +restore_fpu_state(CPUState *env, qemu_siginfo_fpu_t *fpu) | |
1504 | 1504 | { |
1505 | 1505 | int err; |
1506 | 1506 | #if 0 | ... | ... |