xref: /plan9/sys/src/cmd/ql/asmout.c (revision 9b943567965ba040fd275927fbe088656eb8ce4f)
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 int
85 asmout(Prog *p, Optab *o, int aflag)
86 {
87 	long o1, o2, o3, o4, o5, v;
88 	Prog *ct;
89 	int r, a;
90 	uchar mask[2];
91 
92 	o1 = 0;
93 	o2 = 0;
94 	o3 = 0;
95 	o4 = 0;
96 	o5 = 0;
97 	switch(o->type) {
98 	default:
99 		if(aflag)
100 			return 0;
101 		diag("unknown type %d", o->type);
102 		if(!debug['a'])
103 			prasm(p);
104 		break;
105 
106 	case 0:		/* pseudo ops */
107 		if(aflag) {
108 			if(p->link) {
109 				if(p->as == ATEXT) {
110 					ct = curtext;
111 					o2 = autosize;
112 					curtext = p;
113 					autosize = p->to.offset + 4;
114 					o1 = asmout(p->link, oplook(p->link), aflag);
115 					curtext = ct;
116 					autosize = o2;
117 				} else
118 					o1 = asmout(p->link, oplook(p->link), aflag);
119 			}
120 			return o1;
121 		}
122 		break;
123 
124 	case 1:		/* mov r1,r2 ==> OR Rs,Rs,Ra */
125 		o1 = LOP_RRR(OP_OR, p->to.reg, p->from.reg, p->from.reg);
126 		break;
127 
128 	case 2:		/* int/cr/fp op Rb,[Ra],Rd */
129 		r = p->reg;
130 		if(r == NREG)
131 			r = p->to.reg;
132 		o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);
133 		break;
134 
135 	case 3:		/* mov $soreg/addcon/ucon, r ==> addis/addi $i,reg',r */
136 		v = regoff(&p->from);
137 		r = p->from.reg;
138 		if(r == NREG)
139 			r = o->param;
140 		a = OP_ADDI;
141 		if(o->a1 == C_UCON) {
142 			a = OP_ADDIS;
143 			v >>= 16;
144 		}
145 		o1 = AOP_IRR(a, p->to.reg, r, v);
146 		break;
147 
148 	case 4:		/* add/mul $scon,[r1],r2 */
149 		v = regoff(&p->from);
150 		r = p->reg;
151 		if(r == NREG)
152 			r = p->to.reg;
153 		else if(p->as == AADD && r == 0)
154 			diag("literal operation on R0\n%P", p);
155 		o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);
156 		break;
157 
158 	case 5:		/* syscall */
159 		if(aflag)
160 			return 0;
161 		o1 = oprrr(p->as);
162 		break;
163 
164 	case 6:		/* logical op Rb,[Rs,]Ra; no literal */
165 		r = p->reg;
166 		if(r == NREG)
167 			r = p->to.reg;
168 		o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, p->from.reg);
169 		break;
170 
171 	case 7:		/* mov r, soreg ==> stw o(r) */
172 		r = p->to.reg;
173 		if(r == NREG)
174 			r = o->param;
175 		v = regoff(&p->to);
176 		if(p->to.type == D_OREG && p->reg != NREG) {
177 			if(v)
178 				diag("illegal indexed instruction\n%P", p);
179 			o1 = AOP_RRR(opstorex(p->as), p->from.reg, p->reg, r);
180 		} else
181 			o1 = AOP_IRR(opstore(p->as), p->from.reg, r, v);
182 		break;
183 
184 	case 8:		/* mov soreg, r ==> lbz/lhz/lwz o(r) */
185 		r = p->from.reg;
186 		if(r == NREG)
187 			r = o->param;
188 		v = regoff(&p->from);
189 		if(p->from.type == D_OREG && p->reg != NREG) {
190 			if(v)
191 				diag("illegal indexed instruction\n%P", p);
192 			o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);
193 		} else
194 			o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);
195 		break;
196 
197 	case 9:		/* movb soreg, r ==> lbz o(r),r2; extsb r2,r2 */
198 		r = p->from.reg;
199 		if(r == NREG)
200 			r = o->param;
201 		v = regoff(&p->from);
202 		if(p->from.type == D_OREG && p->reg != NREG) {
203 			if(v)
204 				diag("illegal indexed instruction\n%P", p);
205 			o1 = AOP_RRR(oploadx(p->as), p->to.reg, p->reg, r);
206 		} else
207 			o1 = AOP_IRR(opload(p->as), p->to.reg, r, v);
208 		o2 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
209 		break;
210 
211 	case 10:		/* sub Ra,[Rb],Rd => subf Rd,Ra,Rb */
212 		r = p->reg;
213 		if(r == NREG)
214 			r = p->to.reg;
215 		o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, r);
216 		break;
217 
218 	case 11:	/* br/bl lbra */
219 		if(aflag)
220 			return 0;
221 		v = 0;
222 		if(p->cond)
223 			v = p->cond->pc - p->pc;
224 		if(v & 03) {
225 			diag("odd branch target address\n%P", p);
226 			v &= ~03;
227 		}
228 		if(v < -(1L<<25) || v >= (1L<<25))
229 			diag("branch too far\n%P", p);
230 		o1 = OP_BR(opirr(p->as), v, 0);
231 		break;
232 
233 	case 12:	/* movb r,r (signed); extsb is on PowerPC but not POWER */
234 		o1 = LOP_RRR(OP_EXTSB, p->to.reg, p->from.reg, 0);
235 		break;
236 
237 	case 13:	/* mov[bh]z r,r; uses rlwinm not andi. to avoid changing CC */
238 		if(p->as == AMOVBZ)
239 			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 24, 31);
240 		else if(p->as == AMOVH)
241 			o1 = LOP_RRR(OP_EXTSH, p->to.reg, p->from.reg, 0);
242 		else if(p->as == AMOVHZ)
243 			o1 = OP_RLW(OP_RLWINM, p->to.reg, p->from.reg, 0, 16, 31);
244 		else
245 			diag("internal: bad mov[bh]z\n%P", p);
246 		break;
247 
248 /*14 */
249 
250 	case 17:	/* bc bo,bi,lbra (same for now) */
251 	case 16:	/* bc bo,bi,sbra */
252 		if(aflag)
253 			return 0;
254 		a = 0;
255 		if(p->from.type == D_CONST)
256 			a = regoff(&p->from);
257 		r = p->reg;
258 		if(r == NREG)
259 			r = 0;
260 		v = 0;
261 		if(p->cond)
262 			v = p->cond->pc - p->pc;
263 		if(v & 03) {
264 			diag("odd branch target address\n%P", p);
265 			v &= ~03;
266 		}
267 		if(v < -(1L<<16) || v >= (1L<<16))
268 			diag("branch too far\n%P", p);
269 		o1 = OP_BC(opirr(p->as), a, r, v, 0);
270 		break;
271 
272 	case 15:	/* br/bl (r) => mov r,lr; br/bl (lr) */
273 		if(aflag)
274 			return 0;
275 		if(p->as == ABC || p->as == ABCL)
276 			v = regoff(&p->to)&31L;
277 		else
278 			v = 20;	/* unconditional */
279 		r = p->reg;
280 		if(r == NREG)
281 			r = 0;
282 		o1 = AOP_RRR(OP_MTSPR, p->to.reg, 0, 0) | ((D_LR&0x1f)<<16) | (((D_LR>>5)&0x1f)<<11);
283 		o2 = OPVCC(19, 16, 0, 0);
284 		if(p->as == ABL || p->as == ABCL)
285 			o2 |= 1;
286 		o2 = OP_BCR(o2, v, r);
287 		break;
288 
289 	case 18:	/* br/bl (lr/ctr); bc/bcl bo,bi,(lr/ctr) */
290 		if(aflag)
291 			return 0;
292 		if(p->as == ABC || p->as == ABCL)
293 			v = regoff(&p->from)&31L;
294 		else
295 			v = 20;	/* unconditional */
296 		r = p->reg;
297 		if(r == NREG)
298 			r = 0;
299 		switch(oclass(p->to)) {
300 		case C_CTR:
301 			o1 = OPVCC(19, 528, 0, 0);
302 			break;
303 		case C_LR:
304 			o1 = OPVCC(19, 16, 0, 0);
305 			break;
306 		default:
307 			diag("bad optab entry (18): %d\n%P", p->to.class, p);
308 			v = 0;
309 		}
310 		if(p->as == ABL || p->as == ABCL)
311 			o1 |= 1;
312 		o1 = OP_BCR(o1, v, r);
313 		break;
314 
315 	case 19:	/* mov $lcon,r ==> cau+or */
316 		v = regoff(&p->from);
317 		o1 = AOP_IRR(OP_ADDIS, p->to.reg, REGZERO, v>>16);
318 		o2 = LOP_IRR(OP_ORI, p->to.reg, p->to.reg, v);
319 		break;
320 
321 	case 20:	/* add $ucon,,r */
322 		v = regoff(&p->from);
323 		r = p->reg;
324 		if(r == NREG)
325 			r = p->to.reg;
326 		if(p->as == AADD && r == 0)
327 			diag("literal operation on R0\n%P", p);
328 		o1 = AOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16);
329 		break;
330 
331 	case 22:	/* add $lcon,r1,r2 ==> cau+or+add */	/* could do add/sub more efficiently */
332 		v = regoff(&p->from);
333 		if(p->to.reg == REGTMP || p->reg == REGTMP)
334 			diag("cant synthesize large constant\n%P", p);
335 		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
336 		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
337 		r = p->reg;
338 		if(r == NREG)
339 			r = p->to.reg;
340 		o3 = AOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);
341 		break;
342 
343 	case 23:	/* and $lcon,r1,r2 ==> cau+or+and */	/* masks could be done using rlnm etc. */
344 		v = regoff(&p->from);
345 		if(p->to.reg == REGTMP || p->reg == REGTMP)
346 			diag("cant synthesize large constant\n%P", p);
347 		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
348 		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
349 		r = p->reg;
350 		if(r == NREG)
351 			r = p->to.reg;
352 		o3 = LOP_RRR(oprrr(p->as), p->to.reg, REGTMP, r);
353 		break;
354 /*24*/
355 
356 	case 26:	/* mov $lsext/auto/oreg,,r2 ==> cau+add */
357 		v = regoff(&p->from);
358 		if(v & 0x8000L)
359 			v += 0x10000L;
360 		if(p->to.reg == REGTMP)
361 			diag("can't synthesize large constant\n%P", p);
362 		r = p->from.reg;
363 		if(r == NREG)
364 			r = o->param;
365 		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
366 		o2 = AOP_IRR(OP_ADDI, p->to.reg, REGTMP, v);
367 		break;
368 
369 	case 27:		/* subc ra,$simm,rd => subfic rd,ra,$simm */
370 		v = regoff(&p->from3);
371 		r = p->from.reg;
372 		o1 = AOP_IRR(opirr(p->as), p->to.reg, r, v);
373 		break;
374 
375 	case 28:	/* subc r1,$lcon,r2 ==> cau+or+subfc */
376 		v = regoff(&p->from3);
377 		if(p->to.reg == REGTMP || p->from.reg == REGTMP)
378 			diag("can't synthesize large constant\n%P", p);
379 		o1 = AOP_IRR(OP_ADDIS, REGTMP, REGZERO, v>>16);
380 		o2 = LOP_IRR(OP_ORI, REGTMP, REGTMP, v);
381 		o3 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, REGTMP);
382 		break;
383 
384 /*29, 30, 31 */
385 
386 	case 32:	/* fmul frc,fra,frd */
387 		r = p->reg;
388 		if(r == NREG)
389 			r = p->to.reg;
390 		o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, 0)|((p->from.reg&31L)<<6);
391 		break;
392 
393 	case 33:	/* fabs [frb,]frd; fmr. frb,frd */
394 		r = p->from.reg;
395 		if(oclass(p->from) == C_NONE)
396 			r = p->to.reg;
397 		o1 = AOP_RRR(oprrr(p->as), p->to.reg, 0, r);
398 		break;
399 
400 	case 34:	/* FMADDx fra,frb,frc,frd (d=a*b+c) */
401 		o1 = AOP_RRR(oprrr(p->as), p->to.reg, p->from.reg, p->reg)|((p->from3.reg&31L)<<6);
402 		break;
403 
404 	case 35:	/* mov r,lext/lauto/loreg ==> cau $(v>>16),sb,r'; store o(r') */
405 		v = regoff(&p->to);
406 		if(v & 0x8000L)
407 			v += 0x10000L;
408 		r = p->to.reg;
409 		if(r == NREG)
410 			r = o->param;
411 		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
412 		o2 = AOP_IRR(opstore(p->as), p->from.reg, REGTMP, v);
413 		break;
414 
415 	case 36:	/* mov bz/h/hz lext/lauto/lreg,r ==> lbz/lha/lhz etc */
416 		v = regoff(&p->from);
417 		if(v & 0x8000L)
418 			v += 0x10000L;
419 		r = p->from.reg;
420 		if(r == NREG)
421 			r = o->param;
422 		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
423 		o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
424 		break;
425 
426 	case 37:	/* movb lext/lauto/lreg,r ==> lbz o(reg),r; extsb r */
427 		v = regoff(&p->from);
428 		if(v & 0x8000L)
429 			v += 0x10000L;
430 		r = p->from.reg;
431 		if(r == NREG)
432 			r = o->param;
433 		o1 = AOP_IRR(OP_ADDIS, REGTMP, r, v>>16);
434 		o2 = AOP_IRR(opload(p->as), p->to.reg, REGTMP, v);
435 		o3 = LOP_RRR(OP_EXTSB, p->to.reg, p->to.reg, 0);
436 		break;
437 
438 	case 40:	/* word */
439 		if(aflag)
440 			return 0;
441 		o1 = regoff(&p->from);
442 		break;
443 
444 	case 41:	/* stswi */
445 		o1 = AOP_RRR(opirr(p->as), p->from.reg, p->to.reg, 0) | ((regoff(&p->from3)&0x7F)<<11);
446 		break;
447 
448 	case 42:	/* lswi */
449 		o1 = AOP_RRR(opirr(p->as), p->to.reg, p->from.reg, 0) | ((regoff(&p->from3)&0x7F)<<11);
450 		break;
451 
452 	case 43:	/* unary indexed source: dcbf (b); dcbf (a+b) */
453 		r = p->reg;
454 		if(r == NREG)
455 			r = 0;
456 		o1 = AOP_RRR(oprrr(p->as), 0, r, p->from.reg);
457 		break;
458 
459 	case 44:	/* indexed store */
460 		r = p->reg;
461 		if(r == NREG)
462 			r = 0;
463 		o1 = AOP_RRR(opstorex(p->as), p->from.reg, r, p->to.reg);
464 		break;
465 	case 45:	/* indexed load */
466 		r = p->reg;
467 		if(r == NREG)
468 			r = 0;
469 		o1 = AOP_RRR(oploadx(p->as), p->to.reg, r, p->from.reg);
470 		break;
471 
472 	case 46:	/* plain op */
473 		o1 = oprrr(p->as);
474 		break;
475 
476 	case 47:	/* op Ra, Rd; also op [Ra,] Rd */
477 		r = p->from.reg;
478 		if(r == NREG)
479 			r = p->to.reg;
480 		o1 = AOP_RRR(oprrr(p->as), p->to.reg, r, 0);
481 		break;
482 
483 	case 48:	/* op Rs, Ra */
484 		r = p->from.reg;
485 		if(r == NREG)
486 			r = p->to.reg;
487 		o1 = LOP_RRR(oprrr(p->as), p->to.reg, r, 0);
488 		break;
489 
490 	case 49:	/* op Rb */
491 		o1 = AOP_RRR(oprrr(p->as), 0, 0, p->from.reg);
492 		break;
493 
494 /*50*/
495 
496 	case 51:	/* rem[u] r1[,r2],r3 */
497 		r = p->reg;
498 		if(r == NREG)
499 			r = p->to.reg;
500 		o1 = AOP_RRR(oprrr(p->as), REGTMP, r, p->from.reg);
501 		o2 = AOP_RRR(OP_MULLW, REGTMP, REGTMP, p->from.reg);
502 		o3 = AOP_RRR(OP_SUBF, p->to.reg, REGTMP, r);	/* BUG: check V, CC */
503 		break;
504 
505 	case 52:	/* mtfsbNx cr(n) */
506 		v = regoff(&p->from)&31L;
507 		o1 = AOP_RRR(oprrr(p->as), v, 0, 0);
508 		break;
509 
510 	case 53:	/* mffsX ,fr1 */
511 		o1 = AOP_RRR(OP_MFFS, p->to.reg, 0, 0);
512 		break;
513 
514 	case 54:	/* mov msr,r1; mov r1, msr*/
515 		if(oclass(p->from) == C_REG)
516 			o1 = AOP_RRR(OP_MTMSR, p->from.reg, 0, 0);
517 		else
518 			o1 = AOP_RRR(OP_MFMSR, p->to.reg, 0, 0);
519 		break;
520 
521 	case 55:	/* mov sreg,r1; mov r1,sreg */
522 		v = 0;
523 		if(p->from.type == D_SREG) {
524 			r = p->from.reg;
525 			o1 = OP_MFSR;
526 			if(r == NREG && p->reg != NREG) {
527 				r = 0;
528 				v = p->reg;
529 				o1 = OP_MFSRIN;
530 			}
531 			o1 = AOP_RRR(o1, p->to.reg, r&15L, v);
532 		} else {
533 			r = p->to.reg;
534 			o1 = OP_MTSR;
535 			if(r == NREG && p->reg != NREG) {
536 				r = 0;
537 				v = p->reg;
538 				o1 = OP_MTSRIN;
539 			}
540 			o1 = AOP_RRR(o1, p->from.reg, r&15L, v);
541 		}
542 		if(r == NREG)
543 			diag("illegal move indirect to/from segment register\n%P", p);
544 		break;
545 
546 	case 56:	/* sra $sh,[s,]a */
547 		v = regoff(&p->from);
548 		r = p->reg;
549 		if(r == NREG)
550 			r = p->to.reg;
551 		o1 = AOP_RRR(opirr(p->as), r, p->to.reg, v&31L);
552 		break;
553 
554 	case 57:	/* slw $sh,[s,]a -> rlwinm ... */
555 		v = regoff(&p->from);
556 		r = p->reg;
557 		if(r == NREG)
558 			r = p->to.reg;
559 		if(p->as == ASRW || p->as == ASRWCC) {	/* shift right */
560 			mask[0] = v;
561 			mask[1] = 31;
562 			v = 32-v;
563 		} else {
564 			mask[0] = 0;
565 			mask[1] = 31-v;
566 		}
567 		o1 = OP_RLW(OP_RLWINM, p->to.reg, r, v, mask[0], mask[1]);
568 		if(p->as == ASLWCC || p->as == ASRWCC)
569 			o1 |= 1;	/* Rc */
570 		break;
571 
572 	case 58:		/* logical $andcon,[s],a */
573 		v = regoff(&p->from);
574 		r = p->reg;
575 		if(r == NREG)
576 			r = p->to.reg;
577 		o1 = LOP_IRR(opirr(p->as), p->to.reg, r, v);
578 		break;
579 
580 	case 59:	/* or/and $ucon,,r */
581 		v = regoff(&p->from);
582 		r = p->reg;
583 		if(r == NREG)
584 			r = p->to.reg;
585 		o1 = LOP_IRR(opirr(p->as+AEND), p->to.reg, r, v>>16);	/* oris, xoris, andis */
586 		break;
587 
588 	case 60:	/* tw to,a,b */
589 		r = regoff(&p->from)&31L;
590 		o1 = AOP_RRR(oprrr(p->as), r, p->reg, p->to.reg);
591 		break;
592 
593 	case 61:	/* tw to,a,$simm */
594 		r = regoff(&p->from)&31L;
595 		v = regoff(&p->to);
596 		o1 = AOP_IRR(opirr(p->as), r, p->reg, v);
597 		break;
598 
599 	case 62:	/* rlwmi $sh,s,$mask,a */
600 		v = regoff(&p->from);
601 		maskgen(p, mask, regoff(&p->from3));
602 		o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, v);
603 		o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
604 		break;
605 
606 	case 63:	/* rlwmi b,s,$mask,a */
607 		maskgen(p, mask, regoff(&p->from3));
608 		o1 = AOP_RRR(opirr(p->as), p->reg, p->to.reg, p->from.reg);
609 		o1 |= ((mask[0]&31L)<<6)|((mask[1]&31L)<<1);
610 		break;
611 
612 	case 64:	/* mtfsf fr[, $m] {,fpcsr} */
613 		if(p->from3.type != D_NONE)
614 			v = regoff(&p->from3)&255L;
615 		else
616 			v = 255;
617 		o1 = OP_MTFSF | (v<<17) | (p->from.reg<<11);
618 		break;
619 
620 	case 65:	/* MOVFL $imm,FPSCR(n) => mtfsfi crfd,imm */
621 		if(p->to.reg == NREG)
622 			diag("must specify FPSCR(n)\n%P", p);
623 		o1 = OP_MTFSFI | ((p->to.reg&15L)<<23) | ((regoff(&p->from)&31L)<<12);
624 		break;
625 
626 	case 66:	/* mov spr,r1; mov r1,spr */
627 		if(p->from.type == D_REG) {
628 			r = p->from.reg;
629 			v = p->to.offset;
630 			o1 = OPVCC(31,467,0,0); /* mtspr */
631 		} else {
632 			r = p->to.reg;
633 			v = p->from.offset;
634 			o1 = OPVCC(31,339,0,0);	/* mfspr */
635 		}
636 		o1 = AOP_RRR(o1, r, 0, 0) | ((v&0x1f)<<16) | (((v>>5)&0x1f)<<11);
637 		break;
638 
639 	case 67:	/* mcrf crfD,crfS */
640 		if(p->from.type != D_CREG || p->from.reg == NREG ||
641 		   p->to.type != D_CREG || p->to.reg == NREG)
642 			diag("illegal CR field number\n%P", p);
643 		o1 = AOP_RRR(OP_MCRF, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
644 		break;
645 
646 	case 68:	/* mfcr rD */
647 		if(p->from.type == D_CREG && p->from.reg != NREG)
648 			diag("must move whole CR to register\n%P", p);
649 		o1 = AOP_RRR(OP_MFCR, p->to.reg, 0, 0);
650 		break;
651 
652 	case 69:	/* mtcrf CRM,rS */
653 		if(p->from3.type != D_NONE) {
654 			if(p->to.reg != NREG)
655 				diag("can't use both mask and CR(n)\n%P", p);
656 			v = regoff(&p->from3) & 0xff;
657 		} else {
658 			if(p->to.reg == NREG)
659 				v = 0xff;	/* CR */
660 			else
661 				v = 1<<(7-(p->to.reg&7));	/* CR(n) */
662 		}
663 		o1 = AOP_RRR(OP_MTCRF, p->from.reg, 0, 0) | (v<<12);
664 		break;
665 
666 	case 70:	/* [f]cmp r,r,cr*/
667 		if(p->reg == NREG)
668 			r = 0;
669 		else
670 			r = (p->reg&7)<<2;
671 		o1 = AOP_RRR(oprrr(p->as), r, p->from.reg, p->to.reg);
672 		break;
673 
674 	case 71:	/* cmp[l] r,i,cr*/
675 		if(p->reg == NREG)
676 			r = 0;
677 		else
678 			r = (p->reg&7)<<2;
679 		o1 = AOP_RRR(opirr(p->as), r, p->from.reg, 0) | (regoff(&p->to)&0xffff);
680 		break;
681 
682 	case 72:	/* mcrxr crfD */
683 		if(p->to.reg == NREG)
684 			diag("must move XER to CR(n)\n%P", p);
685 		o1 = AOP_RRR(OP_MCRXR, ((p->to.reg&7L)<<2), 0, 0);
686 		break;
687 
688 	case 73:	/* mcrfs crfD,crfS */
689 		if(p->from.type != D_FPSCR || p->from.reg == NREG ||
690 		   p->to.type != D_CREG || p->to.reg == NREG)
691 			diag("illegal FPSCR/CR field number\n%P", p);
692 		o1 = AOP_RRR(OP_MCRFS, ((p->to.reg&7L)<<2), ((p->from.reg&7)<<2), 0);
693 		break;
694 
695 	}
696 	if(aflag)
697 		return o1;
698 	v = p->pc;
699 	switch(o->size) {
700 	default:
701 		if(debug['a'])
702 			Bprint(&bso, " %.8lux:\t\t%P\n", v, p);
703 		break;
704 	case 4:
705 		if(debug['a'])
706 			Bprint(&bso, " %.8lux: %.8lux\t%P\n", v, o1, p);
707 		lput(o1);
708 		break;
709 	case 8:
710 		if(debug['a'])
711 			Bprint(&bso, " %.8lux: %.8lux %.8lux%P\n", v, o1, o2, p);
712 		lput(o1);
713 		lput(o2);
714 		break;
715 	case 12:
716 		if(debug['a'])
717 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux%P\n", v, o1, o2, o3, p);
718 		lput(o1);
719 		lput(o2);
720 		lput(o3);
721 		break;
722 	case 16:
723 		if(debug['a'])
724 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux%P\n",
725 				v, o1, o2, o3, o4, p);
726 		lput(o1);
727 		lput(o2);
728 		lput(o3);
729 		lput(o4);
730 		break;
731 	case 20:
732 		if(debug['a'])
733 			Bprint(&bso, " %.8lux: %.8lux %.8lux %.8lux %.8lux %.8lux%P\n",
734 				v, o1, o2, o3, o4, o5, p);
735 		lput(o1);
736 		lput(o2);
737 		lput(o3);
738 		lput(o4);
739 		lput(o5);
740 		break;
741 	}
742 	return 0;
743 }
744 
745 long
746 oprrr(int a)
747 {
748 	switch(a) {
749 	case AADD:	return OPVCC(31,266,0,0);
750 	case AADDCC:	return OPVCC(31,266,0,1);
751 	case AADDV:	return OPVCC(31,266,1,0);
752 	case AADDVCC:	return OPVCC(31,266,1,1);
753 	case AADDC:	return OPVCC(31,10,0,0);
754 	case AADDCCC:	return OPVCC(31,10,0,1);
755 	case AADDCV:	return OPVCC(31,10,1,0);
756 	case AADDCVCC:	return OPVCC(31,10,1,1);
757 	case AADDE:	return OPVCC(31,138,0,0);
758 	case AADDECC:	return OPVCC(31,138,0,1);
759 	case AADDEV:	return OPVCC(31,138,1,0);
760 	case AADDEVCC:	return OPVCC(31,138,1,1);
761 	case AADDME:	return OPVCC(31,234,0,0);
762 	case AADDMECC:	return OPVCC(31,234,0,1);
763 	case AADDMEV:	return OPVCC(31,234,1,0);
764 	case AADDMEVCC:	return OPVCC(31,234,1,1);
765 	case AADDZE:	return OPVCC(31,202,0,0);
766 	case AADDZECC:	return OPVCC(31,202,0,1);
767 	case AADDZEV:	return OPVCC(31,202,1,0);
768 	case AADDZEVCC:	return OPVCC(31,202,1,1);
769 
770 	case AAND:	return OPVCC(31,28,0,0);
771 	case AANDCC:	return OPVCC(31,28,0,1);
772 	case AANDN:	return OPVCC(31,60,0,0);
773 	case AANDNCC:	return OPVCC(31,60,0,1);
774 
775 	case ACMP:	return OPVCC(31,0,0,0);
776 	case ACMPU:	return OPVCC(31,32,0,0);
777 
778 	case ACNTLZW:	return OPVCC(31,26,0,0);
779 	case ACNTLZWCC:	return OPVCC(31,26,0,1);
780 
781 	case ACRAND:	return OPVCC(19,257,0,0);
782 	case ACRANDN:	return OPVCC(19,129,0,0);
783 	case ACREQV:	return OPVCC(19,289,0,0);
784 	case ACRNAND:	return OPVCC(19,225,0,0);
785 	case ACRNOR:	return OPVCC(19,33,0,0);
786 	case ACROR:	return OPVCC(19,449,0,0);
787 	case ACRORN:	return OPVCC(19,417,0,0);
788 	case ACRXOR:	return OPVCC(19,193,0,0);
789 
790 	case ADCBF:	return OPVCC(31,86,0,0);
791 	case ADCBI:	return OPVCC(31,470,0,0);
792 	case ADCBST:	return OPVCC(31,54,0,0);
793 	case ADCBT:	return OPVCC(31,278,0,0);
794 	case ADCBTST:	return OPVCC(31,246,0,0);
795 	case ADCBZ:	return OPVCC(31,1014,0,0);
796 
797 	case AREM:
798 	case ADIVW:	return OPVCC(31,491,0,0);
799 	case AREMCC:
800 	case ADIVWCC:	return OPVCC(31,491,0,1);
801 	case AREMV:
802 	case ADIVWV:	return OPVCC(31,491,1,0);
803 	case AREMVCC:
804 	case ADIVWVCC:	return OPVCC(31,491,1,1);
805 	case AREMU:
806 	case ADIVWU:	return OPVCC(31,459,0,0);
807 	case AREMUCC:
808 	case ADIVWUCC:	return OPVCC(31,459,0,1);
809 	case AREMUV:
810 	case ADIVWUV:	return OPVCC(31,459,1,0);
811 	case AREMUVCC:
812 	case ADIVWUVCC:	return OPVCC(31,459,1,1);
813 
814 	case AEIEIO:	return OPVCC(31,854,0,0);
815 
816 	case AEQV:	return OPVCC(31,284,0,0);
817 	case AEQVCC:	return OPVCC(31,284,0,1);
818 
819 	case AEXTSB:	return OPVCC(31,954,0,0);
820 	case AEXTSBCC:	return OPVCC(31,954,0,1);
821 	case AEXTSH:	return OPVCC(31,922,0,0);
822 	case AEXTSHCC:	return OPVCC(31,922,0,1);
823 
824 	case AFABS:	return OPVCC(63,264,0,0);
825 	case AFABSCC:	return OPVCC(63,264,0,1);
826 	case AFADD:	return OPVCC(63,21,0,0);
827 	case AFADDCC:	return OPVCC(63,21,0,1);
828 	case AFADDS:	return OPVCC(59,21,0,0);
829 	case AFADDSCC:	return OPVCC(59,21,0,1);
830 	case AFCMPO:	return OPVCC(63,32,0,0);
831 	case AFCMPU:	return OPVCC(63,0,0,0);
832 	case AFCTIW:	return OPVCC(63,14,0,0);
833 	case AFCTIWCC:	return OPVCC(63,14,0,1);
834 	case AFCTIWZ:	return OPVCC(63,15,0,0);
835 	case AFCTIWZCC:	return OPVCC(63,15,0,1);
836 	case AFDIV:	return OPVCC(63,18,0,0);
837 	case AFDIVCC:	return OPVCC(63,18,0,1);
838 	case AFDIVS:	return OPVCC(59,18,0,0);
839 	case AFDIVSCC:	return OPVCC(59,18,0,1);
840 	case AFMADD:	return OPVCC(63,29,0,0);
841 	case AFMADDCC:	return OPVCC(63,29,0,1);
842 	case AFMADDS:	return OPVCC(59,29,0,0);
843 	case AFMADDSCC:	return OPVCC(59,29,0,1);
844 	case AFMOVS:
845 	case AFMOVD:	return OPVCC(63,72,0,0);	/* load */
846 	case AFMOVDCC:	return OPVCC(63,72,0,1);
847 	case AFMSUB:	return OPVCC(63,28,0,0);
848 	case AFMSUBCC:	return OPVCC(63,28,0,1);
849 	case AFMSUBS:	return OPVCC(59,28,0,0);
850 	case AFMSUBSCC:	return OPVCC(59,28,0,1);
851 	case AFMUL:	return OPVCC(63,25,0,0);
852 	case AFMULCC:	return OPVCC(63,25,0,1);
853 	case AFMULS:	return OPVCC(59,25,0,0);
854 	case AFMULSCC:	return OPVCC(59,25,0,1);
855 	case AFNABS:	return OPVCC(63,136,0,0);
856 	case AFNABSCC:	return OPVCC(63,136,0,1);
857 	case AFNEG:	return OPVCC(63,40,0,0);
858 	case AFNEGCC:	return OPVCC(63,40,0,1);
859 	case AFNMADD:	return OPVCC(63,31,0,0);
860 	case AFNMADDCC:	return OPVCC(63,31,0,1);
861 	case AFNMADDS:	return OPVCC(59,31,0,0);
862 	case AFNMADDSCC:	return OPVCC(59,31,0,1);
863 	case AFNMSUB:	return OPVCC(63,30,0,0);
864 	case AFNMSUBCC:	return OPVCC(63,30,0,1);
865 	case AFNMSUBS:	return OPVCC(59,30,0,0);
866 	case AFNMSUBSCC:	return OPVCC(59,30,0,1);
867 	case AFRSP:	return OPVCC(63,12,0,0);
868 	case AFRSPCC:	return OPVCC(63,12,0,1);
869 	case AFSUB:	return OPVCC(63,20,0,0);
870 	case AFSUBCC:	return OPVCC(63,20,0,1);
871 	case AFSUBS:	return OPVCC(59,20,0,0);
872 	case AFSUBSCC:	return OPVCC(59,20,0,1);
873 
874 	case AICBI:	return OPVCC(31,982,0,0);
875 	case AISYNC:	return OPVCC(19,150,0,0);
876 
877 	/* lscb etc are not PowerPC instructions */
878 
879 	case AMTFSB0:	return OPVCC(63,70,0,0);
880 	case AMTFSB0CC:	return OPVCC(63,70,0,1);
881 	case AMTFSB1:	return OPVCC(63,38,0,0);
882 	case AMTFSB1CC:	return OPVCC(63,38,0,1);
883 
884 	case AMULHW:	return OPVCC(31,75,0,0);
885 	case AMULHWCC:	return OPVCC(31,75,0,1);
886 	case AMULHWU:	return OPVCC(31,11,0,0);
887 	case AMULHWUCC:	return OPVCC(31,11,0,1);
888 	case AMULLW:	return OPVCC(31,235,0,0);
889 	case AMULLWCC:	return OPVCC(31,235,0,1);
890 	case AMULLWV:	return OPVCC(31,235,1,0);
891 	case AMULLWVCC:	return OPVCC(31,235,1,1);
892 
893 	case ANAND:	return OPVCC(31,476,0,0);
894 	case ANANDCC:	return OPVCC(31,476,0,1);
895 	case ANEG:	return OPVCC(31,104,0,0);
896 	case ANEGCC:	return OPVCC(31,104,0,1);
897 	case ANEGV:	return OPVCC(31,104,1,0);
898 	case ANEGVCC:	return OPVCC(31,104,1,1);
899 	case ANOR:	return OPVCC(31,124,0,0);
900 	case ANORCC:	return OPVCC(31,124,0,1);
901 	case AOR:	return OPVCC(31,444,0,0);
902 	case AORCC:	return OPVCC(31,444,0,1);
903 	case AORN:	return OPVCC(31,412,0,0);
904 	case AORNCC:	return OPVCC(31,412,0,1);
905 
906 	case ARFI:	return OPVCC(19,50,0,0);
907 
908 	case ARLWMI:	return OPVCC(20,0,0,0);
909 	case ARLWMICC: return OPVCC(20,0,0,1);
910 	case ARLWNM:	return OPVCC(23,0,0,0);
911 	case ARLWNMCC:	return OPVCC(23,0,0,1);
912 
913 	case ASYSCALL:	return OPVCC(17,1,0,0);
914 
915 	case ASLW:	return OPVCC(31,24,0,0);
916 	case ASLWCC:	return OPVCC(31,24,0,1);
917 
918 	case ASRAW:	return OPVCC(31,792,0,0);
919 	case ASRAWCC:	return OPVCC(31,792,0,1);
920 
921 	case ASRW:	return OPVCC(31,536,0,0);
922 	case ASRWCC:	return OPVCC(31,536,0,1);
923 
924 	case ASUB:	return OPVCC(31,40,0,0);
925 	case ASUBCC:	return OPVCC(31,40,0,1);
926 	case ASUBV:	return OPVCC(31,40,1,0);
927 	case ASUBVCC:	return OPVCC(31,40,1,1);
928 	case ASUBC:	return OPVCC(31,8,0,0);
929 	case ASUBCCC:	return OPVCC(31,8,0,1);
930 	case ASUBCV:	return OPVCC(31,8,1,0);
931 	case ASUBCVCC:	return OPVCC(31,8,1,1);
932 	case ASUBE:	return OPVCC(31,136,0,0);
933 	case ASUBECC:	return OPVCC(31,136,0,1);
934 	case ASUBEV:	return OPVCC(31,136,1,0);
935 	case ASUBEVCC:	return OPVCC(31,136,1,1);
936 	case ASUBME:	return OPVCC(31,232,0,0);
937 	case ASUBMECC:	return OPVCC(31,232,0,1);
938 	case ASUBMEV:	return OPVCC(31,232,1,0);
939 	case ASUBMEVCC:	return OPVCC(31,232,1,1);
940 	case ASUBZE:	return OPVCC(31,200,0,0);
941 	case ASUBZECC:	return OPVCC(31,200,0,1);
942 	case ASUBZEV:	return OPVCC(31,200,1,0);
943 	case ASUBZEVCC:	return OPVCC(31,200,1,1);
944 
945 	case ASYNC:	return OPVCC(31,598,0,0);
946 	case ATLBIE:	return OPVCC(31,306,0,0);
947 	case ATW:	return OPVCC(31,4,0,0);
948 
949 	case AXOR:	return OPVCC(31,316,0,0);
950 	}
951 	diag("bad r/r opcode %A", a);
952 	return 0;
953 }
954 
955 long
956 opirr(int a)
957 {
958 	switch(a) {
959 	case AADD:	return OPVCC(14,0,0,0);
960 	case AADDC:	return OPVCC(12,0,0,0);
961 	case AADDCCC:	return OPVCC(13,0,0,0);
962 	case AADD+AEND:	return OPVCC(15,0,0,0);		/* ADDIS/CAU */
963 
964 	case AANDCC:	return OPVCC(28,0,0,0);
965 	case AANDCC+AEND:	return OPVCC(29,0,0,0);		/* ANDIS./ANDIU. */
966 
967 	case ABR:	return OPVCC(18,0,0,0);
968 	case ABL:	return OPVCC(18,0,0,0) | 1;
969 	case ABC:	return OPVCC(16,0,0,0);
970 	case ABCL:	return OPVCC(16,0,0,0) | 1;
971 
972 	case ABEQ:	return AOP_RRR(16<<26,12,2,0);
973 	case ABGE:	return AOP_RRR(16<<26,4,0,0);
974 	case ABGT:	return AOP_RRR(16<<26,12,1,0);
975 	case ABLE:	return AOP_RRR(16<<26,4,1,0);
976 	case ABLT:	return AOP_RRR(16<<26,12,0,0);
977 	case ABNE:	return AOP_RRR(16<<26,4,2,0);
978 	case ABVC:	return AOP_RRR(16<<26,4,3,0);
979 	case ABVS:	return AOP_RRR(16<<26,12,3,0);
980 
981 	case ACMP:	return OPVCC(11,0,0,0);
982 	case ACMPU:	return OPVCC(10,0,0,0);
983 	case ALSW:	return OPVCC(31,597,0,0);
984 
985 	case AMULLW:	return OPVCC(7,0,0,0);
986 
987 	case AOR:	return OPVCC(24,0,0,0);
988 	case AOR+AEND:	return OPVCC(25,0,0,0);		/* ORIS/ORIU */
989 
990 	case ARLWMI:	return OPVCC(20,0,0,0);		/* rlwimi */
991 	case ARLWMICC:	return OPVCC(20,0,0,1);
992 
993 	case ARLWNM:	return OPVCC(21,0,0,0);		/* rlwinm */
994 	case ARLWNMCC:	return OPVCC(21,0,0,1);
995 
996 	case ASRAW:	return OPVCC(31,824,0,0);
997 	case ASRAWCC:	return OPVCC(31,824,0,1);
998 
999 	case ASTSW:	return OPVCC(31,725,0,0);
1000 
1001 	case ASUBC:	return OPVCC(8,0,0,0);
1002 
1003 	case ATW:	return OPVCC(3,0,0,0);
1004 
1005 	case AXOR:	return OPVCC(26,0,0,0);		/* XORIL */
1006 	case AXOR+AEND:	return OPVCC(27,0,0,0);		/* XORIU */
1007 	}
1008 	diag("bad opcode i/r %A", a);
1009 	return 0;
1010 }
1011 
1012 /*
1013  * load o(a),d
1014  */
1015 long
1016 opload(int a)
1017 {
1018 	switch(a) {
1019 	case AMOVW:	return OPVCC(32,0,0,0);		/* lwz */
1020 	case AMOVWU:	return OPVCC(33,0,0,0);		/* lwzu */
1021 	case AMOVB:
1022 	case AMOVBZ:	return OPVCC(34,0,0,0);		/* load */
1023 	case AMOVBU:
1024 	case AMOVBZU:	return OPVCC(35,0,0,0);
1025 	case AFMOVD:	return OPVCC(50,0,0,0);
1026 	case AFMOVDU:	return OPVCC(51,0,0,0);
1027 	case AFMOVS:	return OPVCC(48,0,0,0);
1028 	case AFMOVSU:	return OPVCC(49,0,0,0);
1029 	case AMOVH:	return OPVCC(42,0,0,0);
1030 	case AMOVHU:	return OPVCC(43,0,0,0);
1031 	case AMOVHZ:	return OPVCC(40,0,0,0);
1032 	case AMOVHZU:	return OPVCC(41,0,0,0);
1033 	case AMOVMW:	return OPVCC(46,0,0,0);	/* lmw */
1034 	}
1035 	diag("bad load opcode %A", a);
1036 	return 0;
1037 }
1038 
1039 /*
1040  * indexed load a(b),d
1041  */
1042 long
1043 oploadx(int a)
1044 {
1045 	switch(a) {
1046 	case AMOVW: return OPVCC(31,23,0,0);	/* lwzx */
1047 	case AMOVWU:	return OPVCC(31,55,0,0); /* lwzux */
1048 	case AMOVB:
1049 	case AMOVBZ: return OPVCC(31,87,0,0);	/* lbzx */
1050 	case AMOVBU:
1051 	case AMOVBZU: return OPVCC(31,119,0,0);	/* lbzux */
1052 	case AFMOVD:	return OPVCC(31,599,0,0);	/* lfdx */
1053 	case AFMOVDU:	return OPVCC(31,631,0,0);	/*  lfdux */
1054 	case AFMOVS:	return OPVCC(31,535,0,0);	/* lfsx */
1055 	case AFMOVSU:	return OPVCC(31,567,0,0);	/* lfsux */
1056 	case AMOVH:	return OPVCC(31,343,0,0);	/* lhax */
1057 	case AMOVHU:	return OPVCC(31,375,0,0);	/* lhaux */
1058 	case AMOVHBR:	return OPVCC(31,790,0,0);	/* lhbrx */
1059 	case AMOVWBR:	return OPVCC(31,534,0,0);	/* lwbrx */
1060 	case AMOVHZ:	return OPVCC(31,279,0,0);	/* lhzx */
1061 	case AMOVHZU:	return OPVCC(31,311,0,0);	/* lhzux */
1062 	case AECIWX:	return OPVCC(31,310,0,0);	/* eciwx */
1063 	case ALWAR:	return OPVCC(31,20,0,0);	/* lwarx */
1064 	case ALSW:	return OPVCC(31,533,0,0);	/* lswx */
1065 	}
1066 	diag("bad loadx opcode %A", a);
1067 	return 0;
1068 }
1069 
1070 /*
1071  * store s,o(d)
1072  */
1073 long
1074 opstore(int a)
1075 {
1076 	switch(a) {
1077 	case AMOVB:
1078 	case AMOVBZ:	return OPVCC(38,0,0,0);	/* stb */
1079 	case AMOVBU:
1080 	case AMOVBZU:	return OPVCC(39,0,0,0);	/* stbu */
1081 	case AFMOVD:	return OPVCC(54,0,0,0);	/* stfd */
1082 	case AFMOVDU:	return OPVCC(55,0,0,0);	/* stfdu */
1083 	case AFMOVS:	return OPVCC(52,0,0,0);	/* stfs */
1084 	case AFMOVSU:	return OPVCC(53,0,0,0);	/* stfsu */
1085 	case AMOVHZ:
1086 	case AMOVH:	return OPVCC(44,0,0,0);	/* sth */
1087 	case AMOVHZU:
1088 	case AMOVHU:	return OPVCC(45,0,0,0);	/* sthu */
1089 	case AMOVMW:	return OPVCC(47,0,0,0);	/* stmw */
1090 	case ASTSW:	return OPVCC(31,725,0,0);	/* stswi */
1091 	case AMOVW:	return OPVCC(36,0,0,0);	/* stw */
1092 	case AMOVWU:	return OPVCC(37,0,0,0);	/* stwu */
1093 	}
1094 	diag("unknown store opcode %A", a);
1095 	return 0;
1096 }
1097 
1098 /*
1099  * indexed store s,a(b)
1100  */
1101 long
1102 opstorex(int a)
1103 {
1104 	switch(a) {
1105 	case AMOVB:
1106 	case AMOVBZ:	return OPVCC(31,215,0,0);	/* stbx */
1107 	case AMOVBU:
1108 	case AMOVBZU:	return OPVCC(31,247,0,0);	/* stbux */
1109 	case AFMOVD:	return OPVCC(31,727,0,0);	/* stfdx */
1110 	case AFMOVDU:	return OPVCC(31,759,0,0);	/* stfdux */
1111 	case AFMOVS:	return OPVCC(31,663,0,0);	/* stfsx */
1112 	case AFMOVSU:	return OPVCC(31,695,0,0);	/* stfsux */
1113 	case AMOVHZ:
1114 	case AMOVH:	return OPVCC(31,407,0,0);	/* sthx */
1115 	case AMOVHBR:	return OPVCC(31,918,0,0);	/* sthbrx */
1116 	case AMOVHZU:
1117 	case AMOVHU:	return OPVCC(31,439,0,0);	/* sthux */
1118 	case AMOVW:	return OPVCC(31,151,0,0);	/* stwx */
1119 	case AMOVWU:	return OPVCC(31,183,0,0);	/* stwux */
1120 	case ASTSW:	return OPVCC(31,661,0,0);	/* stswx */
1121 	case AMOVWBR:	return OPVCC(31,662,0,0);	/* stwbrx */
1122 	case ASTWCCC:	return OPVCC(31,150,0,1);	/* stwcx. */
1123 	case AECOWX:	return OPVCC(31,438,0,0);	/* ecowx */
1124 	}
1125 	diag("unknown storex opcode %A", a);
1126 	return 0;
1127 }
1128