More opcodes. sti can now cope with non-standard sizes (really need a better
fix for this). Hack in crude support for mismatched stack pushes and pops (ints vs longs).
This commit is contained in:
parent
68419da235
commit
61349389fb
|
@ -229,7 +229,7 @@ PATTERNS
|
||||||
out:(int)reg = FPTOLB.I(in:(int)reg)
|
out:(int)reg = FPTOLB.I(in:(int)reg)
|
||||||
with %out == %in
|
with %out == %in
|
||||||
cost 1;
|
cost 1;
|
||||||
|
|
||||||
out:(int)reg = GETSP.I
|
out:(int)reg = GETSP.I
|
||||||
emit "mr %out, sp"
|
emit "mr %out, sp"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
@ -417,6 +417,19 @@ PATTERNS
|
||||||
emit "bl .fromui2d"
|
emit "bl .fromui2d"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
out:(lret)reg = FROMIPAIR.L(in1:(int)reg, in2:(int)reg)
|
||||||
|
emit "mr %out.0, %in1"
|
||||||
|
emit "mr %out.1, %in2"
|
||||||
|
cost 8;
|
||||||
|
|
||||||
|
out:(int)reg = FROML0.I(in:(long)reg)
|
||||||
|
emit "mr %out, %in.0"
|
||||||
|
cost 4;
|
||||||
|
|
||||||
|
out:(int)reg = FROML1.I(in:(long)reg)
|
||||||
|
emit "mr %out, %in.1"
|
||||||
|
cost 4;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Locals */
|
/* Locals */
|
||||||
|
@ -448,6 +461,11 @@ PATTERNS
|
||||||
emit "b $addr"
|
emit "b $addr"
|
||||||
cost 4;
|
cost 4;
|
||||||
|
|
||||||
|
JUMP(dest:(int)reg)
|
||||||
|
emit "mtspr ctr, %dest"
|
||||||
|
emit "bcctrl 20, 0, 0"
|
||||||
|
cost 8;
|
||||||
|
|
||||||
CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK.I, false:BLOCK.I))
|
CJUMPEQ(value:(cr)cr, PAIR(true:BLOCK.I, false:BLOCK.I))
|
||||||
emit "bc 12, 2, $true" /* IFTRUE EQ */
|
emit "bc 12, 2, $true" /* IFTRUE EQ */
|
||||||
emit "b $false"
|
emit "b $false"
|
||||||
|
|
|
@ -64,7 +64,8 @@ void data_float(const char* data, size_t size, bool is_ro)
|
||||||
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
|
emit_header(is_ro ? SECTION_ROM : SECTION_DATA);
|
||||||
assert((size == 4) || (size == 8));
|
assert((size == 4) || (size == 8));
|
||||||
|
|
||||||
if (float_cst(data, size, (char*) buffer))
|
i = float_cst(data, size, (char*) buffer);
|
||||||
|
if ((i != 0) && (i != 2)) /* 2 == overflow */
|
||||||
fatal("cannot parse floating point constant %s sz %d", data, size);
|
fatal("cannot parse floating point constant %s sz %d", data, size);
|
||||||
|
|
||||||
fprintf(outputfile, "\t!float %s sz %d\n", data, size);
|
fprintf(outputfile, "\t!float %s sz %d\n", data, size);
|
||||||
|
|
|
@ -59,7 +59,37 @@ static struct ir* pop(int size)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (ir->size != size)
|
if (ir->size != size)
|
||||||
fatal("expected an item on stack of size %d, but got %d\n", size, ir->size);
|
{
|
||||||
|
if ((size == (EM_wordsize*2)) && (ir->size == EM_wordsize))
|
||||||
|
{
|
||||||
|
/* Tried to read a long, but we got an int. Assemble the long
|
||||||
|
* out of two ints. Note that EM doesn't specify an order. */
|
||||||
|
return
|
||||||
|
new_ir2(
|
||||||
|
IR_FROMIPAIR, size,
|
||||||
|
ir,
|
||||||
|
pop(EM_wordsize)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else if ((size == EM_wordsize) && (ir->size == (EM_wordsize*2)))
|
||||||
|
{
|
||||||
|
/* Tried to read an int, but we got a long. */
|
||||||
|
push(
|
||||||
|
new_ir1(
|
||||||
|
IR_FROML1, EM_wordsize,
|
||||||
|
ir
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
return
|
||||||
|
new_ir1(
|
||||||
|
IR_FROML0, EM_wordsize,
|
||||||
|
ir
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fatal("expected an item on stack of size %d, but got %d\n", size, ir->size);
|
||||||
|
}
|
||||||
return ir;
|
return ir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -864,15 +894,34 @@ static void insn_ivalue(int opcode, arith value)
|
||||||
case op_sti:
|
case op_sti:
|
||||||
{
|
{
|
||||||
struct ir* ptr = pop(EM_pointersize);
|
struct ir* ptr = pop(EM_pointersize);
|
||||||
struct ir* val = pop(value);
|
int offset = 0;
|
||||||
|
|
||||||
appendir(
|
/* FIXME: this is awful; need a better way of dealing with
|
||||||
store(
|
* non-standard EM sizes. */
|
||||||
value,
|
if (value > (EM_wordsize*2))
|
||||||
ptr, 0,
|
appendir(ptr);
|
||||||
val
|
|
||||||
)
|
while (value > 0)
|
||||||
);
|
{
|
||||||
|
int s;
|
||||||
|
if (value > (EM_wordsize*2))
|
||||||
|
s = EM_wordsize*2;
|
||||||
|
else
|
||||||
|
s = value;
|
||||||
|
|
||||||
|
appendir(
|
||||||
|
store(
|
||||||
|
s,
|
||||||
|
ptr, offset,
|
||||||
|
pop(s)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
value -= s;
|
||||||
|
offset += s;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(value == 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1483,6 +1532,31 @@ static void insn_lvalue(int opcode, const char* label, arith offset)
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case op_gto:
|
||||||
|
{
|
||||||
|
struct ir* descriptor = pop(EM_pointersize);
|
||||||
|
|
||||||
|
appendir(
|
||||||
|
new_ir1(
|
||||||
|
IR_SETSP, EM_pointersize,
|
||||||
|
load(EM_pointersize, descriptor, EM_pointersize*2)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
appendir(
|
||||||
|
new_ir1(
|
||||||
|
IR_SETFP, EM_pointersize,
|
||||||
|
load(EM_pointersize, descriptor, EM_pointersize*1)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
appendir(
|
||||||
|
new_ir1(
|
||||||
|
IR_JUMP, 0,
|
||||||
|
load(EM_pointersize, descriptor, EM_pointersize*0)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case op_fil:
|
case op_fil:
|
||||||
{
|
{
|
||||||
/* Set filename --- ignore. */
|
/* Set filename --- ignore. */
|
||||||
|
|
|
@ -71,6 +71,9 @@ S ?=I. FROMSI
|
||||||
S ?=L. FROMSL
|
S ?=L. FROMSL
|
||||||
S ?=F. FROMF
|
S ?=F. FROMF
|
||||||
S ?=D. FROMD
|
S ?=D. FROMD
|
||||||
|
S L=II FROMIPAIR
|
||||||
|
S I=L. FROML0
|
||||||
|
S I=L. FROML1
|
||||||
|
|
||||||
# The H versions are only used if wordsize > 2
|
# The H versions are only used if wordsize > 2
|
||||||
S I=I. EXTENDB
|
S I=I. EXTENDB
|
||||||
|
|
Loading…
Reference in a new issue