fork of PCE focusing on macplus, supporting DaynaPort SCSI network emulation
1/*****************************************************************************
2 * pce *
3 *****************************************************************************/
4
5/*****************************************************************************
6 * File name: src/cpu/ppc405/opcodes.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 "ppc405.h"
30#include "internal.h"
31
32
33static inline
34uint32_t p405_get_mask (unsigned mb, unsigned me)
35{
36 uint32_t msk;
37
38 if (mb <= me) {
39 msk = ((2UL << (me - mb)) - 1) << (31 - me);
40 }
41 else {
42 msk = ((2UL << me) - 1) << (31 - me);
43 msk |= (2UL << (31 - mb)) - 1;
44 }
45
46 return (msk);
47}
48
49uint64_t p405_mul (uint32_t s1, uint32_t s2)
50{
51 int ss1, ss2;
52 uint64_t ret;
53
54 ss1 = (s1 & 0x80000000UL) != 0;
55 ss2 = (s2 & 0x80000000UL) != 0;
56
57 if (ss1) {
58 s1 = (~s1 + 1) & 0xffffffffUL;
59 }
60
61 if (ss2) {
62 s2 = (~s2 + 1) & 0xffffffffUL;
63 }
64
65 ret = (uint64_t) s1 * (uint64_t) s2;
66
67 if (ss1 != ss2) {
68 ret = (~ret + 1) & 0xffffffffffffffffULL;
69 }
70
71 return (ret);
72}
73
74/*
75 * Byte reverse a 16 bit value
76 */
77uint16_t p405_br16 (uint16_t x)
78{
79 return (((x & 0xff) << 8) | ((x >> 8) & 0xff));
80}
81
82/*
83 * Byte reverse a 32 bit value
84 */
85uint32_t p405_br32 (uint32_t x)
86{
87 return (((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00) | ((x >> 24) & 0xff));
88}
89
90void p405_op_branch (p405_t *c, uint32_t dst, unsigned bo, unsigned bi, int aa, int lk)
91{
92 int bo0, bo1, bo2, bo3, crb;
93
94 bo0 = (bo & 0x10) != 0;
95 bo1 = (bo & 0x08) != 0;
96 bo2 = (bo & 0x04) != 0;
97 bo3 = (bo & 0x02) != 0;
98
99 crb = (c->cr & (0x80000000UL >> bi)) != 0;
100
101 if (bo2 == 0) {
102 c->ctr = (c->ctr - 1) & 0xffffffffUL;
103 }
104
105 if (lk) {
106 p405_set_lr (c, (c->pc + 4) & 0xffffffffUL);
107 }
108
109 if ((bo2 || ((c->ctr == 0) == bo3)) && (bo0 || (crb == bo1))) {
110 if (aa) {
111 c->pc = dst;
112 }
113 else {
114 c->pc = (c->pc + dst) & 0xffffffffUL;
115 }
116 }
117 else {
118 c->pc = (c->pc + 4) & 0xffffffffUL;
119 }
120
121 p405_set_clk (c, 0, 1);
122}
123
124/* generic cr bit op */
125void p405_op_crop (p405_t *c, unsigned bt, unsigned ba, unsigned bb, unsigned booltab)
126{
127 unsigned msk;
128 uint32_t mt, ma, mb;
129
130 if (c->ir & P405_IR_RC) {
131 p405_op_undefined (c);
132 return;
133 }
134
135 mt = 0x80000000UL >> bt;
136 ma = 0x80000000UL >> ba;
137 mb = 0x80000000UL >> bb;
138
139 msk = (c->cr & ma) ? 0x04 : 0x01;
140
141 if (c->cr & mb) {
142 msk = msk << 1;
143 }
144
145 if (booltab & msk) {
146 c->cr |= mt;
147 }
148 else {
149 c->cr &= ~mt;
150 }
151
152 p405_set_clk (c, 4, 1);
153}
154
155/* generic load string word */
156void p405_op_lsw (p405_t *c, unsigned rt, unsigned ra, unsigned rb, uint32_t ea, unsigned cnt)
157{
158 unsigned i;
159 unsigned shl, rfinal, clk;
160 uint8_t val;
161 uint32_t msk;
162
163 rfinal = (rt + (cnt + 3) / 4 - 1) & 0x1f;
164
165 msk = 0;
166 shl = 24;
167
168 clk = ((ea & 0x03) == 0) ? 0 : 1;
169
170 for (i = 0; i < cnt; i++) {
171 if ((ea & 0x03) == 0) {
172 clk += 1;
173 }
174
175 if (((rt != ra) && (rt != rb)) || (rt == rfinal)) {
176 if (p405_dload8 (c, ea, &val)) {
177 return;
178 }
179
180 p405_set_gpr (c, rt, (p405_get_gpr (c, rt) & msk) | ((uint32_t) val << shl));
181 }
182
183 if (shl == 0) {
184 msk = 0;
185 shl = 24;
186 rt = (rt + 1) & 0x1f;
187 }
188 else {
189 msk = (msk >> 8) | 0xff000000UL;
190 shl -= 8;
191 }
192
193 ea += 1;
194 }
195
196 p405_set_clk (c, 4, (clk > 0) ? clk : 1);
197}
198
199/* generic store string word */
200void p405_op_stsw (p405_t *c, unsigned rs, uint32_t ea, unsigned cnt)
201{
202 unsigned i;
203 unsigned sh, clk;
204
205 sh = 24;
206
207 clk = ((ea & 0x03) == 0) ? 0 : 1;
208
209 for (i = 0; i < cnt; i++) {
210 if ((ea & 0x03) == 0) {
211 clk += 1;
212 }
213
214 if (p405_dstore8 (c, ea, (p405_get_gpr (c, rs) >> sh) & 0xff)) {
215 return;
216 }
217
218 if (sh == 0) {
219 sh = 24;
220 rs = (rs + 1) & 0x1f;
221 }
222 else {
223 sh -= 8;
224 }
225
226 ea += 1;
227 }
228
229 p405_set_clk (c, 4, (clk > 0) ? clk : 1);
230}
231
232void p405_op_undefined (p405_t *c)
233{
234 p405_undefined (c);
235 p405_exception_program (c, P405_ESR_PIL);
236 p405_set_clk (c, 0, 1);
237}
238
239/*****************************************************************************/
240
241/* 03: twi to, ra, simm16 */
242static
243void op_03 (p405_t *c)
244{
245 int cond;
246 unsigned to;
247 uint32_t ra1, im1, ra2, im2;
248
249 to = p405_bits (c->ir, 6, 5);
250 ra1 = p405_get_ra (c, c->ir);
251 im1 = p405_sext (c->ir, 16);
252
253 ra2 = (ra1 + 0x80000000UL) & 0xffffffffUL;
254 im2 = (im1 + 0x80000000UL) & 0xffffffffUL;
255
256 if ((to & 0x10) && (ra2 < im2)) {
257 cond = 1;
258 }
259 else if ((to & 0x08) && (ra2 > im2)) {
260 cond = 1;
261 }
262 else if ((to & 0x04) && (ra1 == im2)) {
263 cond = 1;
264 }
265 else if ((to & 0x02) && (ra1 < im1)) {
266 cond = 1;
267 }
268 else if ((to & 0x01) && (ra1 > im1)) {
269 cond = 1;
270 }
271 else {
272 cond = 0;
273 }
274
275 if (cond) {
276 p405_exception_program (c, P405_ESR_PTR);
277 }
278 else {
279 p405_set_clk (c, 4, 1);
280 }
281}
282
283/* 07: mulli rt, ra, simm16 */
284static
285void op_07 (p405_t *c)
286{
287 uint64_t rt;
288
289 rt = p405_mul (p405_get_ra (c, c->ir), p405_sext (c->ir, 16));
290 p405_set_rt (c, c->ir, rt & 0xffffffffUL);
291
292 p405_set_clk (c, 4, 1);
293}
294
295/* 08: subfic rt, ra, simm16 */
296static
297void op_08 (p405_t *c)
298{
299 uint32_t rt, s1, s2;
300
301 s1 = p405_get_simm16 (c->ir);
302 s2 = p405_get_ra (c, c->ir);
303
304 rt = (s1 - s2) & 0xffffffff;
305
306 p405_set_rt (c, c->ir, rt);
307
308 p405_set_xer_ca (c, rt <= s1);
309
310 p405_set_clk (c, 4, 1);
311}
312
313/* 0A: cmpli bf, ra, uimm16 */
314static
315void op_0a (p405_t *c)
316{
317 unsigned f;
318 uint32_t d, s1, s2;
319
320 s1 = p405_get_ra (c, c->ir);
321 s2 = p405_get_uimm16 (c->ir);
322
323 f = (c->ir >> 23) & 0x07;
324
325 if (s1 < s2) {
326 d = P405_CR_LT;
327 }
328 else if (s1 > s2) {
329 d = P405_CR_GT;
330 }
331 else {
332 d = P405_CR_EQ;
333 }
334
335 if (p405_get_xer_so (c)) {
336 d |= P405_CR_SO;
337 }
338
339 f = 4 * (7 - f);
340
341 c->cr &= ~(0x0fUL << f);
342 c->cr |= d << f;
343
344 p405_set_clk (c, 4, 1);
345}
346
347/* 0B: cmpi bf, ra, simm16 */
348static
349void op_0b (p405_t *c)
350{
351 unsigned f;
352 uint32_t d, s1, s2;
353
354 s1 = p405_get_ra (c, c->ir);
355 s2 = p405_get_simm16 (c->ir);
356
357 s1 ^= 0x80000000;
358 s2 ^= 0x80000000;
359
360 f = (c->ir >> 23) & 0x07;
361
362 if (s1 < s2) {
363 d = P405_CR_LT;
364 }
365 else if (s1 > s2) {
366 d = P405_CR_GT;
367 }
368 else {
369 d = P405_CR_EQ;
370 }
371
372 if (p405_get_xer_so (c)) {
373 d |= P405_CR_SO;
374 }
375
376 f = 4 * (7 - f);
377
378 c->cr &= ~(0x0fUL << f);
379 c->cr |= d << f;
380
381 p405_set_clk (c, 4, 1);
382}
383
384/* 0C: addic rt, ra, simm16 */
385static
386void op_0c (p405_t *c)
387{
388 uint32_t rt, s1, s2;
389
390 s1 = p405_get_ra (c, c->ir);
391 s2 = p405_get_simm16 (c->ir);
392
393 rt = (s1 + s2) & 0xffffffff;
394
395 p405_set_rt (c, c->ir, rt);
396
397 p405_set_xer_ca (c, rt < s1);
398
399 p405_set_clk (c, 4, 1);
400}
401
402/* 0D: addic. rt, ra, simm16 */
403static
404void op_0d (p405_t *c)
405{
406 uint32_t rt, s1, s2;
407
408 s1 = p405_get_ra (c, c->ir);
409 s2 = p405_get_simm16 (c->ir);
410
411 rt = (s1 + s2) & 0xffffffff;
412
413 p405_set_rt (c, c->ir, rt);
414
415 p405_set_xer_ca (c, rt < s1);
416 p405_set_cr0 (c, rt);
417
418 p405_set_clk (c, 4, 1);
419}
420
421/* 0E: addi rt, ra0, simm16 */
422static
423void op_0e (p405_t *c)
424{
425 uint32_t rt, s1, s2;
426
427 s1 = p405_get_ra0 (c, c->ir);
428 s2 = p405_get_simm16 (c->ir);
429
430 rt = s1 + s2;
431
432 p405_set_rt (c, c->ir, rt);
433
434 p405_set_clk (c, 4, 1);
435}
436
437/* 0F: addis rt, ra0, imm16 */
438static
439void op_0f (p405_t *c)
440{
441 uint32_t rt, s1, s2;
442
443 s1 = p405_get_ra0 (c, c->ir);
444 s2 = p405_get_uimm16 (c->ir);
445
446 rt = s1 + (s2 << 16);
447
448 p405_set_rt (c, c->ir, rt);
449
450 p405_set_clk (c, 4, 1);
451}
452
453/* 10: bc/bca/bcl/bcla target */
454static
455void op_10 (p405_t *c)
456{
457 p405_op_branch (c,
458 p405_sext (c->ir & 0xfffcUL, 16),
459 (c->ir >> 21) & 0x1f, (c->ir >> 16) & 0x1f,
460 (c->ir & P405_IR_AA) != 0, (c->ir & P405_IR_LK) != 0
461 );
462}
463
464/* 11: sc */
465static
466void op_11 (p405_t *c)
467{
468 /* hook */
469 if ((c->ir & 0x00ff0000) == 0x00ce0000) {
470 if (c->hook != NULL) {
471 c->hook (c->hook_ext, c->ir);
472 }
473
474 p405_set_clk (c, 4, 1);
475
476 return;
477 }
478
479 if (p405_check_reserved (c, 0x03fffffdUL)) {
480 return;
481 }
482
483 p405_exception_syscall (c);
484
485/* p405_set_clk (c, 0, 1); */
486}
487
488/* 12: b/ba/bl/bla target */
489static
490void op_12 (p405_t *c)
491{
492 uint32_t li;
493
494 li = p405_sext (c->ir, 26) & 0xfffffffcUL;
495
496 if (c->ir & 0x01) {
497 p405_set_lr (c, (c->pc + 4) & 0xffffffffUL);
498 }
499
500 if (c->ir & 0x02) {
501 c->pc = li;
502 }
503 else {
504 c->pc = (c->pc + li) & 0xffffffffUL;
505 }
506
507 p405_set_clk (c, 0, 1);
508}
509
510/* 14: rlwimi[.] ra, rs, sh, mb, me */
511static
512void op_14 (p405_t *c)
513{
514 uint32_t ra, rs, msk;
515 unsigned sh, mb, me;
516
517 ra = p405_get_ra (c, c->ir);
518 rs = p405_get_rs (c, c->ir);
519 sh = (c->ir >> 11) & 0x1f;
520 mb = (c->ir >> 6) & 0x1f;
521 me = (c->ir >> 1) & 0x1f;
522
523 if (sh != 0) {
524 rs = ((rs << sh) | (rs >> (32 - sh))) & 0xffffffffUL;
525 }
526
527 msk = p405_get_mask (mb, me);
528
529 ra = (rs & msk) | (ra & ~msk);
530
531 p405_set_ra (c, c->ir, ra);
532
533 if (p405_get_ir_rc (c->ir)) {
534 p405_set_cr0 (c, ra);
535 }
536
537 p405_set_clk (c, 4, 1);
538}
539
540/* 15: rlwinm[.] ra, rs, sh, mb, me */
541static
542void op_15 (p405_t *c)
543{
544 uint32_t ra, rs;
545 unsigned sh, mb, me;
546
547 ra = p405_get_ra (c, c->ir);
548 rs = p405_get_rs (c, c->ir);
549 sh = (c->ir >> 11) & 0x1f;
550 mb = (c->ir >> 6) & 0x1f;
551 me = (c->ir >> 1) & 0x1f;
552
553 if (sh != 0) {
554 rs = ((rs << sh) | (rs >> (32 - sh))) & 0xffffffffUL;
555 }
556
557 ra = rs & p405_get_mask (mb, me);
558
559 p405_set_ra (c, c->ir, ra);
560
561 if (p405_get_ir_rc (c->ir)) {
562 p405_set_cr0 (c, ra);
563 }
564
565 p405_set_clk (c, 4, 1);
566}
567
568/* 17: rlwnm[.] ra, rs, rb, mb, me */
569static
570void op_17 (p405_t *c)
571{
572 uint32_t ra, rs;
573 unsigned sh, mb, me;
574
575 ra = p405_get_ra (c, c->ir);
576 rs = p405_get_rs (c, c->ir);
577 sh = p405_get_rb (c, c->ir) & 0x1f;
578 mb = (c->ir >> 6) & 0x1f;
579 me = (c->ir >> 1) & 0x1f;
580
581 if (sh != 0) {
582 rs = ((rs << sh) | (rs >> (32 - sh))) & 0xffffffffUL;
583 }
584
585 ra = rs & p405_get_mask (mb, me);
586
587 p405_set_ra (c, c->ir, ra);
588
589 if (p405_get_ir_rc (c->ir)) {
590 p405_set_cr0 (c, ra);
591 }
592
593 p405_set_clk (c, 4, 1);
594}
595
596/* 18: ori ra, rs, uimm16 */
597static
598void op_18 (p405_t *c)
599{
600 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) | p405_uext (c->ir, 16));
601 p405_set_clk (c, 4, 1);
602}
603
604/* 19: oris ra, rs, uimm16 */
605static
606void op_19 (p405_t *c)
607{
608 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) | (p405_uext (c->ir, 16) << 16));
609 p405_set_clk (c, 4, 1);
610}
611
612/* 1A: xori ra, rs, uimm16 */
613static
614void op_1a (p405_t *c)
615{
616 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) ^ p405_uext (c->ir, 16));
617 p405_set_clk (c, 4, 1);
618}
619
620/* 1B: xoris ra, rs, uimm16 */
621static
622void op_1b (p405_t *c)
623{
624 p405_set_ra (c, c->ir, p405_get_rs (c, c->ir) ^ (p405_uext (c->ir, 16) << 16));
625 p405_set_clk (c, 4, 1);
626}
627
628/* 1C: andi. ra, rs, uimm16 */
629static
630void op_1c (p405_t *c)
631{
632 uint32_t rt, s1, s2;
633
634 s1 = p405_get_rs (c, c->ir);
635 s2 = p405_get_uimm16 (c->ir);
636
637 rt = s1 & s2;
638
639 p405_set_ra (c, c->ir, rt);
640
641 p405_set_cr0 (c, rt);
642
643 p405_set_clk (c, 4, 1);
644}
645
646/* 1D: andis. ra, rs, uimm16 */
647static
648void op_1d (p405_t *c)
649{
650 uint32_t rt, s1, s2;
651
652 s1 = p405_get_rs (c, c->ir);
653 s2 = p405_get_uimm16 (c->ir);
654
655 rt = s1 & (s2 << 16);
656
657 p405_set_ra (c, c->ir, rt);
658
659 p405_set_cr0 (c, rt);
660
661 p405_set_clk (c, 4, 1);
662}
663
664/* 20: lwz rt, ra0, simm16 */
665static
666void op_20 (p405_t *c)
667{
668 uint32_t rt, ea;
669
670 if (p405_get_ea (c, &ea, 0, 0)) {
671 return;
672 }
673
674 if (p405_dload32 (c, ea, &rt)) {
675 return;
676 }
677
678 p405_set_rt (c, c->ir, rt);
679
680 p405_set_clk (c, 4, 1);
681}
682
683/* 21: lwzu rt, ra, simm16 */
684static
685void op_21 (p405_t *c)
686{
687 uint32_t rt, ea;
688
689 if (p405_get_ea (c, &ea, 0, 1)) {
690 return;
691 }
692
693 if (p405_dload32 (c, ea, &rt)) {
694 return;
695 }
696
697 p405_set_ra (c, c->ir, ea);
698 p405_set_rt (c, c->ir, rt);
699
700 p405_set_clk (c, 4, 1);
701}
702
703/* 22: lbz rt, ra0, simm16 */
704static
705void op_22 (p405_t *c)
706{
707 uint8_t rt;
708 uint32_t ea;
709
710 if (p405_get_ea (c, &ea, 0, 0)) {
711 return;
712 }
713
714 if (p405_dload8 (c, ea, &rt)) {
715 return;
716 }
717
718 p405_set_rt (c, c->ir, p405_uext (rt, 8));
719
720 p405_set_clk (c, 4, 1);
721}
722
723/* 23: lbzu rt, ra, simm16 */
724static
725void op_23 (p405_t *c)
726{
727 uint8_t rt;
728 uint32_t ea;
729
730 if (p405_get_ea (c, &ea, 0, 1)) {
731 return;
732 }
733
734 if (p405_dload8 (c, ea, &rt)) {
735 return;
736 }
737
738 p405_set_ra (c, c->ir, ea);
739 p405_set_rt (c, c->ir, p405_uext (rt, 8));
740
741 p405_set_clk (c, 4, 1);
742}
743
744/* 24: stw rs, ra0, simm16 */
745static
746void op_24 (p405_t *c)
747{
748 uint32_t ea;
749
750 if (p405_get_ea (c, &ea, 0, 0)) {
751 return;
752 }
753
754 if (p405_dstore32 (c, ea, p405_get_rs (c, c->ir))) {
755 return;
756 }
757
758 p405_set_clk (c, 4, 1);
759}
760
761/* 25: stwu rs, ra, simm16 */
762static
763void op_25 (p405_t *c)
764{
765 uint32_t ea;
766
767 if (p405_get_ea (c, &ea, 0, 1)) {
768 return;
769 }
770
771 if (p405_dstore32 (c, ea, p405_get_rs (c, c->ir))) {
772 return;
773 }
774
775 p405_set_ra (c, c->ir, ea);
776
777 p405_set_clk (c, 4, 1);
778}
779
780/* 26: stb rs, ra0, simm16 */
781static
782void op_26 (p405_t *c)
783{
784 uint32_t ea;
785
786 if (p405_get_ea (c, &ea, 0, 0)) {
787 return;
788 }
789
790 if (p405_dstore8 (c, ea, p405_uext (p405_get_rs (c, c->ir), 8))) {
791 return;
792 }
793
794 p405_set_clk (c, 4, 1);
795}
796
797/* 27: stbu rs, ra, simm16 */
798static
799void op_27 (p405_t *c)
800{
801 uint32_t ea;
802
803 if (p405_get_ea (c, &ea, 0, 1)) {
804 return;
805 }
806
807 if (p405_dstore8 (c, ea, p405_uext (p405_get_rs (c, c->ir), 8))) {
808 return;
809 }
810
811 p405_set_ra (c, c->ir, ea);
812
813 p405_set_clk (c, 4, 1);
814}
815
816/* 28: lhz rt, ra0, simm16 */
817static
818void op_28 (p405_t *c)
819{
820 uint16_t rt;
821 uint32_t ea;
822
823 if (p405_get_ea (c, &ea, 0, 0)) {
824 return;
825 }
826
827 if (p405_dload16 (c, ea, &rt)) {
828 return;
829 }
830
831 p405_set_rt (c, c->ir, p405_uext (rt, 16));
832
833 p405_set_clk (c, 4, 1);
834}
835
836/* 29: lhzu rt, ra, simm16 */
837static
838void op_29 (p405_t *c)
839{
840 uint16_t rt;
841 uint32_t ea;
842
843 if (p405_get_ea (c, &ea, 0, 1)) {
844 return;
845 }
846
847 if (p405_dload16 (c, ea, &rt)) {
848 return;
849 }
850
851 p405_set_ra (c, c->ir, ea);
852 p405_set_rt (c, c->ir, p405_uext (rt, 16));
853
854 p405_set_clk (c, 4, 1);
855}
856
857/* 2A: lha rt, ra0, simm16 */
858static
859void op_2a (p405_t *c)
860{
861 uint16_t rt;
862 uint32_t ea;
863
864 if (p405_get_ea (c, &ea, 0, 0)) {
865 return;
866 }
867
868 if (p405_dload16 (c, ea, &rt)) {
869 return;
870 }
871
872 p405_set_rt (c, c->ir, p405_sext (rt, 16));
873
874 p405_set_clk (c, 4, 1);
875}
876
877/* 2B: lhau rt, ra, simm16 */
878static
879void op_2b (p405_t *c)
880{
881 uint16_t rt;
882 uint32_t ea;
883
884 if (p405_get_ea (c, &ea, 0, 1)) {
885 return;
886 }
887
888 if (p405_dload16 (c, ea, &rt)) {
889 return;
890 }
891
892 p405_set_ra (c, c->ir, ea);
893 p405_set_rt (c, c->ir, p405_sext (rt, 16));
894
895 p405_set_clk (c, 4, 1);
896}
897
898/* 2C: sth rs, ra0, simm16 */
899static
900void op_2c (p405_t *c)
901{
902 uint32_t ea;
903
904 if (p405_get_ea (c, &ea, 0, 0)) {
905 return;
906 }
907
908 if (p405_dstore16 (c, ea, p405_uext (p405_get_rs (c, c->ir), 16))) {
909 return;
910 }
911
912 p405_set_clk (c, 4, 1);
913}
914
915/* 2D: sthu rs, ra, simm16 */
916static
917void op_2d (p405_t *c)
918{
919 uint32_t ea;
920
921 if (p405_get_ea (c, &ea, 0, 1)) {
922 return;
923 }
924
925 if (p405_dstore16 (c, ea, p405_uext (p405_get_rs (c, c->ir), 16))) {
926 return;
927 }
928
929 p405_set_ra (c, c->ir, ea);
930
931 p405_set_clk (c, 4, 1);
932}
933
934/* 2E: lmw rt, ra, simm16 */
935static
936void op_2e (p405_t *c)
937{
938 unsigned rt, ra, cnt;
939 uint32_t val;
940 uint32_t ea;
941
942 if (p405_get_ea (c, &ea, 0, 0)) {
943 return;
944 }
945
946 rt = p405_get_ir_rt (c->ir);
947 ra = p405_get_ir_ra (c->ir);
948
949 if (ra >= rt) {
950 p405_op_undefined (c);
951 return;
952 }
953
954 cnt = 32 - rt;
955
956 while (rt <= 31) {
957 if ((rt != ra) || (rt == 31)) {
958 if (p405_dload32 (c, ea, &val)) {
959 return;
960 }
961
962 p405_set_gpr (c, rt, val);
963 }
964
965 rt += 1;
966 ea += 4;
967 }
968
969 p405_set_clk (c, 4, cnt);
970}
971
972/* 2F: stmw rs, ra, simm16 */
973static
974void op_2f (p405_t *c)
975{
976 unsigned rs, cnt;
977 uint32_t ea;
978
979 if (p405_get_ea (c, &ea, 0, 0)) {
980 return;
981 }
982
983 rs = p405_get_ir_rs (c->ir);
984
985 cnt = 32 - rs;
986
987 while (rs <= 31) {
988 if (p405_dstore32 (c, ea, p405_get_gpr (c, rs))) {
989 return;
990 }
991
992 rs += 1;
993 ea += 4;
994 }
995
996 p405_set_clk (c, 4, cnt);
997}
998
999/* 30: lfs */
1000static
1001void op_30 (p405_t *c)
1002{
1003 p405_set_clk (c, 0, 1);
1004 p405_exception_program_fpu (c);
1005}
1006
1007/* 31: lfsu */
1008static
1009void op_31 (p405_t *c)
1010{
1011 p405_set_clk (c, 0, 1);
1012 p405_exception_program_fpu (c);
1013}
1014
1015/* 32: lfd */
1016static
1017void op_32 (p405_t *c)
1018{
1019 p405_set_clk (c, 0, 1);
1020 p405_exception_program_fpu (c);
1021}
1022
1023/* 33: lfdu */
1024static
1025void op_33 (p405_t *c)
1026{
1027 p405_set_clk (c, 0, 1);
1028 p405_exception_program_fpu (c);
1029}
1030
1031/* 34: stfs */
1032static
1033void op_34 (p405_t *c)
1034{
1035 p405_set_clk (c, 0, 1);
1036 p405_exception_program_fpu (c);
1037}
1038
1039/* 35: stfsu */
1040static
1041void op_35 (p405_t *c)
1042{
1043 p405_set_clk (c, 0, 1);
1044 p405_exception_program_fpu (c);
1045}
1046
1047/* 36: stfd */
1048static
1049void op_36 (p405_t *c)
1050{
1051 p405_set_clk (c, 0, 1);
1052 p405_exception_program_fpu (c);
1053}
1054
1055/* 37: stfdu */
1056static
1057void op_37 (p405_t *c)
1058{
1059 p405_set_clk (c, 0, 1);
1060 p405_exception_program_fpu (c);
1061}
1062
1063/* 3B: single precision floating point instructions */
1064static
1065void op_3b (p405_t *c)
1066{
1067 p405_set_clk (c, 0, 1);
1068 p405_exception_program_fpu (c);
1069}
1070
1071/* 3F: double precision floating point instructions */
1072static
1073void op_3f (p405_t *c)
1074{
1075 p405_set_clk (c, 0, 1);
1076 p405_exception_program_fpu (c);
1077}
1078
1079
1080static
1081p405_opcode_f p405_opcodes[64] = {
1082 NULL, NULL, NULL, &op_03, NULL, NULL, NULL, &op_07, /* 00 */
1083 &op_08, NULL, &op_0a, &op_0b, &op_0c, &op_0d, &op_0e, &op_0f,
1084 &op_10, &op_11, &op_12, NULL, &op_14, &op_15, NULL, &op_17, /* 10 */
1085 &op_18, &op_19, &op_1a, &op_1b, &op_1c, &op_1d, NULL, NULL,
1086 &op_20, &op_21, &op_22, &op_23, &op_24, &op_25, &op_26, &op_27, /* 20 */
1087 &op_28, &op_29, &op_2a, &op_2b, &op_2c, &op_2d, &op_2e, &op_2f,
1088 &op_30, &op_31, &op_32, &op_33, &op_34, &op_35, &op_36, &op_37, /* 30 */
1089 NULL, NULL, NULL, &op_3b, NULL, NULL, NULL, &op_3f
1090};
1091
1092
1093void p405_set_opcodes (p405_t *c)
1094{
1095 unsigned i;
1096
1097 for (i = 0; i < 64; i++) {
1098 if (p405_opcodes[i] != NULL) {
1099 c->opcodes.op[i] = p405_opcodes[i];
1100 }
1101 else {
1102 c->opcodes.op[i] = &p405_op_undefined;
1103 }
1104 }
1105
1106 p405_set_opcode13 (c);
1107 p405_set_opcode1f (c);
1108}