xref: /plan9/sys/src/cmd/qi/iu.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #define Extern extern
6 #include "power.h"
7 
8 void	add(ulong);
9 void	addc(ulong);
10 void	adde(ulong);
11 void	addme(ulong);
12 void	addze(ulong);
13 void	and(ulong);
14 void	andc(ulong);
15 void	cmp(ulong);
16 void	cmpl(ulong);
17 void	cntlzw(ulong);
18 void	dcbf(ulong);
19 void	dcbi(ulong);
20 void	dcbst(ulong);
21 void	dcbt(ulong);
22 void	dcbtst(ulong);
23 void	dcbz(ulong);
24 void	divw(ulong);
25 void	divwu(ulong);
26 void	eciwx(ulong);
27 void	ecowx(ulong);
28 void	eieio(ulong);
29 void	eqv(ulong);
30 void	extsb(ulong);
31 void	extsh(ulong);
32 void	icbi(ulong);
33 void	lbzx(ulong);
34 void	lfdx(ulong);
35 void	lfsx(ulong);
36 void	lhax(ulong);
37 void	lhbrx(ulong);
38 void	lhzx(ulong);
39 void	lswi(ulong);
40 void	lswx(ulong);
41 void	lwarx(ulong);
42 void	lwbrx(ulong);
43 void	lwzx(ulong);
44 void	mcrxr(ulong);
45 void	mfcr(ulong);
46 void	mfmsr(ulong);
47 void	mfpmr(ulong);
48 void	mfspr(ulong);
49 void	mfsr(ulong);
50 void	mfsrin(ulong);
51 void	mftb(ulong);
52 void	mftbu(ulong);
53 void	mspr(ulong);
54 void	mtcrf(ulong);
55 void	mtmsr(ulong);
56 void	mtpmr(ulong);
57 void	mtspr(ulong);
58 void	mtsr(ulong);
59 void	mtsrin(ulong);
60 void	mttb(ulong);
61 void	mttbu(ulong);
62 void	mulhw(ulong);
63 void	mulhwu(ulong);
64 void	mullw(ulong);
65 void	nand(ulong);
66 void	neg(ulong);
67 void	nor(ulong);
68 void	or(ulong);
69 void	orc(ulong);
70 void	slbia(ulong);
71 void	slbia(ulong);
72 void	slw(ulong);
73 void	sraw(ulong);
74 void	srawi(ulong);
75 void	srw(ulong);
76 void	stbx(ulong);
77 void	stfdx(ulong);
78 void	stfiwx(ulong);
79 void	stfsx(ulong);
80 void	sthbrx(ulong);
81 void	sthx(ulong);
82 void	stswi(ulong);
83 void	stswx(ulong);
84 void	stwbrx(ulong);
85 void	stwcx(ulong);
86 void	stwx(ulong);
87 void	subf(ulong);
88 void	subfc(ulong);
89 void	subfe(ulong);
90 void	subfme(ulong);
91 void	subfze(ulong);
92 void	sync(ulong);
93 void	tlbie(ulong);
94 void	tw(ulong);
95 void	xor(ulong);
96 
97 Inst	op31[] = {
98 [0] {cmp, "cmp", Iarith},
99 [4] {tw, "tw", Iarith},
100 [8] {subfc, "subfc", Iarith},
101 [10] {addc, "addc", Iarith},
102 [11] {mulhwu, "mulhwu", Iarith},
103 [19] {mfcr, "mfcr", Iarith},
104 [20] {lwarx, "lwarx", Iload},
105 [23] {lwzx, "lwzx", Iload},
106 [24] {slw, "slw", Ilog},
107 [26] {cntlzw, "cntlzw", Ilog},
108 [28] {and, "and", Ilog},
109 [32] {cmpl, "cmpl", Iarith},
110 [40] {subf, "subf", Iarith},
111 [54] {dcbst, "dcbst", Icontrol},
112 [55] {lwzx, "lwzux", Iload},
113 [60] {andc, "andc", Ilog},
114 [75] {mulhw, "mulhw", Iarith},
115 [83] {0, "mfmsr", Icontrol},
116 [86] {dcbf, "dcbf", Icontrol},
117 [87] {lbzx, "lbzx", Iload},
118 [104] {neg, "neg", Iarith},
119 [115] {0, "mfpmr", Iarith},
120 [119] {lbzx, "lbzux", Iload},
121 [124] {nor, "nor", Iarith},
122 [136] {subfe, "subfe", Iarith},
123 [138] {adde, "adde", Iarith},
124 [144] {mtcrf, "mtcrf", Ireg},
125 [146] {0, "mtmsr", Icontrol},
126 [150] {stwcx, "stwcx.", Istore},
127 [151] {stwx, "stwx", Istore},
128 [178] {0, "mtpmr", Icontrol},
129 [183] {stwx, "stwux", Istore},
130 [200] {subfze, "subfze", Iarith},
131 [202] {addze, "addze", Iarith},
132 [210] {0, "mtsr", Ireg},
133 [215] {stbx, "stbx", Istore},
134 [232] {subfme, "subfme", Iarith},
135 [234] {addme, "addme", Iarith},
136 [235] {mullw, "mullw", Iarith},
137 [242] {0, "mtsrin", Ireg},
138 [246] {dcbtst, "dcbtst", Icontrol},
139 [247] {stbx, "stbux", Istore},
140 [266] {add, "add", Iarith},
141 [275] {0, "mftb", Icontrol},
142 [278] {dcbt, "dcbt", Icontrol},
143 [279] {lhzx, "lhzx", Iload},
144 [284] {eqv, "eqv", Ilog},
145 [306] {0, "tlbie", Icontrol},
146 [307] {0, "mftbu", Icontrol},
147 [310] {0, "eciwx", Icontrol},
148 [311] {lhzx, "lhzux", Iload},
149 [316] {xor, "xor", Ilog},
150 [339] {mspr, "mfspr", Ireg},
151 [343] {lhax, "lhax", Iload},
152 [375] {lhax, "lhaux", Iload},
153 [403] {0, "mttb", Icontrol},
154 [407] {sthx, "sthx", Istore},
155 [412] {orc, "orc", Ilog},
156 [434] {0, "slbia", Iarith},
157 [435] {0, "mttbu", Icontrol},
158 [438] {0, "ecowx", Icontrol},
159 [439] {sthx, "sthux", Istore},
160 [444] {or, "or", Ilog},
161 [459] {divwu, "divwu", Iarith},
162 [467] {mspr, "mtspr", Ireg},
163 [470] {0, "dcbi", Icontrol},
164 [476] {nand, "nand", Ilog},
165 [491] {divw, "divw", Iarith},
166 [498] {0, "slbia", Icontrol},
167 [512] {mcrxr, "mcrxr", Ireg},
168 [533] {lswx, "lswx", Iload},
169 [534] {lwbrx, "lwbrx", Iload},
170 [535] {lfsx, "lfsx", Ifloat},
171 [536] {srw, "srw", Ilog},
172 [567] {lfsx, "lfsux", Ifloat},
173 [595] {0, "mfsr", Iarith},
174 [597] {lswi, "lswi", Iarith},
175 [598] {sync, "sync", Iarith},
176 [599] {lfdx, "lfdx", Ifloat},
177 [631] {lfdx, "lfdux", Ifloat},
178 [659] {0, "mfsrin", Ireg},
179 [661] {stswx, "stswx", Istore},
180 [662] {stwbrx, "stwbrx", Istore},
181 [663] {stfsx, "stfsx", Istore},
182 [695] {stfsx, "stfsux", Istore},
183 [725] {stswi, "stswi", Istore},
184 [727] {stfdx, "stfdx", Istore},
185 [759] {stfdx, "stfdux", Istore},
186 [790] {lhbrx, "lhbrx", Iload},
187 [792] {sraw, "sraw", Ilog},
188 [824] {srawi, "srawi", Ilog},
189 [854] {0, "eieio", Icontrol},
190 [918] {sthbrx, "sthbrx", Istore},
191 [922] {extsh, "extsh", Iarith},
192 [954] {extsb, "extsb", Iarith},
193 [982] {icbi, "icbi", Icontrol},
194 [983] {unimp, "stfiwx", Istore},
195 [1014] {dcbz, "dcbz", Icontrol},
196 };
197 
198 Inset	ops31 = {op31, nelem(op31)};
199 
200 void
201 mspr(ulong ir)
202 {
203 	int rd, ra, rb;
204 	ulong *d;
205 	char *n;
206 	char buf[20];
207 
208 	getarrr(ir);
209 	switch((rb<<5) | ra) {
210 	case 0:
211 		undef(ir);	/* was mq */
212 		return;
213 	case 1:
214 		d = &reg.xer; n = "xer";
215 		break;
216 	case 268:
217 	case 284:
218 		d = &reg.tbl; n = "tbl";
219 		break;
220 	case 269:
221 	case 285:
222 		d = &reg.tbu; n = "tbu";
223 		break;
224 	case 22:
225 		d = &reg.dec; n = "dec";
226 		break;
227 	case 8:
228 		d = &reg.lr; n = "lr";
229 		break;
230 	case 9:
231 		d = &reg.ctr; n = "ctr";
232 		break;
233 	default:
234 		d = 0; sprint(n = buf, "spr%d", rd);
235 		break;
236 	}
237 	if(getxo(ir) == 339) {
238 		if(trace)
239 			itrace("%s\tr%d,%s", ci->name, rd, n);
240 		reg.r[rd] = *d;
241 	} else {
242 		if(trace)
243 			itrace("%s\t%s,r%d", ci->name, n, rd);
244 		*d = reg.r[rd];
245 	}
246 }
247 
248 static void
249 setcr(int d, long r)
250 {
251 	int c;
252 
253 	c = 0;
254 	if(reg.xer & XER_SO)
255 		c |= 1;
256 	if(r == 0)
257 		c |= 2;
258 	else if(r > 0)
259 		c |= 4;
260 	else
261 		c |= 8;
262 	reg.cr = (reg.cr & ~mkCR(d, 0xF)) | mkCR(d, c);
263 }
264 
265 void
266 addi(ulong ir)
267 {
268 	int rd, ra;
269 	long imm;
270 
271 	getairr(ir);
272 	if(trace) {
273 		if(ra)
274 			itrace("%s\tr%d,r%d,$0x%lux", ci->name, rd, ra, imm);
275 		else
276 			itrace("li\tr%d,$0x%lux", rd, imm);
277 	}
278 	if(ra)
279 		imm += reg.r[ra];
280 	reg.r[rd] = imm;
281 }
282 
283 void
284 addis(ulong ir)
285 {
286 	int rd, ra;
287 	long imm;
288 
289 	getairr(ir);
290 	if(trace) {
291 		if(ra)
292 			itrace("%s\tr%d,r%d,$0x%lux", ci->name, rd, ra, imm);
293 		else
294 			itrace("lis\tr%d,$0x%lux", rd, imm);
295 	}
296 	imm <<= 16;
297 	if(ra)
298 		imm += reg.r[ra];
299 	reg.r[rd] = imm;
300 }
301 
302 void
303 and(ulong ir)
304 {
305 	int rs, ra, rb;
306 
307 	getlrrr(ir);
308 	reg.r[ra] = reg.r[rs] & reg.r[rb];
309 	if(trace)
310 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
311 	if(ir & 1)
312 		setcr(0, reg.r[ra]);
313 }
314 
315 void
316 andc(ulong ir)
317 {
318 	int rs, ra, rb;
319 
320 	getlrrr(ir);
321 	reg.r[ra] = reg.r[rs] & ~reg.r[rb];
322 	if(trace)
323 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
324 	if(ir & 1)
325 		setcr(0, reg.r[ra]);
326 }
327 
328 void
329 andicc(ulong ir)
330 {
331 	int rs, ra;
332 	ulong imm;
333 
334 	getlirr(ir);
335 	reg.r[ra] = reg.r[rs] & imm;
336 	if(trace)
337 		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
338 	setcr(0, reg.r[ra]);
339 }
340 
341 void
342 andiscc(ulong ir)
343 {
344 	int rs, ra;
345 	ulong imm;
346 
347 	getlirr(ir);
348 	reg.r[ra] = reg.r[rs] & (imm<<16);
349 	if(trace)
350 		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
351 	setcr(0, reg.r[ra]);
352 }
353 
354 void
355 cmpli(ulong ir)
356 {
357 	int rd, ra;
358 	ulong c;
359 	ulong imm, v;
360 
361 	getairr(ir);
362 	imm &= 0xFFFF;
363 	if(rd & 3)
364 		undef(ir);
365 	rd >>= 2;
366 	v = reg.r[ra];
367 	c = 0;
368 	if(reg.xer & XER_SO)
369 		c |= CRSO;
370 	if(v < imm)
371 		c |= CRLT;
372 	else if(v == imm)
373 		c |= CREQ;
374 	else
375 		c |= CRGT;
376 	c >>= 28;
377 	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
378 	if(trace)
379 		itrace("%s\tcrf%d,r%d,0x%lux [cr=#%x]", ci->name, rd, ra, imm, c);
380 }
381 
382 void
383 cmp(ulong ir)
384 {
385 	int rd, ra, rb;
386 	ulong c;
387 	long va, vb;
388 
389 	getarrr(ir);
390 	if(rd & 3)
391 		undef(ir);
392 	rd >>= 2;
393 	c = 0;
394 	if(reg.xer & XER_SO)
395 		c |= CRSO;
396 	va = reg.r[ra];
397 	vb = reg.r[rb];
398 	if(va < vb)
399 		c |= CRLT;
400 	else if(va == vb)
401 		c |= CREQ;
402 	else
403 		c |= CRGT;
404 	c >>= 28;
405 	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
406 	if(trace)
407 		itrace("%s\tcrf%d,r%d,r%d [cr=#%x]", ci->name, rd, ra, rb, c);
408 }
409 
410 void
411 cmpi(ulong ir)
412 {
413 	int rd, ra;
414 	ulong c;
415 	long imm, v;
416 
417 	getairr(ir);
418 	if(rd & 3)
419 		undef(ir);
420 	rd >>= 2;
421 	v = reg.r[ra];
422 	c = 0;
423 	if(reg.xer & XER_SO)
424 		c |= CRSO;
425 	if(v < imm)
426 		c |= CRLT;
427 	else if(v == imm)
428 		c |= CREQ;
429 	else
430 		c |= CRGT;
431 	c >>= 28;
432 	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
433 	if(trace)
434 		itrace("%s\tcrf%d,r%d,0x%lux [cr=#%x]", ci->name, rd, ra, imm, c);
435 }
436 
437 void
438 cmpl(ulong ir)
439 {
440 	int rd, ra, rb;
441 	ulong c;
442 	ulong va, vb;
443 
444 	getarrr(ir);
445 	if(rd & 3)
446 		undef(ir);
447 	rd >>= 2;
448 	c = 0;
449 	if(reg.xer & XER_SO)
450 		c |= CRSO;
451 	va = reg.r[ra];
452 	vb = reg.r[rb];
453 	if(va < vb)
454 		c |= CRLT;
455 	else if(va == vb)
456 		c |= CREQ;
457 	else
458 		c |= CRGT;
459 	c >>= 28;
460 	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, c);
461 	if(trace)
462 		itrace("%s\tcrf%d,r%d,r%d [cr=#%x]", ci->name, rd, ra, rb, c);
463 }
464 
465 void
466 cntlzw(ulong ir)
467 {
468 	int rs, ra, rb, n;
469 
470 	getlrrr(ir);
471 	if(rb)
472 		undef(ir);
473 	for(n=0; n<32 && (reg.r[rs] & (1L<<(31-n))) == 0; n++)
474 		;
475 	reg.r[ra] = n;
476 	if(trace)
477 		itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
478 	if(ir & 1)
479 		setcr(0, reg.r[ra]);
480 }
481 
482 void
483 eqv(ulong ir)
484 {
485 	int rs, ra, rb;
486 
487 	getlrrr(ir);
488 	reg.r[ra] = ~(reg.r[rs] ^ reg.r[rb]);
489 	if(trace)
490 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
491 	if(ir & 1)
492 		setcr(0, reg.r[ra]);
493 }
494 
495 void
496 extsb(ulong ir)
497 {
498 	int rs, ra, rb;
499 
500 	getlrrr(ir);
501 	if(rb)
502 		undef(ir);
503 	reg.r[ra] = (schar)reg.r[rs];
504 	if(trace)
505 		itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
506 	if(ir & 1)
507 		setcr(0, reg.r[ra]);
508 }
509 
510 void
511 extsh(ulong ir)
512 {
513 	int rs, ra, rb;
514 
515 	getlrrr(ir);
516 	if(rb)
517 		undef(ir);
518 	reg.r[ra] = (short)reg.r[rs];
519 	if(trace)
520 		itrace("%s%s\tr%d,r%d", ci->name, ir&1?".":"", ra, rs);
521 	if(ir & 1)
522 		setcr(0, reg.r[ra]);
523 }
524 
525 void
526 add(ulong ir)
527 {
528 	int rd, ra, rb;
529 	uvlong r;
530 
531 	getarrr(ir);
532 	r = (uvlong)(ulong)reg.r[ra] + reg.r[rb];
533 	if(ir & OE) {
534 		reg.xer &= ~XER_OV;
535 		if(r >> 16)
536 			reg.xer |= XER_SO | XER_OV;
537 	}
538 	reg.r[rd] = (ulong)r;
539 	if(ir & Rc)
540 		setcr(0, reg.r[rd]);
541 	if(trace)
542 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
543 }
544 
545 void
546 addc(ulong ir)
547 {
548 	int rd, ra, rb;
549 	ulong v;
550 	uvlong r;
551 
552 	getarrr(ir);
553 	r = (uvlong)(ulong)reg.r[ra] + reg.r[rb];
554 	v = r>>32;
555 	reg.xer &= ~XER_CA;
556 	if(v)
557 		reg.xer |= XER_CA;
558 	if(ir & OE) {
559 		reg.xer &= ~XER_OV;
560 		if(v>>1)
561 			reg.xer |= XER_SO | XER_OV;
562 	}
563 	reg.r[rd] = (ulong)r;
564 	if(ir & Rc)
565 		setcr(0, reg.r[rd]);
566 	if(trace)
567 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
568 }
569 
570 void
571 adde(ulong ir)
572 {
573 	int rd, ra, rb;
574 	ulong v;
575 	uvlong r;
576 
577 	getarrr(ir);
578 	r = (uvlong)(ulong)reg.r[ra] + reg.r[rb] + (reg.xer&XER_CA)!=0;
579 	v = r>>32;
580 	reg.xer &= ~XER_CA;
581 	if(v)
582 		reg.xer |= XER_CA;
583 	if(ir & OE) {
584 		reg.xer &= ~XER_OV;
585 		if(v>>1)
586 			reg.xer |= XER_SO | XER_OV;
587 	}
588 	reg.r[rd] = (ulong)r;
589 	if(ir & Rc)
590 		setcr(0, reg.r[rd]);
591 	if(trace)
592 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
593 }
594 
595 void
596 addic(ulong ir)
597 {
598 	int rd, ra;
599 	long imm;
600 	ulong v;
601 	uvlong r;
602 
603 	getairr(ir);
604 	r = (uvlong)(ulong)reg.r[ra] + imm;
605 	v = r>>32;
606 	reg.xer &= ~XER_CA;
607 	if(v)
608 		reg.xer |= XER_CA;
609 	reg.r[rd] = (ulong)r;
610 	if(trace)
611 		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
612 }
613 
614 void
615 addiccc(ulong ir)
616 {
617 	int rd, ra;
618 	long imm;
619 	ulong v;
620 	uvlong r;
621 
622 	getairr(ir);
623 	r = (uvlong)(ulong)reg.r[ra] + imm;
624 	v = r>>32;
625 	reg.xer &= ~XER_CA;
626 	if(v)
627 		reg.xer |= XER_CA;
628 	reg.r[rd] = (ulong)r;
629 	setcr(0, reg.r[rd]);
630 	if(trace)
631 		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
632 }
633 
634 void
635 addme(ulong ir)
636 {
637 	int rd, ra, rb;
638 	ulong v;
639 	uvlong r;
640 
641 	getarrr(ir);
642 	if(rb)
643 		undef(ir);
644 	r = (uvlong)(ulong)reg.r[ra] + 0xFFFFFFFF + (reg.xer&XER_CA)!=0;
645 	v = r>>32;
646 	reg.xer &= ~XER_CA;
647 	if(v)
648 		reg.xer |= XER_CA;
649 	if(ir & OE) {
650 		reg.xer &= ~XER_OV;
651 		if(v>>1)
652 			reg.xer |= XER_SO | XER_OV;
653 	}
654 	reg.r[rd] = (ulong)r;
655 	if(ir & Rc)
656 		setcr(0, reg.r[rd]);
657 	if(trace)
658 		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
659 }
660 
661 void
662 addze(ulong ir)
663 {
664 	int rd, ra, rb;
665 	ulong v;
666 	uvlong r;
667 
668 	getarrr(ir);
669 	if(rb)
670 		undef(ir);
671 	r = (uvlong)(ulong)reg.r[ra] + (reg.xer&XER_CA)!=0;
672 	v = r>>32;
673 	reg.xer &= ~XER_CA;
674 	if(v)
675 		reg.xer |= XER_CA;
676 	if(ir & OE) {
677 		reg.xer &= ~XER_OV;
678 		if(v>>1)
679 			reg.xer |= XER_SO | XER_OV;
680 	}
681 	reg.r[rd] = (ulong)r;
682 	if(ir & Rc)
683 		setcr(0, reg.r[rd]);
684 	if(trace)
685 		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
686 }
687 
688 void
689 divw(ulong ir)
690 {
691 	int rd, ra, rb;
692 
693 	getarrr(ir);
694 	if(reg.r[rb] != 0 && ((ulong)reg.r[ra] != 0x80000000 || reg.r[rb] != -1))
695 		reg.r[rd] = reg.r[ra]/reg.r[rb];
696 	else if(ir & OE)
697 		reg.xer |= XER_SO | XER_OV;
698 	if(ir & Rc)
699 		setcr(0, reg.r[rd]);
700 	if(trace)
701 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
702 }
703 
704 void
705 divwu(ulong ir)
706 {
707 	int rd, ra, rb;
708 
709 	getarrr(ir);
710 	if(reg.r[rb] != 0)
711 		reg.r[rd] = (ulong)reg.r[ra]/(ulong)reg.r[rb];
712 	else if(ir & OE)
713 		reg.xer |= XER_SO | XER_OV;
714 	if(ir & Rc)
715 		setcr(0, reg.r[rd]);
716 	if(trace)
717 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
718 }
719 
720 void
721 mcrxr(ulong ir)
722 {
723 	int rd, ra, rb;
724 
725 	getarrr(ir);
726 	if(rd & 3 || ra != 0 || rb != 0 || ir & Rc)
727 		undef(ir);
728 	rd >>= 2;
729 	reg.cr = (reg.cr & ~mkCR(rd, 0xF)) | mkCR(rd, reg.xer>>28);
730 	reg.xer &= ~(0xF<<28);
731 }
732 
733 void
734 mtcrf(ulong ir)
735 {
736 	int rs, crm, i;
737 	ulong m;
738 
739 	if(ir & ((1<<20)|(1<<11)|Rc))
740 		undef(ir);
741 	rs = (ir>>21)&0x1F;
742 	crm = (ir>>12)&0xFF;
743 	m = 0;
744 	for(i = 0x80; i; i >>= 1) {
745 		m <<= 4;
746 		if(crm & i)
747 			m |= 0xF;
748 	}
749 	reg.cr = (reg.cr & ~m) | (reg.r[rs] & m);
750 }
751 
752 void
753 mfcr(ulong ir)
754 {
755 	int rd, ra, rb;
756 
757 	getarrr(ir);
758 	if(ra != 0 || rb != 0 || ir & Rc)
759 		undef(ir);
760 	reg.r[rd] = reg.cr;
761 }
762 
763 void
764 mulhw(ulong ir)
765 {
766 	int rd, ra, rb;
767 
768 	getarrr(ir);
769 	reg.r[rd] = ((vlong)(long)reg.r[ra]*(long)reg.r[rb])>>32;
770 	if(ir & Rc)
771 		setcr(0, reg.r[rd]);
772 	if(trace)
773 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
774 	/* BUG: doesn't set OV */
775 }
776 
777 void
778 mulhwu(ulong ir)
779 {
780 	int rd, ra, rb;
781 
782 	getarrr(ir);
783 	reg.r[rd] = ((uvlong)(ulong)reg.r[ra]*(ulong)reg.r[rb])>>32;
784 	if(ir & Rc)
785 		setcr(0, reg.r[rd]);	/* not sure whether CR setting is signed or unsigned */
786 	if(trace)
787 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
788 	/* BUG: doesn't set OV */
789 }
790 
791 void
792 mullw(ulong ir)
793 {
794 	int rd, ra, rb;
795 
796 	getarrr(ir);
797 	reg.r[rd] = (uvlong)(ulong)reg.r[ra]*(ulong)reg.r[rb];
798 	if(ir & Rc)
799 		setcr(0, reg.r[rd]);
800 	if(trace)
801 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&Rc?".":"", rd, ra, rb);
802 	/* BUG: doesn't set OV */
803 }
804 
805 void
806 mulli(ulong ir)
807 {
808 	int rd, ra;
809 	long imm;
810 
811 	getairr(ir);
812 	reg.r[rd] = (uvlong)(ulong)reg.r[ra]*(ulong)imm;
813 	if(trace)
814 		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
815 }
816 
817 void
818 nand(ulong ir)
819 {
820 	int rs, ra, rb;
821 
822 	getlrrr(ir);
823 	reg.r[ra] = ~(reg.r[rs] & reg.r[rb]);
824 	if(ir & Rc)
825 		setcr(0, reg.r[ra]);
826 	if(trace)
827 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
828 }
829 
830 void
831 neg(ulong ir)
832 {
833 	int rd, ra, rb;
834 
835 	getarrr(ir);
836 	if(rb)
837 		undef(ir);
838 	if(ir & OE)
839 		reg.xer &= ~XER_OV;
840 	if((ulong)reg.r[ra] == 0x80000000) {
841 		if(ir & OE)
842 			reg.xer |= XER_SO | XER_OV;
843 		reg.r[rd] = reg.r[ra];
844 	} else
845 		reg.r[rd] = -reg.r[ra];
846 	if(ir & Rc)
847 		setcr(0, reg.r[rd]);
848 }
849 
850 void
851 nor(ulong ir)
852 {
853 	int rs, ra, rb;
854 
855 	getlrrr(ir);
856 	reg.r[ra] = ~(reg.r[rs] | reg.r[rb]);
857 	if(ir & Rc)
858 		setcr(0, reg.r[ra]);
859 	if(trace)
860 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
861 }
862 
863 void
864 or(ulong ir)
865 {
866 	int rs, ra, rb;
867 
868 	getlrrr(ir);
869 	reg.r[ra] = reg.r[rs] | reg.r[rb];
870 	if(ir & Rc)
871 		setcr(0, reg.r[ra]);
872 	if(trace) {
873 		if(rs == rb)
874 			itrace("mr%s\tr%d,r%d", ir&1?".":"", ra, rs);
875 		else
876 			itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
877 	}
878 }
879 
880 void
881 orc(ulong ir)
882 {
883 	int rs, ra, rb;
884 
885 	getlrrr(ir);
886 	reg.r[ra] = reg.r[rs] | ~reg.r[rb];
887 	if(ir & Rc)
888 		setcr(0, reg.r[ra]);
889 	if(trace)
890 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
891 }
892 
893 void
894 ori(ulong ir)
895 {
896 	int rs, ra;
897 	ulong imm;
898 
899 	getlirr(ir);
900 	reg.r[ra] = reg.r[rs] | imm;
901 	if(trace)
902 		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
903 }
904 
905 void
906 oris(ulong ir)
907 {
908 	int rs, ra;
909 	ulong imm;
910 
911 	getlirr(ir);
912 	reg.r[ra] = reg.r[rs] | (imm<<16);
913 	if(trace)
914 		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
915 }
916 
917 static ulong
918 mkmask(int mb, int me)
919 {
920 	int i;
921 	ulong v;
922 
923 	if(mb > me)
924 		return mkmask(0, me) | mkmask(mb, 31);
925 	v = 0;
926 	for(i=mb; i<=me; i++)
927 		v |= 1L << (31-i);	/* don't need a loop, but i'm lazy */
928 	return v;
929 }
930 
931 static ulong
932 rotl(ulong v, int sh)
933 {
934 	if(sh == 0)
935 		return v;
936 	return (v<<sh) | (v>>(32-sh));
937 }
938 
939 void
940 rlwimi(ulong ir)
941 {
942 	int rs, ra, rb, sh;
943 	ulong m;
944 
945 	getlrrr(ir);
946 	sh = rb;
947 	m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
948 	reg.r[ra] = (reg.r[ra] & ~m) | (rotl(reg.r[rs], sh) & m);
949 	if(trace)
950 		itrace("%s\tr%d,r%d,%d,#%lux", ci->name, ra, rs, sh, m);
951 	if(ir & 1)
952 		setcr(0, reg.r[ra]);
953 }
954 
955 void
956 rlwinm(ulong ir)
957 {
958 	int rs, ra, rb, sh;
959 	ulong m;
960 
961 	getlrrr(ir);
962 	sh = rb;
963 	m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
964 	reg.r[ra] = rotl(reg.r[rs], sh) & m;
965 	if(trace)
966 		itrace("%s%s\tr%d,r%d,%d,#%lux", ci->name, ir&Rc?".":"", ra, rs, sh, m);
967 	if(ir & Rc)
968 		setcr(0, reg.r[ra]);
969 }
970 
971 void
972 rlwnm(ulong ir)
973 {
974 	int rs, ra, rb, sh;
975 	ulong m;
976 
977 	getlrrr(ir);
978 	sh = reg.r[rb] & 0x1F;
979 	m = mkmask((ir>>6)&0x1F, (ir>>1)&0x1F);
980 	reg.r[ra] = rotl(reg.r[rs], sh) & m;
981 	if(trace)
982 		itrace("%s\tr%d,r%d,r%d,#%lux", ci->name, ra, rs, rb, m);
983 	if(ir & 1)
984 		setcr(0, reg.r[ra]);
985 }
986 
987 void
988 slw(ulong ir)
989 {
990 	int rs, ra, rb;
991 	long v;
992 
993 	getlrrr(ir);
994 	v = reg.r[rb];
995 	if((v & 0x20) == 0) {
996 		v &= 0x1F;
997 		reg.r[ra] = (ulong)reg.r[rs] << v;
998 	} else
999 		reg.r[ra] = 0;
1000 	if(ir & Rc)
1001 		setcr(0, reg.r[ra]);
1002 	if(trace)
1003 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
1004 }
1005 
1006 void
1007 sraw(ulong ir)
1008 {
1009 	int rs, ra, rb;
1010 	long v;
1011 
1012 	getlrrr(ir);
1013 	v = reg.r[rb];
1014 	if((v & 0x20) == 0) {
1015 		v &= 0x1F;
1016 		if(reg.r[rs]&SIGNBIT && v)
1017 			reg.r[ra] = reg.r[rs]>>v | ~((1<<(32-v))-1);
1018 		else
1019 			reg.r[ra] = reg.r[rs]>>v;
1020 	} else
1021 		reg.r[ra] = reg.r[rs]&SIGNBIT? ~0: 0;
1022 	if(ir & Rc)
1023 		setcr(0, reg.r[ra]);
1024 	if(trace)
1025 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
1026 }
1027 
1028 void
1029 srawi(ulong ir)
1030 {
1031 	int rs, ra, rb;
1032 	long v;
1033 
1034 	getlrrr(ir);
1035 	v = rb;
1036 	if((v & 0x20) == 0) {
1037 		v &= 0x1F;
1038 		if(reg.r[rs]&SIGNBIT && v)
1039 			reg.r[ra] = reg.r[rs]>>v | ~((1<<(32-v))-1);
1040 		else
1041 			reg.r[ra] = reg.r[rs]>>v;
1042 	} else
1043 		reg.r[ra] = reg.r[rs]&SIGNBIT? ~0: 0;
1044 	if(ir & Rc)
1045 		setcr(0, reg.r[ra]);
1046 	if(trace)
1047 		itrace("%s%s\tr%d,r%d,$%d", ci->name, ir&1?".":"", ra, rs, v);
1048 }
1049 
1050 void
1051 srw(ulong ir)
1052 {
1053 	int rs, ra, rb;
1054 	long v;
1055 
1056 	getlrrr(ir);
1057 	v = reg.r[rb];
1058 	if((v & 0x20) == 0)
1059 		reg.r[ra] = (ulong)reg.r[rs] >> (v&0x1F);
1060 	else
1061 		reg.r[ra] = 0;
1062 	if(ir & Rc)
1063 		setcr(0, reg.r[ra]);
1064 	if(trace)
1065 		itrace("%s%s\tr%d,r%d,r%d", ci->name, ir&1?".":"", ra, rs, rb);
1066 }
1067 
1068 void
1069 subf(ulong ir)
1070 {
1071 	int rd, ra, rb;
1072 	uvlong r;
1073 
1074 	getarrr(ir);
1075 	r = (uvlong)((ulong)~reg.r[ra]) + reg.r[rb] + 1;
1076 	if(ir & OE) {
1077 		reg.xer &= ~XER_OV;
1078 		if(r >> 16)
1079 			reg.xer |= XER_SO | XER_OV;
1080 	}
1081 	reg.r[rd] = (ulong)r;
1082 	if(ir & Rc)
1083 		setcr(0, reg.r[rd]);
1084 	if(trace)
1085 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
1086 }
1087 
1088 void
1089 subfc(ulong ir)
1090 {
1091 	int rd, ra, rb;
1092 	ulong v;
1093 	uvlong r;
1094 
1095 	getarrr(ir);
1096 	r = (uvlong)((ulong)~reg.r[ra]) + reg.r[rb] + 1;
1097 	v = r>>32;
1098 	reg.xer &= ~XER_CA;
1099 	if(v)
1100 		reg.xer |= XER_CA;
1101 	if(ir & OE) {
1102 		reg.xer &= ~XER_OV;
1103 		if(v>>1)
1104 			reg.xer |= XER_SO | XER_OV;
1105 	}
1106 	reg.r[rd] = (ulong)r;
1107 	if(ir & Rc)
1108 		setcr(0, reg.r[rd]);
1109 	if(trace)
1110 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
1111 }
1112 
1113 void
1114 subfe(ulong ir)
1115 {
1116 	int rd, ra, rb;
1117 	ulong v;
1118 	uvlong r;
1119 
1120 	getarrr(ir);
1121 	r = (uvlong)((ulong)~reg.r[ra]) + reg.r[rb] + (reg.xer&XER_CA)!=0;
1122 	v = r>>32;
1123 	reg.xer &= ~XER_CA;
1124 	if(v)
1125 		reg.xer |= XER_CA;
1126 	if(ir & OE) {
1127 		reg.xer &= ~XER_OV;
1128 		if(v>>1)
1129 			reg.xer |= XER_SO | XER_OV;
1130 	}
1131 	reg.r[rd] = (ulong)r;
1132 	if(ir & Rc)
1133 		setcr(0, reg.r[rd]);
1134 	if(trace)
1135 		itrace("%s%s%s\tr%d,r%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra, rb);
1136 }
1137 
1138 void
1139 subfic(ulong ir)
1140 {
1141 	int rd, ra;
1142 	long imm;
1143 	ulong v;
1144 	uvlong r;
1145 
1146 	getairr(ir);
1147 	r = (uvlong)((ulong)~reg.r[ra]) + imm + 1;
1148 	v = r>>32;
1149 	reg.xer &= ~XER_CA;
1150 	if(v)
1151 		reg.xer |= XER_CA;
1152 	reg.r[rd] = (ulong)r;
1153 	if(trace)
1154 		itrace("%s\tr%d,r%d,$%ld", ci->name, rd, ra, imm);
1155 }
1156 
1157 void
1158 subfme(ulong ir)
1159 {
1160 	int rd, ra, rb;
1161 	ulong v;
1162 	uvlong r;
1163 
1164 	getarrr(ir);
1165 	if(rb)
1166 		undef(ir);
1167 	r = (uvlong)((ulong)~reg.r[ra]) + 0xFFFFFFFF + (reg.xer&XER_CA)!=0;
1168 	v = r>>32;
1169 	reg.xer &= ~XER_CA;
1170 	if(v)
1171 		reg.xer |= XER_CA;
1172 	if(ir & OE) {
1173 		reg.xer &= ~XER_OV;
1174 		if(v>>1)
1175 			reg.xer |= XER_SO | XER_OV;
1176 	}
1177 	reg.r[rd] = (ulong)r;
1178 	if(ir & Rc)
1179 		setcr(0, reg.r[rd]);
1180 	if(trace)
1181 		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
1182 }
1183 
1184 void
1185 subfze(ulong ir)
1186 {
1187 	int rd, ra, rb;
1188 	ulong v;
1189 	uvlong r;
1190 
1191 	getarrr(ir);
1192 	if(rb)
1193 		undef(ir);
1194 	r = (uvlong)((ulong)~reg.r[ra]) + (reg.xer&XER_CA)!=0;
1195 	v = r>>32;
1196 	reg.xer &= ~XER_CA;
1197 	if(v)
1198 		reg.xer |= XER_CA;
1199 	if(ir & OE) {
1200 		reg.xer &= ~XER_OV;
1201 		if(v>>1)
1202 			reg.xer |= XER_SO | XER_OV;
1203 	}
1204 	reg.r[rd] = (ulong)r;
1205 	if(ir & Rc)
1206 		setcr(0, reg.r[rd]);
1207 	if(trace)
1208 		itrace("%s%s%s\tr%d,r%d", ci->name, ir&OE?"o":"", ir&1?".":"", rd, ra);
1209 }
1210 
1211 void
1212 xor(ulong ir)
1213 {
1214 	int rs, ra, rb;
1215 
1216 	getlrrr(ir);
1217 	reg.r[ra] = reg.r[rs] ^ reg.r[rb];
1218 	if(trace)
1219 		itrace("%s\tr%d,r%d,r%d", ci->name, ra, rs, rb);
1220 }
1221 
1222 void
1223 xori(ulong ir)
1224 {
1225 	int rs, ra;
1226 	ulong imm;
1227 
1228 	getlirr(ir);
1229 	reg.r[ra] = reg.r[rs] ^ imm;
1230 	if(trace)
1231 		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
1232 }
1233 
1234 void
1235 xoris(ulong ir)
1236 {
1237 	int rs, ra;
1238 	ulong imm;
1239 
1240 	getlirr(ir);
1241 	reg.r[ra] = reg.r[rs] ^ (imm<<16);
1242 	if(trace)
1243 		itrace("%s\tr%d,r%d,$0x%lx", ci->name, ra, rs, imm);
1244 }
1245 
1246 void
1247 lwz(ulong ir)
1248 {
1249 	ulong ea;
1250 	int ra, rd, upd;
1251 	long imm;
1252 
1253 	getairr(ir);
1254 	ea = imm;
1255 	upd = (ir&(1L<<26))!=0;
1256 	if(ra) {
1257 		ea += reg.r[ra];
1258 		if(upd)
1259 			reg.r[ra] = ea;
1260 	} else {
1261 		if(upd)
1262 			undef(ir);
1263 	}
1264 	if(trace)
1265 		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1266 
1267 	reg.r[rd] = getmem_w(ea);
1268 }
1269 
1270 void
1271 lwzx(ulong ir)
1272 {
1273 	ulong ea;
1274 	int rb, ra, rd, upd;
1275 
1276 	getarrr(ir);
1277 	ea = reg.r[rb];
1278 	upd = getxo(ir)==55;
1279 	if(ra) {
1280 		ea += reg.r[ra];
1281 		if(upd)
1282 			reg.r[ra] = ea;
1283 		if(trace)
1284 			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1285 	} else {
1286 		if(upd)
1287 			undef(ir);
1288 		if(trace)
1289 			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1290 	}
1291 
1292 	reg.r[rd] = getmem_w(ea);
1293 }
1294 
1295 void
1296 lwarx(ulong ir)
1297 {
1298 	lwzx(ir);
1299 }
1300 
1301 void
1302 lbz(ulong ir)
1303 {
1304 	ulong ea;
1305 	int ra, rd, upd;
1306 	long imm;
1307 
1308 	getairr(ir);
1309 	ea = imm;
1310 	upd = (ir&(1L<<26))!=0;
1311 	if(ra) {
1312 		ea += reg.r[ra];
1313 		if(upd)
1314 			reg.r[ra] = ea;
1315 	} else {
1316 		if(upd)
1317 			undef(ir);
1318 	}
1319 	if(trace)
1320 		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1321 
1322 	reg.r[rd] = getmem_b(ea);
1323 }
1324 
1325 void
1326 lbzx(ulong ir)
1327 {
1328 	ulong ea;
1329 	int rb, ra, rd, upd;
1330 
1331 	getarrr(ir);
1332 	ea = reg.r[rb];
1333 	upd = getxo(ir)==119;
1334 	if(ra) {
1335 		ea += reg.r[ra];
1336 		if(upd)
1337 			reg.r[ra] = ea;
1338 		if(trace)
1339 			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1340 	} else {
1341 		if(upd)
1342 			undef(ir);
1343 		if(trace)
1344 			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1345 	}
1346 
1347 	reg.r[rd] = getmem_b(ea);
1348 }
1349 
1350 void
1351 stw(ulong ir)
1352 {
1353 	ulong ea;
1354 	int ra, rd, upd;
1355 	long imm;
1356 
1357 	getairr(ir);
1358 	ea = imm;
1359 	upd = (ir&(1L<<26))!=0;
1360 	if(ra) {
1361 		ea += reg.r[ra];
1362 		if(upd)
1363 			reg.r[ra] = ea;
1364 	} else {
1365 		if(upd)
1366 			undef(ir);
1367 	}
1368 	if(trace)
1369 		itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
1370 					ci->name, rd, imm, ra, ea, reg.r[rd], reg.r[rd]);
1371 	putmem_w(ea, reg.r[rd]);
1372 
1373 }
1374 
1375 void
1376 stwx(ulong ir)
1377 {
1378 	ulong ea;
1379 	int ra, rd, upd, rb;
1380 
1381 	getarrr(ir);
1382 	ea = reg.r[rb];
1383 	upd = getxo(ir)==183;
1384 	if(ra) {
1385 		ea += reg.r[ra];
1386 		if(upd)
1387 			reg.r[ra] = ea;
1388 		if(trace)
1389 			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1390 					ci->name, rd, ra, rb, ea, reg.r[rd], reg.r[rd]);
1391 	} else {
1392 		if(upd)
1393 			undef(ir);
1394 		if(trace)
1395 			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1396 					ci->name, rd, rb, ea, reg.r[rd], reg.r[rd]);
1397 	}
1398 	putmem_w(ea, reg.r[rd]);
1399 
1400 }
1401 
1402 void
1403 stwcx(ulong ir)
1404 {
1405 	ulong ea;
1406 	int ra, rd, rb;
1407 
1408 	if((ir & Rc) == 0)
1409 		undef(ir);
1410 	getarrr(ir);
1411 	ea = reg.r[rb];
1412 	if(ra) {
1413 		ea += reg.r[ra];
1414 		if(trace)
1415 			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1416 					ci->name, rd, ra, rb, ea, reg.r[rd], reg.r[rd]);
1417 	} else {
1418 		if(trace)
1419 			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1420 					ci->name, rd, rb, ea, reg.r[rd], reg.r[rd]);
1421 	}
1422 	putmem_w(ea, reg.r[rd]);	/* assume a reservation exists; store succeeded */
1423 	setcr(0, 0);
1424 
1425 }
1426 
1427 void
1428 stb(ulong ir)
1429 {
1430 	ulong ea;
1431 	int ra, rd, upd, v;
1432 	long imm;
1433 
1434 	getairr(ir);
1435 	ea = imm;
1436 	upd = (ir&(1L<<26))!=0;
1437 	if(ra) {
1438 		ea += reg.r[ra];
1439 		if(upd)
1440 			reg.r[ra] = ea;
1441 	} else {
1442 		if(upd)
1443 			undef(ir);
1444 	}
1445 	v = reg.r[rd] & 0xFF;
1446 	if(trace)
1447 		itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
1448 					ci->name, rd, imm, ra, ea, v, v);
1449 	putmem_b(ea, v);
1450 }
1451 
1452 void
1453 stbx(ulong ir)
1454 {
1455 	ulong ea;
1456 	int ra, rd, upd, rb, v;
1457 
1458 	getarrr(ir);
1459 	ea = reg.r[rb];
1460 	upd = getxo(ir)==247;
1461 	v = reg.r[rd] & 0xFF;
1462 	if(ra) {
1463 		ea += reg.r[ra];
1464 		if(upd)
1465 			reg.r[ra] = ea;
1466 		if(trace)
1467 			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1468 					ci->name, rd, ra, rb, ea, v, v);
1469 	} else {
1470 		if(upd)
1471 			undef(ir);
1472 		if(trace)
1473 			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1474 					ci->name, rd, rb, ea, v, v);
1475 	}
1476 	putmem_b(ea, v);
1477 
1478 }
1479 
1480 void
1481 lhz(ulong ir)
1482 {
1483 	ulong ea;
1484 	int imm, ra, rd, upd;
1485 
1486 	getairr(ir);
1487 	ea = imm;
1488 	upd = (ir&(1L<<26))!=0;
1489 	if(ra) {
1490 		ea += reg.r[ra];
1491 		if(upd)
1492 			reg.r[ra] = ea;
1493 	} else {
1494 		if(upd)
1495 			undef(ir);
1496 	}
1497 	if(trace)
1498 		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1499 
1500 	reg.r[rd] = getmem_h(ea);
1501 }
1502 
1503 void
1504 lhzx(ulong ir)
1505 {
1506 	ulong ea;
1507 	int rb, ra, rd, upd;
1508 
1509 	getarrr(ir);
1510 	ea = reg.r[rb];
1511 	upd = getxo(ir)==311;
1512 	if(ra) {
1513 		ea += reg.r[ra];
1514 		if(upd)
1515 			reg.r[ra] = ea;
1516 		if(trace)
1517 			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1518 	} else {
1519 		if(upd)
1520 			undef(ir);
1521 		if(trace)
1522 			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1523 	}
1524 
1525 	reg.r[rd] = getmem_h(ea);
1526 }
1527 
1528 void
1529 lha(ulong ir)
1530 {
1531 	ulong ea;
1532 	int imm, ra, rd, upd;
1533 
1534 	getairr(ir);
1535 	ea = imm;
1536 	upd = (ir&(1L<<26))!=0;
1537 	if(ra) {
1538 		ea += reg.r[ra];
1539 		if(upd)
1540 			reg.r[ra] = ea;
1541 	} else {
1542 		if(upd)
1543 			undef(ir);
1544 	}
1545 	if(trace)
1546 		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1547 
1548 	reg.r[rd] = (short)getmem_h(ea);
1549 }
1550 
1551 void
1552 lhax(ulong ir)
1553 {
1554 	ulong ea;
1555 	int rb, ra, rd, upd;
1556 
1557 	getarrr(ir);
1558 	ea = reg.r[rb];
1559 	upd = getxo(ir)==311;
1560 	if(ra) {
1561 		ea += reg.r[ra];
1562 		if(upd)
1563 			reg.r[ra] = ea;
1564 		if(trace)
1565 			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1566 	} else {
1567 		if(upd)
1568 			undef(ir);
1569 		if(trace)
1570 			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1571 	}
1572 
1573 	reg.r[rd] = (short)getmem_h(ea);
1574 }
1575 
1576 void
1577 lhbrx(ulong ir)
1578 {
1579 	ulong ea;
1580 	int rb, ra, rd;
1581 	ulong v;
1582 
1583 	getarrr(ir);
1584 	ea = reg.r[rb];
1585 	if(ra) {
1586 		ea += reg.r[ra];
1587 		if(trace)
1588 			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1589 	} else {
1590 		if(trace)
1591 			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1592 	}
1593 	v = getmem_h(ea);
1594 
1595 	reg.r[rd] = ((v&0xFF)<<8)|(v&0xFF);
1596 }
1597 
1598 void
1599 sth(ulong ir)
1600 {
1601 	ulong ea;
1602 	int imm, ra, rd, upd, v;
1603 
1604 	getairr(ir);
1605 	ea = imm;
1606 	upd = (ir&(1L<<26))!=0;
1607 	if(ra) {
1608 		ea += reg.r[ra];
1609 		if(upd)
1610 			reg.r[ra] = ea;
1611 	} else {
1612 		if(upd)
1613 			undef(ir);
1614 	}
1615 	v = reg.r[rd] & 0xFFFF;
1616 	if(trace)
1617 		itrace("%s\tr%d,%ld(r%d) #%lux=#%lux (%ld)",
1618 					ci->name, rd, imm, ra, ea, v, v);
1619 	putmem_h(ea, v);
1620 
1621 }
1622 
1623 void
1624 sthx(ulong ir)
1625 {
1626 	ulong ea;
1627 	int ra, rd, upd, rb, v;
1628 
1629 	getarrr(ir);
1630 	ea = reg.r[rb];
1631 	upd = getxo(ir)==247;
1632 	v = reg.r[rd] & 0xFFFF;
1633 	if(ra) {
1634 		ea += reg.r[ra];
1635 		if(upd)
1636 			reg.r[ra] = ea;
1637 		if(trace)
1638 			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1639 					ci->name, rd, ra, rb, ea, v, v);
1640 	} else {
1641 		if(upd)
1642 			undef(ir);
1643 		if(trace)
1644 			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1645 					ci->name, rd, rb, ea, v, v);
1646 	}
1647 	putmem_h(ea, v);
1648 }
1649 
1650 void
1651 sthbrx(ulong ir)
1652 {
1653 	ulong ea;
1654 	int ra, rd, rb;
1655 	ulong v;
1656 
1657 	getarrr(ir);
1658 	ea = reg.r[rb];
1659 	v = reg.r[rd];
1660 	v = ((v&0xFF)<<8)|(v&0xFF);
1661 	if(ra) {
1662 		ea += reg.r[ra];
1663 		if(trace)
1664 			itrace("%s\tr%d,(r%d+r%d) #%lux=#%lux (%ld)",
1665 					ci->name, rd, ra, rb, ea, v, v);
1666 	} else {
1667 		if(trace)
1668 			itrace("%s\tr%d,(r%d) #%lux=#%lux (%ld)",
1669 					ci->name, rd, rb, ea, v, v);
1670 	}
1671 	putmem_h(ea, v);
1672 }
1673 
1674 void
1675 lwbrx(ulong ir)
1676 {
1677 	ulong ea;
1678 	int rb, ra, rd, i;
1679 	ulong v;
1680 
1681 	getarrr(ir);
1682 	if(ir & Rc)
1683 		undef(ir);
1684 	ea = reg.r[rb];
1685 	if(ra) {
1686 		ea += reg.r[ra];
1687 		if(trace)
1688 			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1689 	} else {
1690 		if(trace)
1691 			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1692 	}
1693 	v = 0;
1694 	for(i = 0; i < 4; i++)
1695 		v = v>>8 | getmem_b(ea++);	/* assume unaligned load is allowed */
1696 	reg.r[rd] = v;
1697 }
1698 
1699 void
1700 stwbrx(ulong ir)
1701 {
1702 	ulong ea;
1703 	int rb, ra, rd, i;
1704 	ulong v;
1705 
1706 	getarrr(ir);
1707 	if(ir & Rc)
1708 		undef(ir);
1709 	ea = reg.r[rb];
1710 	if(ra) {
1711 		ea += reg.r[ra];
1712 		if(trace)
1713 			itrace("%s\tr%d,(r%d+r%d) ea=%lux", ci->name, rd, ra, rb, ea);
1714 	} else {
1715 		if(trace)
1716 			itrace("%s\tr%d,(r%d) ea=%lux", ci->name, rd, rb, ea);
1717 	}
1718 	v = 0;
1719 	for(i = 0; i < 4; i++) {
1720 		putmem_b(ea++, v & 0xFF);	/* assume unaligned store is allowed */
1721 		v >>= 8;
1722 	}
1723 }
1724 
1725 void
1726 lswi(ulong ir)
1727 {
1728 	ulong ea;
1729 	int rb, ra, rd, n, i, r, b;
1730 
1731 	getarrr(ir);
1732 	if(ir & Rc)
1733 		undef(ir);
1734 	n = rb;
1735 	if(n == 0)
1736 		n = 32;
1737 	ea = 0;
1738 	if(ra) {
1739 		ea += reg.r[ra];
1740 		if(trace)
1741 			itrace("%s\tr%d,(r%d),%d ea=%lux", ci->name, rd, ra, n, ea);
1742 	} else {
1743 		if(trace)
1744 			itrace("%s\tr%d,(0),%d ea=0", ci->name, rd, n);
1745 	}
1746 	i = -1;
1747 	r = rd-1;
1748 	while(--n >= 0) {
1749 		if(i < 0) {
1750 			r = (r+1)&0x1F;
1751 			if(ra == 0 || r != ra)
1752 				reg.r[r] = 0;
1753 			i = 24;
1754 		}
1755 		b = getmem_b(ea++);
1756 		if(ra == 0 || r != ra)
1757 			reg.r[r] = (reg.r[r] & ~(0xFF<<i)) | (b << i);
1758 		i -= 8;
1759 	}
1760 }
1761 
1762 void
1763 lswx(ulong ir)
1764 {
1765 	ulong ea;
1766 	int rb, ra, rd, n, i, r, b;
1767 
1768 	getarrr(ir);
1769 	if(ir & Rc)
1770 		undef(ir);
1771 	n = reg.xer & 0x7F;
1772 	ea = reg.r[rb];
1773 	if(ra) {
1774 		ea += reg.r[ra];
1775 		if(trace)
1776 			itrace("%s\tr%d,(r%d+r%d) ea=%lux n=%d", ci->name, rd, ra, rb, ea, n);
1777 	} else {
1778 		if(trace)
1779 			itrace("%s\tr%d,(r%d) ea=%lux n=%d", ci->name, rd, rb, ea, n);
1780 	}
1781 	i = -1;
1782 	r = rd-1;
1783 	while(--n >= 0) {
1784 		if(i < 0) {
1785 			r = (r+1)&0x1F;
1786 			if((ra == 0 || r != ra) && r != rb)
1787 				reg.r[r] = 0;
1788 			i = 24;
1789 		}
1790 		b = getmem_b(ea++);
1791 		if((ra == 0 || r != ra) && r != rb)
1792 			reg.r[r] = (reg.r[r] & ~(0xFF<<i)) | (b << i);
1793 		i -= 8;
1794 	}
1795 }
1796 
1797 void
1798 stswx(ulong ir)
1799 {
1800 	ulong ea;
1801 	int rb, ra, rd, n, i, r;
1802 
1803 	getarrr(ir);
1804 	if(ir & Rc)
1805 		undef(ir);
1806 	n = reg.xer & 0x7F;
1807 	ea = reg.r[rb];
1808 	if(ra) {
1809 		ea += reg.r[ra];
1810 		if(trace)
1811 			itrace("%s\tr%d,(r%d+r%d) ea=%lux n=%d", ci->name, rd, ra, rb, ea, n);
1812 	} else {
1813 		if(trace)
1814 			itrace("%s\tr%d,(r%d) ea=%lux n=%d", ci->name, rd, rb, ea, n);
1815 	}
1816 	i = -1;
1817 	r = rd-1;
1818 	while(--n >= 0) {
1819 		if(i < 0) {
1820 			r = (r+1)&0x1F;
1821 			i = 24;
1822 		}
1823 		putmem_b(ea++, (reg.r[r]>>i)&0xFF);
1824 		i -= 8;
1825 	}
1826 }
1827 
1828 void
1829 stswi(ulong ir)
1830 {
1831 	ulong ea;
1832 	int rb, ra, rd, n, i, r;
1833 
1834 	getarrr(ir);
1835 	if(ir & Rc)
1836 		undef(ir);
1837 	n = rb;
1838 	if(n == 0)
1839 		n = 32;
1840 	ea = 0;
1841 	if(ra) {
1842 		ea += reg.r[ra];
1843 		if(trace)
1844 			itrace("%s\tr%d,(r%d),%d ea=%lux", ci->name, rd, ra, n, ea);
1845 	} else {
1846 		if(trace)
1847 			itrace("%s\tr%d,(0),%d ea=0", ci->name, rd, n);
1848 	}
1849 	i = -1;
1850 	r = rd-1;
1851 	while(--n >= 0) {
1852 		if(i < 0) {
1853 			r = (r+1)&0x1F;
1854 			i = 24;
1855 		}
1856 		putmem_b(ea++, (reg.r[r]>>i)&0xFF);
1857 		i -= 8;
1858 	}
1859 }
1860 
1861 void
1862 lmw(ulong ir)
1863 {
1864 	ulong ea;
1865 	int ra, rd, r;
1866 	long imm;
1867 
1868 	getairr(ir);
1869 	ea = imm;
1870 	if(ra)
1871 		ea += reg.r[ra];
1872 	if(trace)
1873 		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1874 
1875 	for(r = rd; r <= 31; r++) {
1876 		if(r != 0 && r != rd)
1877 			reg.r[rd] = getmem_w(ea);
1878 		ea += 4;
1879 	}
1880 }
1881 
1882 void
1883 stmw(ulong ir)
1884 {
1885 	ulong ea;
1886 	int ra, rd, r;
1887 	long imm;
1888 
1889 	getairr(ir);
1890 	ea = imm;
1891 	if(ra)
1892 		ea += reg.r[ra];
1893 	if(trace)
1894 		itrace("%s\tr%d,%ld(r%d) ea=%lux", ci->name, rd, imm, ra, ea);
1895 
1896 	for(r = rd; r <= 31; r++) {
1897 		putmem_w(ea, reg.r[rd]);
1898 		ea += 4;
1899 	}
1900 }
1901 
1902 void
1903 twi(ulong ir)
1904 {
1905 	int rd, ra;
1906 	long a, imm;
1907 
1908 	getairr(ir);
1909 	a = reg.r[ra];
1910 	if(trace)
1911 		itrace("twi\t#%.2x,r%d,$0x%lux (%ld)", rd, ra, imm, imm);
1912 	if(a < imm && rd&0x10 ||
1913 	   a > imm && rd&0x08 ||
1914 	   a == imm && rd&0x04 ||
1915 	   (ulong)a < imm && rd&0x02 ||
1916 	   (ulong)a > imm && rd&0x01) {
1917 		Bprint(bioout, "program_exception (trap type)\n");
1918 		longjmp(errjmp, 0);
1919 	}
1920 }
1921 
1922 void
1923 tw(ulong ir)
1924 {
1925 	int rd, ra, rb;
1926 	long a, b;
1927 
1928 	getarrr(ir);
1929 	a = reg.r[ra];
1930 	b = reg.r[rb];
1931 	if(trace)
1932 		itrace("tw\t#%.2x,r%d,r%d", rd, ra, rb);
1933 	if(a < b && rd&0x10 ||
1934 	   a > b && rd&0x08 ||
1935 	   a == b && rd&0x04 ||
1936 	   (ulong)a < b && rd&0x02 ||
1937 	   (ulong)a > b && rd&0x01) {
1938 		Bprint(bioout, "program_exception (trap type)\n");
1939 		longjmp(errjmp, 0);
1940 	}
1941 }
1942 
1943 void
1944 sync(ulong ir)
1945 {
1946 	USED(ir);
1947 	if(trace)
1948 		itrace("sync");
1949 }
1950 
1951 void
1952 icbi(ulong ir)
1953 {
1954 	int rd, ra, rb;
1955 
1956 	if(ir & Rc)
1957 		undef(ir);
1958 	getarrr(ir);
1959 	USED(rd);
1960 	if(trace)
1961 		itrace("%s\tr%d,r%d", ci->name, ra, rb);
1962 }
1963 
1964 void
1965 dcbf(ulong ir)
1966 {
1967 	int rd, ra, rb;
1968 
1969 	if(ir & Rc)
1970 		undef(ir);
1971 	getarrr(ir);
1972 	USED(rd);
1973 	if(trace)
1974 		itrace("%s\tr%d,r%d", ci->name, ra, rb);
1975 }
1976 
1977 void
1978 dcbst(ulong ir)
1979 {
1980 	int rd, ra, rb;
1981 
1982 	if(ir & Rc)
1983 		undef(ir);
1984 	getarrr(ir);
1985 	USED(rd);
1986 	if(trace)
1987 		itrace("%s\tr%d,r%d", ci->name, ra, rb);
1988 }
1989 
1990 void
1991 dcbt(ulong ir)
1992 {
1993 	int rd, ra, rb;
1994 
1995 	if(ir & Rc)
1996 		undef(ir);
1997 	getarrr(ir);
1998 	USED(rd);
1999 	if(trace)
2000 		itrace("%s\tr%d,r%d", ci->name, ra, rb);
2001 }
2002 
2003 void
2004 dcbtst(ulong ir)
2005 {
2006 	int rd, ra, rb;
2007 
2008 	if(ir & Rc)
2009 		undef(ir);
2010 	getarrr(ir);
2011 	USED(rd);
2012 	if(trace)
2013 		itrace("%s\tr%d,r%d", ci->name, ra, rb);
2014 }
2015 
2016 void
2017 dcbz(ulong ir)
2018 {
2019 	int rd, ra, rb;
2020 
2021 	if(ir & Rc)
2022 		undef(ir);
2023 	getarrr(ir);
2024 	USED(rd);
2025 	if(trace)
2026 		itrace("%s\tr%d,r%d", ci->name, ra, rb);
2027 }
2028