1*ce95e1b3SDavid du Colombier #include "l.h"
2*ce95e1b3SDavid du Colombier
3*ce95e1b3SDavid du Colombier #define COMPREG(r) ((r & ~0x7) == 0x8)
4*ce95e1b3SDavid du Colombier #define COP_CR(op,rs,rd)\
5*ce95e1b3SDavid du Colombier (op | (rs)<<2 | (rd)<<7)
6*ce95e1b3SDavid du Colombier #define COP_CI(op,rd,i)\
7*ce95e1b3SDavid du Colombier (op | (rd)<<7 | ((i)&0x20)<<7 | ((i)&0x1F)<<2)
8*ce95e1b3SDavid du Colombier #define COP_CIW(op,rd,i)\
9*ce95e1b3SDavid du Colombier (op | (rd)<<2 | (i)<<5)
10*ce95e1b3SDavid du Colombier #define COP_CJ(op,i)\
11*ce95e1b3SDavid du Colombier (op | (i)<<2)
12*ce95e1b3SDavid du Colombier #define COP_CB(op,rs,i)\
13*ce95e1b3SDavid du Colombier (op | (rs)<<7 | ((i)&0x1f)<<2 | ((i)&0xE0)<<5)
14*ce95e1b3SDavid du Colombier #define COP_CL(op,rs,rd,i)\
15*ce95e1b3SDavid du Colombier (op | (rs)<<7 | (rd)<<2 | ((i)&0x7)<<4 | ((i)&0x38)<<7)
16*ce95e1b3SDavid du Colombier #define COP_CSS(op,rs,i)\
17*ce95e1b3SDavid du Colombier (op | (rs)<<2 | ((i)&0x3F)<<7)
18*ce95e1b3SDavid du Colombier #define COP_CS(op,rs2,rs1,i)\
19*ce95e1b3SDavid du Colombier (op | (rs2)<<2 | (rs1)<<7 | ((i)&0x7)<<4 | ((i)&0x38)<<7)
20*ce95e1b3SDavid du Colombier
21*ce95e1b3SDavid du Colombier static int
immbits(int v,char * permute)22*ce95e1b3SDavid du Colombier immbits(int v, char *permute)
23*ce95e1b3SDavid du Colombier {
24*ce95e1b3SDavid du Colombier int r, i, c;
25*ce95e1b3SDavid du Colombier
26*ce95e1b3SDavid du Colombier r = 0;
27*ce95e1b3SDavid du Colombier for(i = 0; (c = *permute++) != 0; i++)
28*ce95e1b3SDavid du Colombier r |= ((v>>c) & 0x01) << i;
29*ce95e1b3SDavid du Colombier return r;
30*ce95e1b3SDavid du Colombier }
31*ce95e1b3SDavid du Colombier
32*ce95e1b3SDavid du Colombier long
asmcjmp(int a,Prog * p,int first)33*ce95e1b3SDavid du Colombier asmcjmp(int a, Prog *p, int first)
34*ce95e1b3SDavid du Colombier {
35*ce95e1b3SDavid du Colombier long v;
36*ce95e1b3SDavid du Colombier
37*ce95e1b3SDavid du Colombier if(p->cond == P)
38*ce95e1b3SDavid du Colombier v = 0;
39*ce95e1b3SDavid du Colombier else
40*ce95e1b3SDavid du Colombier v = (p->cond->pc - p->pc);
41*ce95e1b3SDavid du Colombier if(first || ((v&0x01) == 0 && v >= -0x800 && v < 0x800))
42*ce95e1b3SDavid du Colombier return COP_CJ(a, immbits(v, "\5\1\2\3\7\6\12\10\11\4\13"));
43*ce95e1b3SDavid du Colombier return 0;
44*ce95e1b3SDavid du Colombier }
45*ce95e1b3SDavid du Colombier
46*ce95e1b3SDavid du Colombier int
asmcbz(int a,Prog * p,int first)47*ce95e1b3SDavid du Colombier asmcbz(int a, Prog *p, int first)
48*ce95e1b3SDavid du Colombier {
49*ce95e1b3SDavid du Colombier long v;
50*ce95e1b3SDavid du Colombier int r;
51*ce95e1b3SDavid du Colombier
52*ce95e1b3SDavid du Colombier r = p->reg;
53*ce95e1b3SDavid du Colombier if(r == REGZERO || r == NREG)
54*ce95e1b3SDavid du Colombier r = p->from.reg;
55*ce95e1b3SDavid du Colombier else if(p->from.reg != REGZERO)
56*ce95e1b3SDavid du Colombier return 0;
57*ce95e1b3SDavid du Colombier if(!COMPREG(r))
58*ce95e1b3SDavid du Colombier return 0;
59*ce95e1b3SDavid du Colombier if(p->cond == P)
60*ce95e1b3SDavid du Colombier v = 0;
61*ce95e1b3SDavid du Colombier else
62*ce95e1b3SDavid du Colombier v = (p->cond->pc - p->pc);
63*ce95e1b3SDavid du Colombier if(first || ((v&0x01) == 0 && v >= -0x100 && v < 0x100))
64*ce95e1b3SDavid du Colombier return COP_CB(a, r&0x7, immbits(v, "\5\1\2\6\7\3\4\10"));
65*ce95e1b3SDavid du Colombier return 0;
66*ce95e1b3SDavid du Colombier }
67*ce95e1b3SDavid du Colombier
68*ce95e1b3SDavid du Colombier int
asmcload(Prog * p,int a,uint len,uint maxoff)69*ce95e1b3SDavid du Colombier asmcload(Prog *p, int a, uint len, uint maxoff)
70*ce95e1b3SDavid du Colombier {
71*ce95e1b3SDavid du Colombier int v;
72*ce95e1b3SDavid du Colombier int r;
73*ce95e1b3SDavid du Colombier
74*ce95e1b3SDavid du Colombier v = regoff(&p->from);
75*ce95e1b3SDavid du Colombier if((v & (len-1)) != 0 || v < 0)
76*ce95e1b3SDavid du Colombier return 0;
77*ce95e1b3SDavid du Colombier r = classreg(&p->from);
78*ce95e1b3SDavid du Colombier if(COMPREG(r) && COMPREG(p->to.reg)){
79*ce95e1b3SDavid du Colombier if(v < maxoff){
80*ce95e1b3SDavid du Colombier v |= (v>>5) & ~0x1;
81*ce95e1b3SDavid du Colombier return COP_CL(a, r&0x7, p->to.reg&0x7, v);
82*ce95e1b3SDavid du Colombier }
83*ce95e1b3SDavid du Colombier }else if(r == REGSP){
84*ce95e1b3SDavid du Colombier if(v < 2*maxoff){
85*ce95e1b3SDavid du Colombier v |= (v>>6);
86*ce95e1b3SDavid du Colombier return COP_CI(a | 0x2, p->to.reg, v);
87*ce95e1b3SDavid du Colombier }
88*ce95e1b3SDavid du Colombier }
89*ce95e1b3SDavid du Colombier return 0;
90*ce95e1b3SDavid du Colombier }
91*ce95e1b3SDavid du Colombier
92*ce95e1b3SDavid du Colombier int
asmcstore(Prog * p,int a,uint len,uint maxoff)93*ce95e1b3SDavid du Colombier asmcstore(Prog *p, int a, uint len, uint maxoff)
94*ce95e1b3SDavid du Colombier {
95*ce95e1b3SDavid du Colombier int v;
96*ce95e1b3SDavid du Colombier int r;
97*ce95e1b3SDavid du Colombier
98*ce95e1b3SDavid du Colombier v = regoff(&p->to);
99*ce95e1b3SDavid du Colombier if((v & (len-1)) != 0 || v < 0)
100*ce95e1b3SDavid du Colombier return 0;
101*ce95e1b3SDavid du Colombier r = classreg(&p->to);
102*ce95e1b3SDavid du Colombier if(COMPREG(r) && COMPREG(p->from.reg)){
103*ce95e1b3SDavid du Colombier if(v < maxoff){
104*ce95e1b3SDavid du Colombier v |= (v>>5) & ~0x1;
105*ce95e1b3SDavid du Colombier return COP_CS(a, p->from.reg&0x7, r&0x7, v);
106*ce95e1b3SDavid du Colombier }
107*ce95e1b3SDavid du Colombier }else if(r == REGSP){
108*ce95e1b3SDavid du Colombier if(v < 2*maxoff){
109*ce95e1b3SDavid du Colombier v |= (v>>6);
110*ce95e1b3SDavid du Colombier return COP_CSS(a | 0x2, (p->from.reg&0x1F), v);
111*ce95e1b3SDavid du Colombier }
112*ce95e1b3SDavid du Colombier }
113*ce95e1b3SDavid du Colombier return 0;
114*ce95e1b3SDavid du Colombier }
115*ce95e1b3SDavid du Colombier
116*ce95e1b3SDavid du Colombier int
asmcompressed(Prog * p,Optab * o,int r,int first)117*ce95e1b3SDavid du Colombier asmcompressed(Prog *p, Optab *o, int r, int first)
118*ce95e1b3SDavid du Colombier {
119*ce95e1b3SDavid du Colombier long v;
120*ce95e1b3SDavid du Colombier int a;
121*ce95e1b3SDavid du Colombier
122*ce95e1b3SDavid du Colombier switch(o->ctype){
123*ce95e1b3SDavid du Colombier case 1: /* C.ADD */
124*ce95e1b3SDavid du Colombier if(p->from.reg != REGZERO && p->to.reg != REGZERO && r == p->to.reg)
125*ce95e1b3SDavid du Colombier return COP_CR(0x9002, p->from.reg, r);
126*ce95e1b3SDavid du Colombier break;
127*ce95e1b3SDavid du Colombier case 2: /* C.MV */
128*ce95e1b3SDavid du Colombier if(p->from.type != D_REG)
129*ce95e1b3SDavid du Colombier diag("compress MOVW R,R doesn't apply\n%P", p);
130*ce95e1b3SDavid du Colombier if(p->to.reg != REGZERO){
131*ce95e1b3SDavid du Colombier if(p->from.type == D_REG && p->from.reg != REGZERO)
132*ce95e1b3SDavid du Colombier return COP_CR(0x8002, p->from.reg, p->to.reg);
133*ce95e1b3SDavid du Colombier else
134*ce95e1b3SDavid du Colombier return COP_CI(0x4001, p->to.reg, 0);
135*ce95e1b3SDavid du Colombier }
136*ce95e1b3SDavid du Colombier break;
137*ce95e1b3SDavid du Colombier case 3: /* C.JALR */
138*ce95e1b3SDavid du Colombier if(r == REGLINK && p->to.reg != REGZERO && p->to.offset == 0)
139*ce95e1b3SDavid du Colombier return COP_CR(0x9002, 0, p->to.reg);
140*ce95e1b3SDavid du Colombier break;
141*ce95e1b3SDavid du Colombier case 4: /* C.JR */
142*ce95e1b3SDavid du Colombier if(p->to.reg != REGZERO &&p->to.offset == 0)
143*ce95e1b3SDavid du Colombier return COP_CR(0x8002, 0, p->to.reg);
144*ce95e1b3SDavid du Colombier break;
145*ce95e1b3SDavid du Colombier case 5: /* C.AND C.OR C.SUB C.XOR */
146*ce95e1b3SDavid du Colombier if(r == p->to.reg && COMPREG(p->from.reg) && COMPREG(p->to.reg)){
147*ce95e1b3SDavid du Colombier v = 0x8C01;
148*ce95e1b3SDavid du Colombier switch(o->as){
149*ce95e1b3SDavid du Colombier case AXOR:
150*ce95e1b3SDavid du Colombier v |= 1<<5;
151*ce95e1b3SDavid du Colombier break;
152*ce95e1b3SDavid du Colombier case AOR:
153*ce95e1b3SDavid du Colombier v |= 2<<5;
154*ce95e1b3SDavid du Colombier break;
155*ce95e1b3SDavid du Colombier case AAND:
156*ce95e1b3SDavid du Colombier v |= 3<<5;
157*ce95e1b3SDavid du Colombier break;
158*ce95e1b3SDavid du Colombier }
159*ce95e1b3SDavid du Colombier return COP_CR(v, p->from.reg&0x7, p->to.reg&0x7);
160*ce95e1b3SDavid du Colombier }
161*ce95e1b3SDavid du Colombier break;
162*ce95e1b3SDavid du Colombier case 6: /* C.LI */
163*ce95e1b3SDavid du Colombier v = p->from.offset;
164*ce95e1b3SDavid du Colombier if(p->to.reg != REGZERO && v >= -0x20 && v < 0x20){
165*ce95e1b3SDavid du Colombier return COP_CI(0x4001, p->to.reg, v);
166*ce95e1b3SDavid du Colombier }
167*ce95e1b3SDavid du Colombier break;
168*ce95e1b3SDavid du Colombier case 7: /* C.LUI */
169*ce95e1b3SDavid du Colombier v = p->from.offset;
170*ce95e1b3SDavid du Colombier if((v&0xFFF) != 0)
171*ce95e1b3SDavid du Colombier return 0;
172*ce95e1b3SDavid du Colombier v >>= 12;
173*ce95e1b3SDavid du Colombier if(p->to.reg != REGZERO && p->to.reg != REGSP && v >= -0x20 && v < 0x20)
174*ce95e1b3SDavid du Colombier return COP_CI(0x6001, p->to.reg, v);
175*ce95e1b3SDavid du Colombier break;
176*ce95e1b3SDavid du Colombier case 8: /* C.SLLI */
177*ce95e1b3SDavid du Colombier v = p->from.offset;
178*ce95e1b3SDavid du Colombier if((v & 0x20) != 0 && thechar == 'i')
179*ce95e1b3SDavid du Colombier break;
180*ce95e1b3SDavid du Colombier if(r == p->to.reg && r != REGZERO && v != 0 && (v & ~0x3F) == 0)
181*ce95e1b3SDavid du Colombier return COP_CI(0x0002, p->to.reg, v);
182*ce95e1b3SDavid du Colombier break;
183*ce95e1b3SDavid du Colombier case 9: /* C.SRAI C.SRLI */
184*ce95e1b3SDavid du Colombier v = p->from.offset;
185*ce95e1b3SDavid du Colombier if((v & 0x20) != 0 && thechar == 'i')
186*ce95e1b3SDavid du Colombier break;
187*ce95e1b3SDavid du Colombier a = (o->as == ASRA) << 10;
188*ce95e1b3SDavid du Colombier if(r == p->to.reg && COMPREG(r) && v != 0 && (v & ~0x3F) == 0)
189*ce95e1b3SDavid du Colombier return COP_CI(0x8001 | a, r&0x7, v);
190*ce95e1b3SDavid du Colombier break;
191*ce95e1b3SDavid du Colombier case 10: /* C.ADDI C.ADDI16SP C.ADDI4SPN C.NOP */
192*ce95e1b3SDavid du Colombier v = p->from.offset;
193*ce95e1b3SDavid du Colombier if(r == p->to.reg && r != REGZERO && v != 0 && v >= -0x20 && v < 0x20)
194*ce95e1b3SDavid du Colombier return COP_CI(0x0001, p->to.reg, v);
195*ce95e1b3SDavid du Colombier if(r == p->to.reg && r == REGSP && v != 0 && (v&0xF) == 0 && v >= -0x200 && v < 0x200)
196*ce95e1b3SDavid du Colombier return COP_CI(0x6001, REGSP, immbits(v, "\5\7\10\6\4\11"));
197*ce95e1b3SDavid du Colombier if(r == REGSP && COMPREG(p->to.reg) && (v&0x3) == 0 && v > 0 && v < 0x400)
198*ce95e1b3SDavid du Colombier return COP_CIW(0x0000, p->to.reg&0x7, immbits(v, "\3\2\6\7\10\11\4\5"));
199*ce95e1b3SDavid du Colombier if(r == p->to.reg && r == REGZERO && v == 0)
200*ce95e1b3SDavid du Colombier return COP_CI(0x0001, 0, 0);
201*ce95e1b3SDavid du Colombier break;
202*ce95e1b3SDavid du Colombier case 11: /* C.JAL (rv32) */
203*ce95e1b3SDavid du Colombier if(thechar != 'i')
204*ce95e1b3SDavid du Colombier break;
205*ce95e1b3SDavid du Colombier if(r == REGLINK)
206*ce95e1b3SDavid du Colombier return asmcjmp(0x2001, p, first);
207*ce95e1b3SDavid du Colombier break;
208*ce95e1b3SDavid du Colombier case 12: /* C.J */
209*ce95e1b3SDavid du Colombier return asmcjmp(0xA001, p, first);
210*ce95e1b3SDavid du Colombier break;
211*ce95e1b3SDavid du Colombier case 13: /* C.ANDI */
212*ce95e1b3SDavid du Colombier v = p->from.offset;
213*ce95e1b3SDavid du Colombier if(r == p->to.reg && COMPREG(r) && v >= -0x20 && v < 0x20)
214*ce95e1b3SDavid du Colombier return COP_CI(0x8801, r&0x7, v);
215*ce95e1b3SDavid du Colombier break;
216*ce95e1b3SDavid du Colombier case 14: /* C.BEQZ */
217*ce95e1b3SDavid du Colombier return asmcbz(0xC001, p, first);
218*ce95e1b3SDavid du Colombier case 15: /* C.BNEZ */
219*ce95e1b3SDavid du Colombier return asmcbz(0xE001, p, first);
220*ce95e1b3SDavid du Colombier case 16: /* C.LW C.LWSP */
221*ce95e1b3SDavid du Colombier return asmcload(p, 0x4000, 4, 0x80);
222*ce95e1b3SDavid du Colombier case 17: /* C.FLW, C.FLWSP (rv32) */
223*ce95e1b3SDavid du Colombier if(thechar != 'i')
224*ce95e1b3SDavid du Colombier break;
225*ce95e1b3SDavid du Colombier return asmcload(p, 0x6000, 4, 0x80);
226*ce95e1b3SDavid du Colombier case 18: /* C.FLD, C.FLDSP */
227*ce95e1b3SDavid du Colombier return asmcload(p, 0x2000, 8, 0x100);
228*ce95e1b3SDavid du Colombier case 19: /* C.SW C.SWSP */
229*ce95e1b3SDavid du Colombier return asmcstore(p, 0xC000, 4, 0x80);
230*ce95e1b3SDavid du Colombier case 20: /* C.FSW, C.FSWSP (rv32) */
231*ce95e1b3SDavid du Colombier if(thechar != 'i')
232*ce95e1b3SDavid du Colombier break;
233*ce95e1b3SDavid du Colombier return asmcstore(p, 0xE000, 4, 0x80);
234*ce95e1b3SDavid du Colombier case 21: /* C.FSD, C.FSDSP */
235*ce95e1b3SDavid du Colombier return asmcstore(p, 0xA000, 8, 0x100);
236*ce95e1b3SDavid du Colombier case 22: /* C.ADDW C.SUBW (rv64) */
237*ce95e1b3SDavid du Colombier if(thechar != 'j')
238*ce95e1b3SDavid du Colombier break;
239*ce95e1b3SDavid du Colombier if(r == p->to.reg && COMPREG(p->from.reg) && COMPREG(p->to.reg)){
240*ce95e1b3SDavid du Colombier v = 0x9C01;
241*ce95e1b3SDavid du Colombier switch(o->as){
242*ce95e1b3SDavid du Colombier case AADDW:
243*ce95e1b3SDavid du Colombier v |= 1<<5;
244*ce95e1b3SDavid du Colombier break;
245*ce95e1b3SDavid du Colombier }
246*ce95e1b3SDavid du Colombier return COP_CR(v, p->from.reg&0x7, p->to.reg&0x7);
247*ce95e1b3SDavid du Colombier }
248*ce95e1b3SDavid du Colombier break;
249*ce95e1b3SDavid du Colombier case 23: /* C.ADDIW (rv64) */
250*ce95e1b3SDavid du Colombier if(thechar != 'j')
251*ce95e1b3SDavid du Colombier break;
252*ce95e1b3SDavid du Colombier v = p->from.offset;
253*ce95e1b3SDavid du Colombier if(p->as == AMOVW){
254*ce95e1b3SDavid du Colombier v = 0;
255*ce95e1b3SDavid du Colombier r = p->from.reg;
256*ce95e1b3SDavid du Colombier }
257*ce95e1b3SDavid du Colombier if(r == p->to.reg && r != REGZERO && v >= -0x20 && v < 0x20)
258*ce95e1b3SDavid du Colombier return COP_CI(0x2001, p->to.reg, v);
259*ce95e1b3SDavid du Colombier break;
260*ce95e1b3SDavid du Colombier case 24: /* C.LD (rv64) */
261*ce95e1b3SDavid du Colombier if(thechar != 'j')
262*ce95e1b3SDavid du Colombier break;
263*ce95e1b3SDavid du Colombier return asmcload(p, 0x6000, 8, 0x100);
264*ce95e1b3SDavid du Colombier case 25: /* C.SD (rv64) */
265*ce95e1b3SDavid du Colombier if(thechar != 'j')
266*ce95e1b3SDavid du Colombier break;
267*ce95e1b3SDavid du Colombier return asmcstore(p, 0xE000, 8, 0x100);
268*ce95e1b3SDavid du Colombier }
269*ce95e1b3SDavid du Colombier return 0;
270*ce95e1b3SDavid du Colombier }
271