From: David Given Date: Sat, 18 May 2013 23:56:56 +0000 (+0100) Subject: Add most vanilla memory load/store instructions. X-Git-Tag: release-6-0-pre-5~10^2~73 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=fc2833d4568f5e474661dec3c3cf93b33cbd2cc5;p=ack.git Add most vanilla memory load/store instructions. --HG-- branch : dtrg-videocore --- diff --git a/mach/vc4/as/mach0.c b/mach/vc4/as/mach0.c index b6294ecfc..d12994de0 100644 --- a/mach/vc4/as/mach0.c +++ b/mach/vc4/as/mach0.c @@ -19,6 +19,8 @@ #undef word_t #define word_t long +typedef unsigned long quad; + #undef ALIGNWORD #define ALIGNWORD 4 diff --git a/mach/vc4/as/mach1.c b/mach/vc4/as/mach1.c index 915d1fb51..bfb298f68 100644 --- a/mach/vc4/as/mach1.c +++ b/mach/vc4/as/mach1.c @@ -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); \ No newline at end of file +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); diff --git a/mach/vc4/as/mach2.c b/mach/vc4/as/mach2.c index 6fd2b0e45..2abde7136 100644 --- a/mach/vc4/as/mach2.c +++ b/mach/vc4/as/mach2.c @@ -19,8 +19,4 @@ %token OP_MISCL %token OP_STACK -/* Other token types */ -/* %type c */ -%type e16 u8 u7 u6 u5 u4 u2 u1 -/* %type nb ds bda bdl lia lil */ diff --git a/mach/vc4/as/mach3.c b/mach/vc4/as/mach3.c index b2cd1c2c9..64b503a98 100644 --- a/mach/vc4/as/mach3.c +++ b/mach/vc4/as/mach3.c @@ -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", + diff --git a/mach/vc4/as/mach4.c b/mach/vc4/as/mach4.c index 05dba83b8..7bd183829 100644 --- a/mach/vc4/as/mach4.c +++ b/mach/vc4/as/mach4.c @@ -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 ')' '+' '+' ; diff --git a/mach/vc4/as/mach5.c b/mach/vc4/as/mach5.c index 83d73da2a..32d7507f3 100644 --- a/mach/vc4/as/mach5.c +++ b/mach/vc4/as/mach5.c @@ -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"); +} diff --git a/mach/vc4/test/opcodes.s b/mach/vc4/test/opcodes.s index 6dedc4168..2f9c1c709 100644 --- a/mach/vc4/test/opcodes.s +++ b/mach/vc4/test/opcodes.s @@ -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)