fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/ppc405/disasm.c *
7 * Created: 2003-11-08 by Hampa Hug <hampa@hampa.ch> *
8 * Copyright: (C) 2003-2018 Hampa Hug <hampa@hampa.ch> *
9 * Copyright: (C) 2003-2006 Lukas Ruf <ruf@lpr.ch> *
10 *****************************************************************************/
11
12/*****************************************************************************
13 * This program is free software. You can redistribute it and / or modify it *
14 * under the terms of the GNU General Public License version 2 as published *
15 * by the Free Software Foundation. *
16 * *
17 * This program is distributed in the hope that it will be useful, but *
18 * WITHOUT ANY WARRANTY, without even the implied warranty of *
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General *
20 * Public License for more details. *
21 *****************************************************************************/
22
23/*****************************************************************************
24 * This software was developed at the Computer Engineering and Networks *
25 * Laboratory (TIK), Swiss Federal Institute of Technology (ETH) Zurich. *
26 *****************************************************************************/
27
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "ppc405.h"
34#include "internal.h"
35
36
37typedef void (*p405_disasm_f) (p405_disasm_t *dis);
38
39typedef struct {
40 unsigned op;
41 p405_disasm_f fct;
42} p405_disasm_list_t;
43
44
45static void p405_disasm_init (void);
46
47static p405_disasm_f p405_op13[1024];
48static p405_disasm_f p405_op1f[1024];
49static p405_disasm_f p405_op[64];
50
51
52#define ARG_NONE 0
53#define ARG_RA 1
54#define ARG_RB 2
55#define ARG_RS 3
56#define ARG_RT 4
57#define ARG_RA0 5
58#define ARG_SIMM16 6
59#define ARG_UIMM16 7
60#define ARG_IMM16S 8
61#define ARG_UINT3 9
62#define ARG_UINT5 10
63#define ARG_UINT8 11
64#define ARG_UINT16 12
65#define ARG_UINT32 13
66#define ARG_CRBIT 14
67#define ARG_SPRN 15
68#define ARG_DCRN 16
69
70
71#define OPF_OE 0x0001
72#define OPF_RC 0x0002
73
74
75static char p405_disasm_inited = 0;
76
77static
78char *p405_cr_name[2][4] = {
79 { "lt", "gt", "eq", "so" },
80 { "ge", "le", "ne", "ns" }
81};
82
83
84static
85const char *disasm_get_spr (unsigned sprn)
86{
87 switch (sprn) {
88 case P405_SPRN_CCR0:
89 return ("ccr0");
90
91 case P405_SPRN_CTR:
92 return ("ctr");
93
94 case P405_SPRN_DAC1:
95 return ("dac1");
96
97 case P405_SPRN_DAC2:
98 return ("dac2");
99
100 case P405_SPRN_DBCR0:
101 return ("dbcr0");
102
103 case P405_SPRN_DBCR1:
104 return ("dbcr1");
105
106 case P405_SPRN_DBSR:
107 return ("dbsr");
108
109 case P405_SPRN_DCCR:
110 return ("dccr");
111
112 case P405_SPRN_DCWR:
113 return ("dcwr");
114
115 case P405_SPRN_DVC1:
116 return ("dvc1");
117
118 case P405_SPRN_DVC2:
119 return ("dvc2");
120
121 case P405_SPRN_DEAR:
122 return ("dear");
123
124 case P405_SPRN_ESR:
125 return ("esr");
126
127 case P405_SPRN_EVPR:
128 return ("evpr");
129
130 case P405_SPRN_IAC1:
131 return ("iac1");
132
133 case P405_SPRN_IAC2:
134 return ("iac2");
135
136 case P405_SPRN_IAC3:
137 return ("iac3");
138
139 case P405_SPRN_IAC4:
140 return ("iac4");
141
142 case P405_SPRN_ICCR:
143 return ("iccr");
144
145 case P405_SPRN_ICDBDR:
146 return ("icdbdr");
147
148 case P405_SPRN_LR:
149 return ("lr");
150
151 case P405_SPRN_PID:
152 return ("pid");
153
154 case P405_SPRN_PIT:
155 return ("pit");
156
157 case P405_SPRN_PVR:
158 return ("pvr");
159
160 case P405_SPRN_SGR:
161 return ("sgr");
162
163 case P405_SPRN_SLER:
164 return ("sler");
165
166 case P405_SPRN_SPRG0:
167 return ("sprg0");
168
169 case P405_SPRN_SPRG1:
170 return ("sprg1");
171
172 case P405_SPRN_SPRG2:
173 return ("sprg2");
174
175 case P405_SPRN_SPRG3:
176 return ("sprg3");
177
178 case P405_SPRN_SPRG4:
179 return ("sprg4");
180
181 case P405_SPRN_SPRG5:
182 return ("sprg5");
183
184 case P405_SPRN_SPRG6:
185 return ("sprg6");
186
187 case P405_SPRN_SPRG7:
188 return ("sprg7");
189
190 case P405_SPRN_SPRG4R:
191 return ("sprg4r");
192
193 case P405_SPRN_SPRG5R:
194 return ("sprg5r");
195
196 case P405_SPRN_SPRG6R:
197 return ("sprg6r");
198
199 case P405_SPRN_SPRG7R:
200 return ("sprg7r");
201
202 case P405_SPRN_SRR0:
203 return ("srr0");
204
205 case P405_SPRN_SRR1:
206 return ("srr1");
207
208 case P405_SPRN_SRR2:
209 return ("srr2");
210
211 case P405_SPRN_SRR3:
212 return ("srr3");
213
214 case P405_SPRN_SU0R:
215 return ("su0r");
216
217 case P405_SPRN_TBL:
218 case P405_SPRN_TBLU:
219 return ("tbl");
220
221 case P405_SPRN_TBU:
222 case P405_SPRN_TBUU:
223 return ("tbu");
224
225 case P405_SPRN_TCR:
226 return ("tcr");
227
228 case P405_SPRN_TSR:
229 return ("tsr");
230
231 case P405_SPRN_USPRG0:
232 return ("usprg0");
233
234 case P405_SPRN_XER:
235 return ("xer");
236
237 case P405_SPRN_ZPR:
238 return ("zpr");
239 }
240
241 return (NULL);
242}
243
244static
245void disasm_dw (p405_disasm_t *dis, uint32_t val)
246{
247 dis->argn = 1;
248 strcpy (dis->op, "dw");
249 sprintf (dis->arg1, "%08lx", (unsigned long) val);
250}
251
252static
253void disasm_arg_reg (p405_disasm_t *dis, char *dst, unsigned r)
254{
255 r &= 0x1f;
256
257 *(dst++) = 'r';
258
259 if (r > 9) {
260 *(dst++) = '0' + (r / 10);
261 }
262
263 *(dst++) = '0' + (r % 10);
264
265 *dst = 0;
266
267 dis->reg |= 1UL << r;
268}
269
270static
271void disasm_arg_imm32 (char *dst, unsigned long val)
272{
273 unsigned i, tmp;
274
275 dst += 8;
276 *dst = 0;
277
278 for (i = 0; i < 8; i++) {
279 tmp = val & 0x0f;
280 val = val >> 4;
281
282 if (tmp < 10) {
283 tmp += '0';
284 }
285 else {
286 tmp = tmp - 10 + 'a';
287 }
288
289 *(--dst) = tmp;
290 }
291}
292
293static
294void disasm_arg (p405_disasm_t *dis, char *dst, uint32_t ir, unsigned arg, uint32_t par)
295{
296 switch (arg) {
297 case ARG_NONE:
298 dst[0] = 0;
299 break;
300
301 case ARG_RA:
302 disasm_arg_reg (dis, dst, p405_get_ir_ra (ir));
303 break;
304
305 case ARG_RB:
306 disasm_arg_reg (dis, dst, p405_get_ir_rb (ir));
307 break;
308
309 case ARG_RS:
310 disasm_arg_reg (dis, dst, p405_get_ir_rs (ir));
311 break;
312
313 case ARG_RT:
314 disasm_arg_reg (dis, dst, p405_get_ir_rt (ir));
315 break;
316
317 case ARG_RA0:
318 if (p405_get_ir_ra (ir) == 0) {
319 dst[0] = '0';
320 dst[1] = 0;
321 }
322 else {
323 disasm_arg_reg (dis, dst, p405_get_ir_ra (ir));
324 }
325 break;
326
327 case ARG_SIMM16:
328 disasm_arg_imm32 (dst, p405_sext (ir, 16));
329 break;
330
331 case ARG_UIMM16:
332 disasm_arg_imm32 (dst, p405_uext (ir, 16));
333 break;
334
335 case ARG_IMM16S:
336 disasm_arg_imm32 (dst, (ir & 0xffff) << 16);
337 break;
338
339 case ARG_UINT3:
340 sprintf (dst, "%x", (unsigned) (par & 0x07));
341 break;
342
343 case ARG_UINT5:
344 sprintf (dst, "%02x", (unsigned) (par & 0x1f));
345 break;
346
347 case ARG_UINT8:
348 sprintf (dst, "%02x", (unsigned) (par & 0xff));
349 break;
350
351 case ARG_UINT16:
352 sprintf (dst, "%04x", (unsigned) (par & 0xffffU));
353 break;
354
355 case ARG_UINT32:
356 disasm_arg_imm32 (dst, par & 0xffffffff);
357 break;
358
359 case ARG_CRBIT:
360 sprintf (dst, "%s[%u]", p405_cr_name[0][par & 0x03], (unsigned) par / 4);
361 break;
362
363 case ARG_SPRN: {
364 const char *spr = disasm_get_spr (par);
365 if (spr != NULL) {
366 strcpy (dst, spr);
367 }
368 else {
369 sprintf (dst, "%03x", par);
370 }
371 }
372 break;
373
374 case ARG_DCRN:
375 sprintf (dst, "%03x", par);
376 break;
377 }
378}
379
380static
381int disasm_op0 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res)
382{
383 if (dis->ir & res) {
384 disasm_dw (dis, dis->ir);
385 return (1);
386 }
387
388 strcpy (dis->op, op);
389
390 if (opf & OPF_OE) {
391 if (p405_get_ir_oe (dis->ir)) {
392 strcat (dis->op, "o");
393 }
394 }
395
396 if (opf & OPF_RC) {
397 if (p405_get_ir_rc (dis->ir)) {
398 strcat (dis->op, ".");
399 }
400 }
401
402 dis->argn = 0;
403
404 return (0);
405}
406
407static
408int disasm_op1 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res,
409 unsigned arg1, uint32_t par1)
410{
411 if (disasm_op0 (dis, op, opf, res)) {
412 return (1);
413 }
414
415 dis->argn = 1;
416 disasm_arg (dis, dis->arg1, dis->ir, arg1, par1);
417
418 return (0);
419}
420
421static
422int disasm_op2 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res,
423 unsigned arg1, unsigned arg2, uint32_t par1, uint32_t par2)
424{
425 if (disasm_op1 (dis, op, opf, res, arg1, par1)) {
426 return (1);
427 }
428
429 dis->argn = 2;
430 disasm_arg (dis, dis->arg2, dis->ir, arg2, par2);
431
432 return (0);
433}
434
435static
436int disasm_op3 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res,
437 unsigned arg1, unsigned arg2, unsigned arg3,
438 uint32_t par1, uint32_t par2, uint32_t par3)
439{
440 if (disasm_op2 (dis, op, opf, res, arg1, arg2, par1, par2)) {
441 return (1);
442 }
443
444 dis->argn = 3;
445 disasm_arg (dis, dis->arg3, dis->ir, arg3, par3);
446
447 return (0);
448}
449
450static
451int disasm_op4 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res,
452 unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4,
453 uint32_t par1, uint32_t par2, uint32_t par3, uint32_t par4)
454{
455 if (disasm_op3 (dis, op, opf, res, arg1, arg2, arg3, par1, par2, par3)) {
456 return (1);
457 }
458
459 dis->argn = 4;
460 disasm_arg (dis, dis->arg4, dis->ir, arg4, par4);
461
462 return (0);
463}
464
465static
466int disasm_op5 (p405_disasm_t *dis, const char *op, uint32_t opf, uint32_t res,
467 unsigned arg1, unsigned arg2, unsigned arg3, unsigned arg4, unsigned arg5,
468 uint32_t par1, uint32_t par2, uint32_t par3, uint32_t par4, uint32_t par5)
469{
470 if (disasm_op4 (dis, op, opf, res, arg1, arg2, arg3, arg4, par1, par2, par3, par4)) {
471 return (1);
472 }
473
474 dis->argn = 5;
475 disasm_arg (dis, dis->arg5, dis->ir, arg5, par5);
476
477 return (0);
478}
479
480static
481void disasm_u32 (char *dst, unsigned long val)
482{
483 sprintf (dst, "%08lx", val & 0xffffffffUL);
484}
485
486static
487void disasm_undefined (p405_disasm_t *dis)
488{
489 disasm_dw (dis, dis->ir);
490}
491
492/* crxxx bt, ba, bb */
493static
494void disasm_crxxx (p405_disasm_t *dis, const char *op)
495{
496 disasm_op3 (dis, op, 0, 0x01, ARG_CRBIT, ARG_CRBIT, ARG_CRBIT,
497 p405_get_ir_rt (dis->ir), p405_get_ir_ra (dis->ir), p405_get_ir_rb (dis->ir)
498 );
499}
500
501
502/* branch conditional */
503static
504void disasm_bc (p405_disasm_t *dis, const char *op, const char *dst,
505 unsigned bo, unsigned bi, int aa, int lk)
506{
507 int bo0, bo1, bo2, bo3;
508 char buf[64];
509
510 bo0 = (bo & 0x10) != 0;
511 bo1 = (bo & 0x08) != 0;
512 bo2 = (bo & 0x04) != 0;
513 bo3 = (bo & 0x02) != 0;
514
515 strcpy (dis->op, "b");
516
517 dis->argn = 0;
518
519 if (bo2 == 0) {
520 strcat (dis->op, "d");
521 }
522
523 if (bo0 == 0) {
524 strcat (dis->op, p405_cr_name[!bo1][bi & 0x03]);
525
526 if (bi > 3) {
527 sprintf (buf, "[%u]", bi / 4);
528 strcat (dis->op, buf);
529 }
530 }
531
532 strcat (dis->op, op);
533
534 if (lk) {
535 strcat (dis->op, "l");
536 dis->flags |= P405_DFLAG_CALL;
537 }
538
539 if (aa) {
540 strcat (dis->op, "a");
541 }
542
543 if (bo2 == 0) {
544 if (bo3) {
545 strcat (dis->op, "=");
546 }
547 else {
548 strcat (dis->op, ">");
549 }
550 }
551
552 if (dst != NULL) {
553 strcpy (dis->arg1, dst);
554 dis->argn += 1;
555 }
556}
557
558
559static void opd_ud (p405_disasm_t *dis)
560{
561 disasm_undefined (dis);
562}
563
564/* 03: twi to, ra, simm16 */
565static
566void opd_03 (p405_disasm_t *dis)
567{
568 disasm_op3 (dis, "twi", 0, 0, ARG_UINT5, ARG_RA, ARG_SIMM16,
569 p405_bits (dis->ir, 6, 5), 0, 0
570 );
571}
572
573/* 07: mulli rt, ra, simm16 */
574static
575void opd_07 (p405_disasm_t *dis)
576{
577 disasm_op3 (dis, "mulli", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
578}
579
580/* 08: subfic rt, ra, simm16 */
581static
582void opd_08 (p405_disasm_t *dis)
583{
584 disasm_op3 (dis, "subfic", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
585}
586
587/* 0A: cmpli bf, ra, simm16 */
588static
589void opd_0a (p405_disasm_t *dis)
590{
591 disasm_op3 (dis, "cmpli", 0, 0,
592 ARG_UINT3, ARG_RA, ARG_SIMM16, (dis->ir >> 23) & 0x07, 0, 0
593 );
594}
595
596/* 0B: cmpi bf, ra, simm16 */
597static
598void opd_0b (p405_disasm_t *dis)
599{
600 disasm_op3 (dis, "cmpi", 0, 0,
601 ARG_UINT3, ARG_RA, ARG_SIMM16, (dis->ir >> 23) & 0x07, 0, 0
602 );
603}
604
605/* 0C: addic rt, ra, simm16 */
606static
607void opd_0c (p405_disasm_t *dis)
608{
609 disasm_op3 (dis, "addic", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
610}
611
612/* 0D: addic. rt, ra, simm16 */
613static
614void opd_0d (p405_disasm_t *dis)
615{
616 disasm_op3 (dis, "addic.", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
617}
618
619/* 0E: addi rt, ra0, simm16 */
620static
621void opd_0e (p405_disasm_t *dis)
622{
623 if (p405_get_ir_ra (dis->ir) == 0) {
624 disasm_op2 (dis, "li", 0, 0, ARG_RT, ARG_SIMM16, 0, 0);
625 }
626 else {
627 disasm_op3 (dis, "addi", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0);
628 }
629}
630
631/* 0F: addis rt, ra0, simm16 */
632static
633void opd_0f (p405_disasm_t *dis)
634{
635 if (p405_get_ir_ra (dis->ir) == 0) {
636 disasm_op2 (dis, "lis", 0, 0, ARG_RT, ARG_IMM16S, 0, 0);
637 }
638 else {
639 disasm_op3 (dis, "addis", 0, 0, ARG_RT, ARG_RA0, ARG_IMM16S, 0, 0, 0);
640 }
641}
642
643/* 10: bc/bcl/bca/bcla target */
644static
645void opd_10 (p405_disasm_t *dis)
646{
647 uint32_t bd;
648 char dst[256];
649
650 bd = p405_sext (dis->ir & 0xfffcUL, 16);
651
652 if (p405_get_ir_aa (dis->ir) == 0) {
653 bd = (dis->pc + bd) & 0xffffffffUL;
654 }
655
656 if (p405_get_ir_lk (dis->ir)) {
657 dis->flags |= P405_DFLAG_CALL;
658 }
659
660 disasm_u32 (dst, bd);
661
662 disasm_bc (dis, "", dst,
663 (dis->ir >> 21) & 0x1f, (dis->ir >> 16) & 0x1f,
664 (dis->ir & P405_IR_AA) != 0, (dis->ir & P405_IR_LK) != 0
665 );
666}
667
668/* 11: sc */
669static
670void opd_11 (p405_disasm_t *dis)
671{
672 disasm_op0 (dis, "sc", 0, 0x03fffffdUL);
673 dis->flags |= P405_DFLAG_CALL;
674}
675
676/* 12: b/bl/ba/bla target */
677static
678void opd_12 (p405_disasm_t *dis)
679{
680 uint32_t li;
681
682 strcpy (dis->op, "b");
683
684 li = p405_sext (dis->ir, 26) & 0xfffffffcUL;
685
686 if (p405_get_ir_lk (dis->ir)) {
687 strcat (dis->op, "l");
688 dis->flags |= P405_DFLAG_CALL;
689 }
690
691 if (p405_get_ir_aa (dis->ir)) {
692 strcat (dis->op, "a");
693 disasm_u32 (dis->arg1, li);
694 }
695 else {
696 disasm_u32 (dis->arg1, dis->pc + li);
697 }
698
699 dis->argn = 1;
700}
701
702/* 13 000: mcrf bf, bfa */
703static
704void opd_13_000 (p405_disasm_t *dis)
705{
706 disasm_op2 (dis, "mcrf", 0, 0x0063f801UL, ARG_UINT3, ARG_UINT3,
707 p405_get_ir_rt (dis->ir) >> 2, p405_get_ir_ra (dis->ir) >> 2
708 );
709}
710
711/* 13 010: bclr/bclrl */
712static
713void opd_13_010 (p405_disasm_t *dis)
714{
715 if (p405_get_ir_lk (dis->ir)) {
716 dis->flags |= P405_DFLAG_CALL;
717 }
718
719 disasm_bc (dis, "lr", NULL,
720 (dis->ir >> 21) & 0x1f, (dis->ir >> 16) & 0x1f,
721 0, (dis->ir & P405_IR_LK) != 0
722 );
723}
724
725/* 13 021: crnor bt, ba, bb */
726static
727void opd_13_021 (p405_disasm_t *dis)
728{
729 disasm_crxxx (dis, "crnor");
730}
731
732/* 13 032: rfi */
733static
734void opd_13_032 (p405_disasm_t *dis)
735{
736 disasm_op0 (dis, "rfi", 0, 0x03fff801UL);
737 dis->flags |= P405_DFLAG_RFI;
738}
739
740/* 13 033: rfci */
741static
742void opd_13_033 (p405_disasm_t *dis)
743{
744 disasm_op0 (dis, "rfci", 0, 0x03fff801UL);
745 dis->flags |= P405_DFLAG_RFI;
746}
747
748/* 13 081: crandc bt, ba, bb */
749static
750void opd_13_081 (p405_disasm_t *dis)
751{
752 disasm_crxxx (dis, "crandc");
753}
754
755/* 13 096: isync */
756static
757void opd_13_096 (p405_disasm_t *dis)
758{
759 disasm_op0 (dis, "isync", 0, 0);
760}
761
762/* 13 0c1: crxor bt, ba, bb */
763static
764void opd_13_0c1 (p405_disasm_t *dis)
765{
766 disasm_crxxx (dis, "crxor");
767}
768
769/* 13 0e1: crnand bt, ba, bb */
770static
771void opd_13_0e1 (p405_disasm_t *dis)
772{
773 disasm_crxxx (dis, "crnand");
774}
775
776/* 13 101: crand bt, ba, bb */
777static
778void opd_13_101 (p405_disasm_t *dis)
779{
780 disasm_crxxx (dis, "crand");
781}
782
783/* 13 121: creqv bt, ba, bb */
784static
785void opd_13_121 (p405_disasm_t *dis)
786{
787 disasm_crxxx (dis, "creqv");
788}
789
790/* 13 1a1: crorc bt, ba, bb */
791static
792void opd_13_1a1 (p405_disasm_t *dis)
793{
794 disasm_crxxx (dis, "crorc");
795}
796
797/* 13 1c1: cror bt, ba, bb */
798static
799void opd_13_1c1 (p405_disasm_t *dis)
800{
801 disasm_crxxx (dis, "cror");
802}
803
804/* 13 210: bcctr/bcctrl */
805static
806void opd_13_210 (p405_disasm_t *dis)
807{
808 if (p405_get_ir_lk (dis->ir)) {
809 dis->flags |= P405_DFLAG_CALL;
810 }
811
812 disasm_bc (dis, "ctr", NULL,
813 (dis->ir >> 21) & 0x1f, (dis->ir >> 16) & 0x1f,
814 0, (dis->ir & P405_IR_LK) != 0
815 );
816}
817
818/* 13: */
819static
820void opd_13 (p405_disasm_t *dis)
821{
822 unsigned op2;
823
824 op2 = (dis->ir >> 1) & 0x3ff;
825
826 p405_op13[op2] (dis);
827}
828
829/* 14: rlwimi[.] ra, rs, sh, mb, me */
830static
831void opd_14 (p405_disasm_t *dis)
832{
833 disasm_op5 (dis, "rlwimi", OPF_RC, 0,
834 ARG_RA, ARG_RS, ARG_UINT5, ARG_UINT5, ARG_UINT5,
835 0, 0, (dis->ir >> 11) & 0x1f, (dis->ir >> 6) & 0x1f, (dis->ir >> 1) & 0x1f
836 );
837}
838
839/* 15: rlwinm[.] ra, rs, sh, mb, me */
840static
841void opd_15 (p405_disasm_t *dis)
842{
843 unsigned sh, mb, me;
844
845 sh = (dis->ir >> 11) & 0x1f;
846 mb = (dis->ir >> 6) & 0x1f;
847 me = (dis->ir >> 1) & 0x1f;
848
849 if ((sh == 0) && (me == 31)) {
850 disasm_op3 (dis, "clrlwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, mb);
851 }
852 else if ((sh == 0) && (mb == 0)) {
853 disasm_op3 (dis, "clrrwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, 31 - me);
854 }
855 else if ((mb == 0) && (me == 31)) {
856 disasm_op3 (dis, "rotlwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, sh);
857 }
858 else if ((mb == 0) && (me == (31 - sh))) {
859 disasm_op3 (dis, "slwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, sh);
860 }
861 else if ((mb == (32 - sh)) && (me == 31)) {
862 disasm_op3 (dis, "srwi", OPF_RC, 0, ARG_RA, ARG_RS, ARG_UINT5, 0, 0, 32 - sh);
863 }
864 else {
865 disasm_op5 (dis, "rlwinm", OPF_RC, 0,
866 ARG_RA, ARG_RS, ARG_UINT5, ARG_UINT5, ARG_UINT5, 0, 0, sh, mb, me
867 );
868 }
869}
870
871/* 17: rlwnm[.] ra, rs, rb, mb, me */
872static
873void opd_17 (p405_disasm_t *dis)
874{
875 unsigned mb, me;
876
877 mb = (dis->ir >> 6) & 0x1f;
878 me = (dis->ir >> 1) & 0x1f;
879
880 if ((mb == 0) && (me == 31)) {
881 disasm_op3 (dis, "rotlw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
882 }
883 else {
884 disasm_op5 (dis, "rlwnm", OPF_RC, 0,
885 ARG_RA, ARG_RS, ARG_RB, ARG_UINT5, ARG_UINT5, 0, 0, 0, mb, me
886 );
887 }
888}
889
890/* 18: ori ra, rs, uimm16 */
891static
892void opd_18 (p405_disasm_t *dis)
893{
894 if ((dis->ir & 0x03ffffffUL) == 0) {
895 disasm_op0 (dis, "nop", 0, 0);
896 }
897 else {
898 disasm_op3 (dis, "ori", 0, 0, ARG_RA, ARG_RS, ARG_UIMM16, 0, 0, 0);
899 }
900}
901
902/* 19: oris ra, rs, uimm16 */
903static
904void opd_19 (p405_disasm_t *dis)
905{
906 disasm_op3 (dis, "oris", 0, 0, ARG_RA, ARG_RS, ARG_IMM16S, 0, 0, 0);
907}
908
909/* 1A: xori ra, rs, uimm16 */
910static
911void opd_1a (p405_disasm_t *dis)
912{
913 disasm_op3 (dis, "xori", 0, 0, ARG_RA, ARG_RS, ARG_UIMM16, 0, 0, 0);
914}
915
916/* 1B: xoris ra, rs, uimm16 */
917static
918void opd_1b (p405_disasm_t *dis)
919{
920 disasm_op3 (dis, "xoris", 0, 0, ARG_RA, ARG_RS, ARG_IMM16S, 0, 0, 0);
921}
922
923/* 1C: andi. ra, rs, uimm16 */
924static
925void opd_1c (p405_disasm_t *dis)
926{
927 disasm_op3 (dis, "andi.", 0, 0, ARG_RA, ARG_RS, ARG_UIMM16, 0, 0, 0);
928}
929
930/* 1D: andis. ra, rs, uimm16 */
931static
932void opd_1d (p405_disasm_t *dis)
933{
934 disasm_op3 (dis, "andis.", 0, 0, ARG_RA, ARG_RS, ARG_IMM16S, 0, 0, 0);
935}
936
937/* 1F 000: cmpw bf, ra, rb */
938static
939void opd_1f_000 (p405_disasm_t *dis)
940{
941 disasm_op3 (dis, "cmpw", 0, 0,
942 ARG_UINT3, ARG_RA, ARG_RB, (dis->ir >> 23) & 0x07, 0, 0
943 );
944}
945
946/* 1F 008: subfc[o][.] rt, ra, rb */
947static
948void opd_1f_008 (p405_disasm_t *dis)
949{
950 disasm_op3 (dis, "subc", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RB, ARG_RA, 0, 0, 0);
951}
952
953/* 1F 00A: addc[o][.] rt, ra, rb */
954static
955void opd_1f_00a (p405_disasm_t *dis)
956{
957 disasm_op3 (dis, "addc", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
958}
959
960/* 1F 00B: mulhwu[.] rt, ra, rb */
961static
962void opd_1f_00b (p405_disasm_t *dis)
963{
964 disasm_op3 (dis, "mulhwu", OPF_RC, 0x00000400UL,
965 ARG_RT, ARG_RA, ARG_RB, 0, 0, 0
966 );
967}
968
969/* 1F 013: mfcr rt */
970static
971void opd_1f_013 (p405_disasm_t *dis)
972{
973 disasm_op1 (dis, "mfcr", 0, 0x001ff801UL, ARG_RT, 0);
974}
975
976/* 1F 014: lwarx rt, ra0, rb */
977static
978void opd_1f_014 (p405_disasm_t *dis)
979{
980 disasm_op3 (dis, "lwarx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
981}
982
983/* 1F 017: lwzx rt, ra0, rb */
984static
985void opd_1f_017 (p405_disasm_t *dis)
986{
987 disasm_op3 (dis, "lwzx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
988}
989
990/* 1F 018: slw[.] ra, rs, rb */
991static
992void opd_1f_018 (p405_disasm_t *dis)
993{
994 disasm_op3 (dis, "slw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
995}
996
997/* 1F 01A: cntlzw[.] ra, rs */
998static
999void opd_1f_01a (p405_disasm_t *dis)
1000{
1001 disasm_op2 (dis, "cntlzw", OPF_RC, 0xf800UL, ARG_RA, ARG_RS, 0, 0);
1002}
1003
1004/* 1F 01C: and[.] ra, rs, rb */
1005static
1006void opd_1f_01c (p405_disasm_t *dis)
1007{
1008 disasm_op3 (dis, "and", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1009}
1010
1011/* 1F 020: cmpwl bf, ra, rb */
1012static
1013void opd_1f_020 (p405_disasm_t *dis)
1014{
1015 disasm_op3 (dis, "cmpwl", 0, 0,
1016 ARG_UINT3, ARG_RA, ARG_RB, (dis->ir >> 23) & 0x07, 0, 0
1017 );
1018}
1019
1020/* 1F 028: subf[o][.] rt, ra, rb */
1021static
1022void opd_1f_028 (p405_disasm_t *dis)
1023{
1024 disasm_op3 (dis, "sub", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RB, ARG_RA, 0, 0, 0);
1025}
1026
1027/* 1F 036: dcbst ra0, rb */
1028static
1029void opd_1f_036 (p405_disasm_t *dis)
1030{
1031 disasm_op2 (dis, "dcbst", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1032}
1033
1034/* 1F 037: lwzux rt, ra, rb */
1035static
1036void opd_1f_037 (p405_disasm_t *dis)
1037{
1038 disasm_op3 (dis, "lwzux", 0, 0x01, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1039}
1040
1041/* 1F 03C: andc[.] ra, rs, rb */
1042static
1043void opd_1f_03c (p405_disasm_t *dis)
1044{
1045 disasm_op3 (dis, "andc", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1046}
1047
1048/* 1F 04B: mulhw[.] rt, ra, rb */
1049static
1050void opd_1f_04b (p405_disasm_t *dis)
1051{
1052 disasm_op3 (dis, "mulhw", OPF_RC, 0x00000400UL,
1053 ARG_RT, ARG_RA, ARG_RB, 0, 0, 0
1054 );
1055}
1056
1057/* 1F 053: mfmsr rt */
1058static
1059void opd_1f_053 (p405_disasm_t *dis)
1060{
1061 disasm_op1 (dis, "mfmsr", 0, 0x001ff801UL, ARG_RT, 0);
1062}
1063
1064/* 1F 056: dcbf ra0, rb */
1065static
1066void opd_1f_056 (p405_disasm_t *dis)
1067{
1068 disasm_op2 (dis, "dcbf", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1069}
1070
1071/* 1F 057: lbzx rt, ra0, rb */
1072static
1073void opd_1f_057 (p405_disasm_t *dis)
1074{
1075 disasm_op3 (dis, "lbzx", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1076}
1077
1078/* 1F 068: neg[o][.] rt, ra */
1079static
1080void opd_1f_068 (p405_disasm_t *dis)
1081{
1082 disasm_op2 (dis, "neg", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, 0, 0);
1083}
1084
1085/* 1F 077: lbzux rt, ra, rb */
1086static
1087void opd_1f_077 (p405_disasm_t *dis)
1088{
1089 disasm_op3 (dis, "lbzux", 0, 0x01, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1090}
1091
1092/* 1F 07C: nor[.] ra, rs, rb */
1093static
1094void opd_1f_07c (p405_disasm_t *dis)
1095{
1096 if (p405_get_ir_rs (dis->ir) == p405_get_ir_rb (dis->ir)) {
1097 disasm_op2 (dis, "not", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0);
1098 }
1099 else {
1100 disasm_op3 (dis, "nor", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1101 }
1102}
1103
1104/* 1F 083: wrtee rs */
1105static
1106void opd_1f_083 (p405_disasm_t *dis)
1107{
1108 disasm_op1 (dis, "wrtee", 0, 0x001ff801UL, ARG_RS, 0);
1109}
1110
1111/* 1F 086: dcbf ra0, rb */
1112static
1113void opd_1f_086 (p405_disasm_t *dis)
1114{
1115 disasm_op2 (dis, "dcbf", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1116}
1117
1118/* 1F 088: subfe[o][.] rt, ra, rb */
1119static
1120void opd_1f_088 (p405_disasm_t *dis)
1121{
1122 disasm_op3 (dis, "subfe", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1123}
1124
1125/* 1F 08A: adde[o][.] rt, ra, rb */
1126static
1127void opd_1f_08a (p405_disasm_t *dis)
1128{
1129 disasm_op3 (dis, "adde", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1130}
1131
1132/* 1F 090: mtcrf fxm, rs */
1133static
1134void opd_1f_090 (p405_disasm_t *dis)
1135{
1136 disasm_op2 (dis, "mtcrf", 0, 0x00100801UL,
1137 ARG_UINT8, ARG_RS, (dis->ir >> 12) & 0xff, 0
1138 );
1139}
1140
1141/* 1F 092: mtmsr rs */
1142static
1143void opd_1f_092 (p405_disasm_t *dis)
1144{
1145 disasm_op1 (dis, "mtmsr", 0, 0x001ff801UL, ARG_RS, 0);
1146}
1147
1148/* 1F 096: stwcx. rs, ra0, rb */
1149static
1150void opd_1f_096 (p405_disasm_t *dis)
1151{
1152 disasm_op3 (dis, "stwcx.", 0, 0, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0);
1153}
1154
1155/* 1F 097: stwx rs, ra0, rb */
1156static
1157void opd_1f_097 (p405_disasm_t *dis)
1158{
1159 disasm_op3 (dis, "stwx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0);
1160}
1161
1162/* 1F 0A3: wrteei e */
1163static
1164void opd_1f_0a3 (p405_disasm_t *dis)
1165{
1166 disasm_op1 (dis, "wrteei", 0, 0x03ff7801UL,
1167 ARG_UINT3, (dis->ir & 0x8000UL) != 0
1168 );
1169}
1170
1171/* 1F 0B7: stwux rs, ra, rb */
1172static
1173void opd_1f_0b7 (p405_disasm_t *dis)
1174{
1175 disasm_op3 (dis, "stwux", 0, 0x01, ARG_RS, ARG_RA, ARG_RB, 0, 0, 0);
1176}
1177
1178/* 1F 0C8: subfze[o][.] rt, ra */
1179static
1180void opd_1f_0c8 (p405_disasm_t *dis)
1181{
1182 disasm_op2 (dis, "subfze", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0);
1183}
1184
1185/* 1F 0CA: addze[o][.] rt, ra */
1186static
1187void opd_1f_0ca (p405_disasm_t *dis)
1188{
1189 disasm_op2 (dis, "addze", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0);
1190}
1191
1192/* 1F 0D7: stbx rs, ra0, rb */
1193static
1194void opd_1f_0d7 (p405_disasm_t *dis)
1195{
1196 disasm_op3 (dis, "stbx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0);
1197}
1198
1199/* 1F 0E8: subfme[o][.] rt, ra */
1200static
1201void opd_1f_0e8 (p405_disasm_t *dis)
1202{
1203 disasm_op2 (dis, "subfme", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0);
1204}
1205
1206/* 1F 0EA: addme[o][.] rt, ra */
1207static
1208void opd_1f_0ea (p405_disasm_t *dis)
1209{
1210 disasm_op2 (dis, "addme", OPF_OE | OPF_RC, 0xf800UL, ARG_RT, ARG_RA, 0, 0);
1211}
1212
1213/* 1F 0EB: mullw[o][.] rt, ra, rb */
1214static
1215void opd_1f_0eb (p405_disasm_t *dis)
1216{
1217 disasm_op3 (dis, "mullw", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1218}
1219
1220/* 1F 0F6: dcbtst ra0, rb */
1221static
1222void opd_1f_0f6 (p405_disasm_t *dis)
1223{
1224 disasm_op2 (dis, "dcbtst", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1225}
1226
1227/* 1F 0F7: stbux rs, ra, rb */
1228static
1229void opd_1f_0f7 (p405_disasm_t *dis)
1230{
1231 disasm_op3 (dis, "stbux", 0, 0x01, ARG_RS, ARG_RA, ARG_RB, 0, 0, 0);
1232}
1233
1234/* 1F 106: icbt ra, rb */
1235static
1236void opd_1f_106 (p405_disasm_t *dis)
1237{
1238 disasm_op2 (dis, "icbt", 0, 0x03e00001UL, ARG_RA, ARG_RB, 0, 0);
1239}
1240
1241/* 1F 10A: add[o][.] rt, ra, rb */
1242static
1243void opd_1f_10a (p405_disasm_t *dis)
1244{
1245 disasm_op3 (dis, "add", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1246}
1247
1248/* 1F 116: dcbt ra0, rb */
1249static
1250void opd_1f_116 (p405_disasm_t *dis)
1251{
1252 disasm_op2 (dis, "dcbt", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1253}
1254
1255/* 1F 117: lhzx rt, ra0, rb */
1256static
1257void opd_1f_117 (p405_disasm_t *dis)
1258{
1259 disasm_op3 (dis, "lhzx", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1260}
1261
1262/* 1F 11C: eqv[.] ra, rs, rb */
1263static
1264void opd_1f_11c (p405_disasm_t *dis)
1265{
1266 disasm_op3 (dis, "eqv", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1267}
1268
1269/* 1F 137: lhzux rt, ra, rb */
1270static
1271void opd_1f_137 (p405_disasm_t *dis)
1272{
1273 disasm_op3 (dis, "lhzux", 0, 0x01, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1274}
1275
1276/* 1F 13C: xor[.] ra, rs, rb */
1277static
1278void opd_1f_13c (p405_disasm_t *dis)
1279{
1280 disasm_op3 (dis, "xor", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1281}
1282
1283/* 1F 143: mfdcr rt, dcrn */
1284static
1285void opd_1f_143 (p405_disasm_t *dis)
1286{
1287 unsigned dcrf, dcrn;
1288
1289 dcrf = (dis->ir >> 11) & 0x3ff;
1290 dcrn = ((dcrf & 0x1f) << 5) | ((dcrf >> 5) & 0x1f);
1291
1292 disasm_op2 (dis, "mfdcr", 0, 0x01, ARG_RT, ARG_DCRN, 0, dcrn);
1293}
1294
1295/* 1F 153: mfspr rt, sprn */
1296static
1297void opd_1f_153 (p405_disasm_t *dis)
1298{
1299 unsigned sprf, sprn;
1300
1301 sprf = (dis->ir >> 11) & 0x3ff;
1302 sprn = ((sprf & 0x1f) << 5) | ((sprf >> 5) & 0x1f);
1303
1304 disasm_op2 (dis, "mfspr", 0, 0x01, ARG_RT, ARG_SPRN, 0, sprn);
1305}
1306
1307/* 1F 157: lhax rt, ra0, rb */
1308static
1309void opd_1f_157 (p405_disasm_t *dis)
1310{
1311 disasm_op3 (dis, "lhax", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1312}
1313
1314/* 1F 172: tlbia */
1315static
1316void opd_1f_172 (p405_disasm_t *dis)
1317{
1318 disasm_op0 (dis, "tlbia", 0, 0x03fff801UL);
1319}
1320
1321/* 1F 173: mftb rt, tbrn */
1322static
1323void opd_1f_173 (p405_disasm_t *dis)
1324{
1325 unsigned tbrf, tbrn;
1326
1327 tbrf = (dis->ir >> 11) & 0x3ff;
1328 tbrn = ((tbrf & 0x1f) << 5) | ((tbrf >> 5) & 0x1f);
1329
1330 switch (tbrn) {
1331 case P405_TBRN_TBL:
1332 disasm_op1 (dis, "mftb", 0, 0x01, ARG_RT, 0);
1333 break;
1334
1335 case P405_TBRN_TBU:
1336 disasm_op1 (dis, "mftbu", 0, 0x01, ARG_RT, 0);
1337 break;
1338
1339 default:
1340 disasm_op2 (dis, "mftb", 0, 0x01, ARG_RT, ARG_UINT16, 0, tbrn);
1341 break;
1342 }
1343}
1344
1345/* 1F 177: lhaux rt, ra0, rb */
1346static
1347void opd_1f_177 (p405_disasm_t *dis)
1348{
1349 disasm_op3 (dis, "lhaux", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1350}
1351
1352/* 1F 197: sthx rs, ra0, rb */
1353static
1354void opd_1f_197 (p405_disasm_t *dis)
1355{
1356 disasm_op3 (dis, "sthx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0);
1357}
1358
1359/* 1F 19C: orc[.] ra, rs, rb */
1360static
1361void opd_1f_19c (p405_disasm_t *dis)
1362{
1363 disasm_op3 (dis, "orc", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1364}
1365
1366/* 1F 1B7: sthux rs, ra, rb */
1367static
1368void opd_1f_1b7 (p405_disasm_t *dis)
1369{
1370 disasm_op3 (dis, "sthux", 0, 0x01, ARG_RS, ARG_RA, ARG_RB, 0, 0, 0);
1371}
1372
1373/* 1F 1BC: or[.] ra, rs, rb */
1374static
1375void opd_1f_1bc (p405_disasm_t *dis)
1376{
1377 if (p405_get_ir_rs (dis->ir) == p405_get_ir_rb (dis->ir)) {
1378 disasm_op2 (dis, "mr", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0);
1379 }
1380 else {
1381 disasm_op3 (dis, "or", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1382 }
1383}
1384
1385/* 1F 1C3: mtdcr dcrn, rs */
1386static
1387void opd_1f_1c3 (p405_disasm_t *dis)
1388{
1389 unsigned dcrf, dcrn;
1390
1391 dcrf = (dis->ir >> 11) & 0x3ff;
1392 dcrn = ((dcrf & 0x1f) << 5) | ((dcrf >> 5) & 0x1f);
1393
1394 disasm_op2 (dis, "mtdcr", 0, 0x01, ARG_DCRN, ARG_RS, dcrn, 0);
1395}
1396
1397/* 1F 1C6: dccci ra0, rb */
1398static
1399void opd_1f_1c6 (p405_disasm_t *dis)
1400{
1401 disasm_op2 (dis, "dccci", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1402}
1403
1404/* 1F 1CB: divwu[o][.] rt, ra, rb */
1405static
1406void opd_1f_1cb (p405_disasm_t *dis)
1407{
1408 disasm_op3 (dis, "divwu", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1409}
1410
1411/* 1F 1D3: mtspr sprn, rs */
1412static
1413void opd_1f_1d3 (p405_disasm_t *dis)
1414{
1415 unsigned sprf, sprn;
1416
1417 sprf = (dis->ir >> 11) & 0x3ff;
1418 sprn = ((sprf & 0x1f) << 5) | ((sprf >> 5) & 0x1f);
1419
1420 disasm_op2 (dis, "mtspr", 0, 0x01, ARG_SPRN, ARG_RS, sprn, 0);
1421}
1422
1423/* 1F 1D6: dcbi ra0, rb */
1424static
1425void opd_1f_1d6 (p405_disasm_t *dis)
1426{
1427 disasm_op2 (dis, "dcbi", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1428}
1429
1430/* 1F 1DC: nand[.] ra, rs, rb */
1431static
1432void opd_1f_1dc (p405_disasm_t *dis)
1433{
1434 disasm_op3 (dis, "nand", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1435}
1436
1437/* 1F 1EB: divw[o][.] rt, ra, rb */
1438static
1439void opd_1f_1eb (p405_disasm_t *dis)
1440{
1441 disasm_op3 (dis, "divw", OPF_OE | OPF_RC, 0, ARG_RT, ARG_RA, ARG_RB, 0, 0, 0);
1442}
1443
1444/* 1F 200: mcrxr bf */
1445static
1446void opd_1f_200 (p405_disasm_t *dis)
1447{
1448 disasm_op1 (dis, "mcrxr", 0, 0x007ff801UL, ARG_UINT3,
1449 p405_get_ir_rt (dis->ir) >> 2
1450 );
1451}
1452
1453/* 1F 215: lswx rt, ra0, rb */
1454static
1455void opd_1f_215 (p405_disasm_t *dis)
1456{
1457 disasm_op3 (dis, "lswx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1458}
1459
1460/* 1F 216: lwbrx rt, ra0, rb */
1461static
1462void opd_1f_216 (p405_disasm_t *dis)
1463{
1464 disasm_op3 (dis, "lwbrx", 0, 0x01, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1465}
1466
1467/* 1F 218: srw[.] ra, rs, rb */
1468static
1469void opd_1f_218 (p405_disasm_t *dis)
1470{
1471 disasm_op3 (dis, "srw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1472}
1473
1474/* 1F 236: tlbsync */
1475static
1476void opd_1f_236 (p405_disasm_t *dis)
1477{
1478 disasm_op0 (dis, "tlbsync", 0, 0x03fff801UL);
1479}
1480
1481/* 1F 255: lswi rt, ra0, nb */
1482static
1483void opd_1f_255 (p405_disasm_t *dis)
1484{
1485 unsigned nb;
1486
1487 nb = p405_get_ir_rb (dis->ir);
1488 nb = (nb == 0) ? 32 : nb;
1489
1490 disasm_op3 (dis, "lswi", 0, 0x01, ARG_RT, ARG_RA0, ARG_UINT8, 0, 0, nb);
1491}
1492
1493/* 1F 256: sync */
1494static
1495void opd_1f_256 (p405_disasm_t *dis)
1496{
1497 disasm_op0 (dis, "sync", 0, 0);
1498}
1499
1500/* 1F 295: stswx rs, ra0, rb */
1501static
1502void opd_1f_295 (p405_disasm_t *dis)
1503{
1504 disasm_op3 (dis, "stswx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0);
1505}
1506
1507/* 1F 296: stwbrx rs, ra0, rb */
1508static
1509void opd_1f_296 (p405_disasm_t *dis)
1510{
1511 disasm_op3 (dis, "stwbrx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0);
1512}
1513
1514/* 1F 2D5: stswi rs, ra0, nb */
1515static
1516void opd_1f_2d5 (p405_disasm_t *dis)
1517{
1518 unsigned nb;
1519
1520 nb = p405_get_ir_rb (dis->ir);
1521 nb = (nb == 0) ? 32 : nb;
1522
1523 disasm_op3 (dis, "stswi", 0, 0x01, ARG_RS, ARG_RA0, ARG_UINT8, 0, 0, nb);
1524}
1525
1526/* 1F 2F6: dcba ra0, rb */
1527static
1528void opd_1f_2f6 (p405_disasm_t *dis)
1529{
1530 disasm_op2 (dis, "dcba", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1531}
1532
1533/* 1F 316: lhbrx rt, ra0, rb */
1534static
1535void opd_1f_316 (p405_disasm_t *dis)
1536{
1537 disasm_op3 (dis, "lhbrx", 0, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1538}
1539
1540/* 1F 318: sraw[.] ra, rs, rb */
1541static
1542void opd_1f_318 (p405_disasm_t *dis)
1543{
1544 disasm_op3 (dis, "sraw", OPF_RC, 0, ARG_RA, ARG_RS, ARG_RB, 0, 0, 0);
1545}
1546
1547/* 1F 338: srawi[.] ra, rs, sh */
1548static
1549void opd_1f_338 (p405_disasm_t *dis)
1550{
1551 disasm_op3 (dis, "srawi", OPF_RC, 0,
1552 ARG_RA, ARG_RS, ARG_UINT5, 0, 0, p405_get_ir_rb (dis->ir)
1553 );
1554}
1555
1556/* 1F 356: eieio */
1557static
1558void opd_1f_356 (p405_disasm_t *dis)
1559{
1560 disasm_op0 (dis, "eieio", 0, 0);
1561}
1562
1563/* 1F 392: tlbsx rt, ra0, rb */
1564static
1565void opd_1f_392 (p405_disasm_t *dis)
1566{
1567 disasm_op3 (dis, "tlbsx", OPF_RC, 0, ARG_RT, ARG_RA0, ARG_RB, 0, 0, 0);
1568}
1569
1570/* 1F 396: sthbrx rs, ra0, rb */
1571static
1572void opd_1f_396 (p405_disasm_t *dis)
1573{
1574 disasm_op3 (dis, "sthbrx", 0, 0x01, ARG_RS, ARG_RA0, ARG_RB, 0, 0, 0);
1575}
1576
1577/* 1F 39A: extsh[.] ra, rs */
1578static
1579void opd_1f_39a (p405_disasm_t *dis)
1580{
1581 disasm_op2 (dis, "extsh", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0);
1582}
1583
1584/* 1F 3B2: tlbre rt, ra, ws */
1585static
1586void opd_1f_3b2 (p405_disasm_t *dis)
1587{
1588 switch (p405_get_ir_rb (dis->ir)) {
1589 case 0:
1590 disasm_op2 (dis, "tlbrehi", 0, 0x01, ARG_RT, ARG_RA, 0, 0);
1591 break;
1592
1593 case 1:
1594 disasm_op2 (dis, "tlbrelo", 0, 0x01, ARG_RT, ARG_RA, 0, 0);
1595 break;
1596
1597 default:
1598 disasm_undefined (dis);
1599 break;
1600 }
1601}
1602
1603/* 1F 3BA: extsb[.] ra, rs */
1604static
1605void opd_1f_3ba (p405_disasm_t *dis)
1606{
1607 disasm_op2 (dis, "extsb", OPF_RC, 0, ARG_RA, ARG_RS, 0, 0);
1608}
1609
1610/* 1F 3C6: iccci ra, rb */
1611static
1612void opd_1f_3c6 (p405_disasm_t *dis)
1613{
1614 disasm_op2 (dis, "iccci", 0, 0x03e00001UL, ARG_RA, ARG_RB, 0, 0);
1615}
1616
1617/* 1F 3D2: tlbwe rs, ra, ws */
1618static
1619void opd_1f_3d2 (p405_disasm_t *dis)
1620{
1621 switch (p405_get_ir_rb (dis->ir)) {
1622 case 0:
1623 disasm_op2 (dis, "tlbwehi", 0, 0x01, ARG_RS, ARG_RA, 0, 0);
1624 break;
1625
1626 case 1:
1627 disasm_op2 (dis, "tlbwelo", 0, 0x01, ARG_RS, ARG_RA, 0, 0);
1628 break;
1629
1630 default:
1631 disasm_undefined (dis);
1632 break;
1633 }
1634}
1635
1636/* 1F 3D6: icbi ra, rb */
1637static
1638void opd_1f_3d6 (p405_disasm_t *dis)
1639{
1640 disasm_op2 (dis, "icbi", 0, 0x03e00001UL, ARG_RA, ARG_RB, 0, 0);
1641}
1642
1643/* 1F 3F6: dcbz ra0, rb */
1644static
1645void opd_1f_3f6 (p405_disasm_t *dis)
1646{
1647 disasm_op2 (dis, "dcbz", 0, 0x03e00001UL, ARG_RA0, ARG_RB, 0, 0);
1648}
1649
1650/* 1F: */
1651static
1652void opd_1f (p405_disasm_t *dis)
1653{
1654 unsigned op2;
1655
1656 op2 = (dis->ir >> 1) & 0x3ff;
1657
1658 p405_op1f[op2] (dis);
1659}
1660
1661/* 20: lwz rt, ra0, simm16 */
1662static
1663void opd_20 (p405_disasm_t *dis)
1664{
1665 disasm_op3 (dis, "lwz", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1666}
1667
1668/* 21: lwzu rt, ra, simm16 */
1669static
1670void opd_21 (p405_disasm_t *dis)
1671{
1672 disasm_op3 (dis, "lwzu", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
1673}
1674
1675/* 22: lbz rt, ra0, simm16 */
1676static
1677void opd_22 (p405_disasm_t *dis)
1678{
1679 disasm_op3 (dis, "lbz", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1680}
1681
1682/* 23: lbzu rt, ra, simm16 */
1683static
1684void opd_23 (p405_disasm_t *dis)
1685{
1686 disasm_op3 (dis, "lbzu", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
1687}
1688
1689/* 24: stw rs, ra0, simm16 */
1690static
1691void opd_24 (p405_disasm_t *dis)
1692{
1693 disasm_op3 (dis, "stw", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1694}
1695
1696/* 25: stwu rs, ra, simm16 */
1697static
1698void opd_25 (p405_disasm_t *dis)
1699{
1700 disasm_op3 (dis, "stwu", 0, 0, ARG_RS, ARG_RA, ARG_SIMM16, 0, 0, 0);
1701}
1702
1703/* 26: stb rs, ra0, simm16 */
1704static
1705void opd_26 (p405_disasm_t *dis)
1706{
1707 disasm_op3 (dis, "stb", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1708}
1709
1710/* 27: stbu rs, ra, simm16 */
1711static
1712void opd_27 (p405_disasm_t *dis)
1713{
1714 disasm_op3 (dis, "stbu", 0, 0, ARG_RS, ARG_RA, ARG_SIMM16, 0, 0, 0);
1715}
1716
1717/* 28: lhz rt, ra0, simm16 */
1718static
1719void opd_28 (p405_disasm_t *dis)
1720{
1721 disasm_op3 (dis, "lhz", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1722}
1723
1724/* 29: lhzu rt, ra, simm16 */
1725static
1726void opd_29 (p405_disasm_t *dis)
1727{
1728 disasm_op3 (dis, "lhzu", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
1729}
1730
1731/* 2A: lha rt, ra0, simm16 */
1732static
1733void opd_2a (p405_disasm_t *dis)
1734{
1735 disasm_op3 (dis, "lha", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1736}
1737
1738/* 2B: lhau rt, ra, simm16 */
1739static
1740void opd_2b (p405_disasm_t *dis)
1741{
1742 disasm_op3 (dis, "lhau", 0, 0, ARG_RT, ARG_RA, ARG_SIMM16, 0, 0, 0);
1743}
1744
1745/* 2C: sth rs, ra0, simm16 */
1746static
1747void opd_2c (p405_disasm_t *dis)
1748{
1749 disasm_op3 (dis, "sth", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1750}
1751
1752/* 2D: sthu rs, ra, simm16 */
1753static
1754void opd_2d (p405_disasm_t *dis)
1755{
1756 disasm_op3 (dis, "sthu", 0, 0, ARG_RS, ARG_RA, ARG_SIMM16, 0, 0, 0);
1757}
1758
1759/* 2E: lmw rt, ra0, simm16 */
1760static
1761void opd_2e (p405_disasm_t *dis)
1762{
1763 disasm_op3 (dis, "lmw", 0, 0, ARG_RT, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1764}
1765
1766/* 2F: stmw rs, ra0, simm16 */
1767static
1768void opd_2f (p405_disasm_t *dis)
1769{
1770 disasm_op3 (dis, "stmw", 0, 0, ARG_RS, ARG_RA0, ARG_SIMM16, 0, 0, 0);
1771}
1772
1773void p405_disasm (p405_disasm_t *dis, uint32_t pc, uint32_t ir)
1774{
1775 unsigned op;
1776
1777 if (p405_disasm_inited == 0) {
1778 p405_disasm_init();
1779 }
1780
1781 dis->flags = 0;
1782 dis->reg = 0;
1783
1784 dis->pc = pc;
1785 dis->ir = ir;
1786
1787 op = (ir >> 26) & 0x3f;
1788
1789 p405_op[op] (dis);
1790}
1791
1792void p405_disasm_mem (p405_t *c, p405_disasm_t *dis, uint32_t pc, unsigned xlat)
1793{
1794 uint32_t ir;
1795
1796 if (p405_disasm_inited == 0) {
1797 p405_disasm_init();
1798 }
1799
1800 dis->flags = 0;
1801 dis->reg = 0;
1802
1803 if (p405_get_xlat32 (c, pc, xlat, &ir)) {
1804 dis->pc = pc;
1805 dis->ir = 0xffffffffUL;
1806
1807 disasm_op0 (dis, "TLB_MISS", 0, 0);
1808
1809 dis->flags |= P405_DFLAG_TLBM;
1810 }
1811 else {
1812 p405_disasm (dis, pc, ir);
1813 }
1814}
1815
1816static
1817p405_disasm_list_t p405_op13_list[] = {
1818 { 0x000, opd_13_000 },
1819 { 0x010, opd_13_010 },
1820 { 0x021, opd_13_021 },
1821 { 0x032, opd_13_032 },
1822 { 0x033, opd_13_033 },
1823 { 0x081, opd_13_081 },
1824 { 0x096, opd_13_096 },
1825 { 0x0c1, opd_13_0c1 },
1826 { 0x0e1, opd_13_0e1 },
1827 { 0x101, opd_13_101 },
1828 { 0x121, opd_13_121 },
1829 { 0x1a1, opd_13_1a1 },
1830 { 0x1c1, opd_13_1c1 },
1831 { 0x210, opd_13_210 },
1832 { 0x000, NULL }
1833};
1834
1835static
1836p405_disasm_list_t p405_op1f_list[] = {
1837 { 0x000, opd_1f_000 },
1838 { 0x008, opd_1f_008 },
1839 { 0x00a, opd_1f_00a },
1840 { 0x00b, opd_1f_00b },
1841 { 0x013, opd_1f_013 },
1842 { 0x014, opd_1f_014 },
1843 { 0x017, opd_1f_017 },
1844 { 0x018, opd_1f_018 },
1845 { 0x01a, opd_1f_01a },
1846 { 0x01c, opd_1f_01c },
1847 { 0x020, opd_1f_020 },
1848 { 0x028, opd_1f_028 },
1849 { 0x036, opd_1f_036 },
1850 { 0x037, opd_1f_037 },
1851 { 0x03c, opd_1f_03c },
1852 { 0x04b, opd_1f_04b },
1853 { 0x053, opd_1f_053 },
1854 { 0x056, opd_1f_056 },
1855 { 0x057, opd_1f_057 },
1856 { 0x068, opd_1f_068 },
1857 { 0x077, opd_1f_077 },
1858 { 0x07c, opd_1f_07c },
1859 { 0x083, opd_1f_083 },
1860 { 0x086, opd_1f_086 },
1861 { 0x088, opd_1f_088 },
1862 { 0x08a, opd_1f_08a },
1863 { 0x090, opd_1f_090 },
1864 { 0x092, opd_1f_092 },
1865 { 0x096, opd_1f_096 },
1866 { 0x097, opd_1f_097 },
1867 { 0x0a3, opd_1f_0a3 },
1868 { 0x0b7, opd_1f_0b7 },
1869 { 0x0c8, opd_1f_0c8 },
1870 { 0x0ca, opd_1f_0ca },
1871 { 0x0d7, opd_1f_0d7 },
1872 { 0x0e8, opd_1f_0e8 },
1873 { 0x0ea, opd_1f_0ea },
1874 { 0x0eb, opd_1f_0eb },
1875 { 0x0f6, opd_1f_0f6 },
1876 { 0x0f7, opd_1f_0f7 },
1877 { 0x106, opd_1f_106 },
1878 { 0x10a, opd_1f_10a },
1879 { 0x116, opd_1f_116 },
1880 { 0x117, opd_1f_117 },
1881 { 0x11c, opd_1f_11c },
1882 { 0x137, opd_1f_137 },
1883 { 0x13c, opd_1f_13c },
1884 { 0x143, opd_1f_143 },
1885 { 0x153, opd_1f_153 },
1886 { 0x157, opd_1f_157 },
1887 { 0x172, opd_1f_172 },
1888 { 0x173, opd_1f_173 },
1889 { 0x177, opd_1f_177 },
1890 { 0x197, opd_1f_197 },
1891 { 0x19c, opd_1f_19c },
1892 { 0x1b7, opd_1f_1b7 },
1893 { 0x1bc, opd_1f_1bc },
1894 { 0x1c3, opd_1f_1c3 },
1895 { 0x1c6, opd_1f_1c6 },
1896 { 0x1cb, opd_1f_1cb },
1897 { 0x1d3, opd_1f_1d3 },
1898 { 0x1d6, opd_1f_1d6 },
1899 { 0x1dc, opd_1f_1dc },
1900 { 0x1eb, opd_1f_1eb },
1901 { 0x200, opd_1f_200 },
1902 { 0x208, opd_1f_008 },
1903 { 0x20a, opd_1f_00a },
1904 { 0x215, opd_1f_215 },
1905 { 0x216, opd_1f_216 },
1906 { 0x218, opd_1f_218 },
1907 { 0x228, opd_1f_028 },
1908 { 0x236, opd_1f_236 },
1909 { 0x255, opd_1f_255 },
1910 { 0x256, opd_1f_256 },
1911 { 0x268, opd_1f_068 },
1912 { 0x288, opd_1f_088 },
1913 { 0x28a, opd_1f_08a },
1914 { 0x295, opd_1f_295 },
1915 { 0x296, opd_1f_296 },
1916 { 0x2c8, opd_1f_0c8 },
1917 { 0x2ca, opd_1f_0ca },
1918 { 0x2d5, opd_1f_2d5 },
1919 { 0x2e8, opd_1f_0e8 },
1920 { 0x2ea, opd_1f_0ea },
1921 { 0x2eb, opd_1f_0eb },
1922 { 0x2f6, opd_1f_2f6 },
1923 { 0x30a, opd_1f_10a },
1924 { 0x316, opd_1f_316 },
1925 { 0x318, opd_1f_318 },
1926 { 0x338, opd_1f_338 },
1927 { 0x356, opd_1f_356 },
1928 { 0x392, opd_1f_392 },
1929 { 0x396, opd_1f_396 },
1930 { 0x39a, opd_1f_39a },
1931 { 0x3b2, opd_1f_3b2 },
1932 { 0x3ba, opd_1f_3ba },
1933 { 0x3c6, opd_1f_3c6 },
1934 { 0x3cb, opd_1f_1cb },
1935 { 0x3d2, opd_1f_3d2 },
1936 { 0x3d6, opd_1f_3d6 },
1937 { 0x3eb, opd_1f_1eb },
1938 { 0x3f6, opd_1f_3f6 },
1939 { 0x000, NULL }
1940};
1941
1942static
1943p405_disasm_f p405_op[64] = {
1944 &opd_ud, &opd_ud, &opd_ud, &opd_03, &opd_ud, &opd_ud, &opd_ud, &opd_07, /* 00 */
1945 &opd_08, &opd_ud, &opd_0a, &opd_0b, &opd_0c, &opd_0d, &opd_0e, &opd_0f,
1946 &opd_10, &opd_11, &opd_12, &opd_13, &opd_14, &opd_15, &opd_ud, &opd_17, /* 10 */
1947 &opd_18, &opd_19, &opd_1a, &opd_1b, &opd_1c, &opd_1d, &opd_ud, &opd_1f,
1948 &opd_20, &opd_21, &opd_22, &opd_23, &opd_24, &opd_25, &opd_26, &opd_27, /* 20 */
1949 &opd_28, &opd_29, &opd_2a, &opd_2b, &opd_2c, &opd_2d, &opd_2e, &opd_2f,
1950 &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, /* 30 */
1951 &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud, &opd_ud
1952};
1953
1954static
1955void p405_disasm_init (void)
1956{
1957 unsigned i;
1958 p405_disasm_list_t *lst;
1959
1960 for (i = 0; i < 1024; i++) {
1961 p405_op1f[i] = opd_ud;
1962 p405_op13[i] = opd_ud;
1963 }
1964
1965 lst = p405_op13_list;
1966
1967 while (lst->fct != NULL) {
1968 p405_op13[lst->op] = lst->fct;
1969 lst += 1;
1970 }
1971
1972 lst = p405_op1f_list;
1973
1974 while (lst->fct != NULL) {
1975 p405_op1f[lst->op] = lst->fct;
1976 lst += 1;
1977 }
1978
1979 p405_disasm_inited = 1;
1980}