diff --git a/mach/powerpc/mcg/platform.c b/mach/powerpc/mcg/platform.c index ab08209f3..2e598335a 100644 --- a/mach/powerpc/mcg/platform.c +++ b/mach/powerpc/mcg/platform.c @@ -90,7 +90,7 @@ struct hop* platform_epilogue(void) hop_add_insel(hop, "lwz r0, %d(fp)", current_proc->spills_size + 4); hop_add_insel(hop, "addi sp, fp, %d", current_proc->fp_to_ab); hop_add_insel(hop, "mr fp, r0"); - hop_add_insel(hop, "blr"); + hop_add_insel(hop, "bclr 20, 0, 0"); return hop; } diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index 95ba2a9fd..93bdb1929 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -269,7 +269,7 @@ PATTERNS /* Locals */ out:(int)reg = in:LOCAL4 - emit "addi %out, fp, #$in" + emit "addi %out, fp, $in" cost 4; address = in:LOCAL4 @@ -295,17 +295,17 @@ PATTERNS cost 4; CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4)) - emit "bc IFTRUE, EQ, $true" + emit "bc 12, 2, $true" /* IFTRUE EQ */ emit "b $false" cost 8; CJUMPLE(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4)) - emit "bc IFTRUE, LE, $true" + emit "bc 4, 1, $true" /* IFFALSE GT */ emit "b $false" cost 8; CJUMPLT(value:(cr)cr, PAIR(true:BLOCK4, false:BLOCK4)) - emit "bc IFTRUE, LT, $true" + emit "bc 12, 0, $true" /* IFTRUE LT */ emit "b $false" cost 8; @@ -317,7 +317,7 @@ PATTERNS CALL(dest:(int)reg) with corrupted(volatile) emit "mtspr ctr, %dest" - emit "bcctrl ALWAYS, 0, 0" + emit "bcctrl 20, 0, 0" cost 8; JUMP(dest:LABEL4) @@ -381,11 +381,13 @@ PATTERNS /* Conversions */ out:(int)reg = CIU44(in:(int)reg) - emit "mr %out, %in ! ciu44" + with %out == %in + emit "! ciu44" cost 4; out:(int)reg = CUI44(in:(int)reg) - emit "mr %out, %in ! cui44" + with %out == %in + emit "! cui44" cost 4; @@ -410,7 +412,7 @@ PATTERNS cost 4; out:(int)reg = SUB4(left:(int)reg, right:CONST4) - emit "addi %out, %left, -($right)" + emit "addi %out, %left, -[$right]" cost 4; out:(int)reg = MUL4(left:(int)reg, right:(int)reg) @@ -439,6 +441,18 @@ PATTERNS emit "neg %out, %left" cost 4; + out:(int)reg = AND4(left:CONST4, right:(int)reg) + emit "andi. %out, %right, $left" + cost 4; + + out:(int)reg = AND4(left:(int)reg, right:CONST4) + emit "andi. %out, %left, $right" + cost 4; + + out:(int)reg = AND4(left:(int)reg, right:(int)reg) + emit "and %out, %left, %right" + cost 4; + out:(int)reg = OR4(left:(int)reg, right:(int)reg) emit "or %out, %right, %left" cost 4; diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index e3d0f521d..9fbae16d1 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -528,6 +528,47 @@ static void insn_ivalue(int opcode, arith value) ); break; + case op_loe: + push( + new_ir1( + IR_LOAD, EM_wordsize, + new_ir2( + IR_ADD, EM_pointersize, + new_labelir(".hol0"), + new_wordir(value) + ) + ) + ); + break; + + case op_ste: + appendir( + new_ir2( + IR_STORE, EM_wordsize, + new_ir2( + IR_ADD, EM_pointersize, + new_labelir(".hol0"), + new_wordir(value) + ), + pop(EM_wordsize) + ) + ); + break; + + case op_zre: + appendir( + new_ir2( + IR_STORE, EM_wordsize, + new_ir2( + IR_ADD, EM_pointersize, + new_labelir(".hol0"), + new_wordir(value) + ), + new_wordir(0) + ) + ); + break; + case op_loc: push( new_wordir(value) @@ -577,7 +618,7 @@ static void insn_ivalue(int opcode, arith value) case op_stf: { struct ir* ptr = pop(EM_pointersize); - struct ir* val = pop(value); + struct ir* val = pop(EM_wordsize); appendir( new_ir2( @@ -854,6 +895,48 @@ static void insn_ivalue(int opcode, arith value) break; } + case op_fef: + { + struct ir* e; + struct ir* f = pop(value); + /* fef is implemented by synthesising a call to frexp. */ + push( + new_labelir(".fef_exp") + ); + push( + f + ); + materialise_stack(); + appendir( + new_ir1( + IR_CALL, 0, + new_labelir((value == 4) ? "frexpf" : "frexp") + ) + ); + appendir( + new_ir1( + IR_STACKADJUST, EM_wordsize, + new_wordir(4 + value) + ) + ); + e = appendir( + new_ir0( + IR_GETRET, value + ) + ); + push( + new_ir1( + IR_LOAD, EM_wordsize, + new_labelir(".fef_exp") + ) + ); + push( + e + ); + + break; + } + case op_lin: { /* Set line number --- ignore. */ @@ -905,6 +988,40 @@ static void insn_lvalue(int opcode, const char* label, arith offset) ); break; + case op_ine: + appendir( + new_ir2( + IR_STORE, EM_wordsize, + address_of_external(label, offset), + new_ir2( + IR_ADD, EM_wordsize, + new_ir1( + IR_LOAD, EM_wordsize, + address_of_external(label, offset) + ), + new_wordir(1) + ) + ) + ); + break; + + case op_dee: + appendir( + new_ir2( + IR_STORE, EM_wordsize, + address_of_external(label, offset), + new_ir2( + IR_ADD, EM_wordsize, + new_ir1( + IR_LOAD, EM_wordsize, + address_of_external(label, offset) + ), + new_wordir(-1) + ) + ) + ); + break; + case op_cal: assert(offset == 0); materialise_stack();