1 #include "l.h"
2
3 #define OPVCC(o,xo,oe,rc) (((o)<<26)|((xo)<<1)|((oe)<<10)|((rc)&1))
4 #define OPCC(o,xo,rc) OPVCC((o),(xo),0,(rc))
5 #define OP(o,xo) OPVCC((o),(xo),0,0)
6
7 /* the order is dest, a/s, b/imm for both arithmetic and logical operations */
8 #define AOP_RRR(op,d,a,b) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
9 #define AOP_IRR(op,d,a,simm) ((op)|(((d)&31L)<<21)|(((a)&31L)<<16)|((simm)&0xFFFF))
10 #define LOP_RRR(op,a,s,b) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((b)&31L)<<11))
11 #define LOP_IRR(op,a,s,uimm) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|((uimm)&0xFFFF))
12 #define OP_BR(op,li,aa) ((op)|((li)&0x03FFFFFC)|((aa)<<1))
13 #define OP_BC(op,bo,bi,bd,aa) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16)|((bd)&0xFFFC)|((aa)<<1))
14 #define OP_BCR(op,bo,bi) ((op)|(((bo)&0x1F)<<21)|(((bi)&0x1F)<<16))
15 #define OP_RLW(op,a,s,sh,mb,me) ((op)|(((s)&31L)<<21)|(((a)&31L)<<16)|(((sh)&31L)<<11)|\
16 (((mb)&31L)<<6)|(((me)&31L)<<1))
17
18 #define OP_ADD OPVCC(31,266,0,0)
19 #define OP_ADDI OPVCC(14,0,0,0)
20 #define OP_ADDIS OPVCC(15,0,0,0)
21 #define OP_ANDI OPVCC(28,0,0,0)
22 #define OP_EXTSB OPVCC(31,954,0,0)
23 #define OP_EXTSH OPVCC(31,922,0,0)
24 #define OP_EXTSW OPVCC(31,986,0,0)
25 #define OP_MCRF OPVCC(19,0,0,0)
26 #define OP_MCRFS OPVCC(63,64,0,0)
27 #define OP_MCRXR OPVCC(31,512,0,0)
28 #define OP_MFCR OPVCC(31,19,0,0)
29 #define OP_MFFS OPVCC(63,583,0,0)
30 #define OP_MFMSR OPVCC(31,83,0,0)
31 #define OP_MFSPR OPVCC(31,339,0,0)
32 #define OP_MFSR OPVCC(31,595,0,0)
33 #define OP_MFSRIN OPVCC(31,659,0,0)
34 #define OP_MTCRF OPVCC(31,144,0,0)
35 #define OP_MTFSF OPVCC(63,711,0,0)
36 #define OP_MTFSFI OPVCC(63,134,0,0)
37 #define OP_MTMSR OPVCC(31,146,0,0)
38 #define OP_MTMSRD OPVCC(31,178,0,0)
39 #define OP_MTSPR OPVCC(31,467,0,0)
40 #define OP_MTSR OPVCC(31,210,0,0)
41 #define OP_MTSRIN OPVCC(31,242,0,0)
42 #define OP_MULLW OPVCC(31,235,0,0)
43 #define OP_MULLD OPVCC(31,233,0,0)
44 #define OP_OR OPVCC(31,444,0,0)
45 #define OP_ORI OPVCC(24,0,0,0)
46 #define OP_ORIS OPVCC(25,0,0,0)
47 #define OP_RLWINM OPVCC(21,0,0,0)
48 #define OP_SUBF OPVCC(31,40,0,0)
49 #define OP_RLDIC OPVCC(30,4,0,0)
50 #define OP_RLDICR OPVCC(30,2,0,0)
51 #define OP_RLDICL OPVCC(30,0,0,0)
52
53 #define oclass(v) ((v).class-1)
54
55 long oprrr(int), opirr(int), opload(int), opstore(int), oploadx(int), opstorex(int);
56
57 /*
58 * 32-bit masks
59 */
60 int
getmask(uchar * m,ulong v)61 getmask(uchar *m, ulong v)
62 {
63 int i;
64
65 m[0] = m[1] = 0;
66 if(v != ~0L && v & (1<<31) && v & 1){ /* MB > ME */
67 if(getmask(m, ~v)){
68 i = m[0]; m[0] = m[1]+1; m[1] = i-1;
69 return 1;
70 }
71 return 0;
72 }
73 for(i=0; i<32; i++)
74 if(v & (1<<(31-i))){
75 m[0] = i;
76 do {
77 m[1] = i;
78 } while(++i<32 && (v & (1<<(31-i))) != 0);
79 for(; i<32; i++)
80 if(v & (1<<(31-i)))
81 return 0;
82 return 1;
83 }
84 return 0;
85 }
86
87 void
maskgen(Prog * p,uchar * m,ulong v)88 maskgen(Prog *p, uchar *m, ulong v)
89 {
90 if(!getmask(m, v))
91 diag("cannot generate mask #%lux\n%P", v, p);
92 }
93
94 /*
95 * 64-bit masks (rldic etc)
96 */
97 int
getmask64(uchar * m,uvlong v)98 getmask64(uchar *m, uvlong v)
99 {
100 int i;
101
102 m[0] = m[1] = 0;
103 for(i=0; i<64; i++)
104 if(v & ((uvlong)1<<(63-i))){
105 m[0] = i;
106 do {
107 m[1] = i;
108 } while(++i<64 && (v & ((uvlong)1<<(63-i))) != 0);
109 for(; i<64; i++)
110 if(v & ((uvlong)1<<(63-i)))
111 return 0;
112 return 1;
113 }
114 return 0;
115 }
116
117 void
maskgen64(Prog * p,uchar * m,uvlong v)118 maskgen64(Prog *p, uchar *m, uvlong v)
119 {
120 if(!getmask64(m, v))
121 diag("cannot generate mask #%llux\n%P", v, p);
122 }
123
124 static void
reloc(Adr * a,long pc,int sext)125 reloc(Adr *a, long pc, int sext)
126 {
127 if(a->name == D_EXTERN || a->name == D_STATIC)
128 dynreloc(a->sym, pc, 1, 1, sext);
129 }
130
131 static ulong
loadu32(int r,vlong d)132 loadu32(int r, vlong d)
133 {
134 long v;
135
136 v = d>>16;
137 if(isuint32(d))
138 return LOP_IRR(OP_ORIS, r, REGZERO, v);
139 return AOP_IRR(OP_ADDIS, r, REGZERO, v);
140 }
141
142 int
asmout(Prog * p,Optab * o,int aflag)143 asmout(Prog *p, Optab *o, int aflag)
144 {
145 long o1, o2, o3, o4, o5, v, t;
146 vlong d;
147 Prog *ct;
148 int r, a;
149 uchar mask[2];
150
151 o1 = 0;
152 o2 = 0;
153 o3 = 0;
154 o4 = 0;
155 o5 = 0;
156 switch(o->type) {
157 default:
158 if(aflag)
159 return 0;
160 diag("unknown type %d", o->type);
161 if(!debug['a'])
162 prasm(p);
163 break;
164
165 case 0: /* pseudo ops */
166 if(aflag) {
167 if(p->link) {
168 if(p->as == ATEXT) {
169 ct = curtext;
170 o2 = autosize;
171 curtext = p;
172 autosize = p->to.offset + 8;
173 o1 = asmout(p->link, oplook(p->link), aflag);
174 curtext = ct;
175 autosize = o2;
176 } else
177 o1 = asmout(p->link, oplook(p->link), aflag);
178 }
179 return o1;
180 }
181 break;
182
183 case 1: /* mov r1,r2 ==> OR Rs,Rs,Ra */
184 if(p->to.reg == REGZERO && p->from.type == D_CONST) {
185 v = regoff(&p->from);
186 if(r0iszero && v != 0) {
187 nerrors--;
188 diag("literal operation on R0\n%P", p);
189 }
190 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
191 break;
192 }
193 o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);
194 break;
195
196 case 2: /* int/cr/fp op Rb,[Ra],Rd */
197 r = p->reg;
198 if(r == NREG)
199 r = p->to.reg;
200 o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);
201 break;
202
203 case 3: /* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
204 d = vregoff(&p->from);
205 v = d;
206 r = p->from.reg;
207 if(r == NREG)
208 r = o->param;
209 if(r0iszero && p->to.reg == 0 && (r != 0 || v != 0))
210 diag("literal operation on R0\n%P", p);
211 a = OP_ADDI;
212 if(o->a1 == C_UCON) {
213 v >>= 16;
214 if(r == REGZERO && isuint32(d)){
215 o1 = LOP_IRR(OP_ORIS, p->to.reg, REGZERO, v);
216 break;
217 }
218 a = OP_ADDIS;
219 }
220 o1 = AOP_IRR(a, p->to.reg, r, v);
221 break;
222
223 case 4: /* add/mul $scon,[r1],r2 */
224 v = regoff(&p->from);
225 r = p->reg;
226 if(r == NREG)
227 r = p->to.reg;
228 if(r0iszero && p->to.reg == 0)
229 diag("literal operation on R0\n%P", p);
230 o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);
231 break;
232
233 case 5: /* syscall */
234 if(aflag)
235 return 0;
236 o1 = oprrr(p->as);
237 break;
238
239 case 6: /* logical op Rb,[Rs,]Ra; no literal */
240 r = p->reg;
241 if(r == NREG)
242 r = p->to.reg;
243 o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);
244 break;
245
246 case 7: /* mov r, soreg ==> stw o(r) */
247 r = p->to.reg;
248 if(r == NREG)
249 r = o->param;
250 v = regoff(&p->to);
251 if(p->to.type == D_OREG && p->reg != NREG) {
252 if(v)
253 diag("illegal indexed instruction\n%P", p);
254 o1 = AOP_RRR(opstorex(p->as), p->from.reg, p->reg, r);
255 } else
256 o1 = AOP_IRR(opstore(p->as), p->from.reg, r, v);
257 break;
258
259 case 8: /* mov soreg, r ==> lbz/lhz/lwz o(r) */
260 r = p->from.reg;
261 if(r == NREG)
262 r = o->param;
263 v = regoff(&p->from);
264 if(p->from.type == D_OREG && p->reg != NREG) {
265 if(v)
266 diag("illegal indexed instruction\n%P", p);
267 o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);
268 } else
269 o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);
270 break;
271
272 case 9: /* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
273 r = p->from.reg;
274 if(r == NREG)
275 r = o->param;
276 v = regoff(&p->from);
277 if(p->from.type == D_OREG && p->reg != NREG) {
278 if(v)
279 diag("illegal indexed instruction\n%P", p);
280 o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);
281 } else
282 o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);
283 o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
284 break;
285
286 case 10: /* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
287 r = p->reg;
288 if(r == NREG)
289 r = p->to.reg;
290 o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, r);
291 break;
292
293 case 11: /* br/bl lbra */
294 if(aflag)
295 return 0;
296 v = 0;
297 if(p->cond == UP){
298 if(p->to.sym->type != SUNDEF)
299 diag("bad branch sym type");
300 v = (ulong)p->to.sym->value >> (Roffset-2);
301 dynreloc(p->to.sym, p->pc, 0, 0, 0);
302 }
303 else if(p->cond)
304 v = p->cond->pc - p->pc;
305 if(v & 03) {
306 diag("odd branch target address\n%P", p);
307 v &= ~03;
308 }
309 if(v < -(1L<<25) || v >= (1L<<24))
310 diag("branch too far\n%P", p);
311 o1 = OP_BR(opirr(p->as), v, 0);
312 break;
313
314 case 12: /* movb r,r (extsb); movw r,r (extsw) */
315 if(p->to.reg == REGZERO && p->from.type == D_CONST) {
316 v = regoff(&p->from);
317 if(r0iszero && v != 0) {
318 nerrors--;
319 diag("literal operation on R0\n%P", p);
320 }
321 o1 = LOP_IRR(OP_ADDI, REGZERO, REGZERO, v);
322 break;
323 }
324 if(p->as == AMOVW)
325 o1 = LOP_RRR(OP_EXTSW, p->to.reg, p->from.reg, 0);
326 else
327 o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);
328 break;
329
330 case 13: /* mov[bhw]z r,r; uses rlwinm not andi. to avoid changing CC */
331 if(p->as == AMOVBZ)
332 o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);
333 else if(p->as == AMOVH)
334 o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);
335 else if(p->as == AMOVHZ)
336 o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);
337 else if(p->as == AMOVWZ)
338 o1 = OP_RLW(OP_RLDIC, p->to.reg, p->from.reg, 0, 0, 0) | (1<<5); /* MB=32 */
339 else
340 diag("internal: bad mov[bhw]z\n%P", p);
341 break;
342
343 case 14: /* rldc[lr] Rb,Rs,$mask,Ra -- left, right give different masks */
344 r = p->reg;
345 if(r == NREG)
346 r = p->to.reg;
347 d = vregoff(&p->from3);
348 maskgen64(p, mask, d);
349 switch(p->as){
350 case ARLDCL: case ARLDCLCC:
351 a = mask[0]; /* MB */
352 if(mask[1] != 63)
353 diag("invalid mask for rotate: %llux (end != bit 63)\n%P", d, p);
354 break;
355 case ARLDCR: case ARLDCRCC:
356 a = mask[1]; /* ME */
357 if(mask[0] != 0)
358 diag("invalid mask for rotate: %llux (start != 0)\n%P", d, p);
359 break;
360 default:
361 diag("unexpected op in rldc case\n%P", p);
362 a = 0;
363 }
364 o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);
365 o1 |= (a&31L)<<6;
366 if(a & 0x20)
367 o1 |= 1<<5; /* mb[5] is top bit */
368 break;
369
370 case 17: /* bc bo,bi,lbra (same for now) */
371 case 16: /* bc bo,bi,sbra */
372 if(aflag)
373 return 0;
374 a = 0;
375 if(p->from.type == D_CONST)
376 a = regoff(&p->from);
377 r = p->reg;
378 if(r == NREG)
379 r = 0;
380 v = 0;
381 if(p->cond)
382 v = p->cond->pc - p->pc;
383 if(v & 03) {
384 diag("odd branch target address\n%P", p);
385 v &= ~03;
386 }
387 if(v < -(1L<<16) || v >= (1L<<15))
388 diag("branch too far\n%P", p);
389 o1 = OP_BC(opirr(p->as), a, r, v, 0);
390 break;
391
392 case 15: /* br/bl (r) => mov r,lr; br/bl (lr) */
393 if(aflag)
394 return 0;
395 if(p->as == ABC || p->as == ABCL)
396 v = regoff(&p->to)&31L;
397 else
398 v = 20; /* unconditional */
399 r = p->reg;
400 if(r == NREG)
401 r = 0;
402 o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
403 o2 = OPVCC(19, 16, 0, 0);
404 if(p->as == ABL || p->as == ABCL)
405 o2 |= 1;
406 o2 = OP_BCR(o2, v, r);
407 break;
408
409 case 18: /* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
410 if(aflag)
411 return 0;
412 if(p->as == ABC || p->as == ABCL)
413 v = regoff(&p->from)&31L;
414 else
415 v = 20; /* unconditional */
416 r = p->reg;
417 if(r == NREG)
418 r = 0;
419 switch(oclass(p->to)) {
420 case C_CTR:
421 o1 = OPVCC(19, 528, 0, 0);
422 break;
423 case C_LR:
424 o1 = OPVCC(19, 16, 0, 0);
425 break;
426 default:
427 diag("bad optab entry (18): %d\n%P", p->to.class, p);
428 v = 0;
429 }
430 if(p->as == ABL || p->as == ABCL)
431 o1 |= 1;
432 o1 = OP_BCR(o1, v, r);
433 break;
434
435 case 19: /* mov $lcon,r ==> cau+or */
436 d = vregoff(&p->from);
437 o1 = loadu32(p->to.reg, d);
438 o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, (long)d);
439 if(dlm)
440 reloc(&p->from, p->pc, 0);
441 break;
442
443 case 20: /* add $ucon,,r */
444 v = regoff(&p->from);
445 r = p->reg;
446 if(r == NREG)
447 r = p->to.reg;
448 if(p->as == AADD && (!r0iszero && p->reg == 0 || r0iszero && p->to.reg == 0))
449 diag("literal operation on R0\n%P", p);
450 o1 = AOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16);
451 break;
452
453 case 22: /* add $lcon,r1,r2 ==> cau+or+add */ /* could do add/sub more efficiently */
454 if(p->to.reg == REGTMP || p->reg == REGTMP)
455 diag("cant synthesize large constant\n%P", p);
456 d = vregoff(&p->from);
457 o1 = loadu32(REGTMP, d);
458 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (long)d);
459 r = p->reg;
460 if(r == NREG)
461 r = p->to.reg;
462 o3 = AOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);
463 if(dlm)
464 reloc(&p->from, p->pc, 0);
465 break;
466
467 case 23: /* and $lcon,r1,r2 ==> cau+or+and */ /* masks could be done using rlnm etc. */
468 if(p->to.reg == REGTMP || p->reg == REGTMP)
469 diag("cant synthesize large constant\n%P", p);
470 d = vregoff(&p->from);
471 o1 = loadu32(REGTMP, d);
472 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, (long)d);
473 r = p->reg;
474 if(r == NREG)
475 r = p->to.reg;
476 o3 = LOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);
477 if(dlm)
478 reloc(&p->from, p->pc, 0);
479 break;
480 /*24*/
481
482 case 25: /* sld[.] $sh,rS,rA -> rldicr[.] $sh,rS,mask(0,63-sh),rA; srd[.] -> rldicl */
483 v = regoff(&p->from);
484 if(v < 0)
485 v = 0;
486 else if(v > 63)
487 v = 63;
488 r = p->reg;
489 if(r == NREG)
490 r = p->to.reg;
491 switch(p->as){
492 case ASLD: case ASLDCC:
493 a = 63-v;
494 o1 = OP_RLDICR;
495 break;
496 case ASRD: case ASRDCC:
497 a = v;
498 v = 64-v;
499 o1 = OP_RLDICL;
500 break;
501 default:
502 diag("unexpected op in sldi case\n%P", p);
503 a = 0;
504 o1 = 0;
505 }
506 o1 = AOP_RRR(o1, r, p->to.reg, (v&0x1F));
507 o1 |= (a&31L)<<6;
508 if(v & 0x20)
509 o1 |= 1<<1;
510 if(a & 0x20)
511 o1 |= 1<<5; /* mb[5] is top bit */
512 if(p->as == ASLDCC || p->as == ASRDCC)
513 o1 |= 1; /* Rc */
514 break;
515
516 case 26: /* mov $lsext/auto/oreg,,r2 ==> addis+addi */
517 if(p->to.reg == REGTMP)
518 diag("can't synthesize large constant\n%P", p);
519 v = regoff(&p->from);
520 if(v & 0x8000L)
521 v += 0x10000L;
522 r = p->from.reg;
523 if(r == NREG)
524 r = o->param;
525 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
526 o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);
527 break;
528
529 case 27: /* subc ra,$simm,rd => subfic rd,ra,$simm */
530 v = regoff(&p->from3);
531 r = p->from.reg;
532 o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);
533 break;
534
535 case 28: /* subc r1,$lcon,r2 ==> cau+or+subfc */
536 if(p->to.reg == REGTMP || p->from.reg == REGTMP)
537 diag("can't synthesize large constant\n%P", p);
538 v = regoff(&p->from3);
539 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
540 o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
541 o3 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, REGTMP);
542 if(dlm)
543 reloc(&p->from3, p->pc, 0);
544 break;
545
546 case 29: /* rldic[lr]? $sh,s,$mask,a -- left, right, plain give different masks */
547 v = regoff(&p->from);
548 d = vregoff(&p->from3);
549 maskgen64(p, mask, d);
550 switch(p->as){
551 case ARLDC: case ARLDCCC:
552 a = mask[0]; /* MB */
553 if(mask[1] != (63-v))
554 diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
555 break;
556 case ARLDCL: case ARLDCLCC:
557 a = mask[0]; /* MB */
558 if(mask[1] != 63)
559 diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
560 break;
561 case ARLDCR: case ARLDCRCC:
562 a = mask[1]; /* ME */
563 if(mask[0] != 0)
564 diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
565 break;
566 default:
567 diag("unexpected op in rldic case\n%P", p);
568 a = 0;
569 }
570 o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, (v&0x1F));
571 o1 |= (a&31L)<<6;
572 if(v & 0x20)
573 o1 |= 1<<1;
574 if(a & 0x20)
575 o1 |= 1<<5; /* mb[5] is top bit */
576 break;
577
578 case 30: /* rldimi $sh,s,$mask,a */
579 v = regoff(&p->from);
580 d = vregoff(&p->from3);
581 maskgen64(p, mask, d);
582 if(mask[1] != (63-v))
583 diag("invalid mask for shift: %llux (shift %ld)\n%P", d, v, p);
584 o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, (v&0x1F));
585 o1 |= (mask[0]&31L)<<6;
586 if(v & 0x20)
587 o1 |= 1<<1;
588 if(mask[0] & 0x20)
589 o1 |= 1<<5; /* mb[5] is top bit */
590 break;
591
592 case 31: /* dword */
593 if(aflag)
594 return 0;
595 d = vregoff(&p->from);
596 o1 = d>>32;
597 o2 = d;
598 break;
599
600 case 32: /* fmul frc,fra,frd */
601 r = p->reg;
602 if(r == NREG)
603 r = p->to.reg;
604 o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);
605 break;
606
607 case 33: /* fabs [frb,]frd; fmr. frb,frd */
608 r = p->from.reg;
609 if(oclass(p->from) == C_NONE)
610 r = p->to.reg;
611 o1 = AOP_RRR(oprrr(p->as), p->to.reg, 0, r);
612 break;
613
614 case 34: /* FMADDx fra,frb,frc,frd (d=a*b+c); FSELx a<0? (d=b): (d=c) */
615 o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6);
616 break;
617
618 case 35: /* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
619 v = regoff(&p->to);
620 if(v & 0x8000L)
621 v += 0x10000L;
622 r = p->to.reg;
623 if(r == NREG)
624 r = o->param;
625 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
626 o2 = AOP_IRR(opstore(p->as), p->from.reg, REGTMP, v);
627 break;
628
629 case 36: /* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
630 v = regoff(&p->from);
631 if(v & 0x8000L)
632 v += 0x10000L;
633 r = p->from.reg;
634 if(r == NREG)
635 r = o->param;
636 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
637 o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
638 break;
639
640 case 37: /* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
641 v = regoff(&p->from);
642 if(v & 0x8000L)
643 v += 0x10000L;
644 r = p->from.reg;
645 if(r == NREG)
646 r = o->param;
647 o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
648 o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
649 o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
650 break;
651
652 case 40: /* word */
653 if(aflag)
654 return 0;
655 o1 = regoff(&p->from);
656 break;
657
658 case 41: /* stswi */
659 o1 = AOP_RRR(opirr(p->as), p->from.reg, p->to.reg, 0) | ((regoff(&p->from3)&0x7F)<<11);
660 break;
661
662 case 42: /* lswi */
663 o1 = AOP_RRR(opirr(p->as), p->to.reg, p->from.reg, 0) | ((regoff(&p->from3)&0x7F)<<11);
664 break;
665
666 case 43: /* unary indexed source: dcbf (b); dcbf (a+b) */
667 r = p->reg;
668 if(r == NREG)
669 r = 0;
670 o1 = AOP_RRR(oprrr(p->as), 0, r, p->from.reg);
671 break;
672
673 case 44: /* indexed store */
674 r = p->reg;
675 if(r == NREG)
676 r = 0;
677 o1 = AOP_RRR(opstorex(p->as), p->from.reg, r, p->to.reg);
678 break;
679 case 45: /* indexed load */
680 r = p->reg;
681 if(r == NREG)
682 r = 0;
683 o1 = AOP_RRR(oploadx(p->as), p->to.reg, r, p->from.reg);
684 break;
685
686 case 46: /* plain op */
687 o1 = oprrr(p->as);
688 break;
689
690 case 47: /* op Ra, Rd; also op [Ra,] Rd */
691 r = p->from.reg;
692 if(r == NREG)
693 r = p->to.reg;
694 o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, 0);
695 break;
696
697 case 48: /* op Rs, Ra */
698 r = p->from.reg;
699 if(r == NREG)
700 r = p->to.reg;
701 o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, 0);
702 break;
703
704 case 49: /* op Rb; op $n, Rb */
705 if(p->from.type != D_REG){ /* tlbie $L, rB */
706 v = regoff(&p->from) & 1;
707 o1 = AOP_RRR(oprrr(p->as), 0, 0, p->to.reg) | (v<<21);
708 }else
709 o1 = AOP_RRR(oprrr(p->as), 0, 0, p->from.reg);
710 break;
711
712 case 50: /* rem[u] r1[,r2],r3 */
713 r = p->reg;
714 if(r == NREG)
715 r = p->to.reg;
716 v = oprrr(p->as);
717 t = v & ((1<<10)|1); /* OE|Rc */
718 o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
719 o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
720 o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
721 break;
722
723 case 51: /* remd[u] r1[,r2],r3 */
724 r = p->reg;
725 if(r == NREG)
726 r = p->to.reg;
727 v = oprrr(p->as);
728 t = v & ((1<<10)|1); /* OE|Rc */
729 o1 = AOP_RRR(v&~t, REGTMP, r, p->from.reg);
730 o2 = AOP_RRR(OP_MULLD, REGTMP, REGTMP, p->from.reg);
731 o3 = AOP_RRR(OP_SUBF|t, p->to.reg, REGTMP, r);
732 break;
733
734 case 52: /* mtfsbNx cr(n) */
735 v = regoff(&p->from)&31L;
736 o1 = AOP_RRR(oprrr(p->as), v, 0, 0);
737 break;
738
739 case 53: /* mffsX ,fr1 */
740 o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0);
741 break;
742
743 case 54: /* mov msr,r1; mov r1, msr*/
744 if(oclass(p->from) == C_REG){
745 if(p->as == AMOVD)
746 o1 = AOP_RRR(OP_MTMSRD, p->from.reg, 0, 0);
747 else
748 o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0);
749 }else
750 o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0);
751 break;
752
753 case 55: /* op Rb, Rd */
754 o1 = AOP_RRR(oprrr(p->as), p->to.reg, 0, p->from.reg);
755 break;
756
757 case 56: /* sra $sh,[s,]a; srd $sh,[s,]a */
758 v = regoff(&p->from);
759 r = p->reg;
760 if(r == NREG)
761 r = p->to.reg;
762 o1 = AOP_RRR(opirr(p->as), r, p->to.reg, v&31L);
763 if(p->as == ASRAD && (v&0x20))
764 o1 |= 1<<1; /* mb[5] */
765 break;
766
767 case 57: /* slw $sh,[s,]a -> rlwinm ... */
768 v = regoff(&p->from);
769 r = p->reg;
770 if(r == NREG)
771 r = p->to.reg;
772 /*
773 * Let user (gs) shoot himself in the foot.
774 * qc has already complained.
775 *
776 if(v < 0 || v > 31)
777 diag("illegal shift %ld\n%P", v, p);
778 */
779 if(v < 0)
780 v = 0;
781 else if(v > 32)
782 v = 32;
783 if(p->as == ASRW || p->as == ASRWCC) { /* shift right */
784 mask[0] = v;
785 mask[1] = 31;
786 v = 32-v;
787 } else {
788 mask[0] = 0;
789 mask[1] = 31-v;
790 }
791 o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]);
792 if(p->as == ASLWCC || p->as == ASRWCC)
793 o1 |= 1; /* Rc */
794 break;
795
796 case 58: /* logical $andcon,[s],a */
797 v = regoff(&p->from);
798 r = p->reg;
799 if(r == NREG)
800 r = p->to.reg;
801 o1 = LOP_IRR(opirr(p->as), p->to.reg, r, v);
802 break;
803
804 case 59: /* or/and $ucon,,r */
805 v = regoff(&p->from);
806 r = p->reg;
807 if(r == NREG)
808 r = p->to.reg;
809 o1 = LOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16); /* oris, xoris, andis */
810 break;
811
812 case 60: /* tw to,a,b */
813 r = regoff(&p->from)&31L;
814 o1 = AOP_RRR(oprrr(p->as), r, p->reg, p->to.reg);
815 break;
816
817 case 61: /* tw to,a,$simm */
818 r = regoff(&p->from)&31L;
819 v = regoff(&p->to);
820 o1 = AOP_IRR(opirr(p->as), r, p->reg, v);
821 break;
822
823 case 62: /* rlwmi $sh,s,$mask,a */
824 v = regoff(&p->from);
825 maskgen(p, mask, regoff(&p->from3));
826 o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, v);
827 o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
828 break;
829
830 case 63: /* rlwmi b,s,$mask,a */
831 maskgen(p, mask, regoff(&p->from3));
832 o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, p->from.reg);
833 o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
834 break;
835
836 case 64: /* mtfsf fr[, $m] {,fpcsr} */
837 if(p->from3.type != D_NONE)
838 v = regoff(&p->from3)&255L;
839 else
840 v = 255;
841 o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11);
842 break;
843
844 case 65: /* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
845 if(p->to.reg == NREG)
846 diag("must specify FPSCR(n)\n%P", p);
847 o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(&p->from)&31L)<<12);
848 break;
849
850 case 66: /* mov spr,r1; mov r1,spr, also dcr */
851 if(p->from.type == D_REG) {
852 r = p->from.reg;
853 v = p->to.offset;
854 if(p->to.type == D_DCR)
855 o1 = OPVCC(31,451,0,0); /* mtdcr */
856 else
857 o1 = OPVCC(31,467,0,0); /* mtspr */
858 } else {
859 r = p->to.reg;
860 v = p->from.offset;
861 if(p->from.type == D_DCR)
862 o1 = OPVCC(31,323,0,0); /* mfdcr */
863 else
864 o1 = OPVCC(31,339,0,0); /* mfspr */
865 }
866 o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11);
867 break;
868
869 case 67: /* mcrf crfD,crfS */
870 if(p->from.type != D_CREG || p->from.reg == NREG ||
871 p->to.type != D_CREG || p->to.reg == NREG)
872 diag("illegal CR field number\n%P", p);
873 o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
874 break;
875
876 case 68: /* mfcr rD; mfocrf CRM,rD */
877 if(p->from.type == D_CREG && p->from.reg != NREG){
878 v = 1<<(7-(p->to.reg&7)); /* CR(n) */
879 o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0) | (1<<20) | (v<<12); /* new form, mfocrf */
880 }else
881 o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0); /* old form, whole register */
882 break;
883
884 case 69: /* mtcrf CRM,rS */
885 if(p->from3.type != D_NONE) {
886 if(p->to.reg != NREG)
887 diag("can't use both mask and CR(n)\n%P", p);
888 v = regoff(&p->from3) & 0xff;
889 } else {
890 if(p->to.reg == NREG)
891 v = 0xff; /* CR */
892 else
893 v = 1<<(7-(p->to.reg&7)); /* CR(n) */
894 }
895 o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12);
896 break;
897
898 case 70: /* [f]cmp r,r,cr*/
899 if(p->reg == NREG)
900 r = 0;
901 else
902 r = (p->reg&7)<<2;
903 o1 = AOP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
904 break;
905
906 case 71: /* cmp[l] r,i,cr*/
907 if(p->reg == NREG)
908 r = 0;
909 else
910 r = (p->reg&7)<<2;
911 o1 = AOP_RRR(opirr(p->as), r, p->from.reg, 0) | (regoff(&p->to)&0xffff);
912 break;
913
914 case 72: /* slbmte (Rb+Rs -> slb[Rb]) -> Rs, Rb */
915 o1 = AOP_RRR(oprrr(p->as), p->from.reg, 0, p->to.reg);
916 break;
917
918 case 73: /* mcrfs crfD,crfS */
919 if(p->from.type != D_FPSCR || p->from.reg == NREG ||
920 p->to.type != D_CREG || p->to.reg == NREG)
921 diag("illegal FPSCR/CR field number\n%P", p);
922 o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
923 break;
924
925 /* relocation operations */
926
927 case 74:
928 v = regoff(&p->to);
929 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
930 o2 = AOP_IRR(opstore(p->as), p->from.reg, REGTMP, v);
931 if(dlm)
932 reloc(&p->to, p->pc, 1);
933 break;
934
935 case 75:
936 v = regoff(&p->from);
937 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
938 o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
939 if(dlm)
940 reloc(&p->from, p->pc, 1);
941 break;
942
943 case 76:
944 v = regoff(&p->from);
945 o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
946 o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
947 o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
948 if(dlm)
949 reloc(&p->from, p->pc, 1);
950 break;
951
952 }
953 if(aflag)
954 return o1;
955 v = p->pc;
956 switch(o->size) {
957 default:
958 if(debug['a'])
959 Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
960 break;
961 case 4:
962 if(debug['a'])
963 Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
964 lput(o1);
965 break;
966 case 8:
967 if(debug['a'])
968 Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
969 lput(o1);
970 lput(o2);
971 break;
972 case 12:
973 if(debug['a'])
974 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
975 lput(o1);
976 lput(o2);
977 lput(o3);
978 break;
979 case 16:
980 if(debug['a'])
981 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
982 v, o1, o2, o3, o4, p);
983 lput(o1);
984 lput(o2);
985 lput(o3);
986 lput(o4);
987 break;
988 case 20:
989 if(debug['a'])
990 Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
991 v, o1, o2, o3, o4, o5, p);
992 lput(o1);
993 lput(o2);
994 lput(o3);
995 lput(o4);
996 lput(o5);
997 break;
998 }
999 return 0;
1000 }
1001
1002 long
oprrr(int a)1003 oprrr(int a)
1004 {
1005 switch(a) {
1006 case AADD: return OPVCC(31,266,0,0);
1007 case AADDCC: return OPVCC(31,266,0,1);
1008 case AADDV: return OPVCC(31,266,1,0);
1009 case AADDVCC: return OPVCC(31,266,1,1);
1010 case AADDC: return OPVCC(31,10,0,0);
1011 case AADDCCC: return OPVCC(31,10,0,1);
1012 case AADDCV: return OPVCC(31,10,1,0);
1013 case AADDCVCC: return OPVCC(31,10,1,1);
1014 case AADDE: return OPVCC(31,138,0,0);
1015 case AADDECC: return OPVCC(31,138,0,1);
1016 case AADDEV: return OPVCC(31,138,1,0);
1017 case AADDEVCC: return OPVCC(31,138,1,1);
1018 case AADDME: return OPVCC(31,234,0,0);
1019 case AADDMECC: return OPVCC(31,234,0,1);
1020 case AADDMEV: return OPVCC(31,234,1,0);
1021 case AADDMEVCC: return OPVCC(31,234,1,1);
1022 case AADDZE: return OPVCC(31,202,0,0);
1023 case AADDZECC: return OPVCC(31,202,0,1);
1024 case AADDZEV: return OPVCC(31,202,1,0);
1025 case AADDZEVCC: return OPVCC(31,202,1,1);
1026
1027 case AAND: return OPVCC(31,28,0,0);
1028 case AANDCC: return OPVCC(31,28,0,1);
1029 case AANDN: return OPVCC(31,60,0,0);
1030 case AANDNCC: return OPVCC(31,60,0,1);
1031
1032 case ACMP: return OPVCC(31,0,0,0)|(1<<21); /* L=1 */
1033 case ACMPU: return OPVCC(31,32,0,0)|(1<<21);
1034 case ACMPW: return OPVCC(31,0,0,0); /* L=0 */
1035 case ACMPWU: return OPVCC(31,32,0,0);
1036
1037 case ACNTLZW: return OPVCC(31,26,0,0);
1038 case ACNTLZWCC: return OPVCC(31,26,0,1);
1039 case ACNTLZD: return OPVCC(31,58,0,0);
1040 case ACNTLZDCC: return OPVCC(31,58,0,1);
1041
1042 case ACRAND: return OPVCC(19,257,0,0);
1043 case ACRANDN: return OPVCC(19,129,0,0);
1044 case ACREQV: return OPVCC(19,289,0,0);
1045 case ACRNAND: return OPVCC(19,225,0,0);
1046 case ACRNOR: return OPVCC(19,33,0,0);
1047 case ACROR: return OPVCC(19,449,0,0);
1048 case ACRORN: return OPVCC(19,417,0,0);
1049 case ACRXOR: return OPVCC(19,193,0,0);
1050
1051 case ADCBF: return OPVCC(31,86,0,0);
1052 case ADCBI: return OPVCC(31,470,0,0);
1053 case ADCBST: return OPVCC(31,54,0,0);
1054 case ADCBT: return OPVCC(31,278,0,0);
1055 case ADCBTST: return OPVCC(31,246,0,0);
1056 case ADCBZ: return OPVCC(31,1014,0,0);
1057
1058 case AREM:
1059 case ADIVW: return OPVCC(31,491,0,0);
1060 case AREMCC:
1061 case ADIVWCC: return OPVCC(31,491,0,1);
1062 case AREMV:
1063 case ADIVWV: return OPVCC(31,491,1,0);
1064 case AREMVCC:
1065 case ADIVWVCC: return OPVCC(31,491,1,1);
1066 case AREMU:
1067 case ADIVWU: return OPVCC(31,459,0,0);
1068 case AREMUCC:
1069 case ADIVWUCC: return OPVCC(31,459,0,1);
1070 case AREMUV:
1071 case ADIVWUV: return OPVCC(31,459,1,0);
1072 case AREMUVCC:
1073 case ADIVWUVCC: return OPVCC(31,459,1,1);
1074
1075 case AREMD:
1076 case ADIVD: return OPVCC(31,489,0,0);
1077 case AREMDCC:
1078 case ADIVDCC: return OPVCC(31,489,0,1);
1079 case AREMDV:
1080 case ADIVDV: return OPVCC(31,489,1,0);
1081 case AREMDVCC:
1082 case ADIVDVCC: return OPVCC(31,489,1,1);
1083 case AREMDU:
1084 case ADIVDU: return OPVCC(31,457,0,0);
1085 case AREMDUCC:
1086 case ADIVDUCC: return OPVCC(31,457,0,1);
1087 case AREMDUV:
1088 case ADIVDUV: return OPVCC(31,457,1,0);
1089 case AREMDUVCC:
1090 case ADIVDUVCC: return OPVCC(31,457,1,1);
1091
1092 case AEIEIO: return OPVCC(31,854,0,0);
1093
1094 case AEQV: return OPVCC(31,284,0,0);
1095 case AEQVCC: return OPVCC(31,284,0,1);
1096
1097 case AEXTSB: return OPVCC(31,954,0,0);
1098 case AEXTSBCC: return OPVCC(31,954,0,1);
1099 case AEXTSH: return OPVCC(31,922,0,0);
1100 case AEXTSHCC: return OPVCC(31,922,0,1);
1101 case AEXTSW: return OPVCC(31,986,0,0);
1102 case AEXTSWCC: return OPVCC(31,986,0,1);
1103
1104 case AFABS: return OPVCC(63,264,0,0);
1105 case AFABSCC: return OPVCC(63,264,0,1);
1106 case AFADD: return OPVCC(63,21,0,0);
1107 case AFADDCC: return OPVCC(63,21,0,1);
1108 case AFADDS: return OPVCC(59,21,0,0);
1109 case AFADDSCC: return OPVCC(59,21,0,1);
1110 case AFCMPO: return OPVCC(63,32,0,0);
1111 case AFCMPU: return OPVCC(63,0,0,0);
1112 case AFCFID: return OPVCC(63,846,0,0);
1113 case AFCFIDCC: return OPVCC(63,846,0,1);
1114 case AFCTIW: return OPVCC(63,14,0,0);
1115 case AFCTIWCC: return OPVCC(63,14,0,1);
1116 case AFCTIWZ: return OPVCC(63,15,0,0);
1117 case AFCTIWZCC: return OPVCC(63,15,0,1);
1118 case AFCTID: return OPVCC(63,814,0,0);
1119 case AFCTIDCC: return OPVCC(63,814,0,1);
1120 case AFCTIDZ: return OPVCC(63,815,0,0);
1121 case AFCTIDZCC: return OPVCC(63,815,0,1);
1122 case AFDIV: return OPVCC(63,18,0,0);
1123 case AFDIVCC: return OPVCC(63,18,0,1);
1124 case AFDIVS: return OPVCC(59,18,0,0);
1125 case AFDIVSCC: return OPVCC(59,18,0,1);
1126 case AFMADD: return OPVCC(63,29,0,0);
1127 case AFMADDCC: return OPVCC(63,29,0,1);
1128 case AFMADDS: return OPVCC(59,29,0,0);
1129 case AFMADDSCC: return OPVCC(59,29,0,1);
1130 case AFMOVS:
1131 case AFMOVD: return OPVCC(63,72,0,0); /* load */
1132 case AFMOVDCC: return OPVCC(63,72,0,1);
1133 case AFMSUB: return OPVCC(63,28,0,0);
1134 case AFMSUBCC: return OPVCC(63,28,0,1);
1135 case AFMSUBS: return OPVCC(59,28,0,0);
1136 case AFMSUBSCC: return OPVCC(59,28,0,1);
1137 case AFMUL: return OPVCC(63,25,0,0);
1138 case AFMULCC: return OPVCC(63,25,0,1);
1139 case AFMULS: return OPVCC(59,25,0,0);
1140 case AFMULSCC: return OPVCC(59,25,0,1);
1141 case AFNABS: return OPVCC(63,136,0,0);
1142 case AFNABSCC: return OPVCC(63,136,0,1);
1143 case AFNEG: return OPVCC(63,40,0,0);
1144 case AFNEGCC: return OPVCC(63,40,0,1);
1145 case AFNMADD: return OPVCC(63,31,0,0);
1146 case AFNMADDCC: return OPVCC(63,31,0,1);
1147 case AFNMADDS: return OPVCC(59,31,0,0);
1148 case AFNMADDSCC: return OPVCC(59,31,0,1);
1149 case AFNMSUB: return OPVCC(63,30,0,0);
1150 case AFNMSUBCC: return OPVCC(63,30,0,1);
1151 case AFNMSUBS: return OPVCC(59,30,0,0);
1152 case AFNMSUBSCC: return OPVCC(59,30,0,1);
1153 case AFRES: return OPVCC(59,24,0,0);
1154 case AFRESCC: return OPVCC(59,24,0,1);
1155 case AFRSP: return OPVCC(63,12,0,0);
1156 case AFRSPCC: return OPVCC(63,12,0,1);
1157 case AFRSQRTE: return OPVCC(63,26,0,0);
1158 case AFRSQRTECC: return OPVCC(63,26,0,1);
1159 case AFSEL: return OPVCC(63,23,0,0);
1160 case AFSELCC: return OPVCC(63,23,0,1);
1161 case AFSQRT: return OPVCC(63,22,0,0);
1162 case AFSQRTCC: return OPVCC(63,22,0,1);
1163 case AFSQRTS: return OPVCC(59,22,0,0);
1164 case AFSQRTSCC: return OPVCC(59,22,0,1);
1165 case AFSUB: return OPVCC(63,20,0,0);
1166 case AFSUBCC: return OPVCC(63,20,0,1);
1167 case AFSUBS: return OPVCC(59,20,0,0);
1168 case AFSUBSCC: return OPVCC(59,20,0,1);
1169
1170 case AICBI: return OPVCC(31,982,0,0);
1171 case AISYNC: return OPVCC(19,150,0,0);
1172
1173 case AMTFSB0: return OPVCC(63,70,0,0);
1174 case AMTFSB0CC: return OPVCC(63,70,0,1);
1175 case AMTFSB1: return OPVCC(63,38,0,0);
1176 case AMTFSB1CC: return OPVCC(63,38,0,1);
1177
1178 case AMULHW: return OPVCC(31,75,0,0);
1179 case AMULHWCC: return OPVCC(31,75,0,1);
1180 case AMULHWU: return OPVCC(31,11,0,0);
1181 case AMULHWUCC: return OPVCC(31,11,0,1);
1182 case AMULLW: return OPVCC(31,235,0,0);
1183 case AMULLWCC: return OPVCC(31,235,0,1);
1184 case AMULLWV: return OPVCC(31,235,1,0);
1185 case AMULLWVCC: return OPVCC(31,235,1,1);
1186
1187 case AMULHD: return OPVCC(31,73,0,0);
1188 case AMULHDCC: return OPVCC(31,73,0,1);
1189 case AMULHDU: return OPVCC(31,9,0,0);
1190 case AMULHDUCC: return OPVCC(31,9,0,1);
1191 case AMULLD: return OPVCC(31,233,0,0);
1192 case AMULLDCC: return OPVCC(31,233,0,1);
1193 case AMULLDV: return OPVCC(31,233,1,0);
1194 case AMULLDVCC: return OPVCC(31,233,1,1);
1195
1196 case ANAND: return OPVCC(31,476,0,0);
1197 case ANANDCC: return OPVCC(31,476,0,1);
1198 case ANEG: return OPVCC(31,104,0,0);
1199 case ANEGCC: return OPVCC(31,104,0,1);
1200 case ANEGV: return OPVCC(31,104,1,0);
1201 case ANEGVCC: return OPVCC(31,104,1,1);
1202 case ANOR: return OPVCC(31,124,0,0);
1203 case ANORCC: return OPVCC(31,124,0,1);
1204 case AOR: return OPVCC(31,444,0,0);
1205 case AORCC: return OPVCC(31,444,0,1);
1206 case AORN: return OPVCC(31,412,0,0);
1207 case AORNCC: return OPVCC(31,412,0,1);
1208
1209 case ARFI: return OPVCC(19,50,0,0);
1210 case ARFCI: return OPVCC(19,51,0,0);
1211 case ARFID: return OPVCC(19,18,0,0);
1212 case AHRFID: return OPVCC(19,274,0,0);
1213
1214 case ARLWMI: return OPVCC(20,0,0,0);
1215 case ARLWMICC: return OPVCC(20,0,0,1);
1216 case ARLWNM: return OPVCC(23,0,0,0);
1217 case ARLWNMCC: return OPVCC(23,0,0,1);
1218
1219 case ARLDCL: return OPVCC(30,8,0,0);
1220 case ARLDCR: return OPVCC(30,9,0,0);
1221
1222 case ASYSCALL: return OPVCC(17,1,0,0);
1223
1224 case ASLW: return OPVCC(31,24,0,0);
1225 case ASLWCC: return OPVCC(31,24,0,1);
1226 case ASLD: return OPVCC(31,27,0,0);
1227 case ASLDCC: return OPVCC(31,27,0,1);
1228
1229 case ASRAW: return OPVCC(31,792,0,0);
1230 case ASRAWCC: return OPVCC(31,792,0,1);
1231 case ASRAD: return OPVCC(31,794,0,0);
1232 case ASRADCC: return OPVCC(31,794,0,1);
1233
1234 case ASRW: return OPVCC(31,536,0,0);
1235 case ASRWCC: return OPVCC(31,536,0,1);
1236 case ASRD: return OPVCC(31,539,0,0);
1237 case ASRDCC: return OPVCC(31,539,0,1);
1238
1239 case ASUB: return OPVCC(31,40,0,0);
1240 case ASUBCC: return OPVCC(31,40,0,1);
1241 case ASUBV: return OPVCC(31,40,1,0);
1242 case ASUBVCC: return OPVCC(31,40,1,1);
1243 case ASUBC: return OPVCC(31,8,0,0);
1244 case ASUBCCC: return OPVCC(31,8,0,1);
1245 case ASUBCV: return OPVCC(31,8,1,0);
1246 case ASUBCVCC: return OPVCC(31,8,1,1);
1247 case ASUBE: return OPVCC(31,136,0,0);
1248 case ASUBECC: return OPVCC(31,136,0,1);
1249 case ASUBEV: return OPVCC(31,136,1,0);
1250 case ASUBEVCC: return OPVCC(31,136,1,1);
1251 case ASUBME: return OPVCC(31,232,0,0);
1252 case ASUBMECC: return OPVCC(31,232,0,1);
1253 case ASUBMEV: return OPVCC(31,232,1,0);
1254 case ASUBMEVCC: return OPVCC(31,232,1,1);
1255 case ASUBZE: return OPVCC(31,200,0,0);
1256 case ASUBZECC: return OPVCC(31,200,0,1);
1257 case ASUBZEV: return OPVCC(31,200,1,0);
1258 case ASUBZEVCC: return OPVCC(31,200,1,1);
1259
1260 case ASYNC: return OPVCC(31,598,0,0);
1261 case APTESYNC: return OPVCC(31,598,0,0) | (2<<21);
1262
1263 case ATLBIE: return OPVCC(31,306,0,0);
1264 case ATLBIEL: return OPVCC(31,274,0,0);
1265 case ATLBSYNC: return OPVCC(31,566,0,0);
1266 case ASLBIA: return OPVCC(31,498,0,0);
1267 case ASLBIE: return OPVCC(31,434,0,0);
1268 case ASLBMFEE: return OPVCC(31,915,0,0);
1269 case ASLBMFEV: return OPVCC(31,851,0,0);
1270 case ASLBMTE: return OPVCC(31,402,0,0);
1271
1272 case ATW: return OPVCC(31,4,0,0);
1273 case ATD: return OPVCC(31,68,0,0);
1274
1275 case AXOR: return OPVCC(31,316,0,0);
1276 case AXORCC: return OPVCC(31,316,0,1);
1277 }
1278 diag("bad r/r opcode %A", a);
1279 return 0;
1280 }
1281
1282 long
opirr(int a)1283 opirr(int a)
1284 {
1285 switch(a) {
1286 case AADD: return OPVCC(14,0,0,0);
1287 case AADDC: return OPVCC(12,0,0,0);
1288 case AADDCCC: return OPVCC(13,0,0,0);
1289 case AADD+AEND: return OPVCC(15,0,0,0); /* ADDIS/CAU */
1290
1291 case AANDCC: return OPVCC(28,0,0,0);
1292 case AANDCC+AEND: return OPVCC(29,0,0,0); /* ANDIS./ANDIU. */
1293
1294 case ABR: return OPVCC(18,0,0,0);
1295 case ABL: return OPVCC(18,0,0,0) | 1;
1296 case ABC: return OPVCC(16,0,0,0);
1297 case ABCL: return OPVCC(16,0,0,0) | 1;
1298
1299 case ABEQ: return AOP_RRR(16<<26,12,2,0);
1300 case ABGE: return AOP_RRR(16<<26,4,0,0);
1301 case ABGT: return AOP_RRR(16<<26,12,1,0);
1302 case ABLE: return AOP_RRR(16<<26,4,1,0);
1303 case ABLT: return AOP_RRR(16<<26,12,0,0);
1304 case ABNE: return AOP_RRR(16<<26,4,2,0);
1305 case ABVC: return AOP_RRR(16<<26,4,3,0);
1306 case ABVS: return AOP_RRR(16<<26,12,3,0);
1307
1308 case ACMP: return OPVCC(11,0,0,0)|(1<<21); /* L=1 */
1309 case ACMPU: return OPVCC(10,0,0,0)|(1<<21);
1310 case ACMPW: return OPVCC(11,0,0,0); /* L=0 */
1311 case ACMPWU: return OPVCC(10,0,0,0);
1312 case ALSW: return OPVCC(31,597,0,0);
1313
1314 case AMULLW: return OPVCC(7,0,0,0);
1315
1316 case AOR: return OPVCC(24,0,0,0);
1317 case AOR+AEND: return OPVCC(25,0,0,0); /* ORIS/ORIU */
1318
1319 case ARLWMI: return OPVCC(20,0,0,0); /* rlwimi */
1320 case ARLWMICC: return OPVCC(20,0,0,1);
1321 case ARLDMI: return OPVCC(30,0,0,0) | (3<<2); /* rldimi */
1322 case ARLDMICC: return OPVCC(30,0,0,1) | (3<<2);
1323
1324 case ARLWNM: return OPVCC(21,0,0,0); /* rlwinm */
1325 case ARLWNMCC: return OPVCC(21,0,0,1);
1326
1327 case ARLDCL: return OPVCC(30,0,0,0); /* rldicl */
1328 case ARLDCLCC: return OPVCC(30,0,0,1);
1329 case ARLDCR: return OPVCC(30,1,0,0); /* rldicr */
1330 case ARLDCRCC: return OPVCC(30,1,0,1);
1331 case ARLDC: return OPVCC(30,0,0,0) | (2<<2);
1332 case ARLDCCC: return OPVCC(30,0,0,1) | (2<<2);
1333
1334 case ASRAW: return OPVCC(31,824,0,0);
1335 case ASRAWCC: return OPVCC(31,824,0,1);
1336 case ASRAD: return OPVCC(31,(413<<1),0,0);
1337 case ASRADCC: return OPVCC(31,(413<<1),0,1);
1338
1339 case ASTSW: return OPVCC(31,725,0,0);
1340
1341 case ASUBC: return OPVCC(8,0,0,0);
1342
1343 case ATW: return OPVCC(3,0,0,0);
1344 case ATD: return OPVCC(2,0,0,0);
1345
1346 case AXOR: return OPVCC(26,0,0,0); /* XORIL */
1347 case AXOR+AEND: return OPVCC(27,0,0,0); /* XORIU */
1348 }
1349 diag("bad opcode i/r %A", a);
1350 return 0;
1351 }
1352
1353 /*
1354 * load o(a),d
1355 */
1356 long
opload(int a)1357 opload(int a)
1358 {
1359 switch(a) {
1360 case AMOVD: return OPVCC(58,0,0,0); /* ld */
1361 case AMOVDU: return OPVCC(58,0,0,1); /* ldu */
1362 case AMOVWZ: return OPVCC(32,0,0,0); /* lwz */
1363 case AMOVWZU: return OPVCC(33,0,0,0); /* lwzu */
1364 case AMOVW: return OPVCC(58,0,0,0)|(1<<1); /* lwa */
1365 /* no AMOVWU */
1366 case AMOVB:
1367 case AMOVBZ: return OPVCC(34,0,0,0); /* load */
1368 case AMOVBU:
1369 case AMOVBZU: return OPVCC(35,0,0,0);
1370 case AFMOVD: return OPVCC(50,0,0,0);
1371 case AFMOVDU: return OPVCC(51,0,0,0);
1372 case AFMOVS: return OPVCC(48,0,0,0);
1373 case AFMOVSU: return OPVCC(49,0,0,0);
1374 case AMOVH: return OPVCC(42,0,0,0);
1375 case AMOVHU: return OPVCC(43,0,0,0);
1376 case AMOVHZ: return OPVCC(40,0,0,0);
1377 case AMOVHZU: return OPVCC(41,0,0,0);
1378 case AMOVMW: return OPVCC(46,0,0,0); /* lmw */
1379 }
1380 diag("bad load opcode %A", a);
1381 return 0;
1382 }
1383
1384 /*
1385 * indexed load a(b),d
1386 */
1387 long
oploadx(int a)1388 oploadx(int a)
1389 {
1390 switch(a) {
1391 case AMOVWZ: return OPVCC(31,23,0,0); /* lwzx */
1392 case AMOVWZU: return OPVCC(31,55,0,0); /* lwzux */
1393 case AMOVW: return OPVCC(31,341,0,0); /* lwax */
1394 case AMOVWU: return OPVCC(31,373,0,0); /* lwaux */
1395 case AMOVB:
1396 case AMOVBZ: return OPVCC(31,87,0,0); /* lbzx */
1397 case AMOVBU:
1398 case AMOVBZU: return OPVCC(31,119,0,0); /* lbzux */
1399 case AFMOVD: return OPVCC(31,599,0,0); /* lfdx */
1400 case AFMOVDU: return OPVCC(31,631,0,0); /* lfdux */
1401 case AFMOVS: return OPVCC(31,535,0,0); /* lfsx */
1402 case AFMOVSU: return OPVCC(31,567,0,0); /* lfsux */
1403 case AMOVH: return OPVCC(31,343,0,0); /* lhax */
1404 case AMOVHU: return OPVCC(31,375,0,0); /* lhaux */
1405 case AMOVHBR: return OPVCC(31,790,0,0); /* lhbrx */
1406 case AMOVWBR: return OPVCC(31,534,0,0); /* lwbrx */
1407 case AMOVHZ: return OPVCC(31,279,0,0); /* lhzx */
1408 case AMOVHZU: return OPVCC(31,311,0,0); /* lhzux */
1409 case AECIWX: return OPVCC(31,310,0,0); /* eciwx */
1410 case ALWAR: return OPVCC(31,20,0,0); /* lwarx */
1411 case ALSW: return OPVCC(31,533,0,0); /* lswx */
1412 case AMOVD: return OPVCC(31,21,0,0); /* ldx */
1413 case AMOVDU: return OPVCC(31,53,0,0); /* ldux */
1414 }
1415 diag("bad loadx opcode %A", a);
1416 return 0;
1417 }
1418
1419 /*
1420 * store s,o(d)
1421 */
1422 long
opstore(int a)1423 opstore(int a)
1424 {
1425 switch(a) {
1426 case AMOVB:
1427 case AMOVBZ: return OPVCC(38,0,0,0); /* stb */
1428 case AMOVBU:
1429 case AMOVBZU: return OPVCC(39,0,0,0); /* stbu */
1430 case AFMOVD: return OPVCC(54,0,0,0); /* stfd */
1431 case AFMOVDU: return OPVCC(55,0,0,0); /* stfdu */
1432 case AFMOVS: return OPVCC(52,0,0,0); /* stfs */
1433 case AFMOVSU: return OPVCC(53,0,0,0); /* stfsu */
1434 case AMOVHZ:
1435 case AMOVH: return OPVCC(44,0,0,0); /* sth */
1436 case AMOVHZU:
1437 case AMOVHU: return OPVCC(45,0,0,0); /* sthu */
1438 case AMOVMW: return OPVCC(47,0,0,0); /* stmw */
1439 case ASTSW: return OPVCC(31,725,0,0); /* stswi */
1440 case AMOVWZ:
1441 case AMOVW: return OPVCC(36,0,0,0); /* stw */
1442 case AMOVWZU:
1443 case AMOVWU: return OPVCC(37,0,0,0); /* stwu */
1444 case AMOVD: return OPVCC(62,0,0,0); /* std */
1445 case AMOVDU: return OPVCC(62,0,0,1); /* stdu */
1446 }
1447 diag("unknown store opcode %A", a);
1448 return 0;
1449 }
1450
1451 /*
1452 * indexed store s,a(b)
1453 */
1454 long
opstorex(int a)1455 opstorex(int a)
1456 {
1457 switch(a) {
1458 case AMOVB:
1459 case AMOVBZ: return OPVCC(31,215,0,0); /* stbx */
1460 case AMOVBU:
1461 case AMOVBZU: return OPVCC(31,247,0,0); /* stbux */
1462 case AFMOVD: return OPVCC(31,727,0,0); /* stfdx */
1463 case AFMOVDU: return OPVCC(31,759,0,0); /* stfdux */
1464 case AFMOVS: return OPVCC(31,663,0,0); /* stfsx */
1465 case AFMOVSU: return OPVCC(31,695,0,0); /* stfsux */
1466 case AMOVHZ:
1467 case AMOVH: return OPVCC(31,407,0,0); /* sthx */
1468 case AMOVHBR: return OPVCC(31,918,0,0); /* sthbrx */
1469 case AMOVHZU:
1470 case AMOVHU: return OPVCC(31,439,0,0); /* sthux */
1471 case AMOVWZ:
1472 case AMOVW: return OPVCC(31,151,0,0); /* stwx */
1473 case AMOVWZU:
1474 case AMOVWU: return OPVCC(31,183,0,0); /* stwux */
1475 case ASTSW: return OPVCC(31,661,0,0); /* stswx */
1476 case AMOVWBR: return OPVCC(31,662,0,0); /* stwbrx */
1477 case ASTWCCC: return OPVCC(31,150,0,1); /* stwcx. */
1478 case ASTDCCC: return OPVCC(31,214,0,1); /* stwdx. */
1479 case AECOWX: return OPVCC(31,438,0,0); /* ecowx */
1480 case AMOVD: return OPVCC(31,149,0,0); /* stdx */
1481 case AMOVDU: return OPVCC(31,181,0,0); /* stdux */
1482 }
1483 diag("unknown storex opcode %A", a);
1484 return 0;
1485 }
1486