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