Commits

dtrg  committed b77b6b5

Add most vanilla memory load/store instructions.

  • Participants
  • Parent commits f4bd1df
  • Branches dtrg-videocore

Comments (0)

Files changed (7)

File mach/vc4/as/mach0.c

 #undef word_t
 #define word_t long
 
+typedef unsigned long quad;
+
 #undef ALIGNWORD
 #define ALIGNWORD	4
 

File mach/vc4/as/mach1.c

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

File mach/vc4/as/mach2.c

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

File mach/vc4/as/mach3.c

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

File mach/vc4/as/mach4.c

 	| 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); }
+
+	| 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 ')' '+' '+'
 	;
 
-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;
-	}
-	;
-

File mach/vc4/as/mach5.c

  * 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? */
 
 
 /* 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? */
 
 
 /* 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));
 
 /* 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");
 /* 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. */
 
 
 			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));
 			}
 	}
 }
 
-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)
     {
 		((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");
+}
+

File mach/vc4/test/opcodes.s

 	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)