summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-29 17:32:36 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2003-03-29 17:32:36 +0000
commitfb3e5849bb139e8213b7afb5abd7ef5cc985d10b (patch)
tree667fc6ee486c6a762c1fddb007396660ae3f5733
parent7854b05654b49c2197faef358e3ec1a7559797b9 (diff)
downloadqemu-fb3e5849bb139e8213b7afb5abd7ef5cc985d10b.tar.gz
s390 support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@65 c046a42c-6fe2-441c-8c8c-71466251a162
-rwxr-xr-xconfigure7
-rw-r--r--dyngen.c62
-rw-r--r--exec-i386.c14
-rw-r--r--exec-i386.h6
-rw-r--r--translate-i386.c6
5 files changed, 94 insertions, 1 deletions
diff --git a/configure b/configure
index d58c460795..c8d06adaac 100755
--- a/configure
+++ b/configure
@@ -42,6 +42,9 @@ case "$cpu" in
mips)
cpu="mips"
;;
+ s390)
+ cpu="s390"
+ ;;
*)
cpu="unknown"
;;
@@ -137,7 +140,7 @@ fi
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 @@ elif test "$cpu" = "powerpc" ; then
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 5cd59cb9df..52cabcfabc 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 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
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 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
}
}
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 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum)
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 @@ fprintf(outfile,
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 f59e1ccecf..dedcbfabd6 100644
--- a/exec-i386.c
+++ b/exec-i386.c
@@ -87,6 +87,20 @@ static inline int testandset (int *p)
}
#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 7a6f74b924..28da51def9 100644
--- a/exec-i386.h
+++ b/exec-i386.h
@@ -93,6 +93,12 @@ register unsigned int T1 asm("l1");
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 730398e971..55e8a8dde6 100644
--- a/translate-i386.c
+++ b/translate-i386.c
@@ -50,6 +50,12 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
}
#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 */