xref: /plan9-contrib/sys/src/cmd/9l/asmout.c (revision fbadb1c4d4463e58337ffb1ed396c9caee5d1889)
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