diff options
| author | Richard Miller <millerresearch@gmail.com> | 2020-11-09 18:11:51 +0000 |
|---|---|---|
| committer | Charles Forsyth <charles.forsyth@gmail.com> | 2020-11-09 18:11:51 +0000 |
| commit | ec7a4b742467a19160dfa5322e3e0880e4abed48 (patch) | |
| tree | 523d2f81946b1e0abe4afddf1d2fce7e1525b7d7 /utils/il/compress.c | |
| parent | ed97654bd7a11d480b44505c8300d06b42e5fefe (diff) | |
| parent | 6e84dc968bc4eaf047fbefcba2f670940718dda8 (diff) | |
Merged in millerresearch/inferno-riscv/utils-riscv (pull request #8)
Add toolchain and libmach support for riscv and riscv64
Approved-by: Charles Forsyth <charles.forsyth@gmail.com>
Diffstat (limited to 'utils/il/compress.c')
| -rw-r--r-- | utils/il/compress.c | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/utils/il/compress.c b/utils/il/compress.c new file mode 100644 index 00000000..e0063615 --- /dev/null +++ b/utils/il/compress.c @@ -0,0 +1,270 @@ +#include "l.h" + +#define COMPREG(r) ((r & ~0x7) == 0x8) +#define COP_CR(op,rs,rd)\ + (op | (rs)<<2 | (rd)<<7) +#define COP_CI(op,rd,i)\ + (op | (rd)<<7 | ((i)&0x20)<<7 | ((i)&0x1F)<<2) +#define COP_CIW(op,rd,i)\ + (op | (rd)<<2 | (i)<<5) +#define COP_CJ(op,i)\ + (op | (i)<<2) +#define COP_CB(op,rs,i)\ + (op | (rs)<<7 | ((i)&0x1f)<<2 | ((i)&0xE0)<<5) +#define COP_CL(op,rs,rd,i)\ + (op | (rs)<<7 | (rd)<<2 | ((i)&0x7)<<4 | ((i)&0x38)<<7) +#define COP_CSS(op,rs,i)\ + (op | (rs)<<2 | ((i)&0x3F)<<7) +#define COP_CS(op,rs2,rs1,i)\ + (op | (rs2)<<2 | (rs1)<<7 | ((i)&0x7)<<4 | ((i)&0x38)<<7) + +static int +immbits(int v, char *permute) +{ + int r, i, c; + + r = 0; + for(i = 0; (c = *permute++) != 0; i++) + r |= ((v>>c) & 0x01) << i; + return r; +} + +long +asmcjmp(int a, Prog *p, int first) +{ + long v; + + if(p->cond == P) + v = 0; + else + v = (p->cond->pc - p->pc); + if(first || ((v&0x01) == 0 && v >= -0x800 && v < 0x800)) + return COP_CJ(a, immbits(v, "\5\1\2\3\7\6\12\10\11\4\13")); + return 0; +} + +int +asmcbz(int a, Prog *p, int first) +{ + long v; + int r; + + r = p->reg; + if(r == REGZERO || r == NREG) + r = p->from.reg; + else if(p->from.reg != REGZERO) + return 0; + if(!COMPREG(r)) + return 0; + if(p->cond == P) + v = 0; + else + v = (p->cond->pc - p->pc); + if(first || ((v&0x01) == 0 && v >= -0x100 && v < 0x100)) + return COP_CB(a, r&0x7, immbits(v, "\5\1\2\6\7\3\4\10")); + return 0; +} + +int +asmcload(Prog *p, int a, uint len, uint maxoff) +{ + int v; + int r; + + v = regoff(&p->from); + if((v & (len-1)) != 0 || v < 0) + return 0; + r = classreg(&p->from); + if(COMPREG(r) && COMPREG(p->to.reg)){ + if(v < maxoff){ + v |= (v>>5) & ~0x1; + return COP_CL(a, r&0x7, p->to.reg&0x7, v); + } + }else if(r == REGSP){ + if(v < 2*maxoff){ + v |= (v>>6); + return COP_CI(a | 0x2, p->to.reg, v); + } + } + return 0; +} + +int +asmcstore(Prog *p, int a, uint len, uint maxoff) +{ + int v; + int r; + + v = regoff(&p->to); + if((v & (len-1)) != 0 || v < 0) + return 0; + r = classreg(&p->to); + if(COMPREG(r) && COMPREG(p->from.reg)){ + if(v < maxoff){ + v |= (v>>5) & ~0x1; + return COP_CS(a, p->from.reg&0x7, r&0x7, v); + } + }else if(r == REGSP){ + if(v < 2*maxoff){ + v |= (v>>6); + return COP_CSS(a | 0x2, (p->from.reg&0x1F), v); + } + } + return 0; +} + +int +asmcompressed(Prog *p, Optab *o, int r, int first) +{ + long v; + int a; + + switch(o->ctype){ + case 1: /* C.ADD */ + if(p->from.reg != REGZERO && p->to.reg != REGZERO && r == p->to.reg) + return COP_CR(0x9002, p->from.reg, r); + break; + case 2: /* C.MV */ + if(p->from.type != D_REG) + diag("compress MOVW R,R doesn't apply\n%P", p); + if(p->to.reg != REGZERO){ + if(p->from.type == D_REG && p->from.reg != REGZERO) + return COP_CR(0x8002, p->from.reg, p->to.reg); + else + return COP_CI(0x4001, p->to.reg, 0); + } + break; + case 3: /* C.JALR */ + if(r == REGLINK && p->to.reg != REGZERO && p->to.offset == 0) + return COP_CR(0x9002, 0, p->to.reg); + break; + case 4: /* C.JR */ + if(p->to.reg != REGZERO &&p->to.offset == 0) + return COP_CR(0x8002, 0, p->to.reg); + break; + case 5: /* C.AND C.OR C.SUB C.XOR */ + if(r == p->to.reg && COMPREG(p->from.reg) && COMPREG(p->to.reg)){ + v = 0x8C01; + switch(o->as){ + case AXOR: + v |= 1<<5; + break; + case AOR: + v |= 2<<5; + break; + case AAND: + v |= 3<<5; + break; + } + return COP_CR(v, p->from.reg&0x7, p->to.reg&0x7); + } + break; + case 6: /* C.LI */ + v = p->from.offset; + if(p->to.reg != REGZERO && v >= -0x20 && v < 0x20){ + return COP_CI(0x4001, p->to.reg, v); + } + break; + case 7: /* C.LUI */ + v = p->from.offset; + if((v&0xFFF) != 0) + return 0; + v >>= 12; + if(p->to.reg != REGZERO && p->to.reg != REGSP && v >= -0x20 && v < 0x20) + return COP_CI(0x6001, p->to.reg, v); + break; + case 8: /* C.SLLI */ + v = p->from.offset; + if((v & 0x20) != 0 && thechar == 'i') + break; + if(r == p->to.reg && r != REGZERO && v != 0 && (v & ~0x3F) == 0) + return COP_CI(0x0002, p->to.reg, v); + break; + case 9: /* C.SRAI C.SRLI */ + v = p->from.offset; + if((v & 0x20) != 0 && thechar == 'i') + break; + a = (o->as == ASRA) << 10; + if(r == p->to.reg && COMPREG(r) && v != 0 && (v & ~0x3F) == 0) + return COP_CI(0x8001 | a, r&0x7, v); + break; + case 10: /* C.ADDI C.ADDI16SP C.ADDI4SPN C.NOP */ + v = p->from.offset; + if(r == p->to.reg && r != REGZERO && v != 0 && v >= -0x20 && v < 0x20) + return COP_CI(0x0001, p->to.reg, v); + if(r == p->to.reg && r == REGSP && v != 0 && (v&0xF) == 0 && v >= -0x200 && v < 0x200) + return COP_CI(0x6001, REGSP, immbits(v, "\5\7\10\6\4\11")); + if(r == REGSP && COMPREG(p->to.reg) && (v&0x3) == 0 && v > 0 && v < 0x400) + return COP_CIW(0x0000, p->to.reg&0x7, immbits(v, "\3\2\6\7\10\11\4\5")); + if(r == p->to.reg && r == REGZERO && v == 0) + return COP_CI(0x0001, 0, 0); + break; + case 11: /* C.JAL (rv32) */ + if(thechar != 'i') + break; + if(r == REGLINK) + return asmcjmp(0x2001, p, first); + break; + case 12: /* C.J */ + return asmcjmp(0xA001, p, first); + break; + case 13: /* C.ANDI */ + v = p->from.offset; + if(r == p->to.reg && COMPREG(r) && v >= -0x20 && v < 0x20) + return COP_CI(0x8801, r&0x7, v); + break; + case 14: /* C.BEQZ */ + return asmcbz(0xC001, p, first); + case 15: /* C.BNEZ */ + return asmcbz(0xE001, p, first); + case 16: /* C.LW C.LWSP */ + return asmcload(p, 0x4000, 4, 0x80); + case 17: /* C.FLW, C.FLWSP (rv32) */ + if(thechar != 'i') + break; + return asmcload(p, 0x6000, 4, 0x80); + case 18: /* C.FLD, C.FLDSP */ + return asmcload(p, 0x2000, 8, 0x100); + case 19: /* C.SW C.SWSP */ + return asmcstore(p, 0xC000, 4, 0x80); + case 20: /* C.FSW, C.FSWSP (rv32) */ + if(thechar != 'i') + break; + return asmcstore(p, 0xE000, 4, 0x80); + case 21: /* C.FSD, C.FSDSP */ + return asmcstore(p, 0xA000, 8, 0x100); + case 22: /* C.ADDW C.SUBW (rv64) */ + if(thechar != 'j') + break; + if(r == p->to.reg && COMPREG(p->from.reg) && COMPREG(p->to.reg)){ + v = 0x9C01; + switch(o->as){ + case AADDW: + v |= 1<<5; + break; + } + return COP_CR(v, p->from.reg&0x7, p->to.reg&0x7); + } + break; + case 23: /* C.ADDIW (rv64) */ + if(thechar != 'j') + break; + v = p->from.offset; + if(p->as == AMOVW){ + v = 0; + r = p->from.reg; + } + if(r == p->to.reg && r != REGZERO && v >= -0x20 && v < 0x20) + return COP_CI(0x2001, p->to.reg, v); + break; + case 24: /* C.LD (rv64) */ + if(thechar != 'j') + break; + return asmcload(p, 0x6000, 8, 0x100); + case 25: /* C.SD (rv64) */ + if(thechar != 'j') + break; + return asmcstore(p, 0xE000, 8, 0x100); + } + return 0; +} |
