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
|
#undef word_t
|
||||||
#define word_t long
|
#define word_t long
|
||||||
|
|
||||||
|
typedef unsigned long quad;
|
||||||
|
|
||||||
#undef ALIGNWORD
|
#undef ALIGNWORD
|
||||||
#define ALIGNWORD 4
|
#define ALIGNWORD 4
|
||||||
|
|
||||||
|
|
|
@ -9,19 +9,21 @@
|
||||||
|
|
||||||
#define ALWAYS 14
|
#define ALWAYS 14
|
||||||
|
|
||||||
extern void alu_instr_reg(unsigned opcode, unsigned cc, unsigned rd,
|
extern void alu_instr_reg(quad opcode, quad cc, quad rd,
|
||||||
unsigned ra, unsigned rb);
|
quad ra, quad rb);
|
||||||
|
|
||||||
extern void alu_instr_lit(unsigned opcode, unsigned cc, unsigned rd,
|
extern void alu_instr_lit(quad opcode, quad cc, quad rd,
|
||||||
unsigned ra, unsigned value);
|
quad ra, quad value);
|
||||||
|
|
||||||
extern void misc_instr_reg(unsigned opcode, unsigned cc, unsigned rd,
|
extern void misc_instr_reg(quad opcode, quad cc, quad rd,
|
||||||
unsigned ra, unsigned rb);
|
quad ra, quad rb);
|
||||||
|
|
||||||
extern void misc_instr_lit(unsigned opcode, unsigned cc, unsigned rd,
|
extern void misc_instr_lit(quad opcode, quad cc, quad rd,
|
||||||
unsigned ra, unsigned value);
|
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,
|
extern void stack_instr(quad opcode, quad loreg, quad hireg,
|
||||||
unsigned extrareg);
|
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_MISCL
|
||||||
%token <y_word> OP_STACK
|
%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, 22, "r22",
|
||||||
0, GPR, 23, "r23",
|
0, GPR, 23, "r23",
|
||||||
0, GPR, 24, "r24",
|
0, GPR, 24, "r24",
|
||||||
|
0, GPR, 24, "fp",
|
||||||
|
|
||||||
0, GPR, 25, "r25",
|
0, GPR, 25, "r25",
|
||||||
0, GPR, 25, "sp",
|
0, GPR, 25, "sp",
|
||||||
0, GPR, 26, "r26",
|
0, GPR, 26, "r26",
|
||||||
0, GPR, 26, "lr",
|
0, GPR, 26, "lr",
|
||||||
0, GPR, 27, "r27",
|
0, GPR, 27, "r27",
|
||||||
0, GPR, 27, "fp",
|
|
||||||
0, GPR, 28, "r28",
|
0, GPR, 28, "r28",
|
||||||
0, GPR, 29, "r29",
|
0, GPR, 29, "r29",
|
||||||
0, GPR, 30, "r30",
|
0, GPR, 30, "r30",
|
||||||
|
@ -134,3 +134,13 @@
|
||||||
|
|
||||||
0, OP_STACK, B16(00000010,00000000), "push",
|
0, OP_STACK, B16(00000010,00000000), "push",
|
||||||
0, OP_STACK, B16(00000010,10000000), "pop",
|
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, $2, $4); }
|
||||||
| OP_STACK GPR '-' GPR { stack_instr($1, $2, $4, -1); }
|
| OP_STACK GPR '-' GPR { stack_instr($1, $2, $4, -1); }
|
||||||
| OP_STACK GPR '-' GPR ',' GPR { stack_instr($1, $2, $4, $6); }
|
| OP_STACK GPR '-' GPR ',' GPR { stack_instr($1, $2, $4, $6); }
|
||||||
;
|
|
||||||
|
| OP_MEM GPR ',' '(' GPR ')' { mem_instr($1, ALWAYS, $2, 0, $5); }
|
||||||
e16
|
| OP_MEM CC GPR ',' '(' GPR ')' { mem_instr($1, $2, $3, 0, $6); }
|
||||||
: expr
|
| 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); }
|
||||||
DOTVAL += 2;
|
|
||||||
newrelo($1.typ, RELO2 | FIXUPFLAGS);
|
| OP_MEM GPR ',' '(' GPR ',' GPR ')'
|
||||||
DOTVAL -= 2;
|
| OP_MEM CC GPR ',' '(' GPR ',' GPR ')'
|
||||||
$$ = $1.val & 0xFFFF;
|
|
||||||
}
|
| OP_MEM GPR ',' '(' GPR ')' '+' '+'
|
||||||
;
|
| OP_MEM CC GPR ',' '(' GPR ')' '+' '+'
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,11 @@
|
||||||
* See the file 'Copying' in the root of the distribution for the full text.
|
* 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. */
|
/* Assemble an ALU instruction where rb is a register. */
|
||||||
|
|
||||||
void alu_instr_reg(unsigned op, unsigned cc,
|
void alu_instr_reg(quad op, quad cc, quad rd, quad ra, quad rb)
|
||||||
unsigned rd, unsigned ra, unsigned rb)
|
|
||||||
{
|
{
|
||||||
/* Can we use short form? */
|
/* 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. */
|
/* Assemble an ALU instruction where rb is a literal. */
|
||||||
|
|
||||||
void alu_instr_lit(unsigned op, unsigned cc,
|
void alu_instr_lit(quad op, quad cc, quad rd, quad ra, quad value)
|
||||||
unsigned rd, unsigned ra, unsigned value)
|
|
||||||
{
|
{
|
||||||
/* 16 bit short form? */
|
/* 16 bit short form? */
|
||||||
|
|
||||||
|
@ -68,8 +68,7 @@ void alu_instr_lit(unsigned op, unsigned cc,
|
||||||
|
|
||||||
/* Miscellaneous instructions with three registers and a cc. */
|
/* Miscellaneous instructions with three registers and a cc. */
|
||||||
|
|
||||||
void misc_instr_reg(unsigned op, unsigned cc,
|
void misc_instr_reg(quad op, quad cc, quad rd, quad ra, quad rb)
|
||||||
unsigned rd, unsigned ra, unsigned rb)
|
|
||||||
{
|
{
|
||||||
emit2(op | (rd<<0));
|
emit2(op | (rd<<0));
|
||||||
emit2(B16(00000000,00000000) | (ra<<11) | (cc<<7) | (rb<<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. */
|
/* Miscellaneous instructions with two registers, a literal, and a cc. */
|
||||||
|
|
||||||
void misc_instr_lit(unsigned op, unsigned cc,
|
void misc_instr_lit(quad op, quad cc, quad rd, quad ra, quad value)
|
||||||
unsigned rd, unsigned ra, unsigned value)
|
|
||||||
{
|
{
|
||||||
if (value < 0x1f)
|
if (value < 0x1f)
|
||||||
serror("only constants from 0..31 can be used here");
|
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
|
/* Assemble a branch instruction. This may be a near branch into this
|
||||||
* object file, or a far branch which requires a fixup. */
|
* 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. */
|
/* Sanity checking. */
|
||||||
|
|
||||||
|
@ -142,15 +140,15 @@ void branch_instr(unsigned bl, unsigned cc, struct expr_t* expr)
|
||||||
|
|
||||||
if (bl)
|
if (bl)
|
||||||
{
|
{
|
||||||
unsigned v = d & 0x07ffffff;
|
quad v = d & 0x07ffffff;
|
||||||
unsigned hiv = v >> 23;
|
quad hiv = v >> 23;
|
||||||
unsigned lov = v & 0x007fffff;
|
quad lov = v & 0x007fffff;
|
||||||
emit2(B16(10010000,10000000) | (lov>>16) | (hiv<<8));
|
emit2(B16(10010000,10000000) | (lov>>16) | (hiv<<8));
|
||||||
emit2(B16(00000000,00000000) | (lov&0xffff));
|
emit2(B16(00000000,00000000) | (lov&0xffff));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
unsigned v = d & 0x007fffff;
|
quad v = d & 0x007fffff;
|
||||||
emit2(B16(10010000,00000000) | (cc<<8) | (v>>16));
|
emit2(B16(10010000,00000000) | (cc<<8) | (v>>16));
|
||||||
emit2(B16(00000000,00000000) | (v&0xffff));
|
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,
|
/* Push/pop. */
|
||||||
unsigned extrareg)
|
|
||||||
|
void stack_instr(quad opcode, quad loreg, quad hireg, quad extrareg)
|
||||||
{
|
{
|
||||||
unsigned b;
|
quad b;
|
||||||
|
|
||||||
switch (loreg)
|
switch (loreg)
|
||||||
{
|
{
|
||||||
|
@ -209,4 +208,105 @@ void stack_instr(unsigned opcode, unsigned loreg, unsigned hireg,
|
||||||
((extrareg != -1) ? 0x0100 : 0));
|
((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 r16
|
||||||
pop r24
|
pop r24
|
||||||
pop pc
|
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