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);
|
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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 : */
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue