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,7 +112,7 @@ CFLAGS+=-mcpu=ultrasparc -m32 -ffixed-g2 -ffixed-g3 | ||
112 | LDFLAGS+=-m32 | 112 | LDFLAGS+=-m32 |
113 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0 | 113 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -fno-omit-frame-pointer -ffixed-i0 |
114 | else | 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 | LDFLAGS+=-m32 | 116 | LDFLAGS+=-m32 |
117 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 | 117 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 |
118 | HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat | 118 | HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat |
@@ -122,8 +122,9 @@ endif | @@ -122,8 +122,9 @@ endif | ||
122 | endif | 122 | endif |
123 | 123 | ||
124 | ifeq ($(ARCH),sparc64) | 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 | LDFLAGS+=-m64 | 126 | LDFLAGS+=-m64 |
127 | +LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc64.ld | ||
127 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 | 128 | OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0 |
128 | endif | 129 | endif |
129 | 130 | ||
@@ -415,6 +416,11 @@ ifeq ($(ARCH),ia64) | @@ -415,6 +416,11 @@ ifeq ($(ARCH),ia64) | ||
415 | VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld | 416 | VL_LDFLAGS+=-Wl,-G0 -Wl,-T,$(SRC_PATH)/ia64.ld |
416 | endif | 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 | ifdef CONFIG_WIN32 | 424 | ifdef CONFIG_WIN32 |
419 | SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole | 425 | SDL_LIBS := $(filter-out -mwindows, $(SDL_LIBS)) -mconsole |
420 | endif | 426 | endif |
cpu-all.h
@@ -971,7 +971,7 @@ static inline int64_t cpu_get_real_ticks(void) | @@ -971,7 +971,7 @@ static inline int64_t cpu_get_real_ticks(void) | ||
971 | return val; | 971 | return val; |
972 | } | 972 | } |
973 | 973 | ||
974 | -#elif defined(__sparc__) && defined(HOST_SOLARIS) | 974 | +#elif defined(__sparc_v9__) |
975 | 975 | ||
976 | static inline int64_t cpu_get_real_ticks (void) | 976 | static inline int64_t cpu_get_real_ticks (void) |
977 | { | 977 | { |
dyngen-exec.h
@@ -35,12 +35,15 @@ | @@ -35,12 +35,15 @@ | ||
35 | typedef unsigned char uint8_t; | 35 | typedef unsigned char uint8_t; |
36 | typedef unsigned short uint16_t; | 36 | typedef unsigned short uint16_t; |
37 | typedef unsigned int uint32_t; | 37 | typedef unsigned int uint32_t; |
38 | +// Linux/Sparc64 defines uint64_t | ||
39 | +#if !(defined (__sparc_v9__) && defined(__linux__)) | ||
38 | /* XXX may be done for all 64 bits targets ? */ | 40 | /* XXX may be done for all 64 bits targets ? */ |
39 | #if defined (__x86_64__) || defined(__ia64) | 41 | #if defined (__x86_64__) || defined(__ia64) |
40 | typedef unsigned long uint64_t; | 42 | typedef unsigned long uint64_t; |
41 | #else | 43 | #else |
42 | typedef unsigned long long uint64_t; | 44 | typedef unsigned long long uint64_t; |
43 | #endif | 45 | #endif |
46 | +#endif | ||
44 | 47 | ||
45 | /* if Solaris/__sun__, don't typedef int8_t, as it will be typedef'd | 48 | /* if Solaris/__sun__, don't typedef int8_t, as it will be typedef'd |
46 | prior to this and will cause an error in compliation, conflicting | 49 | prior to this and will cause an error in compliation, conflicting |
@@ -50,11 +53,14 @@ typedef signed char int8_t; | @@ -50,11 +53,14 @@ typedef signed char int8_t; | ||
50 | #endif | 53 | #endif |
51 | typedef signed short int16_t; | 54 | typedef signed short int16_t; |
52 | typedef signed int int32_t; | 55 | typedef signed int int32_t; |
56 | +// Linux/Sparc64 defines int64_t | ||
57 | +#if !(defined (__sparc_v9__) && defined(__linux__)) | ||
53 | #if defined (__x86_64__) || defined(__ia64) | 58 | #if defined (__x86_64__) || defined(__ia64) |
54 | typedef signed long int64_t; | 59 | typedef signed long int64_t; |
55 | #else | 60 | #else |
56 | typedef signed long long int64_t; | 61 | typedef signed long long int64_t; |
57 | #endif | 62 | #endif |
63 | +#endif | ||
58 | 64 | ||
59 | #define INT8_MIN (-128) | 65 | #define INT8_MIN (-128) |
60 | #define INT16_MIN (-32767-1) | 66 | #define INT16_MIN (-32767-1) |
@@ -128,6 +134,12 @@ extern int printf(const char *, ...); | @@ -128,6 +134,12 @@ extern int printf(const char *, ...); | ||
128 | #define AREG3 "g5" | 134 | #define AREG3 "g5" |
129 | #define AREG4 "g6" | 135 | #define AREG4 "g6" |
130 | #else | 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 | #define AREG0 "g6" | 143 | #define AREG0 "g6" |
132 | #define AREG1 "g1" | 144 | #define AREG1 "g1" |
133 | #define AREG2 "g2" | 145 | #define AREG2 "g2" |
@@ -141,6 +153,7 @@ extern int printf(const char *, ...); | @@ -141,6 +153,7 @@ extern int printf(const char *, ...); | ||
141 | #define AREG10 "l6" | 153 | #define AREG10 "l6" |
142 | #define AREG11 "l7" | 154 | #define AREG11 "l7" |
143 | #endif | 155 | #endif |
156 | +#endif | ||
144 | #define USE_FP_CONVERT | 157 | #define USE_FP_CONVERT |
145 | #endif | 158 | #endif |
146 | #ifdef __s390__ | 159 | #ifdef __s390__ |
dyngen.c
@@ -1442,9 +1442,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1442,9 +1442,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
1442 | { | 1442 | { |
1443 | #define INSN_SAVE 0x9de3a000 | 1443 | #define INSN_SAVE 0x9de3a000 |
1444 | #define INSN_RET 0x81c7e008 | 1444 | #define INSN_RET 0x81c7e008 |
1445 | +#define INSN_RETL 0x81c3e008 | ||
1445 | #define INSN_RESTORE 0x81e80000 | 1446 | #define INSN_RESTORE 0x81e80000 |
1446 | #define INSN_RETURN 0x81cfe008 | 1447 | #define INSN_RETURN 0x81cfe008 |
1447 | #define INSN_NOP 0x01000000 | 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 | uint32_t start_insn, end_insn1, end_insn2; | 1452 | uint32_t start_insn, end_insn1, end_insn2; |
1450 | uint8_t *p; | 1453 | uint8_t *p; |
@@ -1454,18 +1457,21 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -1454,18 +1457,21 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
1454 | start_insn = get32((uint32_t *)(p_start + 0x0)); | 1457 | start_insn = get32((uint32_t *)(p_start + 0x0)); |
1455 | end_insn1 = get32((uint32_t *)(p + 0x0)); | 1458 | end_insn1 = get32((uint32_t *)(p + 0x0)); |
1456 | end_insn2 = get32((uint32_t *)(p + 0x4)); | 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 | p_start += 0x4; | 1462 | p_start += 0x4; |
1459 | start_offset += 0x4; | 1463 | start_offset += 0x4; |
1460 | - if ((int)(start_insn | ~0x1fff) < -128) | ||
1461 | - error("Found bogus save at the start of %s", name); | ||
1462 | if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) | 1464 | if (end_insn1 == INSN_RET && end_insn2 == INSN_RESTORE) |
1463 | /* SPARC v7: ret; restore; */ ; | 1465 | /* SPARC v7: ret; restore; */ ; |
1464 | else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) | 1466 | else if (end_insn1 == INSN_RETURN && end_insn2 == INSN_NOP) |
1465 | /* SPARC v9: return; nop; */ ; | 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 | else | 1470 | else |
1467 | 1471 | ||
1468 | error("ret; restore; not found at end of %s", name); | 1472 | error("ret; restore; not found at end of %s", name); |
1473 | + } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { | ||
1474 | + ; | ||
1469 | } else { | 1475 | } else { |
1470 | error("No save at the beginning of %s", name); | 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,21 +1487,41 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
1481 | } | 1487 | } |
1482 | #elif defined(HOST_SPARC64) | 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 | uint32_t start_insn, end_insn1, end_insn2, skip_insn; | 1499 | uint32_t start_insn, end_insn1, end_insn2, skip_insn; |
1485 | uint8_t *p; | 1500 | uint8_t *p; |
1486 | p = (void *)(p_end - 8); | 1501 | p = (void *)(p_end - 8); |
1502 | +#if 0 | ||
1503 | + /* XXX: check why it occurs */ | ||
1487 | if (p <= p_start) | 1504 | if (p <= p_start) |
1488 | error("empty code for %s", name); | 1505 | error("empty code for %s", name); |
1506 | +#endif | ||
1489 | start_insn = get32((uint32_t *)(p_start + 0x0)); | 1507 | start_insn = get32((uint32_t *)(p_start + 0x0)); |
1490 | end_insn1 = get32((uint32_t *)(p + 0x0)); | 1508 | end_insn1 = get32((uint32_t *)(p + 0x0)); |
1491 | end_insn2 = get32((uint32_t *)(p + 0x4)); | 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 | p_start += 0x4; | 1512 | p_start += 0x4; |
1494 | start_offset += 0x4; | 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 | error("ret; restore; not found at end of %s", name); | 1522 | error("ret; restore; not found at end of %s", name); |
1523 | + } else if (end_insn1 == INSN_RETL && end_insn2 == INSN_NOP) { | ||
1524 | + ; | ||
1499 | } else { | 1525 | } else { |
1500 | error("No save at the beginning of %s", name); | 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,7 +2217,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
2191 | rel->r_offset < start_offset + copy_size) { | 2217 | rel->r_offset < start_offset + copy_size) { |
2192 | sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; | 2218 | sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; |
2193 | get_reloc_expr(name, sizeof(name), sym_name); | 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 | addend = rel->r_addend; | 2221 | addend = rel->r_addend; |
2196 | reloc_offset = rel->r_offset - start_offset; | 2222 | reloc_offset = rel->r_offset - start_offset; |
2197 | switch(type) { | 2223 | switch(type) { |
@@ -2215,6 +2241,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -2215,6 +2241,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
2215 | " | ((%s + %d) & 0x3ff);\n", | 2241 | " | ((%s + %d) & 0x3ff);\n", |
2216 | reloc_offset, reloc_offset, name, addend); | 2242 | reloc_offset, reloc_offset, name, addend); |
2217 | break; | 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 | case R_SPARC_WDISP30: | 2253 | case R_SPARC_WDISP30: |
2219 | fprintf(outfile, | 2254 | fprintf(outfile, |
2220 | " *(uint32_t *)(gen_code_ptr + %d) = " | 2255 | " *(uint32_t *)(gen_code_ptr + %d) = " |
@@ -2225,8 +2260,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | @@ -2225,8 +2260,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, | ||
2225 | reloc_offset, reloc_offset, name, addend, | 2260 | reloc_offset, reloc_offset, name, addend, |
2226 | reloc_offset); | 2261 | reloc_offset); |
2227 | break; | 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 | default: | 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,6 +227,7 @@ typedef struct { | ||
227 | 227 | ||
228 | #define ELF64_R_SYM(i) ((i) >> 32) | 228 | #define ELF64_R_SYM(i) ((i) >> 32) |
229 | #define ELF64_R_TYPE(i) ((i) & 0xffffffff) | 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 | #define R_386_NONE 0 | 232 | #define R_386_NONE 0 |
232 | #define R_386_32 1 | 233 | #define R_386_32 1 |
@@ -326,6 +327,7 @@ typedef struct { | @@ -326,6 +327,7 @@ typedef struct { | ||
326 | #define R_SPARC_10 30 | 327 | #define R_SPARC_10 30 |
327 | #define R_SPARC_11 31 | 328 | #define R_SPARC_11 31 |
328 | #define R_SPARC_64 32 | 329 | #define R_SPARC_64 32 |
330 | +#define R_SPARC_OLO10 33 | ||
329 | #define R_SPARC_WDISP16 40 | 331 | #define R_SPARC_WDISP16 40 |
330 | #define R_SPARC_WDISP19 41 | 332 | #define R_SPARC_WDISP19 41 |
331 | #define R_SPARC_7 43 | 333 | #define R_SPARC_7 43 |
linux-user/signal.c
@@ -1334,28 +1334,28 @@ typedef struct { | @@ -1334,28 +1334,28 @@ typedef struct { | ||
1334 | unsigned long *insn_addr; | 1334 | unsigned long *insn_addr; |
1335 | unsigned long insn; | 1335 | unsigned long insn; |
1336 | } si_fpqueue [16]; | 1336 | } si_fpqueue [16]; |
1337 | -} __siginfo_fpu_t; | 1337 | +} qemu_siginfo_fpu_t; |
1338 | 1338 | ||
1339 | 1339 | ||
1340 | struct target_signal_frame { | 1340 | struct target_signal_frame { |
1341 | struct sparc_stackf ss; | 1341 | struct sparc_stackf ss; |
1342 | __siginfo_t info; | 1342 | __siginfo_t info; |
1343 | - __siginfo_fpu_t *fpu_save; | 1343 | + qemu_siginfo_fpu_t *fpu_save; |
1344 | target_ulong insns[2] __attribute__ ((aligned (8))); | 1344 | target_ulong insns[2] __attribute__ ((aligned (8))); |
1345 | target_ulong extramask[TARGET_NSIG_WORDS - 1]; | 1345 | target_ulong extramask[TARGET_NSIG_WORDS - 1]; |
1346 | target_ulong extra_size; /* Should be 0 */ | 1346 | target_ulong extra_size; /* Should be 0 */ |
1347 | - __siginfo_fpu_t fpu_state; | 1347 | + qemu_siginfo_fpu_t fpu_state; |
1348 | }; | 1348 | }; |
1349 | struct target_rt_signal_frame { | 1349 | struct target_rt_signal_frame { |
1350 | struct sparc_stackf ss; | 1350 | struct sparc_stackf ss; |
1351 | siginfo_t info; | 1351 | siginfo_t info; |
1352 | target_ulong regs[20]; | 1352 | target_ulong regs[20]; |
1353 | sigset_t mask; | 1353 | sigset_t mask; |
1354 | - __siginfo_fpu_t *fpu_save; | 1354 | + qemu_siginfo_fpu_t *fpu_save; |
1355 | unsigned int insns[2]; | 1355 | unsigned int insns[2]; |
1356 | stack_t stack; | 1356 | stack_t stack; |
1357 | unsigned int extra_size; /* Should be 0 */ | 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 | #define UREG_O0 16 | 1361 | #define UREG_O0 16 |
@@ -1500,7 +1500,7 @@ sigsegv: | @@ -1500,7 +1500,7 @@ sigsegv: | ||
1500 | force_sig(TARGET_SIGSEGV); | 1500 | force_sig(TARGET_SIGSEGV); |
1501 | } | 1501 | } |
1502 | static inline int | 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 | int err; | 1505 | int err; |
1506 | #if 0 | 1506 | #if 0 |