Better (and more correct) floating point conversions; fif; various new opcodes.

This commit is contained in:
David Given 2016-10-22 00:48:26 +02:00
parent d535be87b1
commit f851ab83af
6 changed files with 148 additions and 39 deletions

View file

@ -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); hop_add_insel(hop, "stwu %H, -4(sp)", src);
break; 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: case burm_float_ATTR:
hop_add_insel(hop, "stfsu %H, -4(sp)", src); hop_add_insel(hop, "stfsu %H, -4(sp)", src);
break; 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); hop_add_insel(hop, "lwz %H, 0(sp)", dest);
break; 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: case burm_float_ATTR:
hop_add_insel(hop, "lfs %H, 0(sp)", dest); hop_add_insel(hop, "lfs %H, 0(sp)", dest);
break; 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); hop_add_insel(hop, "stfs %H, %S(fp) ! %H", src, dest, dest);
break; break;
case burm_double_ATTR:
hop_add_insel(hop, "stfd %H, %S(fp) ! %H", src, dest, dest);
break;
default: default:
assert(false); 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); hop_add_insel(hop, "lfs %H, %S(fp) ! %H", dest, src, src);
break; break;
case burm_double_ATTR:
hop_add_insel(hop, "lfd %H, %S(fp) ! %H", dest, src, src);
break;
default: default:
assert(false); assert(false);
} }

View file

@ -408,38 +408,28 @@ PATTERNS
/* Comparisons */ /* 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" emit "cmp %cr, 0, %left, %right"
cost 4; 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) when signed_constant(%right, 16)
emit "cmpi %cr, 0, %left, $right" emit "cmpi %cr, 0, %left, $right"
cost 4; 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" emit "cmpl %cr, 0, %left, %right"
cost 4; 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) when signed_constant(%right, 16)
emit "cmpli %cr, 0, %left, $right" emit "cmpli %cr, 0, %left, $right"
cost 4; 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) when specific_constant(%result, 0)
emit "cmp %cr, 0, %left, %right" with %out == %in
cost 4; emit "! COMPARES(cr, 0)"
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"
cost 4; cost 4;
@ -580,32 +570,61 @@ PATTERNS
emit "fsubs %out, %left, %right" emit "fsubs %out, %left, %right"
cost 4; 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) out:(float)reg = MULF4(left:(float)reg, right:(float)reg)
emit "fmuls %out, %left, %right" emit "fmuls %out, %left, %right"
cost 4; 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) out:(float)reg = NEGF4(left:(float)reg)
emit "fneg %out, %left" emit "fneg %out, %left"
cost 4; 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" emit "fcmpu %cr, %left, %right"
cost 4; cost 4;
cr:(cr)cr = COMPARES4(COMPAREF4(left:(float)reg, right:(float)reg), result:CONST4) cr:(cr)cr = COMPAREF84(left:(double)reg, right:(double)reg)
when specific_constant(%result, 0)
emit "fcmpu %cr, %left, %right" emit "fcmpu %cr, %left, %right"
cost 4; cost 4;
out:(ret)reg = CFI44(val:(fret)reg) out:(ret)reg = CFI44(val:(fret)reg)
with corrupted(volatile) with corrupted(volatile)
emit "bl .cfi4" emit "bl .cfi44"
cost 4; cost 4;
out:(fret)reg = CIF44(val:(ret)reg) out:(fret)reg = CIF44(val:(ret)reg)
with corrupted(volatile) with corrupted(volatile)
emit "bl .cif4" emit "bl .cif44"
cost 4; 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 : */ /* vim: set sw=4 ts=4 expandtab : */

View file

@ -223,7 +223,10 @@ char* hop_render(struct hop* hop)
case INSEL_HREG: case INSEL_HREG:
{ {
struct hreg* hreg = insel->u.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; break;
} }

View file

@ -69,6 +69,14 @@ static void search_for_promotable_irs(void)
case IR_MULF: case IR_MULF:
case IR_DIVF: case IR_DIVF:
case IR_NEGF: 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) if (ir->left)
promote(ir->left); promote(ir->left);
if (ir->right) if (ir->right)

View file

@ -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); switch (size)
struct ir* left = pop(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 return
new_ir2( 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) static void simple_convert(int opcode)
{ {
struct ir* destsize = pop(EM_wordsize); 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_cui: simple_convert(IR_CUI1); break;
case op_cfi: simple_convert(IR_CFI1); break; case op_cfi: simple_convert(IR_CFI1); break;
case op_cif: simple_convert(IR_CIF1); break; case op_cif: simple_convert(IR_CIF1); break;
case op_cff: simple_convert(IR_CFF1); break;
case op_cmp: case op_cmp:
push( push(
tristate_compare(EM_pointersize, IR_COMPAREU) tristate_compare(EM_pointersize, IR_COMPAREU1)
); );
break; break;
@ -276,6 +293,17 @@ static void insn_simple(int opcode)
break; break;
} }
case op_trp:
{
materialise_stack();
appendir(
new_ir1(
IR_CALL, 0,
new_labelir(".trp")
)
);
}
case op_lni: case op_lni:
{ {
/* Increment line number --- ignore. */ /* Increment line number --- ignore. */
@ -299,10 +327,7 @@ static void simple_branch2(int opcode, int size,
appendir( appendir(
new_ir2( new_ir2(
irop, 0, irop, 0,
new_ir2( compare(left, right, size, IR_COMPARES1),
IR_COMPARES, size,
left, right
),
new_ir2( new_ir2(
IR_PAIR, 0, IR_PAIR, 0,
new_bbir(truebb), 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_ngf: simple_alu1(opcode, value, IR_NEGF); break;
case op_cmu: /* fall through */ case op_cmu: /* fall through */
case op_cms: push(tristate_compare(value, IR_COMPAREU)); break; case op_cms: push(tristate_compare(value, IR_COMPAREU1)); break;
case op_cmi: push(tristate_compare(value, IR_COMPARES)); break; case op_cmi: push(tristate_compare(value, IR_COMPARES1)); break;
case op_cmf: push(tristate_compare(value, IR_COMPAREF)); break; case op_cmf: push(tristate_compare(value, IR_COMPAREF1)); break;
case op_lol: case op_lol:
push( push(
@ -910,8 +935,8 @@ static void insn_ivalue(int opcode, arith value)
case op_fef: case op_fef:
{ {
struct ir* e;
struct ir* f = pop(value); struct ir* f = pop(value);
/* fef is implemented by calling a helper function which then mutates /* 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. We read the return values off the stack when retracting
* the stack pointer. */ * the stack pointer. */
@ -931,6 +956,26 @@ static void insn_ivalue(int opcode, arith value)
break; 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: case op_lin:
{ {
/* Set line number --- ignore. */ /* Set line number --- ignore. */

View file

@ -74,10 +74,26 @@ S CIF2
S CIF4 S CIF4
S CIF8 S CIF8
S CFF1
S CFF2
S CFF4
S CFF8
# Tristate comparisons # Tristate comparisons
S COMPARES S COMPARES1
S COMPAREU S COMPARES2
S COMPAREF S COMPARES4
S COMPARES8
S COMPAREU1
S COMPAREU2
S COMPAREU4
S COMPAREU8
S COMPAREF1
S COMPAREF2
S COMPAREF4
S COMPAREF8
# Boolean comparisons # Boolean comparisons
S IFEQ S IFEQ