]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/mips/mdmx.c
* elfxx-mips.c (ABI_64_P): Use backend's data to determine the
[thirdparty/binutils-gdb.git] / sim / mips / mdmx.c
CommitLineData
f4f1b9f1
CD
1/* Simulation code for the MIPS MDMX ASE.
2 Copyright (C) 2002 Free Software Foundation, Inc.
3 Contributed by Broadcom Corporation (SiByte).
4
5This file is part of GDB, the GNU debugger.
6
7This program is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12This program is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License along
18with this program; if not, write to the Free Software Foundation, Inc.,
1959 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
20
21#include <stdio.h>
22
23#include "sim-main.h"
24
25/* Within mdmx.c we refer to the sim_cpu directly. */
26#define CPU cpu
27#define SD (CPU_STATE(CPU))
28#define SD_ cpu, cia, -1
29
30/* MDMX Representations
31
32 An 8-bit packed byte element (OB) is always unsigned.
33 The 24-bit accumulators are signed and are represented as 32-bit
34 signed values, which are reduced to 24-bit signed values prior to
35 Round and Clamp operations.
36
37 A 16-bit packed halfword element (QH) is always signed.
38 The 48-bit accumulators are signed and are represented as 64-bit
39 signed values, which are reduced to 48-bit signed values prior to
40 Round and Clamp operations.
41
42 The code below assumes a 2's-complement representation of signed
43 quantities. Care is required to clear extended sign bits when
44 repacking fields.
45
46 The code (and the code for arithmetic shifts in mips.igen) also makes
47 the (not guaranteed portable) assumption that right shifts of signed
48 quantities in C do sign extension. */
49
50typedef unsigned64 unsigned48;
51#define MASK48 (UNSIGNED64 (0xffffffffffff))
52
53typedef unsigned32 unsigned24;
54#define MASK24 (UNSIGNED32 (0xffffff))
55
56typedef enum {
57 mdmx_ob, /* OB (octal byte) */
58 mdmx_qh /* QH (quad half-word) */
59} MX_fmt;
60
61typedef enum {
62 sel_elem, /* element select */
63 sel_vect, /* vector select */
64 sel_imm /* immediate select */
65} VT_select;
66
67#define OB_MAX ((unsigned8)0xFF)
68#define QH_MIN ((signed16)0x8000)
69#define QH_MAX ((signed16)0x7FFF)
70
71#define OB_CLAMP(x) ((unsigned8)((x) > OB_MAX ? OB_MAX : (x)))
72#define QH_CLAMP(x) ((signed16)((x) < QH_MIN ? QH_MIN : \
73 ((x) > QH_MAX ? QH_MAX : (x))))
74
75#define MX_FMT(fmtsel) (((fmtsel) & 0x1) == 0 ? mdmx_ob : mdmx_qh)
76#define MX_VT(fmtsel) (((fmtsel) & 0x10) == 0 ? sel_elem : \
77 (((fmtsel) & 0x18) == 0x10 ? sel_vect : sel_imm))
78
79#define QH_ELEM(v,fmtsel) \
80 ((signed16)(((v) >> (((fmtsel) & 0xC) << 2)) & 0xFFFF))
81#define OB_ELEM(v,fmtsel) \
82 ((unsigned8)(((v) >> (((fmtsel) & 0xE) << 2)) & 0xFF))
83
84
85typedef signed16 (*QH_FUNC)(signed16, signed16);
86typedef unsigned8 (*OB_FUNC)(unsigned8, unsigned8);
87
88/* vectorized logical operators */
89
90static signed16
91AndQH(signed16 ts, signed16 tt)
92{
93 return (signed16)((unsigned16)ts & (unsigned16)tt);
94}
95
96static unsigned8
97AndOB(unsigned8 ts, unsigned8 tt)
98{
99 return ts & tt;
100}
101
102static signed16
103NorQH(signed16 ts, signed16 tt)
104{
105 return (signed16)(((unsigned16)ts | (unsigned16)tt) ^ 0xFFFF);
106}
107
108static unsigned8
109NorOB(unsigned8 ts, unsigned8 tt)
110{
111 return (ts | tt) ^ 0xFF;
112}
113
114static signed16
115OrQH(signed16 ts, signed16 tt)
116{
117 return (signed16)((unsigned16)ts | (unsigned16)tt);
118}
119
120static unsigned8
121OrOB(unsigned8 ts, unsigned8 tt)
122{
123 return ts | tt;
124}
125
126static signed16
127XorQH(signed16 ts, signed16 tt)
128{
129 return (signed16)((unsigned16)ts ^ (unsigned16)tt);
130}
131
132static unsigned8
133XorOB(unsigned8 ts, unsigned8 tt)
134{
135 return ts ^ tt;
136}
137
138static signed16
139SLLQH(signed16 ts, signed16 tt)
140{
141 unsigned32 s = (unsigned32)tt & 0xF;
142 return (signed16)(((unsigned32)ts << s) & 0xFFFF);
143}
144
145static unsigned8
146SLLOB(unsigned8 ts, unsigned8 tt)
147{
148 unsigned32 s = tt & 0x7;
149 return (ts << s) & 0xFF;
150}
151
152static signed16
153SRLQH(signed16 ts, signed16 tt)
154{
155 unsigned32 s = (unsigned32)tt & 0xF;
156 return (signed16)((unsigned16)ts >> s);
157}
158
159static unsigned8
160SRLOB(unsigned8 ts, unsigned8 tt)
161{
162 unsigned32 s = tt & 0x7;
163 return ts >> s;
164}
165
166
167/* Vectorized arithmetic operators. */
168
169static signed16
170AddQH(signed16 ts, signed16 tt)
171{
172 signed32 t = (signed32)ts + (signed32)tt;
173 return QH_CLAMP(t);
174}
175
176static unsigned8
177AddOB(unsigned8 ts, unsigned8 tt)
178{
179 unsigned32 t = (unsigned32)ts + (unsigned32)tt;
180 return OB_CLAMP(t);
181}
182
183static signed16
184SubQH(signed16 ts, signed16 tt)
185{
186 signed32 t = (signed32)ts - (signed32)tt;
187 return QH_CLAMP(t);
188}
189
190static unsigned8
191SubOB(unsigned8 ts, unsigned8 tt)
192{
193 signed32 t;
194 t = (signed32)ts - (signed32)tt;
195 if (t < 0)
196 t = 0;
197 return (unsigned8)t;
198}
199
200static signed16
201MinQH(signed16 ts, signed16 tt)
202{
203 return (ts < tt ? ts : tt);
204}
205
206static unsigned8
207MinOB(unsigned8 ts, unsigned8 tt)
208{
209 return (ts < tt ? ts : tt);
210}
211
212static signed16
213MaxQH(signed16 ts, signed16 tt)
214{
215 return (ts > tt ? ts : tt);
216}
217
218static unsigned8
219MaxOB(unsigned8 ts, unsigned8 tt)
220{
221 return (ts > tt ? ts : tt);
222}
223
224static signed16
225MulQH(signed16 ts, signed16 tt)
226{
227 signed32 t = (signed32)ts * (signed32)tt;
228 return QH_CLAMP(t);
229}
230
231static unsigned8
232MulOB(unsigned8 ts, unsigned8 tt)
233{
234 unsigned32 t = (unsigned32)ts * (unsigned32)tt;
235 return OB_CLAMP(t);
236}
237
238/* "msgn" and "sra" are defined only for QH format. */
239
240static signed16
241MsgnQH(signed16 ts, signed16 tt)
242{
243 signed16 t;
244 if (ts < 0)
245 t = (tt == QH_MIN ? QH_MAX : -tt);
246 else if (ts == 0)
247 t = 0;
248 else
249 t = tt;
250 return t;
251}
252
253
254static signed16
255SRAQH(signed16 ts, signed16 tt)
256{
257 unsigned32 s = (unsigned32)tt & 0xF;
258 return (signed16)((signed32)ts >> s);
259}
260
261
262/* Dispatch tables for operations that update a CPR. */
263
264static const QH_FUNC qh_func[] = {
265 AndQH, NorQH, OrQH, XorQH, SLLQH, SRLQH,
266 AddQH, SubQH, MinQH, MaxQH,
267 MulQH, MsgnQH, SRAQH, NULL, NULL
268};
269
270static const OB_FUNC ob_func[] = {
271 AndOB, NorOB, OrOB, XorOB, SLLOB, SRLOB,
272 AddOB, SubOB, MinOB, MaxOB,
273 MulOB, NULL, NULL, NULL, NULL
274};
275
276/* Auxiliary functions for CPR updates. */
277
278/* Vector mapping for QH format. */
279static unsigned64
280qh_vector_op(unsigned64 v1, unsigned64 v2, QH_FUNC func)
281{
282 unsigned64 result = 0;
283 int i;
284 signed16 h, h1, h2;
285
286 for (i = 0; i < 64; i += 16)
287 {
288 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
289 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
290 h = (*func)(h1, h2);
291 result |= ((unsigned64)((unsigned16)h) << i);
292 }
293 return result;
294}
295
296static unsigned64
297qh_map_op(unsigned64 v1, signed16 h2, QH_FUNC func)
298{
299 unsigned64 result = 0;
300 int i;
301 signed16 h, h1;
302
303 for (i = 0; i < 64; i += 16)
304 {
305 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
306 h = (*func)(h1, h2);
307 result |= ((unsigned64)((unsigned16)h) << i);
308 }
309 return result;
310}
311
312
313/* Vector operations for OB format. */
314
315static unsigned64
316ob_vector_op(unsigned64 v1, unsigned64 v2, OB_FUNC func)
317{
318 unsigned64 result = 0;
319 int i;
320 unsigned8 b, b1, b2;
321
322 for (i = 0; i < 64; i += 8)
323 {
324 b1 = v1 & 0xFF; v1 >>= 8;
325 b2 = v2 & 0xFF; v2 >>= 8;
326 b = (*func)(b1, b2);
327 result |= ((unsigned64)b << i);
328 }
329 return result;
330}
331
332static unsigned64
333ob_map_op(unsigned64 v1, unsigned8 b2, OB_FUNC func)
334{
335 unsigned64 result = 0;
336 int i;
337 unsigned8 b, b1;
338
339 for (i = 0; i < 64; i += 8)
340 {
341 b1 = v1 & 0xFF; v1 >>= 8;
342 b = (*func)(b1, b2);
343 result |= ((unsigned64)b << i);
344 }
345 return result;
346}
347
348
349/* Primary entry for operations that update CPRs. */
350unsigned64
351mdmx_cpr_op(sim_cpu *cpu,
352 address_word cia,
353 int op,
354 unsigned64 op1,
355 int vt,
356 MX_fmtsel fmtsel)
357{
358 unsigned64 op2;
359 unsigned64 result = 0;
360
361 switch (MX_FMT (fmtsel))
362 {
363 case mdmx_qh:
364 switch (MX_VT (fmtsel))
365 {
366 case sel_elem:
367 op2 = ValueFPR(vt, fmt_mdmx);
368 result = qh_map_op(op1, QH_ELEM(op2, fmtsel), qh_func[op]);
369 break;
370 case sel_vect:
371 result = qh_vector_op(op1, ValueFPR(vt, fmt_mdmx), qh_func[op]);
372 break;
373 case sel_imm:
374 result = qh_map_op(op1, vt, qh_func[op]);
375 break;
376 }
377 break;
378 case mdmx_ob:
379 switch (MX_VT (fmtsel))
380 {
381 case sel_elem:
382 op2 = ValueFPR(vt, fmt_mdmx);
383 result = ob_map_op(op1, OB_ELEM(op2, fmtsel), ob_func[op]);
384 break;
385 case sel_vect:
386 result = ob_vector_op(op1, ValueFPR(vt, fmt_mdmx), ob_func[op]);
387 break;
388 case sel_imm:
389 result = ob_map_op(op1, vt, ob_func[op]);
390 break;
391 }
392 break;
393 default:
394 Unpredictable ();
395 }
396
397 return result;
398}
399
400
401/* Operations that update CCs */
402
403static void
404qh_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
405{
406 int i;
407 signed16 h1, h2;
408 int boolean;
409
410 for (i = 0; i < 4; i++)
411 {
412 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
413 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
414 boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
415 ((cond & MX_C_LT) && (h1 < h2));
416 SETFCC(i, boolean);
417 }
418}
419
420static void
421qh_map_test(sim_cpu *cpu, unsigned64 v1, signed16 h2, int cond)
422{
423 int i;
424 signed16 h1;
425 int boolean;
426
427 for (i = 0; i < 4; i++)
428 {
429 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
430 boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
431 ((cond & MX_C_LT) && (h1 < h2));
432 SETFCC(i, boolean);
433 }
434}
435
436static void
437ob_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
438{
439 int i;
440 unsigned8 b1, b2;
441 int boolean;
442
443 for (i = 0; i < 8; i++)
444 {
445 b1 = v1 & 0xFF; v1 >>= 8;
446 b2 = v2 & 0xFF; v2 >>= 8;
447 boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
448 ((cond & MX_C_LT) && (b1 < b2));
449 SETFCC(i, boolean);
450 }
451}
452
453static void
454ob_map_test(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int cond)
455{
456 int i;
457 unsigned8 b1;
458 int boolean;
459
460 for (i = 0; i < 8; i++)
461 {
462 b1 = (unsigned8)(v1 & 0xFF); v1 >>= 8;
463 boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
464 ((cond & MX_C_LT) && (b1 < b2));
465 SETFCC(i, boolean);
466 }
467}
468
469
470void
471mdmx_cc_op(sim_cpu *cpu,
472 address_word cia,
473 int cond,
474 unsigned64 v1,
475 int vt,
476 MX_fmtsel fmtsel)
477{
478 unsigned64 op2;
479
480 switch (MX_FMT (fmtsel))
481 {
482 case mdmx_qh:
483 switch (MX_VT (fmtsel))
484 {
485 case sel_elem:
486 op2 = ValueFPR(vt, fmt_mdmx);
487 qh_map_test(cpu, v1, QH_ELEM(op2, fmtsel), cond);
488 break;
489 case sel_vect:
490 qh_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
491 break;
492 case sel_imm:
493 qh_map_test(cpu, v1, vt, cond);
494 break;
495 }
496 break;
497 case mdmx_ob:
498 switch (MX_VT (fmtsel))
499 {
500 case sel_elem:
501 op2 = ValueFPR(vt, fmt_mdmx);
502 ob_map_test(cpu, v1, OB_ELEM(op2, fmtsel), cond);
503 break;
504 case sel_vect:
505 ob_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
506 break;
507 case sel_imm:
508 ob_map_test(cpu, v1, vt, cond);
509 break;
510 }
511 break;
512 default:
513 Unpredictable ();
514 }
515}
516
517
518/* Pick operations. */
519
520static unsigned64
521qh_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
522{
523 unsigned64 result = 0;
524 int i, s;
525 unsigned16 h;
526
527 s = 0;
528 for (i = 0; i < 4; i++)
529 {
530 h = ((GETFCC(i) == tf) ? (v1 & 0xFFFF) : (v2 & 0xFFFF));
531 v1 >>= 16; v2 >>= 16;
532 result |= ((unsigned64)h << s);
533 s += 16;
534 }
535 return result;
536}
537
538static unsigned64
539qh_map_pick(sim_cpu *cpu, unsigned64 v1, signed16 h2, int tf)
540{
541 unsigned64 result = 0;
542 int i, s;
543 unsigned16 h;
544
545 s = 0;
546 for (i = 0; i < 4; i++)
547 {
548 h = (GETFCC(i) == tf) ? (v1 & 0xFFFF) : (unsigned16)h2;
549 v1 >>= 16;
550 result |= ((unsigned64)h << s);
551 s += 16;
552 }
553 return result;
554}
555
556static unsigned64
557ob_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
558{
559 unsigned64 result = 0;
560 int i, s;
561 unsigned8 b;
562
563 s = 0;
564 for (i = 0; i < 8; i++)
565 {
566 b = (GETFCC(i) == tf) ? (v1 & 0xFF) : (v2 & 0xFF);
567 v1 >>= 8; v2 >>= 8;
568 result |= ((unsigned64)b << s);
569 s += 8;
570 }
571 return result;
572}
573
574static unsigned64
575ob_map_pick(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int tf)
576{
577 unsigned64 result = 0;
578 int i, s;
579 unsigned8 b;
580
581 s = 0;
582 for (i = 0; i < 8; i++)
583 {
584 b = (GETFCC(i) == tf) ? (v1 & 0xFF) : b2;
585 v1 >>= 8;
586 result |= ((unsigned64)b << s);
587 s += 8;
588 }
589 return result;
590}
591
592
593unsigned64
594mdmx_pick_op(sim_cpu *cpu,
595 address_word cia,
596 int tf,
597 unsigned64 v1,
598 int vt,
599 MX_fmtsel fmtsel)
600{
601 unsigned64 result = 0;
602 unsigned64 op2;
603
604 switch (MX_FMT (fmtsel))
605 {
606 case mdmx_qh:
607 switch (MX_VT (fmtsel))
608 {
609 case sel_elem:
610 op2 = ValueFPR(vt, fmt_mdmx);
611 result = qh_map_pick(cpu, v1, QH_ELEM(op2, fmtsel), tf);
612 break;
613 case sel_vect:
614 result = qh_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
615 break;
616 case sel_imm:
617 result = qh_map_pick(cpu, v1, vt, tf);
618 break;
619 }
620 break;
621 case mdmx_ob:
622 switch (MX_VT (fmtsel))
623 {
624 case sel_elem:
625 op2 = ValueFPR(vt, fmt_mdmx);
626 result = ob_map_pick(cpu, v1, OB_ELEM(op2, fmtsel), tf);
627 break;
628 case sel_vect:
629 result = ob_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
630 break;
631 case sel_imm:
632 result = ob_map_pick(cpu, v1, vt, tf);
633 break;
634 }
635 break;
636 default:
637 Unpredictable ();
638 }
639 return result;
640}
641
642
643/* Accumulators. */
644
645typedef void (*QH_ACC)(signed48 *a, signed16 ts, signed16 tt);
646
647static void
648AccAddAQH(signed48 *a, signed16 ts, signed16 tt)
649{
650 *a += (signed48)ts + (signed48)tt;
651}
652
653static void
654AccAddLQH(signed48 *a, signed16 ts, signed16 tt)
655{
656 *a = (signed48)ts + (signed48)tt;
657}
658
659static void
660AccMulAQH(signed48 *a, signed16 ts, signed16 tt)
661{
662 *a += (signed48)ts * (signed48)tt;
663}
664
665static void
666AccMulLQH(signed48 *a, signed16 ts, signed16 tt)
667{
668 *a = (signed48)ts * (signed48)tt;
669}
670
671static void
672SubMulAQH(signed48 *a, signed16 ts, signed16 tt)
673{
674 *a -= (signed48)ts * (signed48)tt;
675}
676
677static void
678SubMulLQH(signed48 *a, signed16 ts, signed16 tt)
679{
680 *a = -((signed48)ts * (signed48)tt);
681}
682
683static void
684AccSubAQH(signed48 *a, signed16 ts, signed16 tt)
685{
686 *a += (signed48)ts - (signed48)tt;
687}
688
689static void
690AccSubLQH(signed48 *a, signed16 ts, signed16 tt)
691{
692 *a = (signed48)ts - (signed48)tt;
693}
694
695
696typedef void (*OB_ACC)(signed24 *acc, unsigned8 ts, unsigned8 tt);
697
698static void
699AccAddAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
700{
701 *a += (signed24)ts + (signed24)tt;
702}
703
704static void
705AccAddLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
706{
707 *a = (signed24)ts + (signed24)tt;
708}
709
710static void
711AccMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
712{
713 *a += (signed24)ts * (signed24)tt;
714}
715
716static void
717AccMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
718{
719 *a = (signed24)ts * (signed24)tt;
720}
721
722static void
723SubMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
724{
725 *a -= (signed24)ts * (signed24)tt;
726}
727
728static void
729SubMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
730{
731 *a = -((signed24)ts * (signed24)tt);
732}
733
734static void
735AccSubAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
736{
737 *a += (signed24)ts - (signed24)tt;
738}
739
740static void
741AccSubLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
742{
743 *a = (signed24)ts - (signed24)tt;
744}
745
746
747/* Dispatch tables for operations that update a CPR. */
748
749static const QH_ACC qh_acc[] = {
750 AccAddAQH, AccAddAQH, AccMulAQH, AccMulLQH,
751 SubMulAQH, SubMulLQH, AccSubAQH, AccSubLQH
752};
753
754static const OB_ACC ob_acc[] = {
755 AccAddAOB, AccAddLOB, AccMulAOB, AccMulLOB,
756 SubMulAOB, SubMulLOB, AccSubAOB, AccSubLOB
757};
758
759
760static void
761qh_vector_acc(signed48 a[], unsigned64 v1, unsigned64 v2, QH_ACC acc)
762{
763 int i;
764 signed16 h1, h2;
765
766 for (i = 0; i < 4; i++)
767 {
768 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
769 h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
770 (*acc)(&a[i], h1, h2);
771 }
772}
773
774static void
775qh_map_acc(signed48 a[], unsigned64 v1, signed16 h2, QH_ACC acc)
776{
777 int i;
778 signed16 h1;
779
780 for (i = 0; i < 4; i++)
781 {
782 h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
783 (*acc)(&a[i], h1, h2);
784 }
785}
786
787static void
788ob_vector_acc(signed24 a[], unsigned64 v1, unsigned64 v2, OB_ACC acc)
789{
790 int i;
791 unsigned8 b1, b2;
792
793 for (i = 0; i < 8; i++)
794 {
795 b1 = v1 & 0xFF; v1 >>= 8;
796 b2 = v2 & 0xFF; v2 >>= 8;
797 (*acc)(&a[i], b1, b2);
798 }
799}
800
801static void
802ob_map_acc(signed24 a[], unsigned64 v1, unsigned8 b2, OB_ACC acc)
803{
804 int i;
805 unsigned8 b1;
806
807 for (i = 0; i < 8; i++)
808 {
809 b1 = v1 & 0xFF; v1 >>= 8;
810 (*acc)(&a[i], b1, b2);
811 }
812}
813
814
815/* Primary entry for operations that accumulate */
816void
817mdmx_acc_op(sim_cpu *cpu,
818 address_word cia,
819 int op,
820 unsigned64 op1,
821 int vt,
822 MX_fmtsel fmtsel)
823{
824 unsigned64 op2;
825
826 switch (MX_FMT (fmtsel))
827 {
828 case mdmx_qh:
829 switch (MX_VT (fmtsel))
830 {
831 case sel_elem:
832 op2 = ValueFPR(vt, fmt_mdmx);
833 qh_map_acc(ACC.qh, op1, QH_ELEM(op2, fmtsel), qh_acc[op]);
834 break;
835 case sel_vect:
836 qh_vector_acc(ACC.qh, op1, ValueFPR(vt, fmt_mdmx), qh_acc[op]);
837 break;
838 case sel_imm:
839 qh_map_acc(ACC.qh, op1, vt, qh_acc[op]);
840 break;
841 }
842 break;
843 case mdmx_ob:
844 switch (MX_VT (fmtsel))
845 {
846 case sel_elem:
847 op2 = ValueFPR(vt, fmt_mdmx);
848 ob_map_acc(ACC.ob, op1, OB_ELEM(op2, fmtsel), ob_acc[op]);
849 break;
850 case sel_vect:
851 ob_vector_acc(ACC.ob, op1, ValueFPR(vt, fmt_mdmx), ob_acc[op]);
852 break;
853 case sel_imm:
854 ob_map_acc(ACC.ob, op1, op2, ob_acc[op]);
855 break;
856 }
857 break;
858 default:
859 Unpredictable ();
860 }
861}
862
863
864/* Reading and writing accumulator (no conversion). */
865
866unsigned64
867mdmx_rac_op(sim_cpu *cpu,
868 address_word cia,
869 int op,
870 int fmt)
871{
872 unsigned64 result;
873 unsigned int shift;
874 int i;
875
876 shift = op; /* L = 00, M = 01, H = 10. */
877 result = 0;
878
879 switch (fmt)
880 {
881 case MX_FMT_QH:
882 shift <<= 4; /* 16 bits per element. */
883 for (i = 3; i >= 0; --i)
884 {
885 result <<= 16;
886 result |= ((ACC.qh[i] >> shift) & 0xFFFF);
887 }
888 break;
889 case MX_FMT_OB:
890 shift <<= 3; /* 8 bits per element. */
891 for (i = 7; i >= 0; --i)
892 {
893 result <<= 8;
894 result |= ((ACC.ob[i] >> shift) & 0xFF);
895 }
896 break;
897 default:
898 Unpredictable ();
899 }
900 return result;
901}
902
903void
904mdmx_wacl(sim_cpu *cpu,
905 address_word cia,
906 int fmt,
907 unsigned64 vs,
908 unsigned64 vt)
909{
910 int i;
911
912 switch (fmt)
913 {
914 case MX_FMT_QH:
915 for (i = 0; i < 4; i++)
916 {
917 signed32 s = (signed16)(vs & 0xFFFF);
918 ACC.qh[i] = ((signed48)s << 16) | (vt & 0xFFFF);
919 vs >>= 16; vt >>= 16;
920 }
921 break;
922 case MX_FMT_OB:
923 for (i = 0; i < 8; i++)
924 {
925 signed16 s = (signed8)(vs & 0xFF);
926 ACC.ob[i] = ((signed24)s << 8) | (vt & 0xFF);
927 vs >>= 8; vt >>= 8;
928 }
929 break;
930 default:
931 Unpredictable ();
932 }
933}
934
935void
936mdmx_wach(sim_cpu *cpu,
937 address_word cia,
938 int fmt,
939 unsigned64 vs)
940{
941 int i;
942
943 switch (fmt)
944 {
945 case MX_FMT_QH:
946 for (i = 0; i < 4; i++)
947 {
948 signed32 s = (signed16)(vs & 0xFFFF);
949 ACC.qh[i] &= ~((signed48)0xFFFF << 32);
950 ACC.qh[i] |= ((signed48)s << 32);
951 vs >>= 16;
952 }
953 break;
954 case MX_FMT_OB:
955 for (i = 0; i < 8; i++)
956 {
957 ACC.ob[i] &= ~((signed24)0xFF << 16);
958 ACC.ob[i] |= ((signed24)(vs & 0xFF) << 16);
959 vs >>= 8;
960 }
961 break;
962 default:
963 Unpredictable ();
964 }
965}
966
967
968/* Reading and writing accumulator (rounding conversions).
969 Enumerating function guarantees s >= 0 for QH ops. */
970
971typedef signed16 (*QH_ROUND)(signed48 a, signed16 s);
972
973#define QH_BIT(n) ((unsigned48)1 << (n))
974#define QH_ONES(n) (((unsigned48)1 << (n))-1)
975
976static signed16
977RNASQH(signed48 a, signed16 s)
978{
979 signed48 t;
980 signed16 result = 0;
981
982 if (s > 48)
983 result = 0;
984 else
985 {
986 t = (a >> s);
987 if ((a & QH_BIT(47)) == 0)
988 {
989 if (s > 0 && ((a >> (s-1)) & 1) == 1)
990 t++;
991 if (t > QH_MAX)
992 t = QH_MAX;
993 }
994 else
995 {
996 if (s > 0 && ((a >> (s-1)) & 1) == 1)
997 {
998 if (s > 1 && ((unsigned48)a & QH_ONES(s-1)) != 0)
999 t++;
1000 }
1001 if (t < QH_MIN)
1002 t = QH_MIN;
1003 }
1004 result = (signed16)t;
1005 }
1006 return result;
1007}
1008
1009static signed16
1010RNAUQH(signed48 a, signed16 s)
1011{
1012 unsigned48 t;
1013 signed16 result;
1014
1015 if (s > 48)
1016 result = 0;
1017 else if (s == 48)
1018 result = ((unsigned48)a & MASK48) >> 47;
1019 else
1020 {
1021 t = ((unsigned48)a & MASK48) >> s;
1022 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1023 t++;
1024 if (t > 0xFFFF)
1025 t = 0xFFFF;
1026 result = (signed16)t;
1027 }
1028 return result;
1029}
1030
1031static signed16
1032RNESQH(signed48 a, signed16 s)
1033{
1034 signed48 t;
1035 signed16 result = 0;
1036
1037 if (s > 47)
1038 result = 0;
1039 else
1040 {
1041 t = (a >> s);
1042 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1043 {
1044 if (s == 1 || (a & QH_ONES(s-1)) == 0)
1045 t += t & 1;
1046 else
1047 t += 1;
1048 }
1049 if ((a & QH_BIT(47)) == 0)
1050 {
1051 if (t > QH_MAX)
1052 t = QH_MAX;
1053 }
1054 else
1055 {
1056 if (t < QH_MIN)
1057 t = QH_MIN;
1058 }
1059 result = (signed16)t;
1060 }
1061 return result;
1062}
1063
1064static signed16
1065RNEUQH(signed48 a, signed16 s)
1066{
1067 unsigned48 t;
1068 signed16 result;
1069
1070 if (s > 48)
1071 result = 0;
1072 else if (s == 48)
1073 result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1074 else
1075 {
1076 t = ((unsigned48)a & MASK48) >> s;
1077 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1078 {
1079 if (s > 1 && (a & QH_ONES(s-1)) != 0)
1080 t++;
1081 else
1082 t += t & 1;
1083 }
1084 if (t > 0xFFFF)
1085 t = 0xFFFF;
1086 result = (signed16)t;
1087 }
1088 return result;
1089}
1090
1091static signed16
1092RZSQH(signed48 a, signed16 s)
1093{
1094 signed48 t;
1095 signed16 result = 0;
1096
1097 if (s > 47)
1098 result = 0;
1099 else
1100 {
1101 t = (a >> s);
1102 if ((a & QH_BIT(47)) == 0)
1103 {
1104 if (t > QH_MAX)
1105 t = QH_MAX;
1106 }
1107 else
1108 {
1109 if (t < QH_MIN)
1110 t = QH_MIN;
1111 }
1112 result = (signed16)t;
1113 }
1114 return result;
1115}
1116
1117static signed16
1118RZUQH(signed48 a, signed16 s)
1119{
1120 unsigned48 t;
1121 signed16 result = 0;
1122
1123 if (s > 48)
1124 result = 0;
1125 else if (s == 48)
1126 result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
1127 else
1128 {
1129 t = ((unsigned48)a & MASK48) >> s;
1130 if (t > 0xFFFF)
1131 t = 0xFFFF;
1132 result = (signed16)t;
1133 }
1134 return result;
1135}
1136
1137
1138typedef unsigned8 (*OB_ROUND)(signed24 a, unsigned8 s);
1139
1140#define OB_BIT(n) ((unsigned24)1 << (n))
1141#define OB_ONES(n) (((unsigned24)1 << (n))-1)
1142
1143static unsigned8
1144RNAUOB(signed24 a, unsigned8 s)
1145{
1146 unsigned8 result;
1147 unsigned24 t;
1148
1149 if (s > 24)
1150 result = 0;
1151 else if (s == 24)
1152 result = ((unsigned24)a & MASK24) >> 23;
1153 else
1154 {
1155 t = ((unsigned24)a & MASK24) >> s;
1156 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1157 t ++;
1158 result = OB_CLAMP(t);
1159 }
1160 return result;
1161}
1162
1163static unsigned8
1164RNEUOB(signed24 a, unsigned8 s)
1165{
1166 unsigned8 result;
1167 unsigned24 t;
1168
1169 if (s > 24)
1170 result = 0;
1171 else if (s == 24)
1172 result = (((unsigned24)a & MASK24) > OB_BIT(23) ? 1 : 0);
1173 else
1174 {
1175 t = ((unsigned24)a & MASK24) >> s;
1176 if (s > 0 && ((a >> (s-1)) & 1) == 1)
1177 {
1178 if (s > 1 && (a & OB_ONES(s-1)) != 0)
1179 t++;
1180 else
1181 t += t & 1;
1182 }
1183 result = OB_CLAMP(t);
1184 }
1185 return result;
1186}
1187
1188static unsigned8
1189RZUOB(signed24 a, unsigned8 s)
1190{
1191 unsigned8 result;
1192 unsigned24 t;
1193
1194 if (s >= 24)
1195 result = 0;
1196 else
1197 {
1198 t = ((unsigned24)a & MASK24) >> s;
1199 result = OB_CLAMP(t);
1200 }
1201 return result;
1202}
1203
1204
1205static const QH_ROUND qh_round[] = {
1206 RNASQH, RNAUQH, RNESQH, RNEUQH, RZSQH, RZUQH
1207};
1208
1209static const OB_ROUND ob_round[] = {
1210 NULL, RNAUOB, NULL, RNEUOB, NULL, RZUOB
1211};
1212
1213
1214static unsigned64
1215qh_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, QH_ROUND round)
1216{
1217 unsigned64 result = 0;
1218 int i, s;
1219 signed16 h, h2;
1220
1221 s = 0;
1222 for (i = 0; i < 4; i++)
1223 {
1224 h2 = (signed16)(v2 & 0xFFFF);
1225 if (h2 >= 0)
1226 h = (*round)(ACC.qh[i], h2);
1227 else
1228 {
1229 UnpredictableResult ();
1230 h = 0xdead;
1231 }
1232 v2 >>= 16;
1233 result |= ((unsigned64)((unsigned16)h) << s);
1234 s += 16;
1235 }
1236 return result;
1237}
1238
1239static unsigned64
1240qh_map_round(sim_cpu *cpu, address_word cia, signed16 h2, QH_ROUND round)
1241{
1242 unsigned64 result = 0;
1243 int i, s;
1244 signed16 h;
1245
1246 s = 0;
1247 for (i = 0; i < 4; i++)
1248 {
1249 if (h2 >= 0)
1250 h = (*round)(ACC.qh[i], h2);
1251 else
1252 {
1253 UnpredictableResult ();
1254 h = 0xdead;
1255 }
1256 result |= ((unsigned64)((unsigned16)h) << s);
1257 s += 16;
1258 }
1259 return result;
1260}
1261
1262static unsigned64
1263ob_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, OB_ROUND round)
1264{
1265 unsigned64 result = 0;
1266 int i, s;
1267 unsigned8 b, b2;
1268
1269 s = 0;
1270 for (i = 0; i < 8; i++)
1271 {
1272 b2 = v2 & 0xFF; v2 >>= 8;
1273 b = (*round)(ACC.ob[i], b2);
1274 result |= ((unsigned64)b << s);
1275 s += 8;
1276 }
1277 return result;
1278}
1279
1280static unsigned64
1281ob_map_round(sim_cpu *cpu, address_word cia, unsigned8 b2, OB_ROUND round)
1282{
1283 unsigned64 result = 0;
1284 int i, s;
1285 unsigned8 b;
1286
1287 s = 0;
1288 for (i = 0; i < 8; i++)
1289 {
1290 b = (*round)(ACC.ob[i], b2);
1291 result |= ((unsigned64)b << s);
1292 s += 8;
1293 }
1294 return result;
1295}
1296
1297
1298unsigned64
1299mdmx_round_op(sim_cpu *cpu,
1300 address_word cia,
1301 int rm,
1302 int vt,
1303 MX_fmtsel fmtsel)
1304{
1305 unsigned64 op2;
1306 unsigned64 result = 0;
1307
1308 switch (MX_FMT (fmtsel))
1309 {
1310 case mdmx_qh:
1311 switch (MX_VT (fmtsel))
1312 {
1313 case sel_elem:
1314 op2 = ValueFPR(vt, fmt_mdmx);
1315 result = qh_map_round(cpu, cia, QH_ELEM(op2, fmtsel), qh_round[rm]);
1316 break;
1317 case sel_vect:
1318 op2 = ValueFPR(vt, fmt_mdmx);
1319 result = qh_vector_round(cpu, cia, op2, qh_round[rm]);
1320 break;
1321 case sel_imm:
1322 result = qh_map_round(cpu, cia, vt, qh_round[rm]);
1323 break;
1324 }
1325 break;
1326 case mdmx_ob:
1327 switch (MX_VT (fmtsel))
1328 {
1329 case sel_elem:
1330 op2 = ValueFPR(vt, fmt_mdmx);
1331 result = ob_map_round(cpu, cia, OB_ELEM(op2, fmtsel), ob_round[rm]);
1332 break;
1333 case sel_vect:
1334 op2 = ValueFPR(vt, fmt_mdmx);
1335 result = ob_vector_round(cpu, cia, op2, ob_round[rm]);
1336 break;
1337 case sel_imm:
1338 result = ob_map_round(cpu, cia, vt, ob_round[rm]);
1339 break;
1340 }
1341 break;
1342 default:
1343 Unpredictable ();
1344 }
1345
1346 return result;
1347}
1348
1349
1350/* Shuffle operation. */
1351
1352typedef struct {
1353 enum {vs, ss, vt} source;
1354 unsigned int index;
1355} sh_map;
1356
1357static const sh_map ob_shuffle[][8] = {
1358 /* MDMX 2.0 encodings (3-4, 6-7). */
1359 /* vr5400 encoding (5), otherwise. */
1360 { }, /* RSVD */
1361 {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* RSVD */
1362 {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* RSVD */
1363 {{vs,0}, {ss,0}, {vs,1}, {ss,1}, {vs,2}, {ss,2}, {vs,3}, {ss,3}}, /* upsl */
1364 {{vt,1}, {vt,3}, {vt,5}, {vt,7}, {vs,1}, {vs,3}, {vs,5}, {vs,7}}, /* pach */
1365 {{vt,0}, {vt,2}, {vt,4}, {vt,6}, {vs,0}, {vs,2}, {vs,4}, {vs,6}}, /* pacl */
1366 {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* mixh */
1367 {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}} /* mixl */
1368};
1369
1370static const sh_map qh_shuffle[][4] = {
1371 {{vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* mixh */
1372 {{vt,0}, {vs,0}, {vt,1}, {vs,1}}, /* mixl */
1373 {{vt,1}, {vt,3}, {vs,1}, {vs,3}}, /* pach */
1374 { }, /* RSVD */
1375 {{vt,1}, {vs,0}, {vt,3}, {vs,2}}, /* bfla */
1376 { }, /* RSVD */
1377 {{vt,2}, {vt,3}, {vs,2}, {vs,3}}, /* repa */
1378 {{vt,0}, {vt,1}, {vs,0}, {vs,1}} /* repb */
1379};
1380
1381
1382unsigned64
1383mdmx_shuffle(sim_cpu *cpu,
1384 address_word cia,
1385 int shop,
1386 unsigned64 op1,
1387 unsigned64 op2)
1388{
1389 unsigned64 result = 0;
1390 int i, s;
1391 int op;
1392
1393 if ((shop & 0x3) == 0x1) /* QH format. */
1394 {
1395 op = shop >> 2;
1396 s = 0;
1397 for (i = 0; i < 4; i++)
1398 {
1399 unsigned64 v;
1400
1401 switch (qh_shuffle[op][i].source)
1402 {
1403 case vs:
1404 v = op1;
1405 break;
1406 case vt:
1407 v = op2;
1408 break;
1409 default:
1410 Unpredictable ();
1411 v = 0;
1412 }
1413 result |= (((v >> 16*qh_shuffle[op][i].index) & 0xFFFF) << s);
1414 s += 16;
1415 }
1416 }
1417 else if ((shop & 0x1) == 0x0) /* OB format. */
1418 {
1419 op = shop >> 1;
1420 s = 0;
1421 for (i = 0; i < 8; i++)
1422 {
1423 unsigned8 b;
1424 unsigned int ishift = 8*ob_shuffle[op][i].index;
1425
1426 switch (ob_shuffle[op][i].source)
1427 {
1428 case vs:
1429 b = (op1 >> ishift) & 0xFF;
1430 break;
1431 case ss:
1432 b = ((op1 >> ishift) & 0x80) ? 0xFF : 0;
1433 break;
1434 case vt:
1435 b = (op2 >> ishift) & 0xFF;
1436 break;
1437 default:
1438 Unpredictable ();
1439 b = 0;
1440 }
1441 result |= ((unsigned64)b << s);
1442 s += 8;
1443 }
1444 }
1445 else
1446 Unpredictable ();
1447
1448 return result;
1449}