diff --git a/configure b/configure index d58c46079539735a18eba689b00fdcb317f870b5..c8d06adaac44f34f7107ebe29556757644f02416 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 5cd59cb9dfbb5f3ed75ae6c54f36e1d0e651a26f..52cabcfabcba564b5a9a9686a42b19d4cc3241b0 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 f59e1ccecf1e25d6f5a7005593344edd69764ba9..dedcbfabd6015554d1b479ba0f9494673968df87 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 7a6f74b924903419bad51521addcda9a66fbba3d..28da51def96c0b5d253f90be6d39ed6b64157b24 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 730398e97179cf118a26ee83ae373899d1156246..55e8a8dde6fddc172b3eda8ac7d75022b337c32a 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 */