xref: /inferno-os/utils/ql/asmout.c (revision 06155dbb53eb0585800b239acd6e45b946c6e0cf)
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 }
1386