S/390 host fixed
PATCH 1/1 S/390 host fixed
Hi!
S/390 host support has been broken for a long time (since 0.4.2 or something like that). I finally got around to fix it, adding disassembly support on the way.
CU
Uli
Signature · 1 line
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
Makefile.target +3 -0
@@ -347,6 +347,9 @@ ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4) LIBOBJS+=sh4-dis.o endif +ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390) +LIBOBJS+=s390-dis.o +endif ifdef CONFIG_GDBSTUB OBJS+=gdbstub.o
configure +2 -2
@@ -53,7 +53,7 @@ mips64) cpu="mips64" ;; - s390) + s390*) cpu="s390" ;; sparc|sun4[cdmuv])
@@ -300,7 +300,7 @@ if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then AIOLIBS= else - AIOLIBS="-lrt" + AIOLIBS="-lrt -lpthread" fi # default flags for all hosts
dis-asm.h +3 -0
@@ -202,6 +202,8 @@ bfd_arch_mn10300,/* Matsushita MN10300 */ bfd_arch_last }; +#define bfd_mach_s390_31 31 +#define bfd_mach_s390_64 64 typedef struct symbol_cache_entry {
@@ -379,6 +381,7 @@ extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_ppc PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_s390 PARAMS ((bfd_vma, disassemble_info*));#if 0 /* Fetch the disassembler for a given BFD, if that support is available. */
disas.c +2 -0
@@ -269,6 +269,8 @@ print_insn = print_insn_little_mips;#elif defined(__m68k__) print_insn = print_insn_m68k; +#elif defined(__s390__) + print_insn = print_insn_s390;#else fprintf (out,"0x%lx: Asm output not supported on this arch\n" , (long ) code);
dyngen-exec.h +1 -1
@@ -254,7 +254,7 @@#define GOTO_LABEL_PARAM (n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)#elif defined(__s390__)#define EXIT_TB () asm volatile ("br %r14") -#define GOTO_LABEL_PARAM (n) asm volatile ("b " ASM_NAME(__op_gen_label) #n) +#define GOTO_LABEL_PARAM (n) asm volatile ("bras %r7,8; .long " ASM_NAME(__op_gen_label) #n "; l %r7, 0(%r7); br %r7")#elif defined(__alpha__)#define EXIT_TB () asm volatile ("ret")#elif defined(__ia64__)
exec-all.h +18 -0
@@ -340,6 +340,24 @@ "1:\n");\ } while (0) +#elif defined(__s390__) +/* GCC spills R13, so we have to restore it before branching away */ + +#define GOTO_TB(opname, tbparam, n)\ +do {\ + static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\ + static void __attribute__((used)) *__op_label ## n \ + __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\ + __asm__ __volatile__ ( \ + "l %%r13,52(%%r15)\n" \ + "br %0\n" \ + : : "r" (((TranslationBlock*)tbparam)->tb_next[n]));\ + \ + for(;*((int*)0);); /* just to keep GCC busy */ \ +label ## n: ;\ +dummy_label ## n: ;\ +} while(0) +#else /* jump to next block operations (more portable code, does not need
s390-dis.c +1711 -0
1,711 lines not on this page · raw message
target-i386/helper.c +3 -0
@@ -3852,6 +3852,9 @@int ret;unsigned long pc;CPUX86State *saved_env; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-i386/translate.c +4 -0
@@ -1795,7 +1795,11 @@case CC_OP_SUBW :case CC_OP_SUBL :case CC_OP_SUBQ : +#ifdef __s390__ + func =NULL ;/* does not work on S/390 for unknown reasons */ +#else func = gen_jcc_sub[s->cc_op -CC_OP_SUBB ][jcc_op]; +#endif break ;/* some jumps are easy to compute */
Quoted 8 lines · Ulrich Hecht
Hi!
S/390 host support has been broken for a long time (since 0.4.2 or something like that). I finally got around to fix it, adding disassembly support on the way.
CU
Uli
Do you or anyone else have any plans to add S/390 target support?
Or is there some other S/390 emulator on which it is possible to run S/390 Linux? Hercules is very slow and not really usable for compilation.
Sunil
Quoted 3 lines · Ulrich Hecht
S/390 host support has been broken for a long time (since 0.4.2 or something like that). I finally got around to fix it, adding disassembly support on the way.
And here's an even better patch that also fixes non-i386 targets. MIPS needs a little workaround to keep GCC from creating a jump table, something that dyngen cannot handle. Alpha does not build because of an ICE.
CU
Uli
Signature · 1 line
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
Makefile.target +3 -0
@@ -347,6 +347,9 @@ ifeq ($(findstring sh4, $(TARGET_ARCH) $(ARCH)),sh4) LIBOBJS+=sh4-dis.o endif +ifeq ($(findstring s390, $(TARGET_ARCH) $(ARCH)),s390) +LIBOBJS+=s390-dis.o +endif ifdef CONFIG_GDBSTUB OBJS+=gdbstub.o
configure +2 -2
@@ -53,7 +53,7 @@ mips64) cpu="mips64" ;; - s390) + s390*) cpu="s390" ;; sparc|sun4[cdmuv])
@@ -300,7 +300,7 @@ if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then AIOLIBS= else - AIOLIBS="-lrt" + AIOLIBS="-lrt -lpthread" fi # default flags for all hosts
dis-asm.h +3 -0
@@ -202,6 +202,8 @@ bfd_arch_mn10300,/* Matsushita MN10300 */ bfd_arch_last }; +#define bfd_mach_s390_31 31 +#define bfd_mach_s390_64 64 typedef struct symbol_cache_entry {
@@ -379,6 +381,7 @@ extern int print_insn_tic30 PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_ppc PARAMS ((bfd_vma, disassemble_info*)); extern int print_insn_alpha PARAMS ((bfd_vma, disassemble_info*)); +extern int print_insn_s390 PARAMS ((bfd_vma, disassemble_info*));#if 0 /* Fetch the disassembler for a given BFD, if that support is available. */
disas.c +2 -0
@@ -269,6 +269,8 @@ print_insn = print_insn_little_mips;#elif defined(__m68k__) print_insn = print_insn_m68k; +#elif defined(__s390__) + print_insn = print_insn_s390;#else fprintf (out,"0x%lx: Asm output not supported on this arch\n" , (long ) code);
dyngen-exec.h +1 -1
@@ -254,7 +254,7 @@#define GOTO_LABEL_PARAM (n) asm volatile ("b " ASM_NAME(__op_gen_label) #n)#elif defined(__s390__)#define EXIT_TB () asm volatile ("br %r14") -#define GOTO_LABEL_PARAM (n) asm volatile ("b " ASM_NAME(__op_gen_label) #n) +#define GOTO_LABEL_PARAM (n) asm volatile ("bras %r7,8; .long " ASM_NAME(__op_gen_label) #n "; l %r7, 0(%r7); br %r7")#elif defined(__alpha__)#define EXIT_TB () asm volatile ("ret")#elif defined(__ia64__)
exec-all.h +18 -0
@@ -340,6 +340,24 @@ "1:\n");\ } while (0) +#elif defined(__s390__) +/* GCC spills R13, so we have to restore it before branching away */ + +#define GOTO_TB(opname, tbparam, n)\ +do {\ + static void __attribute__((used)) *dummy ## n = &&dummy_label ## n;\ + static void __attribute__((used)) *__op_label ## n \ + __asm__(ASM_OP_LABEL_NAME(n, opname)) = &&label ## n;\ + __asm__ __volatile__ ( \ + "l %%r13,52(%%r15)\n" \ + "br %0\n" \ + : : "r" (((TranslationBlock*)tbparam)->tb_next[n]));\ + \ + for(;*((int*)0);); /* just to keep GCC busy */ \ +label ## n: ;\ +dummy_label ## n: ;\ +} while(0) +#else /* jump to next block operations (more portable code, does not need
Files qemu/hda and qemu-s390/hda differ
s390-dis.c +1711 -0
1,711 lines not on this page · raw message
target-alpha/op_helper.c +3 -0
@@ -1229,6 +1229,9 @@CPUState *saved_env;target_phys_addr_t pc;int ret; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-arm/op_helper.c +3 -0
@@ -202,6 +202,9 @@CPUState *saved_env;target_phys_addr_t pc;int ret; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-i386/helper.c +3 -0
@@ -3852,6 +3852,9 @@int ret;unsigned long pc;CPUX86State *saved_env; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-i386/translate.c +8 -0
@@ -1795,7 +1795,11 @@case CC_OP_SUBW :case CC_OP_SUBL :case CC_OP_SUBQ : +#ifdef __s390__ + func =NULL ;/* does not work on S/390 for unknown reasons */ +#else func = gen_jcc_sub[s->cc_op -CC_OP_SUBB ][jcc_op]; +#endif break ;/* some jumps are easy to compute */
@@ -1843,7 +1847,11 @@ func = gen_jcc_sub[(s->cc_op -CC_OP_ADDB ) %4 ][jcc_op];break ;case JCC_S : +#ifdef __s390__ + func =NULL ; +#else func = gen_jcc_sub[(s->cc_op -CC_OP_ADDB ) %4 ][jcc_op]; +#endif break ;default : func =NULL ;
target-m68k/op_helper.c +3 -0
@@ -55,6 +55,9 @@CPUState *saved_env;target_phys_addr_t pc;int ret; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-mips/op.c +13 -0
@@ -1616,6 +1616,18 @@void op_cfc1 (void ) { +#ifdef __s390__ +if (!T1 ) +T0 = (int32_t )env->fcr0; +else if (T1 ==25 ) +T0 = ((env->fcr31 >>24 ) &0xfe ) | ((env->fcr31 >>23 ) &0x1 ); +else if (T1 ==26 ) +T0 = env->fcr31 &0x0003f07c ; +else if (T1 ==28 ) +T0 = (env->fcr31 &0x00000f83 ) | ((env->fcr31 >>22 ) &0x4 ); +else +T0 = (int32_t )env->fcr31; +#else switch (T1 ) {case 0 :T0 = (int32_t )env->fcr0;
@@ -1633,6 +1645,7 @@T0 = (int32_t )env->fcr31; break; } +#endif DEBUG_FPU_STATE ();RETURN (); }
target-mips/op_helper.c +3 -0
@@ -571,6 +571,9 @@CPUState *saved_env;unsigned long pc;int ret; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-ppc/op_helper.c +3 -0
@@ -2228,6 +2228,9 @@CPUState *saved_env;target_phys_addr_t pc;int ret; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-sh4/op_helper.c +3 -0
@@ -48,6 +48,9 @@CPUState *saved_env;unsigned long pc;int ret; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
target-sparc/op_helper.c +3 -0
@@ -1070,6 +1070,9 @@int ret;unsigned long pc;CPUState *saved_env; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif /* XXX: hack to restore env in all cases, even if not called from generated code */
Quoted 9 lines · Ulrich Hecht
Quoted 3 lines · Ulrich Hecht
S/390 host support has been broken for a long time (since 0.4.2 or something like that). I finally got around to fix it, adding disassembly support on the way.
And here's an even better patch that also fixes non-i386 targets. MIPS needs a little workaround to keep GCC from creating a jump table, something that dyngen cannot handle. Alpha does not build because of an ICE.
I committed the bits I were comfortable with, which left those:
[snip]
configure line 303
Quoted 6 lines
configure +1
-1@@ -300,7 +300,7 @@ if [ "$bsd" = "yes" -o "$darwin" = "yes" -o "$mingw32" = "yes" ] ; then AIOLIBS= else - AIOLIBS="-lrt" + AIOLIBS="-lrt -lpthread"
Why is this needed? Linux toolchains should add -lpthread implicitly.
[snip]
target-alpha/op_helper.c line 1234
Quoted 10 lines
diff -ruN
qemu/target-alpha/op_helper.cqemu-s390/target-alpha/op_helper.ctarget-alpha/op_helper.c +3
-0@@ -1229,6 +1229,9 @@CPUState *saved_env;target_phys_addr_t pc;int ret; +#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif
All of those look weird. Is this a null-extension vs. sign-extension issue?
[snip]
target-i386/translate.c line 1802
Quoted 12 lines
diff -ruN
qemu/target-i386/translate.cqemu-s390/target-i386/translate.ctarget-i386/translate.c +4
-0@@ -1795,7 +1795,11 @@case CC_OP_SUBW :case CC_OP_SUBL :case CC_OP_SUBQ : +#ifdef __s390__ + func =NULL ;/* does not work on S/390 for unknown reasons */ +#else func = gen_jcc_sub[s->cc_op -CC_OP_SUBB ][jcc_op]; +#endif
Hum. It wold be good to know what happens here.
[snip]
Quoted 9 lines
diff -ruN
qemu/target-mips/op.cqemu-s390/target-mips/op.ctarget-mips/op.c +2
-0@@ -1616,6 +1616,18 @@void op_cfc1 (void ) { +#ifdef __s390__ +if (!T1 )
target-mips/op.c line 1630
Quoted 10 lines
target-mips/op.c +10
-0+T0 = (int32_t )env->fcr0; + else if(T1 == 25) +T0 = ((env->fcr31 >>24 ) &0xfe ) | ((env->fcr31 >>23 ) &0x1 ); + else if(T1 == 26) +T0 = env->fcr31 &0x0003f07c ; + else if(T1 == 28) +T0 = (env->fcr31 &0x00000f83 ) | ((env->fcr31 >>22 ) &0x4 ); + else +T0 = (int32_t )env->fcr31; +#else
I guess this breaks when you _breathe_ at the compiler. Inventing switch-table support in dyngen would be preferable (if possible...).
Thiemo
Quoted 8 lines
target-mips/op.c line 1621
Quoted 5 lines
void
op_cfc1(void)
{target-mips/op.c +3
-0+#ifdef __s390__ +if (!T1 ) +T0 = (int32_t )env->fcr0;I guess this breaks when you _breathe_ at the compiler. Inventing switch-table support in dyngen would be preferable (if possible...).
Actually, I'm surprised this doesn't break on other hosts. Jump tables are death on all targets, I guess s390 gcc happens to use different heuristics for expanding switch statements.
I suspect making dyngen handle jump tables is not going to happen.
Paul
Quoted 1 line · Paul Brook
I suspect making dyngen handle jump tables is not going to happen.
Which brings up the question of dyngen. Very clever and a very good way of bootstrapping QEMU in the early days, but too brittle going forwards now the rest of QEMU works so well.
You had an alternative approach to dyngen, pointed at here:
http://lists.gnu.org/archive/html/qemu-devel/2006-10/msg00227.html
Any thoughts about the future of hand-coded backends in QEMU? I wasn't convinced at first (and, given resources, it isn't nearly as good as a special-purpose language for describing CPUs at this level) but I now think your work is a very good solution for bootstrapping QEMU to the next level of users.
Signature · 2 lines
Dan Shearer [email protected]
Re: [Qemu-devel] replacing dyngen (was: S/390 host fixed)
Quoted 7 lines · Dan Shearer
Quoted 1 line · Paul Brook
I suspect making dyngen handle jump tables is not going to happen.
Which brings up the question of dyngen. Very clever and a very good way of bootstrapping QEMU in the early days, but too brittle going forwards now the rest of QEMU works so well.
Quoted 8 lines
You had an alternative approach to dyngen, pointed at here:
http://lists.gnu.org/archive/html/qemu-devel/2006-10/msg00227.htmlAny thoughts about the future of hand-coded backends in QEMU? I wasn't convinced at first (and, given resources, it isn't nearly as good as a special-purpose language for describing CPUs at this level) but I now think your work is a very good solution for bootstrapping QEMU to the next level of users.
There's also a goolge SoC project to use llvm for code generation.
http://code.google.com/p/llvm-qemu/
This works, however it's also significantly slower than current qemu (no more than half the speed). It may be possible to improve this, but llvm is a fairly heavyweight framework so I'm not convinced it is ever going to be competitive for generalexecution speed.
One interesting thing that did come out of that project is that it's fairly trivial (a few hours work) to turn the existing code into a simple interpreter. Obviously this incurs a large performance hit, but also makes qemu trivially portable to other hosts.
My hand coded generator is currently ~20% slower that dyngen.
I still think this (or something similar) is the way forward, however I haven't made time to do any work on it recently. Some parts of this code effectively are a "special language" for describing a CPU, that happen to be implemented using the C preprocessor :-)
Paul
Re: [Qemu-devel] replacing dyngen (was: S/390 host fixed)
Quoted 3 lines · Paul Brook
Some parts of this code effectively are a "special language" for describing a CPU, that happen to be implemented using the C preprocessor :-)
Right, in the same way that QEMU devices written in C are in a device language? :-)
Signature · 2 lines
Dan Shearer [email protected]
Re: [Qemu-devel] replacing dyngen (was: S/390 host fixed)
Quoted 7 lines · Dan Shearer
Quoted 3 lines · Paul Brook
Some parts of this code effectively are a "special language" for describing a CPU, that happen to be implemented using the C preprocessor :-)
Right, in the same way that QEMU devices written in C are in a device language? :-)
Not really. The cpu backends are mainly defining parameters for the generic code. Most of it doesn't look much like C. The implementation of the code generator itself is in C, but that's shared between all targets.
Paul
Quoted 4 lines · Thiemo Seufer
configure line 303
Quoted 2 lines
configure +1
-1- AIOLIBS="-lrt" + AIOLIBS="-lrt -lpthread"Why is this needed? Linux toolchains should add -lpthread implicitly.
Our SLES9 toolchain seems not to. It's a near-cosmetic change.
Quoted 6 lines
target-alpha/op_helper.c line 1234
Quoted 3 lines
target-alpha/op_helper.c +3
-0+#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif All of those look weird. Is this a null-extension vs. sign-extension issue?
S/390 has a 31 (thirty-one) bit address space; the MSB of the PSW is not part of the address and must be masked out. This is simply part of the architecture, there's no way around it.
Quoted 7 lines
Quoted 5 lines
(quoted diff) +2
-0+#ifdef __s390__ + func = NULL; /* does not work on S/390 for unknownreasons */ +#else
func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];+#endif
Hum. It wold be good to know what happens here.
Indeed. :)
Quoted 4 lines
Quoted 4 lines
target-mips/op.c +4
-0+#ifdef __s390__ +if (!T1 ) +T0 = (int32_t )env->fcr0; +else if (T1 ==25 )
[...]
Quoted 2 lines
I guess this breaks when you _breathe_ at the compiler.
Probably, but that is true for a significant part of the QEMU codebase...
CU
Uli
Signature · 1 line
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
Ulrich Hecht wrote:
[snip]
Quoted 10 lines
Quoted 6 lines
target-alpha/op_helper.c line 1234
Quoted 3 lines
target-alpha/op_helper.c +3
-0+#ifdef __s390__ + retaddr = (void *)((unsigned long )retaddr &0x7fffffffUL ); +#endif All of those look weird. Is this a null-extension vs. sign-extension issue?
S/390 has a 31 (thirty-one) bit address space; the MSB of the PSW is not part of the address and must be masked out. This is simply part of the architecture, there's no way around it.
It looks like the retaddr value is always acquired via the GETPC macro, which does a __builtin_return_address(0). Could you check that
- Gcc's __builtin_return_address isn't just broken
- If the compiler is ok, test if twiddling the bit in the GETPC macro works for s390. I suspect this catches more instances of the problem and might even explain the odd breakage you saw.
Quoted 9 lines
Quoted 7 lines
Quoted 5 lines
(quoted diff) +2
-0+#ifdef __s390__ + func = NULL; /* does not work on S/390 for unknownreasons */ +#else
func = gen_jcc_sub[s->cc_op - CC_OP_SUBB][jcc_op];+#endif
Hum. It wold be good to know what happens here.
Indeed. :)
Thiemo