diff --git a/mach/powerpc/libem/csa.s b/mach/powerpc/libem/csa.s index 64954ff4e..88e6e176a 100644 --- a/mach/powerpc/libem/csa.s +++ b/mach/powerpc/libem/csa.s @@ -12,11 +12,14 @@ ! address and jumps to it. ! traps if resulting address is zero ! -! On entry: r3 = address of CSA table -! r4 = value +! Stack: ( value tableaddr -- ) .define .csa .csa: + lwz r3, 0(sp) + lwz r4, 4(sp) + addi sp, sp, 8 + lwz r5, 0(r3) ! load default mtspr ctr, r5 diff --git a/mach/powerpc/libem/csb.s b/mach/powerpc/libem/csb.s index cbedc8c11..a8df85d7f 100644 --- a/mach/powerpc/libem/csb.s +++ b/mach/powerpc/libem/csb.s @@ -12,11 +12,14 @@ ! address and jumps to it. ! traps if resulting address is zero ! -! On entry: r3 = address of CSB table -! r4 = value +! Stack: ( value tableaddr -- ) .define .csb .csb: + lwz r3, 0(sp) + lwz r4, 4(sp) + addi sp, sp, 8 + lwz r5, 0(r3) ! load default mtspr ctr, r5 diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 03daee94e..79ac7c577 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -466,6 +466,11 @@ PATTERNS emit "b $addr" cost 4; + FARJUMP(addr:LABEL.I) + with corrupted(volatile) + emit "b $addr" + cost 4; + JUMP(dest:(int)reg) emit "mtspr ctr, %dest" emit "bcctrl 20, 0, 0" diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index ed107aceb..6f10c7d4c 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -1898,12 +1898,12 @@ PATTERNS addi SP, SP, {CONST, 12} pat csa /* Array-lookup switch */ - with GPR3 GPR4 STACK + with STACK gen b {LABEL, ".csa"} pat csb /* Table-lookup switch */ - with GPR3 GPR4 STACK + with STACK gen b {LABEL, ".csb"} diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 01e486500..66347447f 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -1130,9 +1130,8 @@ static void insn_ivalue(int opcode, arith value) case op_csa: case op_csb: { - const char* helper = aprintf(".%s%d", - (opcode == op_csa) ? "csa" : "csb", - value); + const char* helper = aprintf(".%s", + (opcode == op_csa) ? "csa" : "csb"); struct ir* descriptor = pop(EM_pointersize); if (descriptor->opcode != IR_LABEL) @@ -1143,7 +1142,7 @@ static void insn_ivalue(int opcode, arith value) materialise_stack(); appendir( new_ir2( - IR_JUMP, 0, + IR_FARJUMP, 0, new_labelir(helper), extract_block_refs(bb_get(descriptor->u.lvalue)) ) diff --git a/plat/qemuppc/descr b/plat/qemuppc/descr index f28e7482d..c0bc1eab0 100644 --- a/plat/qemuppc/descr +++ b/plat/qemuppc/descr @@ -33,8 +33,7 @@ var C_INCLUDES=-I{PLATFORMDIR}/include -I{EM}/share/ack/include/ansi name be from .m.g to .s - # Change this back to ncg to revert to the old code generator - program {EM}/lib/ack/{PLATFORM}/ncg + program {EM}/lib/ack/{PLATFORM}/mcg mapflag -gdb GF=-gdb args {GF?} < stdout diff --git a/plat/qemuppc/tests/_dummy.c b/plat/qemuppc/tests/_dummy.c index 4a56d8238..48104b5aa 100644 --- a/plat/qemuppc/tests/_dummy.c +++ b/plat/qemuppc/tests/_dummy.c @@ -5,4 +5,4 @@ void _m_a_i_n(void) { ASSERT(0 == 0); finished(); -} \ No newline at end of file +} diff --git a/plat/qemuppc/tests/csa_e.c b/plat/qemuppc/tests/csa_e.c new file mode 100644 index 000000000..355b75ee7 --- /dev/null +++ b/plat/qemuppc/tests/csa_e.c @@ -0,0 +1,26 @@ +#include "test.h" + +int csa(int i) +{ + switch (i) + { + case 2: return 2; + case 3: return 3; + case 4: return 4; + default: return 0; + } +} + +/* Bypasses the CRT, so there's no stdio or BSS initialisation. */ +void _m_a_i_n(void) +{ + ASSERT(csa(0) == 0); + ASSERT(csa(1) == 0); + ASSERT(csa(2) == 2); + ASSERT(csa(3) == 3); + ASSERT(csa(4) == 4); + ASSERT(csa(5) == 0); + ASSERT(csa(6) == 0); + + finished(); +} \ No newline at end of file diff --git a/plat/qemuppc/tests/csb_e.c b/plat/qemuppc/tests/csb_e.c new file mode 100644 index 000000000..c86d31fa6 --- /dev/null +++ b/plat/qemuppc/tests/csb_e.c @@ -0,0 +1,26 @@ +#include "test.h" + +int csa(int i) +{ + switch (i) + { + case 200: return 200; + case 300: return 300; + case 400: return 400; + default: return 0; + } +} + +/* Bypasses the CRT, so there's no stdio or BSS initialisation. */ +void _m_a_i_n(void) +{ + ASSERT(csa(0) == 0); + ASSERT(csa(100) == 0); + ASSERT(csa(200) == 200); + ASSERT(csa(300) == 300); + ASSERT(csa(400) == 400); + ASSERT(csa(500) == 0); + ASSERT(csa(600) == 0); + + finished(); +} \ No newline at end of file diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 1db593efc..b34f37fbb 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -103,6 +103,7 @@ S ?=i. SETRET # Flow control --- these never return V .=i. JUMP +V .=i. FARJUMP V .=i. CJUMPEQ V .=i. CJUMPLT V .=i. CJUMPLE