s390 support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@65 c046a42c-6fe2-441c-8c8c-71466251a162
diff --git a/configure b/configure
index d58c460..c8d06ad 100755
--- a/configure
+++ b/configure
@@ -42,6 +42,9 @@
   mips)
     cpu="mips"
   ;;
+  s390)
+    cpu="s390"
+  ;;
   *)
     cpu="unknown"
   ;;
@@ -137,7 +140,7 @@
 else
 
 # if cross compiling, cannot launch a program, so make a static guess
-if test "$cpu" = "powerpc" -o "$cpu" = "mips" ; then
+if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then
     bigendian="yes"
 fi
 
@@ -212,6 +215,8 @@
   echo "ARCH=ppc" >> config.mak
 elif test "$cpu" = "mips" ; then
   echo "ARCH=mips" >> config.mak
+elif test "$cpu" = "s390" ; then
+  echo "ARCH=s390" >> config.mak
 else
   echo "Unsupported CPU"
   exit 1
diff --git a/dyngen.c b/dyngen.c
index 5cd59cb..52cabcf 100644
--- a/dyngen.c
+++ b/dyngen.c
@@ -28,6 +28,15 @@
 
 #include "thunk.h"
 
+/* temporary fix to make it compile with old elf headers (XXX: use
+   included elf.h in all cases) */
+#ifndef EM_390
+#define EM_S390		22		/* IBM S390 */
+#define R_390_8		1	       /* Direct 8 bit.	 */
+#define R_390_16	3	       /* Direct 16 bit.  */
+#define R_390_32	4	       /* Direct 32 bit.  */
+#endif
+
 /* all dynamically generated functions begin with this code */
 #define OP_PREFIX "op_"
 
@@ -236,6 +245,17 @@
             copy_size = p - p_start;
         }
         break;
+    case EM_S390:
+	{
+	    uint8_t *p;
+	    p = (void *)(p_end - 2);
+	    if (p == p_start)
+		error("empty code for %s", name);
+	    if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)
+		error("br %r14 expected at the end of %s", name);
+	    copy_size = p - p_start;
+	}
+        break;
     default:
         error("unsupported CPU (%d)", e_machine);
     }
@@ -405,6 +425,42 @@
                 }
             }
             break;
+        case EM_S390:
+            {
+                Elf32_Rela *rel;
+                char name[256];
+                int type;
+                long addend;
+                for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
+                    if (rel->r_offset >= offset && rel->r_offset < 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);
+                        } else {
+                            snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
+                        }
+                        type = ELF32_R_TYPE(rel->r_info);
+                        addend = rel->r_addend;
+                        switch(type) {
+                        case R_390_32:
+                            fprintf(outfile, "    *(uint32_t *)(gen_code_ptr + %ld) = %s + %ld;\n", 
+                                    rel->r_offset - offset, name, addend);
+                            break;
+                        case R_390_16:
+                            fprintf(outfile, "    *(uint16_t *)(gen_code_ptr + %ld) = %s + %ld;\n", 
+                                    rel->r_offset - offset, name, addend);
+                            break;
+                        case R_390_8:
+                            fprintf(outfile, "    *(uint8_t *)(gen_code_ptr + %ld) = %s + %ld;\n", 
+                                    rel->r_offset - offset, name, addend);
+                            break;
+                        default:
+                            error("unsupported s390 relocation (%d)", type);
+                        }
+                    }
+                }
+            }
+            break;
         default:
             error("unsupported CPU for relocations (%d)", e_machine);
         }
@@ -556,6 +612,9 @@
     case EM_SPARC:
         cpu_name = "sparc";
         break;
+    case EM_S390:
+        cpu_name = "s390";
+        break;
     default:
         error("unsupported CPU (e_machine=%d)", e_machine);
     }
@@ -617,6 +676,9 @@
     case EM_PPC:
         fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x4e800020; /* blr */\n");
         break;
+    case EM_S390:
+        fprintf(outfile, "*((uint16_t *)gen_code_ptr)++ = 0x07fe; /* br %%r14 */\n");
+        break;
     default:
         error("no return generation for cpu '%s'", cpu_name);
     }
diff --git a/exec-i386.c b/exec-i386.c
index f59e1cc..dedcbfa 100644
--- a/exec-i386.c
+++ b/exec-i386.c
@@ -87,6 +87,20 @@
 }
 #endif
 
+#ifdef __s390__
+static inline int testandset (int *p)
+{
+    int ret;
+
+    __asm__ __volatile__ ("0: cs    %0,%1,0(%2)\n"
+			  "   jl    0b"
+			  : "=&d" (ret)
+			  : "r" (1), "a" (p), "0" (*p) 
+			  : "cc", "memory" );
+    return ret;
+}
+#endif
+
 int global_cpu_lock = 0;
 
 void cpu_lock(void)
diff --git a/exec-i386.h b/exec-i386.h
index 7a6f74b..28da51d 100644
--- a/exec-i386.h
+++ b/exec-i386.h
@@ -93,6 +93,12 @@
 register unsigned int A0 asm("l2");
 register struct CPUX86State *env asm("l3");
 #endif
+#ifdef __s390__
+register unsigned int T0 asm("r7");
+register unsigned int T1 asm("r8");
+register unsigned int A0 asm("r9");
+register struct CPUX86State *env asm("r10");
+#endif
 
 /* force GCC to generate only one epilog at the end of the function */
 #define FORCE_RET() asm volatile ("");
diff --git a/translate-i386.c b/translate-i386.c
index 730398e..55e8a8d 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -50,6 +50,12 @@
 }
 #endif
 
+#ifdef __s390__
+static inline void flush_icache_range(unsigned long start, unsigned long stop)
+{
+}
+#endif
+
 #ifdef __powerpc__
 
 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */