Add most vanilla memory load/store instructions.
authorDavid Given <dg@cowlark.com>
Sat, 18 May 2013 23:56:56 +0000 (00:56 +0100)
committerDavid Given <dg@cowlark.com>
Sat, 18 May 2013 23:56:56 +0000 (00:56 +0100)
--HG--
branch : dtrg-videocore

mach/vc4/as/mach0.c
mach/vc4/as/mach1.c
mach/vc4/as/mach2.c
mach/vc4/as/mach3.c
mach/vc4/as/mach4.c
mach/vc4/as/mach5.c
mach/vc4/test/opcodes.s

index b6294ec..d12994d 100644 (file)
@@ -19,6 +19,8 @@
 #undef word_t
 #define word_t long
 
+typedef unsigned long quad;
+
 #undef ALIGNWORD
 #define ALIGNWORD      4
 
index 915d1fb..bfb298f 100644 (file)
@@ -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);
index 6fd2b0e..2abde71 100644 (file)
@@ -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 */
index b2cd1c2..64b503a 100644 (file)
 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",
 
 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",
+
index 05dba83..7bd1838 100644 (file)
@@ -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 ')' '+' '+'
        ;
 
index 83d73da..32d7507 100644 (file)
@@ -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");
+}
 
index 6dedc41..2f9c1c7 100644 (file)
@@ -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)