]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/qi/iu.c
realemu: implement IDIV, mark 0xE0000 writeable, fix DIV overfow trap
[plan9front.git] / sys / src / cmd / qi / iu.c
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                 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1298 lwarx(ulong ir)
1299 {
1300         lwzx(ir);
1301 }
1302
1303 void
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
1946 sync(ulong ir)
1947 {
1948         USED(ir);
1949         if(trace)
1950                 itrace("sync");
1951 }
1952
1953 void
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
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
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
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
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
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 }