Push/pop are the right way round. Don't corrup short-form ALU instructions. Correct encoding of push/pop register ranges.

--HG--
branch : dtrg-videocore
This commit is contained in:
David Given 2013-05-19 23:34:42 +01:00
parent 76ba0bf6b3
commit 11890026db
2 changed files with 19 additions and 16 deletions

View file

@ -133,8 +133,8 @@
0, OP_MISCL, B16(11000100,10000000), "divs", 0, OP_MISCL, B16(11000100,10000000), "divs",
0, OP_MISCL, B16(11000100,11100000), "divu", 0, OP_MISCL, B16(11000100,11100000), "divu",
0, OP_STACK, B16(00000010,00000000), "push", 0, OP_STACK, B16(00000010,10000000), "push",
0, OP_STACK, B16(00000010,10000000), "pop", 0, OP_STACK, B16(00000010,00000000), "pop",
0, OP_MEM, B8(00000000), "ld", 0, OP_MEM, B8(00000000), "ld",
0, OP_MEM, B8(00000001), "st", 0, OP_MEM, B8(00000001), "st",

View file

@ -13,7 +13,7 @@ void alu_instr_reg(quad op, int cc, int rd, int ra, int rb)
{ {
/* Can we use short form? */ /* Can we use short form? */
if ((cc == ALWAYS) && (ra == rd)) if ((cc == ALWAYS) && (ra == rd) && (ra < 0x10) && (rb < 0x10))
{ {
emit2(B16(01000000,00000000) | (op<<8) | (rb<<4) | (rd<<0)); emit2(B16(01000000,00000000) | (op<<8) | (rb<<4) | (rd<<0));
return; return;
@ -32,7 +32,7 @@ void alu_instr_lit(quad op, int cc, int rd, int ra, quad value)
/* 16 bit short form? */ /* 16 bit short form? */
if ((cc == ALWAYS) && !(op & 1) && (value <= 0x1f) && (ra == rd) && if ((cc == ALWAYS) && !(op & 1) && (value <= 0x1f) && (ra == rd) &&
!(ra & 0x10)) (ra < 0x10))
{ {
emit2(B16(01100000,00000000) | (op<<8) | (value<<4) | (rd<<0)); emit2(B16(01100000,00000000) | (op<<8) | (value<<4) | (rd<<0));
return; return;
@ -162,6 +162,7 @@ void branch_instr(int bl, int cc, struct expr_t* expr)
void stack_instr(quad opcode, int loreg, int hireg, int extrareg) void stack_instr(quad opcode, int loreg, int hireg, int extrareg)
{ {
int b; int b;
int m;
switch (loreg) switch (loreg)
{ {
@ -172,15 +173,13 @@ void stack_instr(quad opcode, int loreg, int hireg, int extrareg)
case 26: /* lr */ case 26: /* lr */
extrareg = 26; extrareg = 26;
hireg = 31; hireg = loreg = -1;
loreg = 0;
b = 0; b = 0;
break; break;
case 31: /* pc */ case 31: /* pc */
extrareg = 31; extrareg = 31;
hireg = 31; hireg = loreg = -1;
loreg = 0;
b = 0; b = 0;
break; break;
@ -189,23 +188,27 @@ void stack_instr(quad opcode, int loreg, int hireg, int extrareg)
} }
if (opcode & 0x0080) if (opcode & 0x0080)
{
/* Pop */
if (extrareg == 26)
serror("cannot pop lr");
}
else
{ {
/* Push */ /* Push */
if (extrareg == 31) if (extrareg == 31)
serror("cannot push pc"); serror("cannot push pc");
} }
else
{
/* Pop */
if (extrareg == 26)
serror("cannot pop lr");
}
if (hireg < loreg) if (hireg < loreg)
serror("invalid register range"); serror("invalid register range");
emit2(opcode | (b<<5) | (hireg<<0) | if (hireg == -1)
((extrareg != -1) ? 0x0100 : 0)); m = 31;
else
m = hireg - loreg;
emit2(opcode | (b<<5) | (m<<0) | ((extrareg != -1) ? 0x0100 : 0));
} }
/* Memory operations where the offset is a fixed value (including zero). */ /* Memory operations where the offset is a fixed value (including zero). */