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 | ... | ... |