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:
David Given 2016-10-29 12:48:05 +02:00
parent 68419da235
commit 61349389fb
4 changed files with 107 additions and 11 deletions

View file

@ -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"

View file

@ -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);

View file

@ -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. */

View file

@ -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