Add most vanilla memory load/store instructions.
--HG-- branch : dtrg-videocore
This commit is contained in:
parent
26877d3c4f
commit
fc2833d456
7 changed files with 205 additions and 106 deletions
|
@ -19,6 +19,8 @@
|
|||
#undef word_t
|
||||
#define word_t long
|
||||
|
||||
typedef unsigned long quad;
|
||||
|
||||
#undef ALIGNWORD
|
||||
#define ALIGNWORD 4
|
||||
|
||||
|
|
|
@ -9,19 +9,21 @@
|
|||
|
||||
#define ALWAYS 14
|
||||
|
||||
extern void alu_instr_reg(unsigned opcode, unsigned cc, unsigned rd,
|
||||
unsigned ra, unsigned rb);
|
||||
extern void alu_instr_reg(quad opcode, quad cc, quad rd,
|
||||
quad ra, quad rb);
|
||||
|
||||
extern void alu_instr_lit(unsigned opcode, unsigned cc, unsigned rd,
|
||||
unsigned ra, unsigned value);
|
||||
extern void alu_instr_lit(quad opcode, quad cc, quad rd,
|
||||
quad ra, quad value);
|
||||
|
||||
extern void misc_instr_reg(unsigned opcode, unsigned cc, unsigned rd,
|
||||
unsigned ra, unsigned rb);
|
||||
extern void misc_instr_reg(quad opcode, quad cc, quad rd,
|
||||
quad ra, quad rb);
|
||||
|
||||
extern void misc_instr_lit(unsigned opcode, unsigned cc, unsigned rd,
|
||||
unsigned ra, unsigned value);
|
||||
extern void misc_instr_lit(quad opcode, quad cc, quad rd,
|
||||
quad ra, quad value);
|
||||
|
||||
extern void branch_instr(unsigned bl, unsigned cc, struct expr_t* expr);
|
||||
extern void branch_instr(quad bl, quad cc, struct expr_t* expr);
|
||||
|
||||
extern void stack_instr(unsigned opcode, unsigned loreg, unsigned hireg,
|
||||
unsigned extrareg);
|
||||
extern void stack_instr(quad opcode, quad loreg, quad hireg,
|
||||
quad extrareg);
|
||||
|
||||
extern void mem_instr(quad opcode, quad cc, quad rd, long offset, quad rs);
|
||||
|
|
|
@ -19,8 +19,4 @@
|
|||
%token <y_word> OP_MISCL
|
||||
%token <y_word> OP_STACK
|
||||
|
||||
/* Other token types */
|
||||
|
||||
/* %type <y_word> c */
|
||||
%type <y_word> e16 u8 u7 u6 u5 u4 u2 u1
|
||||
/* %type <y_word> nb ds bda bdl lia lil */
|
||||
|
|
|
@ -33,13 +33,13 @@
|
|||
0, GPR, 22, "r22",
|
||||
0, GPR, 23, "r23",
|
||||
0, GPR, 24, "r24",
|
||||
0, GPR, 24, "fp",
|
||||
|
||||
0, GPR, 25, "r25",
|
||||
0, GPR, 25, "sp",
|
||||
0, GPR, 26, "r26",
|
||||
0, GPR, 26, "lr",
|
||||
0, GPR, 27, "r27",
|
||||
0, GPR, 27, "fp",
|
||||
0, GPR, 28, "r28",
|
||||
0, GPR, 29, "r29",
|
||||
0, GPR, 30, "r30",
|
||||
|
@ -134,3 +134,13 @@
|
|||
|
||||
0, OP_STACK, B16(00000010,00000000), "push",
|
||||
0, OP_STACK, B16(00000010,10000000), "pop",
|
||||
|
||||
0, OP_MEM, B8(00000000), "ld",
|
||||
0, OP_MEM, B8(00000001), "st",
|
||||
0, OP_MEM, B8(00000010), "ldh",
|
||||
0, OP_MEM, B8(00000011), "sth",
|
||||
0, OP_MEM, B8(00000100), "ldb",
|
||||
0, OP_MEM, B8(00000101), "stb",
|
||||
0, OP_MEM, B8(00000110), "ldhs",
|
||||
0, OP_MEM, B8(00000111), "sths",
|
||||
|
||||
|
|
|
@ -41,78 +41,16 @@ operation
|
|||
| OP_STACK GPR ',' GPR { stack_instr($1, $2, $2, $4); }
|
||||
| OP_STACK GPR '-' GPR { stack_instr($1, $2, $4, -1); }
|
||||
| OP_STACK GPR '-' GPR ',' GPR { stack_instr($1, $2, $4, $6); }
|
||||
;
|
||||
|
||||
e16
|
||||
: expr
|
||||
{
|
||||
DOTVAL += 2;
|
||||
newrelo($1.typ, RELO2 | FIXUPFLAGS);
|
||||
DOTVAL -= 2;
|
||||
$$ = $1.val & 0xFFFF;
|
||||
}
|
||||
;
|
||||
|
||||
u8
|
||||
: absexp
|
||||
{
|
||||
if (($1 < 0) || ($1 > 0xFF))
|
||||
serror("8-bit unsigned value out of range");
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
u7
|
||||
: absexp
|
||||
{
|
||||
if (($1 < 0) || ($1 > 0x7F))
|
||||
serror("7-bit unsigned value out of range");
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
u6
|
||||
: absexp
|
||||
{
|
||||
if (($1 < 0) || ($1 > 0x3F))
|
||||
serror("6-bit unsigned value out of range");
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
u5
|
||||
: absexp
|
||||
{
|
||||
if (($1 < 0) || ($1 > 0x1F))
|
||||
serror("5-bit unsigned value out of range");
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
u4
|
||||
: absexp
|
||||
{
|
||||
if (($1 < 0) || ($1 > 0xF))
|
||||
serror("4-bit unsigned value out of range");
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
u1
|
||||
: absexp
|
||||
{
|
||||
if (($1 < 0) || ($1 > 1))
|
||||
serror("1-bit unsigned value out of range");
|
||||
$$ = $1;
|
||||
}
|
||||
;
|
||||
|
||||
u2
|
||||
: absexp
|
||||
{
|
||||
if (($1 < 0) || ($1 > 0x3))
|
||||
serror("2-bit unsigned value out of range");
|
||||
$$ = $1;
|
||||
}
|
||||
|
||||
| OP_MEM GPR ',' '(' GPR ')' { mem_instr($1, ALWAYS, $2, 0, $5); }
|
||||
| OP_MEM CC GPR ',' '(' GPR ')' { mem_instr($1, $2, $3, 0, $6); }
|
||||
| OP_MEM GPR ',' absexp '(' GPR ')' { mem_instr($1, ALWAYS, $2, $4, $6); }
|
||||
| OP_MEM CC GPR ',' absexp '(' GPR ')' { mem_instr($1, $2, $3, $5, $7); }
|
||||
|
||||
| OP_MEM GPR ',' '(' GPR ',' GPR ')'
|
||||
| OP_MEM CC GPR ',' '(' GPR ',' GPR ')'
|
||||
|
||||
| OP_MEM GPR ',' '(' GPR ')' '+' '+'
|
||||
| OP_MEM CC GPR ',' '(' GPR ')' '+' '+'
|
||||
;
|
||||
|
||||
|
|
|
@ -5,10 +5,11 @@
|
|||
* See the file 'Copying' in the root of the distribution for the full text.
|
||||
*/
|
||||
|
||||
#define maskx(v, x) (v & ((1<<(x))-1))
|
||||
|
||||
/* Assemble an ALU instruction where rb is a register. */
|
||||
|
||||
void alu_instr_reg(unsigned op, unsigned cc,
|
||||
unsigned rd, unsigned ra, unsigned rb)
|
||||
void alu_instr_reg(quad op, quad cc, quad rd, quad ra, quad rb)
|
||||
{
|
||||
/* Can we use short form? */
|
||||
|
||||
|
@ -26,8 +27,7 @@ void alu_instr_reg(unsigned op, unsigned cc,
|
|||
|
||||
/* Assemble an ALU instruction where rb is a literal. */
|
||||
|
||||
void alu_instr_lit(unsigned op, unsigned cc,
|
||||
unsigned rd, unsigned ra, unsigned value)
|
||||
void alu_instr_lit(quad op, quad cc, quad rd, quad ra, quad value)
|
||||
{
|
||||
/* 16 bit short form? */
|
||||
|
||||
|
@ -68,8 +68,7 @@ void alu_instr_lit(unsigned op, unsigned cc,
|
|||
|
||||
/* Miscellaneous instructions with three registers and a cc. */
|
||||
|
||||
void misc_instr_reg(unsigned op, unsigned cc,
|
||||
unsigned rd, unsigned ra, unsigned rb)
|
||||
void misc_instr_reg(quad op, quad cc, quad rd, quad ra, quad rb)
|
||||
{
|
||||
emit2(op | (rd<<0));
|
||||
emit2(B16(00000000,00000000) | (ra<<11) | (cc<<7) | (rb<<0));
|
||||
|
@ -77,8 +76,7 @@ void misc_instr_reg(unsigned op, unsigned cc,
|
|||
|
||||
/* Miscellaneous instructions with two registers, a literal, and a cc. */
|
||||
|
||||
void misc_instr_lit(unsigned op, unsigned cc,
|
||||
unsigned rd, unsigned ra, unsigned value)
|
||||
void misc_instr_lit(quad op, quad cc, quad rd, quad ra, quad value)
|
||||
{
|
||||
if (value < 0x1f)
|
||||
serror("only constants from 0..31 can be used here");
|
||||
|
@ -90,9 +88,9 @@ void misc_instr_lit(unsigned op, unsigned cc,
|
|||
/* Assemble a branch instruction. This may be a near branch into this
|
||||
* object file, or a far branch which requires a fixup. */
|
||||
|
||||
void branch_instr(unsigned bl, unsigned cc, struct expr_t* expr)
|
||||
void branch_instr(quad bl, quad cc, struct expr_t* expr)
|
||||
{
|
||||
unsigned type = expr->typ & S_TYP;
|
||||
quad type = expr->typ & S_TYP;
|
||||
|
||||
/* Sanity checking. */
|
||||
|
||||
|
@ -142,15 +140,15 @@ void branch_instr(unsigned bl, unsigned cc, struct expr_t* expr)
|
|||
|
||||
if (bl)
|
||||
{
|
||||
unsigned v = d & 0x07ffffff;
|
||||
unsigned hiv = v >> 23;
|
||||
unsigned lov = v & 0x007fffff;
|
||||
quad v = d & 0x07ffffff;
|
||||
quad hiv = v >> 23;
|
||||
quad lov = v & 0x007fffff;
|
||||
emit2(B16(10010000,10000000) | (lov>>16) | (hiv<<8));
|
||||
emit2(B16(00000000,00000000) | (lov&0xffff));
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned v = d & 0x007fffff;
|
||||
quad v = d & 0x007fffff;
|
||||
emit2(B16(10010000,00000000) | (cc<<8) | (v>>16));
|
||||
emit2(B16(00000000,00000000) | (v&0xffff));
|
||||
}
|
||||
|
@ -159,10 +157,11 @@ void branch_instr(unsigned bl, unsigned cc, struct expr_t* expr)
|
|||
}
|
||||
}
|
||||
|
||||
void stack_instr(unsigned opcode, unsigned loreg, unsigned hireg,
|
||||
unsigned extrareg)
|
||||
/* Push/pop. */
|
||||
|
||||
void stack_instr(quad opcode, quad loreg, quad hireg, quad extrareg)
|
||||
{
|
||||
unsigned b;
|
||||
quad b;
|
||||
|
||||
switch (loreg)
|
||||
{
|
||||
|
@ -209,4 +208,105 @@ void stack_instr(unsigned opcode, unsigned loreg, unsigned hireg,
|
|||
((extrareg != -1) ? 0x0100 : 0));
|
||||
}
|
||||
|
||||
/* Memory operations where the offset is a fixed value (including zero). */
|
||||
|
||||
void mem_instr(quad opcode, quad cc, quad rd, long offset, quad rs)
|
||||
{
|
||||
quad uoffset = (quad) offset;
|
||||
int multiple4 = !(offset & 3);
|
||||
int intonly = ((opcode & B8(00000110)) == 0);
|
||||
|
||||
/* If no CC, there are some special forms we can use. */
|
||||
|
||||
if (cc == ALWAYS)
|
||||
{
|
||||
/* Very short form, special for stack offsets. */
|
||||
|
||||
if (intonly && (rs == 25) && multiple4 && fitx(offset, 7) && (rd < 0x10))
|
||||
{
|
||||
quad o = maskx(offset, 7) / 4;
|
||||
emit2(B16(00000100,00000000) | (opcode<<9) | (o<<4) | (rd<<0));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Slightly longer form for directly dereferencing via a register. */
|
||||
|
||||
if ((rs < 0x10) && (rd < 0x10) && (offset == 0))
|
||||
{
|
||||
emit2(B16(00001000,00000000) | (opcode<<8) | (rs<<4) | (rd<<4));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Integer only, but a limited offset. */
|
||||
|
||||
if (intonly && (uoffset <= 0x3f) && (rs < 0x10) && (rd < 0x10))
|
||||
{
|
||||
quad o = uoffset / 4;
|
||||
emit2(B16(00100000,00000000) | (opcode<<12) | (o<<8) |
|
||||
(rs<<4) | (rd<<0));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Certain registers support 16-bit offsets. */
|
||||
|
||||
if (fitx(offset, 16))
|
||||
{
|
||||
switch (rs)
|
||||
{
|
||||
case 0: opcode = B16(10101011,00000000) | (opcode<<5); goto specialreg;
|
||||
case 24: opcode = B16(10101000,00000000) | (opcode<<5); goto specialreg;
|
||||
case 25: opcode = B16(10101001,00000000) | (opcode<<5); goto specialreg;
|
||||
case 31: opcode = B16(10101010,00000000) | (opcode<<5); goto specialreg;
|
||||
default: break;
|
||||
|
||||
specialreg:
|
||||
{
|
||||
quad o = maskx(offset, 16);
|
||||
emit2(opcode | (rd<<0));
|
||||
emit2(o);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 12-bit displacements. */
|
||||
|
||||
if (fitx(offset, 12))
|
||||
{
|
||||
quad looffset = maskx(offset, 11);
|
||||
quad hioffset = (offset >> 11) & 1;
|
||||
|
||||
emit2(B16(10100010,00000000) | (opcode<<5) | (rd<<0) | (hioffset<<8));
|
||||
emit2(B16(00000000,00000000) | (rs<<11) | (looffset<<0));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Everything else uses Very Long Form. */
|
||||
|
||||
if (!fitx(offset, 27))
|
||||
serror("offset will not fit into load/store instruction");
|
||||
|
||||
if (rs == 31)
|
||||
opcode = B16(11100111,00000000) | (opcode<<5);
|
||||
else
|
||||
opcode = B16(11100110,00000000) | (opcode<<5);
|
||||
|
||||
emit2(opcode | (rd<<0));
|
||||
emit4((rs<<27) | maskx(offset, 27));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now we're on to load/store instructions with ccs. */
|
||||
|
||||
if (uoffset <= 0x1f)
|
||||
{
|
||||
emit2(B16(10100000,00000000) | (opcode<<5) | (rd<<0));
|
||||
emit2(B16(00000000,01000000) | (rs<<11) | (cc<<7) | (uoffset<<0));
|
||||
return;
|
||||
}
|
||||
|
||||
/* No encoding for this instruction. */
|
||||
|
||||
serror("invalid load/store instruction");
|
||||
}
|
||||
|
||||
|
|
|
@ -282,3 +282,54 @@ forward:
|
|||
pop r16
|
||||
pop r24
|
||||
pop pc
|
||||
|
||||
nop
|
||||
|
||||
ld r0, (sp)
|
||||
st r0, (sp)
|
||||
ld r0, 4(sp)
|
||||
st r0, 4(sp)
|
||||
ld r0, -4(sp)
|
||||
st r0, -4(sp)
|
||||
ld r0, 5(sp)
|
||||
st r0, 5(sp)
|
||||
ld r0, -5(sp)
|
||||
st r0, -5(sp)
|
||||
|
||||
ld r0, (r1)
|
||||
st r0, (r1)
|
||||
ld r16, (r1)
|
||||
st r16, (r1)
|
||||
ldh r0, (r1)
|
||||
sth r0, (r1)
|
||||
ldb r0, (r1)
|
||||
stb r0, (r1)
|
||||
ldhs r0, (r1)
|
||||
sths r0, (r1)
|
||||
ldh r16, (r1)
|
||||
sth r16, (r1)
|
||||
ldb r16, (r1)
|
||||
stb r16, (r1)
|
||||
ldhs r16, (r1)
|
||||
sths r16, (r1)
|
||||
ld r0, 0x3c (r1)
|
||||
st r0, 0x3c (r1)
|
||||
ld r0, 0xfff (r1)
|
||||
st r0, 0xfff (r1)
|
||||
ld r1, 0xffff (r0)
|
||||
st r1, 0xffff (r0)
|
||||
ld r0, -1 (r1)
|
||||
st r0, -1 (r1)
|
||||
ld r16, 0x3c (r1)
|
||||
st r16, 0x3c (r1)
|
||||
ld r16, 0xfff (r1)
|
||||
st r16, 0xfff (r1)
|
||||
ld r16, 0xffff (r0)
|
||||
st r16, 0xffff (r0)
|
||||
ld r16, -1 (r1)
|
||||
st r16, -1 (r1)
|
||||
|
||||
ld.f r0, (r1)
|
||||
st.f r0, (r1)
|
||||
ld.f r0, 8 (r1)
|
||||
st.f r0, 8 (r1)
|
||||
|
|
Loading…
Reference in a new issue