Fix a bunch of issues with pushing and popping mismatched sizes, which the B

compiler does a lot; dup 8 for pairs of words is now optimised.
This commit is contained in:
David Given 2017-01-07 18:47:00 +01:00
parent 5a38ce2a69
commit efab08178b

View file

@ -30,6 +30,18 @@ static void push(struct ir* ir)
stack[stackptr++] = ir; stack[stackptr++] = ir;
} }
/* Returns the size of the top item on the stack. */
static int peek(int delta)
{
if (stackptr <= delta)
return EM_wordsize;
else
{
struct ir* ir = stack[stackptr-1-delta];
return ir->size;
}
}
static struct ir* pop(int size) static struct ir* pop(int size)
{ {
if (size < EM_wordsize) if (size < EM_wordsize)
@ -58,7 +70,6 @@ static struct ir* pop(int size)
if (size < EM_wordsize) if (size < EM_wordsize)
ir = convertu(ir, size); ir = convertu(ir, size);
#endif #endif
if (ir->size != size) if (ir->size != size)
{ {
if ((size == (EM_wordsize*2)) && (ir->size == EM_wordsize)) if ((size == (EM_wordsize*2)) && (ir->size == EM_wordsize))
@ -875,17 +886,17 @@ static void insn_ivalue(int opcode, arith value)
struct ir* ptr = pop(EM_pointersize); struct ir* ptr = pop(EM_pointersize);
int offset = 0; int offset = 0;
/* FIXME: this is awful; need a better way of dealing with
* non-standard EM sizes. */
if (value > (EM_wordsize*2)) if (value > (EM_wordsize*2))
{
/* We're going to need to do multiple stores; fix the address
* so it'll go into a register and we can do maths on it. */
appendir(ptr); appendir(ptr);
}
while (value > 0) while (value > 0)
{ {
int s; int s = EM_wordsize*2;
if (value > (EM_wordsize*2)) if (value < s)
s = EM_wordsize*2;
else
s = value; s = value;
push( push(
@ -934,24 +945,25 @@ static void insn_ivalue(int opcode, arith value)
struct ir* ptr = pop(EM_pointersize); struct ir* ptr = pop(EM_pointersize);
int offset = 0; int offset = 0;
/* FIXME: this is awful; need a better way of dealing with if (value > peek(0))
* non-standard EM sizes. */ {
if (value > (EM_wordsize*2)) /* We're going to need to do multiple stores; fix the address
* so it'll go into a register and we can do maths on it. */
appendir(ptr); appendir(ptr);
}
while (value > 0) while (value > 0)
{ {
int s; struct ir* v = pop(peek(0));
if (value > (EM_wordsize*2)) int s = v->size;
s = EM_wordsize*2; if (value < s)
else
s = value; s = value;
appendir( appendir(
store( store(
s, s,
ptr, offset, ptr, offset,
pop(s) v
) )
); );
@ -1044,10 +1056,22 @@ static void insn_ivalue(int opcode, arith value)
case op_dup: case op_dup:
{ {
struct ir* v = pop(value); sequence_point();
appendir(v); if ((value == (EM_wordsize*2)) && (peek(0) == EM_wordsize) && (peek(1) == EM_wordsize))
push(v); {
push(v); struct ir* v1 = pop(EM_wordsize);
struct ir* v2 = pop(EM_wordsize);
push(v2);
push(v1);
push(v2);
push(v1);
}
else
{
struct ir* v = pop(value);
push(v);
push(v);
}
break; break;
} }
@ -1077,8 +1101,11 @@ static void insn_ivalue(int opcode, arith value)
default: default:
while ((value > 0) && (stackptr > 0)) while ((value > 0) && (stackptr > 0))
{ {
struct ir* ir = pop(stack[stackptr-1]->size); int s = peek(0);
value -= ir->size; if (s > value)
s = value;
pop(s);
value -= s;
} }
if (value != 0) if (value != 0)