提交 ae228531 编写于 作者: B bellard

Sparc update (David S. Miller)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@161 c046a42c-6fe2-441c-8c8c-71466251a162
上级 d418c81e
...@@ -29,6 +29,18 @@ OP_CFLAGS=$(CFLAGS) ...@@ -29,6 +29,18 @@ OP_CFLAGS=$(CFLAGS)
LDFLAGS+=-Wl,-T,s390.ld LDFLAGS+=-Wl,-T,s390.ld
endif endif
ifeq ($(ARCH),sparc)
CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m32
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
endif
ifeq ($(ARCH),sparc64)
CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
LDFLAGS+=-m64
OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
endif
ifeq ($(ARCH),alpha) ifeq ($(ARCH),alpha)
# -msmall-data is not used because we want two-instruction relocations # -msmall-data is not used because we want two-instruction relocations
# for the constant constructions # for the constant constructions
......
...@@ -47,6 +47,12 @@ case "$cpu" in ...@@ -47,6 +47,12 @@ case "$cpu" in
s390) s390)
cpu="s390" cpu="s390"
;; ;;
sparc)
cpu="sparc"
;;
sparc64)
cpu="sparc64"
;;
ia64) ia64)
cpu="ia64" cpu="ia64"
;; ;;
...@@ -131,7 +137,7 @@ fi ...@@ -131,7 +137,7 @@ fi
else else
# if cross compiling, cannot launch a program, so make a static guess # if cross compiling, cannot launch a program, so make a static guess
if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64"; then
bigendian="yes" bigendian="yes"
fi fi
...@@ -217,6 +223,12 @@ elif test "$cpu" = "s390" ; then ...@@ -217,6 +223,12 @@ elif test "$cpu" = "s390" ; then
elif test "$cpu" = "alpha" ; then elif test "$cpu" = "alpha" ; then
echo "ARCH=alpha" >> config.mak echo "ARCH=alpha" >> config.mak
echo "#define HOST_ALPHA 1" >> $TMPH echo "#define HOST_ALPHA 1" >> $TMPH
elif test "$cpu" = "sparc" ; then
echo "ARCH=sparc" >> config.mak
echo "#define HOST_SPARC 1" >> $TMPH
elif test "$cpu" = "sparc64" ; then
echo "ARCH=sparc64" >> config.mak
echo "#define HOST_SPARC64 1" >> $TMPH
elif test "$cpu" = "ia64" ; then elif test "$cpu" = "ia64" ; then
echo "ARCH=ia64" >> config.mak echo "ARCH=ia64" >> config.mak
echo "#define HOST_IA64 1" >> $TMPH echo "#define HOST_IA64 1" >> $TMPH
......
...@@ -274,14 +274,20 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -274,14 +274,20 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
{ {
int copy_size = 0; int copy_size = 0;
uint8_t *p_start, *p_end; uint8_t *p_start, *p_end;
host_ulong start_offset;
int nb_args, i, n; int nb_args, i, n;
uint8_t args_present[MAX_ARGS]; uint8_t args_present[MAX_ARGS];
const char *sym_name, *p; const char *sym_name, *p;
ELF_RELOC *rel; ELF_RELOC *rel;
/* compute exact size excluding return instruction */ /* Compute exact size excluding prologue and epilogue instructions.
* Increment start_offset to skip epilogue instructions, then compute
* copy_size the indicate the size of the remaining instructions (in
* bytes).
*/
p_start = text + offset; p_start = text + offset;
p_end = p_start + size; p_end = p_start + size;
start_offset = offset;
switch(ELF_ARCH) { switch(ELF_ARCH) {
case EM_386: case EM_386:
{ {
...@@ -343,41 +349,63 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -343,41 +349,63 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
case EM_SPARC: case EM_SPARC:
case EM_SPARC32PLUS: case EM_SPARC32PLUS:
{ {
uint32_t start_insn, end_insn1, end_insn2, skip_insn;
uint8_t *p; uint8_t *p;
p = (void *)(p_end - 8); p = (void *)(p_end - 8);
if (p <= p_start) if (p <= p_start)
error("empty code for %s", name); error("empty code for %s", name);
if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf98) start_insn = get32((uint32_t *)(p_start + 0x0));
error("save %%sp,-104,%%sp expected at the start of %s " end_insn1 = get32((uint32_t *)(p + 0x0));
"found [%08x]", end_insn2 = get32((uint32_t *)(p + 0x4));
name, get32((uint32_t *)(p_start + 0x0))); if ((start_insn & ~0x1fff) == 0x9de3a000) {
if (get32((uint32_t *)(p + 0x0)) != 0x81c7e008 || p_start += 0x4;
get32((uint32_t *)(p + 0x4)) != 0x81e80000) start_offset += 0x4;
error("ret; restore; expected at the end of %s found [%08x:%08x]", if ((int)(start_insn | ~0x1fff) < -128)
name, error("Found bogus save at the start of %s", name);
get32((uint32_t *)(p + 0x0)), if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
get32((uint32_t *)(p + 0x4))); error("ret; restore; not found at end of %s", name);
} else {
error("No save at the beginning of %s", name);
}
/* Skip a preceeding nop, if present. */
if (p > p_start) {
skip_insn = get32((uint32_t *)(p - 0x4));
if (skip_insn == 0x01000000)
p -= 4;
}
copy_size = p - p_start; copy_size = p - p_start;
} }
break; break;
case EM_SPARCV9: case EM_SPARCV9:
{ {
uint32_t start_insn, end_insn1, end_insn2, skip_insn;
uint8_t *p; uint8_t *p;
p = (void *)(p_end - 8); p = (void *)(p_end - 8);
if (p <= p_start) if (p <= p_start)
error("empty code for %s", name); error("empty code for %s", name);
if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf40) start_insn = get32((uint32_t *)(p_start + 0x0));
error("save %%sp,-192,%%sp expected at the start of %s " end_insn1 = get32((uint32_t *)(p + 0x0));
"found [%08x]", end_insn2 = get32((uint32_t *)(p + 0x4));
name, get32((uint32_t *)(p_start + 0x0))); if ((start_insn & ~0x1fff) == 0x9de3a000) {
if (get32((uint32_t *)(p + 0x0)) != 0x81cfe008 || p_start += 0x4;
get32((uint32_t *)(p + 0x4)) != 0x01000000) start_offset += 0x4;
error("rett %%i7+8; nop; expected at the end of %s " if ((int)(start_insn | ~0x1fff) < -256)
"found [%08x:%08x]", error("Found bogus save at the start of %s", name);
name, if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
get32((uint32_t *)(p + 0x0)), error("ret; restore; not found at end of %s", name);
get32((uint32_t *)(p + 0x4))); } else {
error("No save at the beginning of %s", name);
}
/* Skip a preceeding nop, if present. */
if (p > p_start) {
skip_insn = get32((uint32_t *)(p - 0x4));
if (skip_insn == 0x01000000)
p -= 4;
}
copy_size = p - p_start; copy_size = p - p_start;
} }
break; break;
...@@ -390,7 +418,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -390,7 +418,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
args_present[i] = 0; args_present[i] = 0;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
n = strtoul(p, NULL, 10); n = strtoul(p, NULL, 10);
...@@ -427,7 +456,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -427,7 +456,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
fprintf(outfile, " extern void %s();\n", name); fprintf(outfile, " extern void %s();\n", name);
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
if (*sym_name && !strstart(sym_name, "__op_param", &p)) { if (*sym_name && !strstart(sym_name, "__op_param", &p)) {
#if defined(HOST_SPARC) #if defined(HOST_SPARC)
...@@ -443,7 +473,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -443,7 +473,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
} }
} }
fprintf(outfile, " memcpy(gen_code_ptr, &%s, %d);\n", name, copy_size); fprintf(outfile, " memcpy(gen_code_ptr, (void *)((char *)&%s+%d), %d);\n", name, start_offset - offset, copy_size);
for(i = 0; i < nb_args; i++) { for(i = 0; i < nb_args; i++) {
fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1); fprintf(outfile, " param%d = *opparam_ptr++;\n", i + 1);
} }
...@@ -455,7 +485,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -455,7 +485,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
int type; int type;
int addend; int addend;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, sizeof(name), "param%s", p); snprintf(name, sizeof(name), "param%s", p);
...@@ -467,11 +498,11 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -467,11 +498,11 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
switch(type) { switch(type) {
case R_386_32: case R_386_32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_386_PC32: case R_386_PC32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n", fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s - (long)(gen_code_ptr + %d) + %d;\n",
rel->r_offset - offset, name, rel->r_offset - offset, addend); rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
break; break;
default: default:
error("unsupported i386 relocation (%d)", type); error("unsupported i386 relocation (%d)", type);
...@@ -485,7 +516,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -485,7 +516,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
int type; int type;
int addend; int addend;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, sizeof(name), "param%s", p); snprintf(name, sizeof(name), "param%s", p);
...@@ -497,24 +529,24 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -497,24 +529,24 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
switch(type) { switch(type) {
case R_PPC_ADDR32: case R_PPC_ADDR32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_PPC_ADDR16_LO: case R_PPC_ADDR16_LO:
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n", fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d);\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_PPC_ADDR16_HI: case R_PPC_ADDR16_HI:
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n", fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d) >> 16;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_PPC_ADDR16_HA: case R_PPC_ADDR16_HA:
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n", fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = (%s + %d + 0x8000) >> 16;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_PPC_REL24: case R_PPC_REL24:
/* warning: must be at 32 MB distancy */ /* warning: must be at 32 MB distancy */
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n", fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = (*(uint32_t *)(gen_code_ptr + %d) & ~0x03fffffc) | ((%s - (long)(gen_code_ptr + %d) + %d) & 0x03fffffc);\n",
rel->r_offset - offset, rel->r_offset - offset, name, rel->r_offset - offset, addend); rel->r_offset - start_offset, rel->r_offset - start_offset, name, rel->r_offset - start_offset, addend);
break; break;
default: default:
error("unsupported powerpc relocation (%d)", type); error("unsupported powerpc relocation (%d)", type);
...@@ -528,7 +560,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -528,7 +560,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
int type; int type;
int addend; int addend;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name; sym_name = strtab + symtab[ELFW(R_SYM)(rel->r_info)].st_name;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, sizeof(name), "param%s", p); snprintf(name, sizeof(name), "param%s", p);
...@@ -540,15 +573,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -540,15 +573,15 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
switch(type) { switch(type) {
case R_390_32: case R_390_32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_390_16: case R_390_16:
fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n", fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %d) = %s + %d;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_390_8: case R_390_8:
fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n", fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %d) = %s + %d;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
default: default:
error("unsupported s390 relocation (%d)", type); error("unsupported s390 relocation (%d)", type);
...@@ -559,7 +592,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -559,7 +592,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
#elif defined(HOST_ALPHA) #elif defined(HOST_ALPHA)
{ {
for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) { for (i = 0, rel = relocs; i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
int type; int type;
type = ELF64_R_TYPE(rel->r_info); type = ELF64_R_TYPE(rel->r_info);
...@@ -569,9 +602,9 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -569,9 +602,9 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
/* The gp is just 32 bit, and never changes, so it's easiest to emit it /* The gp is just 32 bit, and never changes, so it's easiest to emit it
as an immediate instead of constructing it from the pv or ra. */ as an immediate instead of constructing it from the pv or ra. */
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n", fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, gp);\n",
rel->r_offset - offset); rel->r_offset - start_offset);
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n", fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, gp);\n",
rel->r_offset - offset + rel->r_addend); rel->r_offset - start_offset + rel->r_addend);
break; break;
case R_ALPHA_LITUSE: case R_ALPHA_LITUSE:
/* jsr to literal hint. Could be used to optimize to bsr. Ignore for /* jsr to literal hint. Could be used to optimize to bsr. Ignore for
...@@ -591,18 +624,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -591,18 +624,18 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
special treatment. */ special treatment. */
if (strstart(sym_name, "__op_param", &p)) if (strstart(sym_name, "__op_param", &p))
fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n", fprintf(outfile, " immediate_ldah(gen_code_ptr + %ld, param%s);\n",
rel->r_offset - offset, p); rel->r_offset - start_offset, p);
break; break;
case R_ALPHA_GPRELLOW: case R_ALPHA_GPRELLOW:
if (strstart(sym_name, "__op_param", &p)) if (strstart(sym_name, "__op_param", &p))
fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n", fprintf(outfile, " immediate_lda(gen_code_ptr + %ld, param%s);\n",
rel->r_offset - offset, p); rel->r_offset - start_offset, p);
break; break;
case R_ALPHA_BRSGP: case R_ALPHA_BRSGP:
/* PC-relative jump. Tweak offset to skip the two instructions that try to /* PC-relative jump. Tweak offset to skip the two instructions that try to
set up the gp from the pv. */ set up the gp from the pv. */
fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld) + 4);\n", fprintf(outfile, " fix_bsr(gen_code_ptr + %ld, (uint8_t *) &%s - (gen_code_ptr + %ld) + 4);\n",
rel->r_offset - offset, sym_name, rel->r_offset - offset); rel->r_offset - start_offset, sym_name, rel->r_offset - start_offset);
break; break;
default: default:
error("unsupported Alpha relocation (%d)", type); error("unsupported Alpha relocation (%d)", type);
...@@ -616,7 +649,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -616,7 +649,7 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
int type; int type;
int addend; int addend;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset && rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, sizeof(name), "param%s", p); snprintf(name, sizeof(name), "param%s", p);
...@@ -642,7 +675,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -642,7 +675,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
int type; int type;
int addend; int addend;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name; sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, sizeof(name), "param%s", p); snprintf(name, sizeof(name), "param%s", p);
...@@ -660,16 +694,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -660,16 +694,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
switch(type) { switch(type) {
case R_SPARC_32: case R_SPARC_32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_SPARC_HI22: case R_SPARC_HI22:
fprintf(outfile, fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + %d) = " " *(uint32_t *)(gen_code_ptr + %d) = "
"((*(uint32_t *)(gen_code_ptr + %d)) " "((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffff) " " & ~0x3fffff) "
" | ((%s + %d) & 0x3fffff);\n", " | (((%s + %d) >> 10) & 0x3fffff);\n",
rel->r_offset - offset, rel->r_offset - start_offset,
rel->r_offset - offset, rel->r_offset - start_offset,
name, addend); name, addend);
break; break;
case R_SPARC_LO10: case R_SPARC_LO10:
...@@ -678,8 +712,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -678,8 +712,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
"((*(uint32_t *)(gen_code_ptr + %d)) " "((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3ff) " " & ~0x3ff) "
" | ((%s + %d) & 0x3ff);\n", " | ((%s + %d) & 0x3ff);\n",
rel->r_offset - offset, rel->r_offset - start_offset,
rel->r_offset - offset, rel->r_offset - start_offset,
name, addend); name, addend);
break; break;
case R_SPARC_WDISP30: case R_SPARC_WDISP30:
...@@ -687,11 +721,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -687,11 +721,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" *(uint32_t *)(gen_code_ptr + %d) = " " *(uint32_t *)(gen_code_ptr + %d) = "
"((*(uint32_t *)(gen_code_ptr + %d)) " "((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffffff) " " & ~0x3fffffff) "
" | ((((%s + %d) - (long)gen_code_ptr)>>2) " " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
" & 0x3fffffff);\n", " & 0x3fffffff);\n",
rel->r_offset - offset, rel->r_offset - start_offset,
rel->r_offset - offset, rel->r_offset - start_offset,
name, addend); name, addend,
rel->r_offset - start_offset);
break; break;
default: default:
error("unsupported sparc relocation (%d)", type); error("unsupported sparc relocation (%d)", type);
...@@ -705,7 +740,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -705,7 +740,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
int type; int type;
int addend; int addend;
for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) { for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) { if (rel->r_offset >= start_offset &&
rel->r_offset < start_offset + copy_size) {
sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name; sym_name = strtab + symtab[ELF64_R_SYM(rel->r_info)].st_name;
if (strstart(sym_name, "__op_param", &p)) { if (strstart(sym_name, "__op_param", &p)) {
snprintf(name, sizeof(name), "param%s", p); snprintf(name, sizeof(name), "param%s", p);
...@@ -717,16 +753,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -717,16 +753,16 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
switch(type) { switch(type) {
case R_SPARC_32: case R_SPARC_32:
fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n", fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %d) = %s + %d;\n",
rel->r_offset - offset, name, addend); rel->r_offset - start_offset, name, addend);
break; break;
case R_SPARC_HI22: case R_SPARC_HI22:
fprintf(outfile, fprintf(outfile,
" *(uint32_t *)(gen_code_ptr + %d) = " " *(uint32_t *)(gen_code_ptr + %d) = "
"((*(uint32_t *)(gen_code_ptr + %d)) " "((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffff) " " & ~0x3fffff) "
" | ((%s + %d) & 0x3fffff);\n", " | (((%s + %d) >> 10) & 0x3fffff);\n",
rel->r_offset - offset, rel->r_offset - start_offset,
rel->r_offset - offset, rel->r_offset - start_offset,
name, addend); name, addend);
break; break;
case R_SPARC_LO10: case R_SPARC_LO10:
...@@ -735,8 +771,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -735,8 +771,8 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
"((*(uint32_t *)(gen_code_ptr + %d)) " "((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3ff) " " & ~0x3ff) "
" | ((%s + %d) & 0x3ff);\n", " | ((%s + %d) & 0x3ff);\n",
rel->r_offset - offset, rel->r_offset - start_offset,
rel->r_offset - offset, rel->r_offset - start_offset,
name, addend); name, addend);
break; break;
case R_SPARC_WDISP30: case R_SPARC_WDISP30:
...@@ -744,11 +780,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size, ...@@ -744,11 +780,12 @@ void gen_code(const char *name, host_ulong offset, host_ulong size,
" *(uint32_t *)(gen_code_ptr + %d) = " " *(uint32_t *)(gen_code_ptr + %d) = "
"((*(uint32_t *)(gen_code_ptr + %d)) " "((*(uint32_t *)(gen_code_ptr + %d)) "
" & ~0x3fffffff) " " & ~0x3fffffff) "
" | ((((%s + %d) - (long)gen_code_ptr)>>2) " " | ((((%s + %d) - (long)(gen_code_ptr + %d))>>2) "
" & 0x3fffffff);\n", " & 0x3fffffff);\n",
rel->r_offset - offset, rel->r_offset - start_offset,
rel->r_offset - offset, rel->r_offset - start_offset,
name, addend); name, addend,
rel->r_offset - start_offset);
break; break;
default: default:
error("unsupported sparc64 relocation (%d)", type); error("unsupported sparc64 relocation (%d)", type);
...@@ -933,7 +970,22 @@ fprintf(outfile, ...@@ -933,7 +970,22 @@ fprintf(outfile,
" const uint32_t *opparam_ptr;\n" " const uint32_t *opparam_ptr;\n"
" gen_code_ptr = gen_code_buf;\n" " gen_code_ptr = gen_code_buf;\n"
" opc_ptr = opc_buf;\n" " opc_ptr = opc_buf;\n"
" opparam_ptr = opparam_buf;\n" " opparam_ptr = opparam_buf;\n");
/* Generate prologue, if needed. */
switch(ELF_ARCH) {
case EM_SPARC:
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a080; /* sub %%sp, 128, %%sp */\n");
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a080; /* sub %%fp, 128, %%fp */\n");
break;
case EM_SPARCV9:
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c23a100; /* sub %%sp, 256, %%sp */\n");
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc27a100; /* sub %%fp, 256, %%fp */\n");
break;
};
fprintf(outfile,
" for(;;) {\n" " for(;;) {\n"
" switch(*opc_ptr++) {\n" " switch(*opc_ptr++) {\n"
); );
...@@ -961,7 +1013,7 @@ fprintf(outfile, ...@@ -961,7 +1013,7 @@ fprintf(outfile,
" the_end:\n" " the_end:\n"
); );
/* generate a return */ /* generate epilogue */
switch(ELF_ARCH) { switch(ELF_ARCH) {
case EM_386: case EM_386:
fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n"); fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n");
...@@ -980,11 +1032,13 @@ fprintf(outfile, ...@@ -980,11 +1032,13 @@ fprintf(outfile,
break; break;
case EM_SPARC: case EM_SPARC:
case EM_SPARC32PLUS: case EM_SPARC32PLUS:
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0xbc07a080; /* add %%fp, 256, %%fp */\n");
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c62008; /* jmpl %%i0 + 8, %%g0 */\n");
fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x9c03a080; /* add %%sp, 256, %%sp */\n");
break;
case EM_SPARCV9: case EM_SPARCV9:
/* Fill the delay slot. */ fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c7e008; /* ret */\n");
fprintf(outfile, "*((uint32_t *)gen_code_ptr) = *((uint32_t *)gen_code_ptr - 1); /* delay slot */\n"); fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81e80000; /* restore */\n");
fprintf(outfile, "*((uint32_t *)gen_code_ptr - 1) = 0x81c3e008; /* retl */\n");
fprintf(outfile, "gen_code_ptr++;\n");
break; break;
default: default:
error("unknown ELF architecture"); error("unknown ELF architecture");
......
...@@ -153,6 +153,13 @@ void raise_exception_err(int exception_index, int error_code) ...@@ -153,6 +153,13 @@ void raise_exception_err(int exception_index, int error_code)
{ {
/* NOTE: the register at this point must be saved by hand because /* NOTE: the register at this point must be saved by hand because
longjmp restore them */ longjmp restore them */
#ifdef __sparc__
/* We have to stay in the same register window as our caller,
* thus this trick.
*/
__asm__ __volatile__("restore\n\t"
"mov\t%o0, %i0");
#endif
#ifdef reg_EAX #ifdef reg_EAX
env->regs[R_EAX] = EAX; env->regs[R_EAX] = EAX;
#endif #endif
...@@ -409,7 +416,15 @@ int cpu_x86_exec(CPUX86State *env1) ...@@ -409,7 +416,15 @@ int cpu_x86_exec(CPUX86State *env1)
/* execute the generated code */ /* execute the generated code */
tc_ptr = tb->tc_ptr; tc_ptr = tb->tc_ptr;
gen_func = (void *)tc_ptr; gen_func = (void *)tc_ptr;
#ifdef __sparc__
__asm__ __volatile__("call %0\n\t"
" mov %%o7,%%i0"
: /* no outputs */
: "r" (gen_func)
: "i0", "i1", "i2", "i3", "i4", "i5");
#else
gen_func(); gen_func();
#endif
} }
} }
ret = env->exception_index; ret = env->exception_index;
......
...@@ -89,11 +89,27 @@ register unsigned int A0 asm("s2"); ...@@ -89,11 +89,27 @@ register unsigned int A0 asm("s2");
register struct CPUX86State *env asm("s3"); register struct CPUX86State *env asm("s3");
#endif #endif
#ifdef __sparc__ #ifdef __sparc__
register unsigned int T0 asm("l0"); register unsigned int EAX asm("l0");
register unsigned int T1 asm("l1"); register unsigned int ECX asm("l1");
register unsigned int A0 asm("l2"); register unsigned int EDX asm("l2");
register struct CPUX86State *env asm("l3"); register unsigned int EBX asm("l3");
register unsigned int ESP asm("l4");
register unsigned int EBP asm("l5");
register unsigned int ESI asm("l6");
register unsigned int EDI asm("l7");
register unsigned int T0 asm("g1");
register unsigned int T1 asm("g2");
register unsigned int A0 asm("g3");
register struct CPUX86State *env asm("g6");
#define USE_FP_CONVERT #define USE_FP_CONVERT
#define reg_EAX
#define reg_ECX
#define reg_EDX
#define reg_EBX
#define reg_ESP
#define reg_EBP
#define reg_ESI
#define reg_EDI
#endif #endif
#ifdef __s390__ #ifdef __s390__
register unsigned int T0 asm("r7"); register unsigned int T0 asm("r7");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册