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:
parent
5a38ce2a69
commit
efab08178b
|
@ -30,6 +30,18 @@ static void push(struct ir* 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)
|
||||
{
|
||||
if (size < EM_wordsize)
|
||||
|
@ -58,7 +70,6 @@ static struct ir* pop(int size)
|
|||
if (size < EM_wordsize)
|
||||
ir = convertu(ir, size);
|
||||
#endif
|
||||
|
||||
if (ir->size != size)
|
||||
{
|
||||
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);
|
||||
int offset = 0;
|
||||
|
||||
/* FIXME: this is awful; need a better way of dealing with
|
||||
* 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);
|
||||
}
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
int s;
|
||||
if (value > (EM_wordsize*2))
|
||||
s = EM_wordsize*2;
|
||||
else
|
||||
int s = EM_wordsize*2;
|
||||
if (value < s)
|
||||
s = value;
|
||||
|
||||
push(
|
||||
|
@ -934,24 +945,25 @@ static void insn_ivalue(int opcode, arith value)
|
|||
struct ir* ptr = pop(EM_pointersize);
|
||||
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 > peek(0))
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
while (value > 0)
|
||||
{
|
||||
int s;
|
||||
if (value > (EM_wordsize*2))
|
||||
s = EM_wordsize*2;
|
||||
else
|
||||
struct ir* v = pop(peek(0));
|
||||
int s = v->size;
|
||||
if (value < s)
|
||||
s = value;
|
||||
|
||||
appendir(
|
||||
store(
|
||||
s,
|
||||
ptr, offset,
|
||||
pop(s)
|
||||
v
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -1044,10 +1056,22 @@ static void insn_ivalue(int opcode, arith value)
|
|||
|
||||
case op_dup:
|
||||
{
|
||||
struct ir* v = pop(value);
|
||||
appendir(v);
|
||||
push(v);
|
||||
push(v);
|
||||
sequence_point();
|
||||
if ((value == (EM_wordsize*2)) && (peek(0) == EM_wordsize) && (peek(1) == EM_wordsize))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1077,8 +1101,11 @@ static void insn_ivalue(int opcode, arith value)
|
|||
default:
|
||||
while ((value > 0) && (stackptr > 0))
|
||||
{
|
||||
struct ir* ir = pop(stack[stackptr-1]->size);
|
||||
value -= ir->size;
|
||||
int s = peek(0);
|
||||
if (s > value)
|
||||
s = value;
|
||||
pop(s);
|
||||
value -= s;
|
||||
}
|
||||
|
||||
if (value != 0)
|
||||
|
|
Loading…
Reference in a new issue