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 = ®.xer; n = "xer";
215 break;
216 case 268:
217 case 284:
218 d = ®.tbl; n = "tbl";
219 break;
220 case 269:
221 case 285:
222 d = ®.tbu; n = "tbu";
223 break;
224 case 22:
225 d = ®.dec; n = "dec";
226 break;
227 case 8:
228 d = ®.lr; n = "lr";
229 break;
230 case 9:
231 d = ®.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