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