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
1 changed files with 48 additions and 21 deletions
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue