qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] Updated Sparc support


From: David S. Miller
Subject: [Qemu-devel] [PATCH] Updated Sparc support
Date: Mon, 12 May 2003 21:13:28 -0700 (PDT)

Fabrice, here are updated patches for Sparc support.
With the mmap changes you installed today, things work
quite well :-)

Please do not miss the configure and Makefile changes, they
somehow disappeared last time you applied my Sparc changes :-)

The main generic change here is to support skipping both prologue and
epilogue during op-i386.h generation.  This is supported via
'start_offset' which the cpu code can advance past initial
instructions.

Also it was necessary to add support for outputting both epilogue
and prologue during code generation.

Like PPC, I now hold all the main x86 registers (EAX etc.) in Sparc
registers.  This was tricky to accomplish with register windows, but
finally it works...

The current state is that for 32-bit Sparc static binaries seem to
work and test-i386 passes except for 2 or 3 float tests which I will
fix shortly.  My plan is to fix the float tests, make sure 64-bit
sparc is working properly, then move on to playing with dynamically
loaded libraries and making other improvements.

Thanks.

--- ./dyngen.c.~1~      Mon May 12 18:05:54 2003
+++ ./dyngen.c  Mon May 12 18:17:20 2003
@@ -274,14 +274,20 @@ void gen_code(const char *name, host_ulo
 {
     int copy_size = 0;
     uint8_t *p_start, *p_end;
+    host_ulong start_offset;
     int nb_args, i, n;
     uint8_t args_present[MAX_ARGS];
     const char *sym_name, *p;
     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_end = p_start + size;
+    start_offset = offset;
     switch(ELF_ARCH) {
     case EM_386:
         {
@@ -343,41 +349,63 @@ void gen_code(const char *name, host_ulo
     case EM_SPARC:
     case EM_SPARC32PLUS:
        {
+           uint32_t start_insn, end_insn1, end_insn2, skip_insn;
             uint8_t *p;
             p = (void *)(p_end - 8);
             if (p <= p_start)
                 error("empty code for %s", name);
-           if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf98)
-                error("save %%sp,-104,%%sp expected at the start of %s "
-                     "found [%08x]",
-                     name, get32((uint32_t *)(p_start + 0x0)));
-            if (get32((uint32_t *)(p + 0x0)) != 0x81c7e008 ||
-               get32((uint32_t *)(p + 0x4)) != 0x81e80000)
-                error("ret; restore; expected at the end of %s found 
[%08x:%08x]",
-                     name,
-                     get32((uint32_t *)(p + 0x0)),
-                     get32((uint32_t *)(p + 0x4)));
+           start_insn = get32((uint32_t *)(p_start + 0x0));
+           end_insn1 = get32((uint32_t *)(p + 0x0));
+           end_insn2 = get32((uint32_t *)(p + 0x4));
+           if ((start_insn & ~0x1fff) == 0x9de3a000) {
+               p_start += 0x4;
+               start_offset += 0x4;
+               if ((int)(start_insn | ~0x1fff) < -128)
+                   error("Found bogus save at the start of %s", name);
+               if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
+                   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;
        }
        break;
     case EM_SPARCV9:
        {
+           uint32_t start_insn, end_insn1, end_insn2, skip_insn;
             uint8_t *p;
             p = (void *)(p_end - 8);
             if (p <= p_start)
                 error("empty code for %s", name);
-           if (get32((uint32_t *)(p_start + 0x0)) != 0x9de3bf40)
-                error("save %%sp,-192,%%sp expected at the start of %s "
-                     "found [%08x]",
-                     name, get32((uint32_t *)(p_start + 0x0)));
-            if (get32((uint32_t *)(p + 0x0)) != 0x81cfe008 ||
-               get32((uint32_t *)(p + 0x4)) != 0x01000000)
-                error("rett %%i7+8; nop; expected at the end of %s "
-                     "found [%08x:%08x]",
-                     name,
-                     get32((uint32_t *)(p + 0x0)),
-                     get32((uint32_t *)(p + 0x4)));
+           start_insn = get32((uint32_t *)(p_start + 0x0));
+           end_insn1 = get32((uint32_t *)(p + 0x0));
+           end_insn2 = get32((uint32_t *)(p + 0x4));
+           if ((start_insn & ~0x1fff) == 0x9de3a000) {
+               p_start += 0x4;
+               start_offset += 0x4;
+               if ((int)(start_insn | ~0x1fff) < -256)
+                   error("Found bogus save at the start of %s", name);
+               if (end_insn1 != 0x81c7e008 || end_insn2 != 0x81e80000)
+                   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;
        }
        break;
@@ -390,7 +418,8 @@ void gen_code(const char *name, host_ulo
         args_present[i] = 0;
 
     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;
             if (strstart(sym_name, "__op_param", &p)) {
                 n = strtoul(p, NULL, 10);
@@ -427,7 +456,8 @@ void gen_code(const char *name, host_ulo
         fprintf(outfile, "    extern void %s();\n", name);
 
         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;
                 if (*sym_name && !strstart(sym_name, "__op_param", &p)) {
 #if defined(HOST_SPARC)
@@ -443,7 +473,7 @@ void gen_code(const char *name, host_ulo
             }
         }
 
-        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++) {
             fprintf(outfile, "    param%d = *opparam_ptr++;\n", i + 1);
         }
@@ -455,7 +485,8 @@ void gen_code(const char *name, host_ulo
                 int type;
                 int addend;
                 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;
                     if (strstart(sym_name, "__op_param", &p)) {
                         snprintf(name, sizeof(name), "param%s", p);
@@ -467,11 +498,11 @@ void gen_code(const char *name, host_ulo
                     switch(type) {
                     case R_386_32:
                         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;
                     case R_386_PC32:
                         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;
                     default:
                         error("unsupported i386 relocation (%d)", type);
@@ -485,7 +516,8 @@ void gen_code(const char *name, host_ulo
                 int type;
                 int addend;
                 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;
                         if (strstart(sym_name, "__op_param", &p)) {
                             snprintf(name, sizeof(name), "param%s", p);
@@ -497,24 +529,24 @@ void gen_code(const char *name, host_ulo
                         switch(type) {
                         case R_PPC_ADDR32:
                             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;
                         case R_PPC_ADDR16_LO:
                             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;
                         case R_PPC_ADDR16_HI:
                             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;
                         case R_PPC_ADDR16_HA:
                             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;
                         case R_PPC_REL24:
                             /* 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", 
-                                    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;
                         default:
                             error("unsupported powerpc relocation (%d)", type);
@@ -528,7 +560,8 @@ void gen_code(const char *name, host_ulo
                 int type;
                 int addend;
                 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;
                         if (strstart(sym_name, "__op_param", &p)) {
                             snprintf(name, sizeof(name), "param%s", p);
@@ -540,15 +573,15 @@ void gen_code(const char *name, host_ulo
                         switch(type) {
                         case R_390_32:
                             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;
                         case R_390_16:
                             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;
                         case R_390_8:
                             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;
                         default:
                             error("unsupported s390 relocation (%d)", type);
@@ -559,7 +592,7 @@ void gen_code(const char *name, host_ulo
 #elif defined(HOST_ALPHA)
             {
                 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;
 
                        type = ELF64_R_TYPE(rel->r_info);
@@ -569,9 +602,9 @@ void gen_code(const char *name, host_ulo
                            /* 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.  */
                            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",
-                                   rel->r_offset - offset + rel->r_addend);
+                                   rel->r_offset - start_offset + 
rel->r_addend);
                            break;
                        case R_ALPHA_LITUSE:
                            /* jsr to literal hint. Could be used to optimize 
to bsr. Ignore for
@@ -591,18 +624,18 @@ void gen_code(const char *name, host_ulo
                               special treatment.  */
                            if (strstart(sym_name, "__op_param", &p))
                                fprintf(outfile, "    
immediate_ldah(gen_code_ptr + %ld, param%s);\n",
-                                       rel->r_offset - offset, p);
+                                       rel->r_offset - start_offset, p);
                            break;
                        case R_ALPHA_GPRELLOW:
                            if (strstart(sym_name, "__op_param", &p))
                                fprintf(outfile, "    
immediate_lda(gen_code_ptr + %ld, param%s);\n",
-                                       rel->r_offset - offset, p);
+                                       rel->r_offset - start_offset, p);
                            break;
                        case R_ALPHA_BRSGP:
                            /* PC-relative jump. Tweak offset to skip the two 
instructions that try to
                               set up the gp from the pv.  */
                            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;
                        default:
                            error("unsupported Alpha relocation (%d)", type);
@@ -616,7 +649,7 @@ void gen_code(const char *name, host_ulo
                 int type;
                 int addend;
                 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;
                         if (strstart(sym_name, "__op_param", &p)) {
                             snprintf(name, sizeof(name), "param%s", p);
@@ -642,7 +675,8 @@ void gen_code(const char *name, host_ulo
                 int type;
                 int addend;
                 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;
                         if (strstart(sym_name, "__op_param", &p)) {
                             snprintf(name, sizeof(name), "param%s", p);
@@ -660,16 +694,16 @@ void gen_code(const char *name, host_ulo
                         switch(type) {
                         case R_SPARC_32:
                             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;
                        case R_SPARC_HI22:
                             fprintf(outfile,
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
                                    " & ~0x3fffff) "
-                                   " | ((%s + %d) & 0x3fffff);\n",
-                                    rel->r_offset - offset,
-                                   rel->r_offset - offset,
+                                   " | (((%s + %d) >> 10) & 0x3fffff);\n",
+                                    rel->r_offset - start_offset,
+                                   rel->r_offset - start_offset,
                                    name, addend);
                            break;
                        case R_SPARC_LO10:
@@ -678,8 +712,8 @@ void gen_code(const char *name, host_ulo
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
                                    " & ~0x3ff) "
                                    " | ((%s + %d) & 0x3ff);\n",
-                                    rel->r_offset - offset,
-                                   rel->r_offset - offset,
+                                    rel->r_offset - start_offset,
+                                   rel->r_offset - start_offset,
                                    name, addend);
                            break;
                        case R_SPARC_WDISP30:
@@ -687,11 +721,12 @@ void gen_code(const char *name, host_ulo
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
                                    " & ~0x3fffffff) "
-                                   " | ((((%s + %d) - (long)gen_code_ptr)>>2) "
+                                   " | ((((%s + %d) - (long)(gen_code_ptr + 
%d))>>2) "
                                    "    & 0x3fffffff);\n",
-                                   rel->r_offset - offset,
-                                   rel->r_offset - offset,
-                                   name, addend);
+                                   rel->r_offset - start_offset,
+                                   rel->r_offset - start_offset,
+                                   name, addend,
+                                   rel->r_offset - start_offset);
                            break;
                         default:
                             error("unsupported sparc relocation (%d)", type);
@@ -705,7 +740,8 @@ void gen_code(const char *name, host_ulo
                 int type;
                 int addend;
                 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;
                         if (strstart(sym_name, "__op_param", &p)) {
                             snprintf(name, sizeof(name), "param%s", p);
@@ -717,16 +753,16 @@ void gen_code(const char *name, host_ulo
                         switch(type) {
                         case R_SPARC_32:
                             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;
                        case R_SPARC_HI22:
                             fprintf(outfile,
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
                                    " & ~0x3fffff) "
-                                   " | ((%s + %d) & 0x3fffff);\n",
-                                    rel->r_offset - offset,
-                                   rel->r_offset - offset,
+                                   " | (((%s + %d) >> 10) & 0x3fffff);\n",
+                                    rel->r_offset - start_offset,
+                                   rel->r_offset - start_offset,
                                    name, addend);
                            break;
                        case R_SPARC_LO10:
@@ -735,8 +771,8 @@ void gen_code(const char *name, host_ulo
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
                                    " & ~0x3ff) "
                                    " | ((%s + %d) & 0x3ff);\n",
-                                    rel->r_offset - offset,
-                                   rel->r_offset - offset,
+                                    rel->r_offset - start_offset,
+                                   rel->r_offset - start_offset,
                                    name, addend);
                            break;
                        case R_SPARC_WDISP30:
@@ -744,11 +780,12 @@ void gen_code(const char *name, host_ulo
                                    "    *(uint32_t *)(gen_code_ptr + %d) = "
                                    "((*(uint32_t *)(gen_code_ptr + %d)) "
                                    " & ~0x3fffffff) "
-                                   " | ((((%s + %d) - (long)gen_code_ptr)>>2) "
+                                   " | ((((%s + %d) - (long)(gen_code_ptr + 
%d))>>2) "
                                    "    & 0x3fffffff);\n",
-                                   rel->r_offset - offset,
-                                   rel->r_offset - offset,
-                                   name, addend);
+                                   rel->r_offset - start_offset,
+                                   rel->r_offset - start_offset,
+                                   name, addend,
+                                   rel->r_offset - start_offset);
                            break;
                         default:
                            error("unsupported sparc64 relocation (%d)", type);
@@ -933,7 +970,22 @@ fprintf(outfile,
 "    const uint32_t *opparam_ptr;\n"
 "    gen_code_ptr = gen_code_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"
 "        switch(*opc_ptr++) {\n"
 );
@@ -961,7 +1013,7 @@ fprintf(outfile,
 " the_end:\n"
 );
 
-/* generate a return */ 
+/* generate epilogue */ 
     switch(ELF_ARCH) {
     case EM_386:
         fprintf(outfile, "*gen_code_ptr++ = 0xc3; /* ret */\n");
@@ -980,11 +1032,13 @@ fprintf(outfile,
         break;
     case EM_SPARC:
     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:
-       /* Fill the delay slot. */
-       fprintf(outfile, "*((uint32_t *)gen_code_ptr) = *((uint32_t 
*)gen_code_ptr - 1); /* delay slot */\n");
-       fprintf(outfile, "*((uint32_t *)gen_code_ptr - 1) = 0x81c3e008; /* retl 
*/\n");
-       fprintf(outfile, "gen_code_ptr++;\n");
+       fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81c7e008; /* ret 
*/\n");
+       fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x81e80000; /* 
restore */\n");
         break;
     default:
        error("unknown ELF architecture");
--- ./exec-i386.c.~1~   Mon May 12 18:05:54 2003
+++ ./exec-i386.c       Mon May 12 18:06:01 2003
@@ -153,6 +153,13 @@ void raise_exception_err(int exception_i
 {
     /* NOTE: the register at this point must be saved by hand because
        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
     env->regs[R_EAX] = EAX;
 #endif
@@ -409,7 +416,15 @@ int cpu_x86_exec(CPUX86State *env1)
             /* execute the generated code */
             tc_ptr = tb->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();
+#endif
         }
     }
     ret = env->exception_index;
--- ./exec-i386.h.~1~   Mon May 12 18:05:54 2003
+++ ./exec-i386.h       Mon May 12 18:06:01 2003
@@ -89,11 +89,27 @@ register unsigned int A0 asm("s2");
 register struct CPUX86State *env asm("s3");
 #endif
 #ifdef __sparc__
-register unsigned int T0 asm("l0");
-register unsigned int T1 asm("l1");
-register unsigned int A0 asm("l2");
-register struct CPUX86State *env asm("l3");
+register unsigned int EAX asm("l0");
+register unsigned int ECX asm("l1");
+register unsigned int EDX asm("l2");
+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 reg_EAX
+#define reg_ECX
+#define reg_EDX
+#define reg_EBX
+#define reg_ESP
+#define reg_EBP
+#define reg_ESI
+#define reg_EDI
 #endif
 #ifdef __s390__
 register unsigned int T0 asm("r7");
--- ./Makefile.~1~      Mon May 12 18:05:54 2003
+++ ./Makefile  Mon May 12 18:13:20 2003
@@ -29,6 +29,18 @@ OP_CFLAGS=$(CFLAGS)
 LDFLAGS+=-Wl,-T,s390.ld
 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)
 # -msmall-data is not used because we want two-instruction relocations
 # for the constant constructions
--- ./configure.~1~     Mon May 12 18:05:54 2003
+++ ./configure Mon May 12 18:06:01 2003
@@ -47,6 +47,12 @@ case "$cpu" in
   s390)
     cpu="s390"
   ;;
+  sparc)
+    cpu="sparc"
+  ;;
+  sparc64)
+    cpu="sparc64"
+  ;;
   ia64)
     cpu="ia64"
   ;;
@@ -131,7 +137,7 @@ fi
 else
 
 # 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"
 fi
 
@@ -217,6 +223,12 @@ elif test "$cpu" = "s390" ; then
 elif test "$cpu" = "alpha" ; then
   echo "ARCH=alpha" >> config.mak
   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
   echo "ARCH=ia64" >> config.mak
   echo "#define HOST_IA64 1" >> $TMPH




reply via email to

[Prev in Thread] Current Thread [Next in Thread]