Add compare-and-branch instructions.
--HG-- branch : dtrg-videocore
This commit is contained in:
parent
80afe75c9b
commit
4f15423d63
|
@ -19,3 +19,7 @@ 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);
|
||||
extern void branch_addcmp_reg_reg_instr(int cc, int rd, int ra, int rs, struct expr_t* expr);
|
||||
extern void branch_addcmp_lit_reg_instr(int cc, int rd, long va, int rs, struct expr_t* expr);
|
||||
extern void branch_addcmp_reg_lit_instr(int cc, int rd, int ra, long vs, struct expr_t* expr);
|
||||
extern void branch_addcmp_lit_lit_instr(int cc, int rd, long va, long vs, struct expr_t* expr);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
%token <y_word> CC
|
||||
|
||||
%token <y_word> OP
|
||||
%token <y_word> OP_BRANCH
|
||||
%token <y_word> OP_BRANCH OP_BRANCHLINK OP_ADDCMPB
|
||||
%token <y_word> OP_ONEREG
|
||||
%token <y_word> OP_ONELREG
|
||||
%token <y_word> OP_ALU
|
||||
|
|
|
@ -73,7 +73,8 @@
|
|||
0, OP, B16(00000000,00001010), "rti",
|
||||
|
||||
0, OP_BRANCH, 0, "b",
|
||||
0, OP_BRANCH, 1, "bl",
|
||||
0, OP_BRANCHLINK, 0, "bl",
|
||||
0, OP_ADDCMPB, 0, "addcmpb",
|
||||
|
||||
0, OP_ONELREG, B16(00000000,10000000), "tbb",
|
||||
0, OP_ONELREG, B16(00000000,10100000), "tbs",
|
||||
|
|
|
@ -8,9 +8,26 @@
|
|||
operation
|
||||
: OP { emit2($1); }
|
||||
|
||||
| OP_BRANCH GPR { emit2($1 | ($2<<0)); }
|
||||
| OP_BRANCH expr { branch_instr($1, ALWAYS, &$2); }
|
||||
| OP_BRANCH CC expr { branch_instr($1, $2, &$3); }
|
||||
| OP_BRANCH GPR { emit2(B16(00000000,01000000) | ($2<<0)); }
|
||||
| OP_BRANCHLINK GPR { emit2(B16(00000000,01100000) | ($2<<0)); }
|
||||
|
||||
| OP_BRANCH expr { branch_instr(0, ALWAYS, &$2); }
|
||||
| OP_BRANCHLINK expr { branch_instr(1, ALWAYS, &$2); }
|
||||
| OP_BRANCH CC expr { branch_instr(0, $2, &$3); }
|
||||
| OP_BRANCHLINK CC expr { branch_instr(1, $2, &$3); }
|
||||
|
||||
| OP_BRANCH GPR ',' GPR ',' expr { branch_addcmp_lit_reg_instr(ALWAYS, 0, $2, $4, &$6); }
|
||||
| OP_BRANCH CC GPR ',' GPR ',' expr { branch_addcmp_lit_reg_instr($2, 0, $3, $5, &$7); }
|
||||
| OP_BRANCH GPR ',' '#' absexp ',' expr { branch_addcmp_lit_lit_instr(ALWAYS, 0, $2, $5, &$7); }
|
||||
| OP_BRANCH CC GPR ',' '#' absexp ',' expr { branch_addcmp_lit_lit_instr($2, 0, $3, $6, &$8); }
|
||||
| OP_ADDCMPB GPR ',' GPR ',' GPR ',' expr { branch_addcmp_reg_reg_instr(ALWAYS, $2, $4, $6, &$8); }
|
||||
| OP_ADDCMPB CC GPR ',' GPR ',' GPR ',' expr { branch_addcmp_reg_reg_instr($2, $3, $5, $7, &$9); }
|
||||
| OP_ADDCMPB GPR ',' '#' absexp ',' GPR ',' expr { branch_addcmp_reg_reg_instr(ALWAYS, $2, $5, $7, &$9); }
|
||||
| OP_ADDCMPB CC GPR ',' '#' absexp ',' GPR ',' expr { branch_addcmp_reg_reg_instr($2, $3, $6, $8, &$10); }
|
||||
| OP_ADDCMPB GPR ',' GPR ',' '#' absexp ',' expr { branch_addcmp_reg_lit_instr(ALWAYS, $2, $4, $7, &$9); }
|
||||
| OP_ADDCMPB CC GPR ',' GPR ',' '#' absexp ',' expr { branch_addcmp_reg_lit_instr($2, $3, $5, $8, &$10); }
|
||||
| OP_ADDCMPB GPR ',' '#' absexp ',' '#' absexp ',' expr { branch_addcmp_lit_lit_instr(ALWAYS, $2, $5, $8, &$10); }
|
||||
| OP_ADDCMPB CC GPR ',' '#' absexp ',' '#' absexp ',' expr { branch_addcmp_lit_lit_instr($2, $3, $6, $9, &$11); }
|
||||
|
||||
| OP_ONELREG GPR
|
||||
{
|
||||
|
|
|
@ -388,3 +388,87 @@ void mem_address_instr(quad opcode, int rd, struct expr_t* expr)
|
|||
}
|
||||
}
|
||||
|
||||
/* Common code for handling addcmp: merge in as much of expr as will fit to
|
||||
* the second pair of the addcmp opcode. */
|
||||
|
||||
static void branch_addcmp_common(quad opcode, int bits, struct expr_t* expr)
|
||||
{
|
||||
quad type = expr->typ & S_TYP;
|
||||
|
||||
switch (pass)
|
||||
{
|
||||
case 0:
|
||||
/* Calculate size of instructions only. */
|
||||
|
||||
emit2(0);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
case 2:
|
||||
{
|
||||
if (type != DOTTYP)
|
||||
serror("can't use this type of branch to jump outside the section");
|
||||
|
||||
/* The VC4 branch instructions express distance in 2-byte
|
||||
* words. */
|
||||
|
||||
int d = (expr->val - DOTVAL-2 + 4) / 2;
|
||||
|
||||
if (!fitx(d, bits))
|
||||
serror("target of branch is too far away");
|
||||
|
||||
emit2(opcode | maskx(d, bits));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void branch_addcmp_reg_reg_instr(int cc, int rd, int ra, int rs, struct expr_t* expr)
|
||||
{
|
||||
if ((rd >= 0x10) || (ra >= 0x10) || (rs >= 0x10))
|
||||
serror("can only use r0-r15 in this instruction");
|
||||
|
||||
emit2(B16(10000000,00000000) | (cc<<8) | (ra<<4) | (rd<<0));
|
||||
branch_addcmp_common(B16(00000000,00000000) | (rs<<10), 10, expr);
|
||||
}
|
||||
|
||||
void branch_addcmp_lit_reg_instr(int cc, int rd, long va, int rs, struct expr_t* expr)
|
||||
{
|
||||
if ((rd >= 0x10) || (rs >= 0x10))
|
||||
serror("can only use r0-r15 in this instruction");
|
||||
|
||||
if (!fitx(va, 4))
|
||||
serror("value too big to encode into instruction");
|
||||
va = maskx(va, 4);
|
||||
|
||||
emit2(B16(10000000,00000000) | (cc<<8) | (va<<4) | (rd<<0));
|
||||
branch_addcmp_common(B16(01000000,00000000) | (rs<<10), 10, expr);
|
||||
}
|
||||
|
||||
void branch_addcmp_reg_lit_instr(int cc, int rd, int ra, long vs, struct expr_t* expr)
|
||||
{
|
||||
if ((rd >= 0x10) || (ra >= 0x10))
|
||||
serror("can only use r0-r15 in this instruction");
|
||||
|
||||
if (!fitx(vs, 6))
|
||||
serror("value too big to encode into instruction");
|
||||
vs = maskx(vs, 6);
|
||||
|
||||
emit2(B16(10000000,00000000) | (cc<<8) | (ra<<4) | (rd<<0));
|
||||
branch_addcmp_common(B16(10000000,00000000) | (vs<<8), 8, expr);
|
||||
}
|
||||
|
||||
void branch_addcmp_lit_lit_instr(int cc, int rd, long va, long vs, struct expr_t* expr)
|
||||
{
|
||||
if (rd >= 0x10)
|
||||
serror("can only use r0-r15 in this instruction");
|
||||
|
||||
if (!fitx(va, 4) || !fitx(vs, 6))
|
||||
serror("value too big to encode into instruction");
|
||||
va = maskx(va, 4);
|
||||
vs = maskx(vs, 6);
|
||||
|
||||
emit2(B16(10000000,00000000) | (cc<<8) | (va<<4) | (rd<<0));
|
||||
branch_addcmp_common(B16(11000000,00000000) | (vs<<8), 8, expr);
|
||||
}
|
||||
|
||||
|
|
|
@ -353,3 +353,10 @@ near:
|
|||
ldb r0, main
|
||||
stb r0, near
|
||||
stb r0, main
|
||||
|
||||
b.eq r0, r1, near
|
||||
b r0, r1, near
|
||||
addcmpb r0, r1, r2, .
|
||||
addcmpb r0, #1, r2, .
|
||||
addcmpb r0, r1, #1, .
|
||||
addcmpb r0, #1, #2, .
|
||||
|
|
Loading…
Reference in a new issue