Commit fb3e5849bb139e8213b7afb5abd7ef5cc985d10b

Authored by bellard
1 parent 7854b056

s390 support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@65 c046a42c-6fe2-441c-8c8c-71466251a162
configure
... ... @@ -42,6 +42,9 @@ case "$cpu" in
42 42 mips)
43 43 cpu="mips"
44 44 ;;
  45 + s390)
  46 + cpu="s390"
  47 + ;;
45 48 *)
46 49 cpu="unknown"
47 50 ;;
... ... @@ -137,7 +140,7 @@ fi
137 140 else
138 141  
139 142 # if cross compiling, cannot launch a program, so make a static guess
140   -if test "$cpu" = "powerpc" -o "$cpu" = "mips" ; then
  143 +if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" ; then
141 144 bigendian="yes"
142 145 fi
143 146  
... ... @@ -212,6 +215,8 @@ elif test "$cpu" = "powerpc" ; then
212 215 echo "ARCH=ppc" >> config.mak
213 216 elif test "$cpu" = "mips" ; then
214 217 echo "ARCH=mips" >> config.mak
  218 +elif test "$cpu" = "s390" ; then
  219 + echo "ARCH=s390" >> config.mak
215 220 else
216 221 echo "Unsupported CPU"
217 222 exit 1
... ...
dyngen.c
... ... @@ -28,6 +28,15 @@
28 28  
29 29 #include "thunk.h"
30 30  
  31 +/* temporary fix to make it compile with old elf headers (XXX: use
  32 + included elf.h in all cases) */
  33 +#ifndef EM_390
  34 +#define EM_S390 22 /* IBM S390 */
  35 +#define R_390_8 1 /* Direct 8 bit. */
  36 +#define R_390_16 3 /* Direct 16 bit. */
  37 +#define R_390_32 4 /* Direct 32 bit. */
  38 +#endif
  39 +
31 40 /* all dynamically generated functions begin with this code */
32 41 #define OP_PREFIX "op_"
33 42  
... ... @@ -236,6 +245,17 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
236 245 copy_size = p - p_start;
237 246 }
238 247 break;
  248 + case EM_S390:
  249 + {
  250 + uint8_t *p;
  251 + p = (void *)(p_end - 2);
  252 + if (p == p_start)
  253 + error("empty code for %s", name);
  254 + if (get16((uint16_t *)p) != 0x07fe && get16((uint16_t *)p) != 0x07f4)
  255 + error("br %r14 expected at the end of %s", name);
  256 + copy_size = p - p_start;
  257 + }
  258 + break;
239 259 default:
240 260 error("unsupported CPU (%d)", e_machine);
241 261 }
... ... @@ -405,6 +425,42 @@ void gen_code(const char *name, unsigned long offset, unsigned long size,
405 425 }
406 426 }
407 427 break;
  428 + case EM_S390:
  429 + {
  430 + Elf32_Rela *rel;
  431 + char name[256];
  432 + int type;
  433 + long addend;
  434 + for(i = 0, rel = relocs;i < nb_relocs; i++, rel++) {
  435 + if (rel->r_offset >= offset && rel->r_offset < offset + copy_size) {
  436 + sym_name = strtab + symtab[ELF32_R_SYM(rel->r_info)].st_name;
  437 + if (strstart(sym_name, "__op_param", &p)) {
  438 + snprintf(name, sizeof(name), "param%s", p);
  439 + } else {
  440 + snprintf(name, sizeof(name), "(long)(&%s)", sym_name);
  441 + }
  442 + type = ELF32_R_TYPE(rel->r_info);
  443 + addend = rel->r_addend;
  444 + switch(type) {
  445 + case R_390_32:
  446 + fprintf(outfile, " *(uint32_t *)(gen_code_ptr + %ld) = %s + %ld;\n",
  447 + rel->r_offset - offset, name, addend);
  448 + break;
  449 + case R_390_16:
  450 + fprintf(outfile, " *(uint16_t *)(gen_code_ptr + %ld) = %s + %ld;\n",
  451 + rel->r_offset - offset, name, addend);
  452 + break;
  453 + case R_390_8:
  454 + fprintf(outfile, " *(uint8_t *)(gen_code_ptr + %ld) = %s + %ld;\n",
  455 + rel->r_offset - offset, name, addend);
  456 + break;
  457 + default:
  458 + error("unsupported s390 relocation (%d)", type);
  459 + }
  460 + }
  461 + }
  462 + }
  463 + break;
408 464 default:
409 465 error("unsupported CPU for relocations (%d)", e_machine);
410 466 }
... ... @@ -556,6 +612,9 @@ int load_elf(const char *filename, FILE *outfile, int do_print_enum)
556 612 case EM_SPARC:
557 613 cpu_name = "sparc";
558 614 break;
  615 + case EM_S390:
  616 + cpu_name = "s390";
  617 + break;
559 618 default:
560 619 error("unsupported CPU (e_machine=%d)", e_machine);
561 620 }
... ... @@ -617,6 +676,9 @@ fprintf(outfile,
617 676 case EM_PPC:
618 677 fprintf(outfile, "*((uint32_t *)gen_code_ptr)++ = 0x4e800020; /* blr */\n");
619 678 break;
  679 + case EM_S390:
  680 + fprintf(outfile, "*((uint16_t *)gen_code_ptr)++ = 0x07fe; /* br %%r14 */\n");
  681 + break;
620 682 default:
621 683 error("no return generation for cpu '%s'", cpu_name);
622 684 }
... ...
exec-i386.c
... ... @@ -87,6 +87,20 @@ static inline int testandset (int *p)
87 87 }
88 88 #endif
89 89  
  90 +#ifdef __s390__
  91 +static inline int testandset (int *p)
  92 +{
  93 + int ret;
  94 +
  95 + __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
  96 + " jl 0b"
  97 + : "=&d" (ret)
  98 + : "r" (1), "a" (p), "0" (*p)
  99 + : "cc", "memory" );
  100 + return ret;
  101 +}
  102 +#endif
  103 +
90 104 int global_cpu_lock = 0;
91 105  
92 106 void cpu_lock(void)
... ...
exec-i386.h
... ... @@ -93,6 +93,12 @@ register unsigned int T1 asm(&quot;l1&quot;);
93 93 register unsigned int A0 asm("l2");
94 94 register struct CPUX86State *env asm("l3");
95 95 #endif
  96 +#ifdef __s390__
  97 +register unsigned int T0 asm("r7");
  98 +register unsigned int T1 asm("r8");
  99 +register unsigned int A0 asm("r9");
  100 +register struct CPUX86State *env asm("r10");
  101 +#endif
96 102  
97 103 /* force GCC to generate only one epilog at the end of the function */
98 104 #define FORCE_RET() asm volatile ("");
... ...
translate-i386.c
... ... @@ -50,6 +50,12 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
50 50 }
51 51 #endif
52 52  
  53 +#ifdef __s390__
  54 +static inline void flush_icache_range(unsigned long start, unsigned long stop)
  55 +{
  56 +}
  57 +#endif
  58 +
53 59 #ifdef __powerpc__
54 60  
55 61 #define MIN_CACHE_LINE_SIZE 8 /* conservative value */
... ...