From f851ab83afa650b476f8a4f9819b60c1aa22a4a3 Mon Sep 17 00:00:00 2001 From: David Given Date: Sat, 22 Oct 2016 00:48:26 +0200 Subject: [PATCH] Better (and more correct) floating point conversions; fif; various new opcodes. --- mach/powerpc/mcg/platform.c | 18 +++++++ mach/powerpc/mcg/table | 65 ++++++++++++++++--------- mach/proto/mcg/hop.c | 5 +- mach/proto/mcg/pass_promotefloatops.c | 8 ++++ mach/proto/mcg/treebuilder.c | 69 ++++++++++++++++++++++----- util/mcgg/ir.dat | 22 +++++++-- 6 files changed, 148 insertions(+), 39 deletions(-) diff --git a/mach/powerpc/mcg/platform.c b/mach/powerpc/mcg/platform.c index e0a7c1a2c..2b22ec1f3 100644 --- a/mach/powerpc/mcg/platform.c +++ b/mach/powerpc/mcg/platform.c @@ -112,6 +112,11 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* hop_add_insel(hop, "stwu %H, -4(sp)", src); break; + case burm_pair_ATTR: + hop_add_insel(hop, "stwu %0H, -4(sp)", src); + hop_add_insel(hop, "stwu %1H, -4(sp)", src); + break; + case burm_float_ATTR: hop_add_insel(hop, "stfsu %H, -4(sp)", src); break; @@ -130,6 +135,11 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* hop_add_insel(hop, "lwz %H, 0(sp)", dest); break; + case burm_pair_ATTR: + hop_add_insel(hop, "lwz %0H, 4(sp)", dest); + hop_add_insel(hop, "lwz %1H, 0(sp)", dest); + break; + case burm_float_ATTR: hop_add_insel(hop, "lfs %H, 0(sp)", dest); break; @@ -174,6 +184,10 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest); break; + case burm_double_ATTR: + hop_add_insel(hop, "stfd %H, %S(fp) ! %H", src, dest, dest); + break; + default: assert(false); } @@ -190,6 +204,10 @@ struct hop* platform_move(struct basicblock* bb, struct hreg* src, struct hreg* hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src); break; + case burm_double_ATTR: + hop_add_insel(hop, "lfd %H, %S(fp) ! %H", dest, src, src); + break; + default: assert(false); } diff --git a/mach/powerpc/mcg/table b/mach/powerpc/mcg/table index f1bc27a47..632a47ef8 100644 --- a/mach/powerpc/mcg/table +++ b/mach/powerpc/mcg/table @@ -408,38 +408,28 @@ PATTERNS /* Comparisons */ - cr:(cr)cr = COMPARES4(left:(int)reg, right:(int)reg) + cr:(cr)cr = COMPARES44(left:(int)reg, right:(int)reg) emit "cmp %cr, 0, %left, %right" cost 4; - cr:(cr)cr = COMPARES4(left:(int)reg, right:CONST4) + cr:(cr)cr = COMPARES44(left:(int)reg, right:CONST4) when signed_constant(%right, 16) emit "cmpi %cr, 0, %left, $right" cost 4; - cr:(cr)cr = COMPAREU4(left:(int)reg, right:(int)reg) + cr:(cr)cr = COMPAREU44(left:(int)reg, right:(int)reg) emit "cmpl %cr, 0, %left, %right" cost 4; - cr:(cr)cr = COMPAREU4(left:(int)reg, right:CONST4) + cr:(cr)cr = COMPAREU44(left:(int)reg, right:CONST4) when signed_constant(%right, 16) emit "cmpli %cr, 0, %left, $right" cost 4; - cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:(int)reg), result:CONST4) + out:(cr)cr = COMPARES44(in:(cr)cr, result:CONST4) when specific_constant(%result, 0) - emit "cmp %cr, 0, %left, %right" - cost 4; - - cr:(cr)cr = COMPARES4(COMPARES4(left:(int)reg, right:CONST4), result:CONST4) - when specific_constant(%result, 0) - when signed_constant(%right, 16) - emit "cmpi %cr, 0, %left, $right" - cost 4; - - cr:(cr)cr = COMPARES4(COMPAREU4(left:(int)reg, right:(int)reg), result:CONST4) - when specific_constant(%result, 0) - emit "cmpl %cr, 0, %left, %right" + with %out == %in + emit "! COMPARES(cr, 0)" cost 4; @@ -580,32 +570,61 @@ PATTERNS emit "fsubs %out, %left, %right" cost 4; + out:(double)reg = SUBF8(left:(double)reg, right:(double)reg) + emit "fsub %out, %left, %right" + cost 4; + out:(float)reg = MULF4(left:(float)reg, right:(float)reg) emit "fmuls %out, %left, %right" cost 4; + out:(double)reg = MULF8(left:(double)reg, right:(double)reg) + emit "fmul %out, %left, %right" + cost 4; + out:(float)reg = NEGF4(left:(float)reg) emit "fneg %out, %left" cost 4; - cr:(cr)cr = COMPAREF4(left:(float)reg, right:(float)reg) + out:(double)reg = NEGF8(left:(double)reg) + emit "fneg %out, %left" + cost 4; + + cr:(cr)cr = COMPAREF44(left:(float)reg, right:(float)reg) emit "fcmpu %cr, %left, %right" cost 4; - cr:(cr)cr = COMPARES4(COMPAREF4(left:(float)reg, right:(float)reg), result:CONST4) - when specific_constant(%result, 0) + cr:(cr)cr = COMPAREF84(left:(double)reg, right:(double)reg) emit "fcmpu %cr, %left, %right" - cost 4; + cost 4; out:(ret)reg = CFI44(val:(fret)reg) with corrupted(volatile) - emit "bl .cfi4" + emit "bl .cfi44" cost 4; out:(fret)reg = CIF44(val:(ret)reg) with corrupted(volatile) - emit "bl .cif4" + emit "bl .cif44" cost 4; + out:(ret)reg = CFI84(val:(dret)reg) + with corrupted(volatile) + emit "bl .cfi84" + cost 4; + + out:(dret)reg = CIF48(val:(ret)reg) + with corrupted(volatile) + emit "bl .cif48" + cost 4; + + out:(float)reg = CFF84(val:(double)reg) + emit "frsp %out, %val" + cost 4; + + out:(double)reg = CFF48(val:(float)reg) + emit "fmr %out, %val" + cost 1; + /* vim: set sw=4 ts=4 expandtab : */ diff --git a/mach/proto/mcg/hop.c b/mach/proto/mcg/hop.c index 32bd44d3b..02f6b2930 100644 --- a/mach/proto/mcg/hop.c +++ b/mach/proto/mcg/hop.c @@ -223,7 +223,10 @@ char* hop_render(struct hop* hop) case INSEL_HREG: { struct hreg* hreg = insel->u.hreg; - appendf("%s", hreg->brd->names[insel->index]); + if (hreg->brd) + appendf("%s", hreg->brd->names[insel->index]); + else + appendf("%s.%d", hreg->id, insel->index); break; } diff --git a/mach/proto/mcg/pass_promotefloatops.c b/mach/proto/mcg/pass_promotefloatops.c index 2708c7fda..7e5f87c19 100644 --- a/mach/proto/mcg/pass_promotefloatops.c +++ b/mach/proto/mcg/pass_promotefloatops.c @@ -69,6 +69,14 @@ static void search_for_promotable_irs(void) case IR_MULF: case IR_DIVF: case IR_NEGF: + case IR_COMPAREF1: + case IR_COMPAREF2: + case IR_COMPAREF4: + case IR_COMPAREF8: + case IR_CFF1: + case IR_CFF2: + case IR_CFF4: + case IR_CFF8: if (ir->left) promote(ir->left); if (ir->right) diff --git a/mach/proto/mcg/treebuilder.c b/mach/proto/mcg/treebuilder.c index 180f41000..a48f59e9c 100644 --- a/mach/proto/mcg/treebuilder.c +++ b/mach/proto/mcg/treebuilder.c @@ -149,10 +149,18 @@ static struct ir* convert(struct ir* src, int destsize, int opcode) ); } -static struct ir* tristate_compare(int size, int opcode) +static struct ir* compare(struct ir* left, struct ir* right, + int size, int opcode) { - struct ir* right = pop(size); - struct ir* left = pop(size); + switch (size) + { + case 1: opcode += 0; break; + case 2: opcode += 1; break; + case 4: opcode += 2; break; + case 8: opcode += 3; break; + default: + fatal("can't compare things of size %d", size); + } return new_ir2( @@ -161,6 +169,14 @@ static struct ir* tristate_compare(int size, int opcode) ); } +static struct ir* tristate_compare(int size, int opcode) +{ + struct ir* right = pop(size); + struct ir* left = pop(size); + + return compare(left, right, size, opcode); +} + static void simple_convert(int opcode) { struct ir* destsize = pop(EM_wordsize); @@ -199,10 +215,11 @@ static void insn_simple(int opcode) case op_cui: simple_convert(IR_CUI1); break; case op_cfi: simple_convert(IR_CFI1); break; case op_cif: simple_convert(IR_CIF1); break; + case op_cff: simple_convert(IR_CFF1); break; case op_cmp: push( - tristate_compare(EM_pointersize, IR_COMPAREU) + tristate_compare(EM_pointersize, IR_COMPAREU1) ); break; @@ -276,6 +293,17 @@ static void insn_simple(int opcode) break; } + case op_trp: + { + materialise_stack(); + appendir( + new_ir1( + IR_CALL, 0, + new_labelir(".trp") + ) + ); + } + case op_lni: { /* Increment line number --- ignore. */ @@ -299,10 +327,7 @@ static void simple_branch2(int opcode, int size, appendir( new_ir2( irop, 0, - new_ir2( - IR_COMPARES, size, - left, right - ), + compare(left, right, size, IR_COMPARES1), new_ir2( IR_PAIR, 0, new_bbir(truebb), @@ -463,9 +488,9 @@ static void insn_ivalue(int opcode, arith value) case op_ngf: simple_alu1(opcode, value, IR_NEGF); break; case op_cmu: /* fall through */ - case op_cms: push(tristate_compare(value, IR_COMPAREU)); break; - case op_cmi: push(tristate_compare(value, IR_COMPARES)); break; - case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break; + case op_cms: push(tristate_compare(value, IR_COMPAREU1)); break; + case op_cmi: push(tristate_compare(value, IR_COMPARES1)); break; + case op_cmf: push(tristate_compare(value, IR_COMPAREF1)); break; case op_lol: push( @@ -910,8 +935,8 @@ static void insn_ivalue(int opcode, arith value) case op_fef: { - struct ir* e; struct ir* f = pop(value); + /* fef is implemented by calling a helper function which then mutates * the stack. We read the return values off the stack when retracting * the stack pointer. */ @@ -931,6 +956,26 @@ static void insn_ivalue(int opcode, arith value) break; } + case op_fif: + { + /* fif is implemented by calling a helper function which then mutates + * the stack. We read the return values off the stack when retracting + * the stack pointer. */ + + /* We start with two floats on the stack. */ + + materialise_stack(); + appendir( + new_ir1( + IR_CALL, 0, + new_labelir((value == 4) ? ".fif4" : ".fif8") + ) + ); + + /* exit, leaving two floats (or doubles) on the stack. */ + break; + } + case op_lin: { /* Set line number --- ignore. */ diff --git a/util/mcgg/ir.dat b/util/mcgg/ir.dat index 576587247..93f7b3c79 100644 --- a/util/mcgg/ir.dat +++ b/util/mcgg/ir.dat @@ -74,10 +74,26 @@ S CIF2 S CIF4 S CIF8 +S CFF1 +S CFF2 +S CFF4 +S CFF8 + # Tristate comparisons -S COMPARES -S COMPAREU -S COMPAREF +S COMPARES1 +S COMPARES2 +S COMPARES4 +S COMPARES8 + +S COMPAREU1 +S COMPAREU2 +S COMPAREU4 +S COMPAREU8 + +S COMPAREF1 +S COMPAREF2 +S COMPAREF4 +S COMPAREF8 # Boolean comparisons S IFEQ