From: David Given Date: Sat, 25 May 2013 22:26:10 +0000 (+0100) Subject: Major bugfix where instructions weren't being shrunk correctly. (Turns out there... X-Git-Tag: release-6-0-pre-5~10^2~36 X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=3b07fee160754546e68c42b0ba69ed41ca91c0e4;p=ack.git Major bugfix where instructions weren't being shrunk correctly. (Turns out there's built-in support for doing this, which I hadn't found.) --HG-- branch : dtrg-videocore --- diff --git a/mach/vc4/as/mach1.c b/mach/vc4/as/mach1.c index de164610e..315468f8e 100644 --- a/mach/vc4/as/mach1.c +++ b/mach/vc4/as/mach1.c @@ -10,7 +10,7 @@ #define ALWAYS 14 extern void alu_instr_reg(quad opcode, int cc, int rd, int ra, int rb); -extern void alu_instr_lit(quad opcode, int cc, int rd, int ra, quad value); +extern void alu_instr_lit(quad opcode, int cc, int rd, int ra, long value); extern void misc_instr_reg(quad opcode, int cc, int rd, int ra, int rb); extern void misc_instr_lit(quad opcode, int cc, int rd, int ra, quad value); extern void branch_instr(int bl, int cc, struct expr_t* expr); diff --git a/mach/vc4/as/mach5.c b/mach/vc4/as/mach5.c index 53ec3464c..a2227fd5e 100644 --- a/mach/vc4/as/mach5.c +++ b/mach/vc4/as/mach5.c @@ -34,12 +34,12 @@ void alu_instr_reg(quad op, int cc, int rd, int ra, int rb) /* Assemble an ALU instruction where rb is a literal. */ -void alu_instr_lit(quad op, int cc, int rd, int ra, quad value) +void alu_instr_lit(quad op, int cc, int rd, int ra, long value) { /* 16 bit short form? */ - if ((cc == ALWAYS) && !(op & 1) && (value <= 0x1f) && (ra == rd) && - (ra < 0x10)) + if ((cc == ALWAYS) && !(op & 1) && (value >= 0) && (value <= 0x1f) && + (ra == rd) && (ra < 0x10)) { emit2(B16(01100000,00000000) | (op<<8) | (value<<4) | (rd<<0)); return; @@ -47,7 +47,7 @@ void alu_instr_lit(quad op, int cc, int rd, int ra, quad value) /* 32 bit medium form? */ - if (value <= 0x1f) + if ((value >= 0) && (value <= 0x1f)) { emit2(B16(11000000,00000000) | (op<<5) | (rd<<0)); emit2(B16(00000000,01000000) | (ra<<11) | (cc<<7) | (value<<0)); @@ -99,6 +99,7 @@ void branch_instr(int bl, int cc, struct expr_t* expr) { quad pc = DOTVAL; quad type = expr->typ & S_TYP; + int d; /* Sanity checking. */ @@ -107,71 +108,52 @@ void branch_instr(int bl, int cc, struct expr_t* expr) 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, 32 bits. */ - - emit4(0); - break; + /* The VC4 branch instructions express distance in 2-byte + * words. */ - case 1: - case 2: - { - /* The VC4 branch instructions express distance in 2-byte - * words. */ + d = (int32_t)expr->val - (int32_t)pc; + if ((pass == 2) && (d > 0) && !(expr->typ & S_DOT)) + d -= DOTGAIN; + d /= 2; - int d = ((int32_t)expr->val - (int32_t)pc) / 2; + /* If this is a reference to code within this section, and it's + * close enough to the program counter, we can use a short- + * form instruction. */ - /* We now know the worst case for the instruction layout. At - * this point we can emit the instructions, which may shrink - * the code. */ - - if (!bl && (type == DOTTYP)) - { - /* This is a reference to code within this section. If it's - * close enough to the program counter, we can use a short- - * form instruction. */ - - if (fitx(d, 7)) - { - emit2(B16(00011000,00000000) | (cc<<7) | (d&0x7f)); - break; - } - } + if (small(!bl && (type == DOTTYP) && fitx(d, 7), 2)) + { + emit2(B16(00011000,00000000) | (cc<<7) | (d&0x7f)); + return; + } - /* Absolute addresses and references to other sections - * need the full 32 bits. */ + /* Absolute addresses and references to other sections + * need the full 32 bits. */ - newrelo(expr->typ, RELOVC4|RELPC); + newrelo(expr->typ, RELOVC4|RELPC); - if (bl) - { - quad v, hiv, lov; + if (bl) + { + quad v, hiv, lov; - if (!fitx(d, 27)) - toobig(); + if (!fitx(d, 27)) + toobig(); - v = maskx(d, 27); - hiv = v >> 23; - lov = v & 0x007fffff; - emit2(B16(10010000,10000000) | (lov>>16) | (hiv<<8)); - emit2(B16(00000000,00000000) | (lov&0xffff)); - } - else - { - quad v; + v = maskx(d, 27); + hiv = v >> 23; + lov = v & 0x007fffff; + emit2(B16(10010000,10000000) | (lov>>16) | (hiv<<8)); + emit2(B16(00000000,00000000) | (lov&0xffff)); + } + else + { + quad v; - if (!fitx(d, 23)) - toobig(); + if (!fitx(d, 23)) + toobig(); - v = maskx(d, 23); - emit2(B16(10010000,00000000) | (cc<<8) | (v>>16)); - emit2(B16(00000000,00000000) | (v&0xffff)); - } - break; - } + v = maskx(d, 23); + emit2(B16(10010000,00000000) | (cc<<8) | (v>>16)); + emit2(B16(00000000,00000000) | (v&0xffff)); } } @@ -352,66 +334,45 @@ void mem_postincr_instr(quad opcode, int cc, int rd, int rs) void mem_address_instr(quad opcode, int rd, struct expr_t* expr) { - static const char sizes[] = {4, 2, 1, 2}; + static const char sizes[] = {4, 4, 2, 2, 1, 1, 2, 2}; int size = sizes[opcode]; quad type = expr->typ & S_TYP; + int d, scaledd; /* 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: - { - int d = expr->val - DOTVAL; + d = expr->val - DOTVAL; + if ((pass == 2) && (d > 0) && !(expr->typ & S_DOT)) + d -= DOTGAIN; + scaledd = d/size; - /* We now know the worst case for the instruction layout. At - * this point we can emit the instructions, which may shrink - * the code. */ + /* If this is a reference to an address within this section, and + * it's close enough to the program counter, we can use a + * shorter instruction. */ - if (type == DOTTYP) - { - int scaledd = d/size; - - /* 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(scaledd, 16)) - { - emit2(B16(10101010,00000000) | (opcode<<5) | (rd<<0)); - emit2(scaledd); - return; - } - } + if (small((type==DOTTYP) && fitx(scaledd, 16), 2)) + { + emit2(B16(10101010,00000000) | (opcode<<5) | (rd<<0)); + emit2(scaledd); + return; + } - /* Otherwise we need the full 48 bits. */ + /* Otherwise we need the full 48 bits. */ - newrelo(expr->typ, RELOVC4|RELPC); + newrelo(expr->typ, RELOVC4|RELPC); - /* VC4 relocations store the PC-relative delta into the - * destination section in the instruction data. The linker will - * massage this, and scale it appropriately. */ + /* VC4 relocations store the PC-relative delta into the + * destination section in the instruction data. The linker will + * massage this, and scale it appropriately. */ - if (!fitx(d, 27)) - toobig(); + if (!fitx(d, 27)) + toobig(); - emit2(B16(11100111,00000000) | (opcode<<5) | (rd<<0)); - emit4((31<<27) | maskx(d, 27)); - break; - } - } + emit2(B16(11100111,00000000) | (opcode<<5) | (rd<<0)); + emit4((31<<27) | maskx(d, 27)); } /* Common code for handling addcmp: merge in as much of expr as will fit to @@ -420,33 +381,23 @@ void mem_address_instr(quad opcode, int rd, struct expr_t* expr) static void branch_addcmp_common(quad opcode, int bits, struct expr_t* expr) { quad type = expr->typ & S_TYP; + int d; - 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"); + 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. */ + /* The VC4 branch instructions express distance in 2-byte + * words. */ - int d = (expr->val - DOTVAL-2 + 4) / 2; + d = (expr->val - DOTVAL-2 + 4); + if ((pass == 2) && (d > 0) && !(expr->typ & S_DOT)) + d -= DOTGAIN; + d /= 2; - if (!fitx(d, bits)) - serror("target of branch is too far away"); + if (!fitx(d, bits)) + serror("target of branch is too far away"); - emit2(opcode | maskx(d, bits)); - break; - } - } + emit2(opcode | maskx(d, bits)); } void branch_addcmp_reg_reg_instr(int cc, int rd, int ra, int rs, struct expr_t* expr) @@ -518,6 +469,10 @@ void lea_address_instr(int rd, struct expr_t* expr) { quad pc = DOTVAL; quad type = expr->typ & S_TYP; + int d = expr->val - pc; + + if ((pass == 2) && (d > 0) && !(expr->typ & S_DOT)) + d -= DOTGAIN; if (type == S_ABS) serror("can't use absolute addresses here");