From 80afe75c9bfc40a2bc7de4354c7fa4c1416724d4 Mon Sep 17 00:00:00 2001 From: David Given Date: Sun, 19 May 2013 13:03:53 +0100 Subject: [PATCH] Added memory operations that work on fixed up addresses. --HG-- branch : dtrg-videocore --- mach/vc4/as/mach1.c | 1 + mach/vc4/as/mach4.c | 2 ++ mach/vc4/as/mach5.c | 62 +++++++++++++++++++++++++++++++++++++++++ mach/vc4/test/opcodes.s | 9 ++++++ 4 files changed, 74 insertions(+) diff --git a/mach/vc4/as/mach1.c b/mach/vc4/as/mach1.c index 25d5034b4..6e7b6819f 100644 --- a/mach/vc4/as/mach1.c +++ b/mach/vc4/as/mach1.c @@ -18,3 +18,4 @@ extern void stack_instr(quad opcode, int loreg, int hireg, int extrareg); extern void mem_instr(quad opcode, int cc, int rd, long offset, int rs); extern void mem_offset_instr(quad opcode, int cc, int rd, int qa, int rb); extern void mem_postincr_instr(quad opcode, int cc, int rd, int rs); +extern void mem_address_instr(quad opcode, int rd, struct expr_t* expr); diff --git a/mach/vc4/as/mach4.c b/mach/vc4/as/mach4.c index f614825e9..78c9337c9 100644 --- a/mach/vc4/as/mach4.c +++ b/mach/vc4/as/mach4.c @@ -52,5 +52,7 @@ operation | OP_MEM GPR ',' '(' GPR ')' '+' '+' { mem_postincr_instr($1, ALWAYS, $2, $5); } | OP_MEM CC GPR ',' '(' GPR ')' '+' '+' { mem_postincr_instr($1, $2, $3, $6); } + + | OP_MEM GPR ',' expr { mem_address_instr($1, $2, &$4); } ; diff --git a/mach/vc4/as/mach5.c b/mach/vc4/as/mach5.c index 0d68c8ff9..265e18f52 100644 --- a/mach/vc4/as/mach5.c +++ b/mach/vc4/as/mach5.c @@ -326,3 +326,65 @@ void mem_postincr_instr(quad opcode, int cc, int rd, int rs) emit2(B16(10100101,00000000) | (opcode<<5) | (rd<<0)); emit2(B16(00000000,00000000) | (rs<<11) | (cc<<7)); } + +/* Memory operations where the destination is an address literal. */ + +void mem_address_instr(quad opcode, int rd, struct expr_t* expr) +{ + quad type = expr->typ & S_TYP; + + /* Sanity checking. */ + + if (type == S_ABS) + serror("can't use absolute addresses here"); + + switch (pass) + { + case 0: + /* Calculate size of instructions only. For now we just assume + * that they're going to be the maximum size, 48 bits. */ + + emit2(0); + emit4(0); + break; + + case 1: + case 2: + { + /* The VC4 branch instructions express distance in 2-byte + * words. */ + + int d = (expr->val - DOTVAL) / 2; + + /* We now know the worst case for the instruction layout. At + * this point we can emit the instructions, which may shrink + * the code. */ + + if (type == DOTTYP) + { + /* This is a reference to an address within this section. If + * it's close enough to the program counter, we can use a + * shorter instruction. */ + + if (fitx(d, 16)) + { + emit2(B16(10101010,00000000) | (opcode<<5) | (rd<<0)); + emit2(d); + return; + } + } + + /* Otherwise we need the full 48 bits. */ + + if (!fitx(d, 27)) + serror("offset too big to encode into instruction"); + + newrelo(expr->typ, RELOVC4 | RELPC); + + emit2(B16(11100111,00000000) | (opcode<<5) | (rd<<0)); + emit4((31<<27) | maskx(d, 27)); + break; + } + } +} + diff --git a/mach/vc4/test/opcodes.s b/mach/vc4/test/opcodes.s index ddc6b1706..a2104fcd7 100644 --- a/mach/vc4/test/opcodes.s +++ b/mach/vc4/test/opcodes.s @@ -339,8 +339,17 @@ forward: ld.f r0, (pc, pc) st.f r0, (pc, pc) +near: ld r0, (r1)++ st r0, (r1)++ ld.f pc, (pc)++ st.f pc, (pc)++ + ld r0, near + ld r0, main + st r0, near + st r0, main + ldb r0, near + ldb r0, main + stb r0, near + stb r0, main -- 2.34.1