Add most vanilla memory load/store instructions.

--HG--
branch : dtrg-videocore
This commit is contained in:
David Given 2013-05-19 00:56:56 +01:00
parent 26877d3c4f
commit fc2833d456
7 changed files with 205 additions and 106 deletions

View file

@ -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

View file

@ -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);

View file

@ -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 */

View file

@ -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",

View file

@ -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;
}
; ;

View file

@ -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");
}

View file

@ -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)