Better (and more correct) floating point conversions; fif; various new opcodes.
This commit is contained in:
parent
d535be87b1
commit
f851ab83af
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
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 : */
|
||||
|
||||
|
|
|
@ -223,7 +223,10 @@ char* hop_render(struct hop* hop)
|
|||
case INSEL_HREG:
|
||||
{
|
||||
struct hreg* hreg = insel->u.hreg;
|
||||
if (hreg->brd)
|
||||
appendf("%s", hreg->brd->names[insel->index]);
|
||||
else
|
||||
appendf("%s.%d", hreg->id, insel->index);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue