aboutsummaryrefslogtreecommitdiff
path: root/sim/mips/mdmx.c
diff options
context:
space:
mode:
Diffstat (limited to 'sim/mips/mdmx.c')
-rw-r--r--sim/mips/mdmx.c1477
1 files changed, 0 insertions, 1477 deletions
diff --git a/sim/mips/mdmx.c b/sim/mips/mdmx.c
deleted file mode 100644
index 3af59b0..0000000
--- a/sim/mips/mdmx.c
+++ /dev/null
@@ -1,1477 +0,0 @@
-/* Simulation code for the MIPS MDMX ASE.
- Copyright (C) 2002 Free Software Foundation, Inc.
- Contributed by Ed Satterthwaite and Chris Demetriou, of Broadcom
- Corporation (SiByte).
-
-This file is part of GDB, the GNU debugger.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along
-with this program; if not, write to the Free Software Foundation, Inc.,
-59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-#include <stdio.h>
-
-#include "sim-main.h"
-
-/* Within mdmx.c we refer to the sim_cpu directly. */
-#define CPU cpu
-#define SD (CPU_STATE(CPU))
-
-/* XXX FIXME: temporary hack while the impact of making unpredictable()
- a "normal" (non-igen) function is evaluated. */
-#undef Unpredictable
-#define Unpredictable() unpredictable_action (cpu, cia)
-
-/* MDMX Representations
-
- An 8-bit packed byte element (OB) is always unsigned.
- The 24-bit accumulators are signed and are represented as 32-bit
- signed values, which are reduced to 24-bit signed values prior to
- Round and Clamp operations.
-
- A 16-bit packed halfword element (QH) is always signed.
- The 48-bit accumulators are signed and are represented as 64-bit
- signed values, which are reduced to 48-bit signed values prior to
- Round and Clamp operations.
-
- The code below assumes a 2's-complement representation of signed
- quantities. Care is required to clear extended sign bits when
- repacking fields.
-
- The code (and the code for arithmetic shifts in mips.igen) also makes
- the (not guaranteed portable) assumption that right shifts of signed
- quantities in C do sign extension. */
-
-typedef unsigned64 unsigned48;
-#define MASK48 (UNSIGNED64 (0xffffffffffff))
-
-typedef unsigned32 unsigned24;
-#define MASK24 (UNSIGNED32 (0xffffff))
-
-typedef enum {
- mdmx_ob, /* OB (octal byte) */
- mdmx_qh /* QH (quad half-word) */
-} MX_fmt;
-
-typedef enum {
- sel_elem, /* element select */
- sel_vect, /* vector select */
- sel_imm /* immediate select */
-} VT_select;
-
-#define OB_MAX ((unsigned8)0xFF)
-#define QH_MIN ((signed16)0x8000)
-#define QH_MAX ((signed16)0x7FFF)
-
-#define OB_CLAMP(x) ((unsigned8)((x) > OB_MAX ? OB_MAX : (x)))
-#define QH_CLAMP(x) ((signed16)((x) < QH_MIN ? QH_MIN : \
- ((x) > QH_MAX ? QH_MAX : (x))))
-
-#define MX_FMT(fmtsel) (((fmtsel) & 0x1) == 0 ? mdmx_ob : mdmx_qh)
-#define MX_VT(fmtsel) (((fmtsel) & 0x10) == 0 ? sel_elem : \
- (((fmtsel) & 0x18) == 0x10 ? sel_vect : sel_imm))
-
-#define QH_ELEM(v,fmtsel) \
- ((signed16)(((v) >> (((fmtsel) & 0xC) << 2)) & 0xFFFF))
-#define OB_ELEM(v,fmtsel) \
- ((unsigned8)(((v) >> (((fmtsel) & 0xE) << 2)) & 0xFF))
-
-
-typedef signed16 (*QH_FUNC)(signed16, signed16);
-typedef unsigned8 (*OB_FUNC)(unsigned8, unsigned8);
-
-/* vectorized logical operators */
-
-static signed16
-AndQH(signed16 ts, signed16 tt)
-{
- return (signed16)((unsigned16)ts & (unsigned16)tt);
-}
-
-static unsigned8
-AndOB(unsigned8 ts, unsigned8 tt)
-{
- return ts & tt;
-}
-
-static signed16
-NorQH(signed16 ts, signed16 tt)
-{
- return (signed16)(((unsigned16)ts | (unsigned16)tt) ^ 0xFFFF);
-}
-
-static unsigned8
-NorOB(unsigned8 ts, unsigned8 tt)
-{
- return (ts | tt) ^ 0xFF;
-}
-
-static signed16
-OrQH(signed16 ts, signed16 tt)
-{
- return (signed16)((unsigned16)ts | (unsigned16)tt);
-}
-
-static unsigned8
-OrOB(unsigned8 ts, unsigned8 tt)
-{
- return ts | tt;
-}
-
-static signed16
-XorQH(signed16 ts, signed16 tt)
-{
- return (signed16)((unsigned16)ts ^ (unsigned16)tt);
-}
-
-static unsigned8
-XorOB(unsigned8 ts, unsigned8 tt)
-{
- return ts ^ tt;
-}
-
-static signed16
-SLLQH(signed16 ts, signed16 tt)
-{
- unsigned32 s = (unsigned32)tt & 0xF;
- return (signed16)(((unsigned32)ts << s) & 0xFFFF);
-}
-
-static unsigned8
-SLLOB(unsigned8 ts, unsigned8 tt)
-{
- unsigned32 s = tt & 0x7;
- return (ts << s) & 0xFF;
-}
-
-static signed16
-SRLQH(signed16 ts, signed16 tt)
-{
- unsigned32 s = (unsigned32)tt & 0xF;
- return (signed16)((unsigned16)ts >> s);
-}
-
-static unsigned8
-SRLOB(unsigned8 ts, unsigned8 tt)
-{
- unsigned32 s = tt & 0x7;
- return ts >> s;
-}
-
-
-/* Vectorized arithmetic operators. */
-
-static signed16
-AddQH(signed16 ts, signed16 tt)
-{
- signed32 t = (signed32)ts + (signed32)tt;
- return QH_CLAMP(t);
-}
-
-static unsigned8
-AddOB(unsigned8 ts, unsigned8 tt)
-{
- unsigned32 t = (unsigned32)ts + (unsigned32)tt;
- return OB_CLAMP(t);
-}
-
-static signed16
-SubQH(signed16 ts, signed16 tt)
-{
- signed32 t = (signed32)ts - (signed32)tt;
- return QH_CLAMP(t);
-}
-
-static unsigned8
-SubOB(unsigned8 ts, unsigned8 tt)
-{
- signed32 t;
- t = (signed32)ts - (signed32)tt;
- if (t < 0)
- t = 0;
- return (unsigned8)t;
-}
-
-static signed16
-MinQH(signed16 ts, signed16 tt)
-{
- return (ts < tt ? ts : tt);
-}
-
-static unsigned8
-MinOB(unsigned8 ts, unsigned8 tt)
-{
- return (ts < tt ? ts : tt);
-}
-
-static signed16
-MaxQH(signed16 ts, signed16 tt)
-{
- return (ts > tt ? ts : tt);
-}
-
-static unsigned8
-MaxOB(unsigned8 ts, unsigned8 tt)
-{
- return (ts > tt ? ts : tt);
-}
-
-static signed16
-MulQH(signed16 ts, signed16 tt)
-{
- signed32 t = (signed32)ts * (signed32)tt;
- return QH_CLAMP(t);
-}
-
-static unsigned8
-MulOB(unsigned8 ts, unsigned8 tt)
-{
- unsigned32 t = (unsigned32)ts * (unsigned32)tt;
- return OB_CLAMP(t);
-}
-
-/* "msgn" and "sra" are defined only for QH format. */
-
-static signed16
-MsgnQH(signed16 ts, signed16 tt)
-{
- signed16 t;
- if (ts < 0)
- t = (tt == QH_MIN ? QH_MAX : -tt);
- else if (ts == 0)
- t = 0;
- else
- t = tt;
- return t;
-}
-
-static signed16
-SRAQH(signed16 ts, signed16 tt)
-{
- unsigned32 s = (unsigned32)tt & 0xF;
- return (signed16)((signed32)ts >> s);
-}
-
-
-/* "pabsdiff" and "pavg" are defined only for OB format. */
-
-static unsigned8
-AbsDiffOB(unsigned8 ts, unsigned8 tt)
-{
- return (ts >= tt ? ts - tt : tt - ts);
-}
-
-static unsigned8
-AvgOB(unsigned8 ts, unsigned8 tt)
-{
- return ((unsigned32)ts + (unsigned32)tt + 1) >> 1;
-}
-
-
-/* Dispatch tables for operations that update a CPR. */
-
-static const QH_FUNC qh_func[] = {
- AndQH, NorQH, OrQH, XorQH, SLLQH, SRLQH,
- AddQH, SubQH, MinQH, MaxQH,
- MulQH, MsgnQH, SRAQH, NULL, NULL
-};
-
-static const OB_FUNC ob_func[] = {
- AndOB, NorOB, OrOB, XorOB, SLLOB, SRLOB,
- AddOB, SubOB, MinOB, MaxOB,
- MulOB, NULL, NULL, AbsDiffOB, AvgOB
-};
-
-/* Auxiliary functions for CPR updates. */
-
-/* Vector mapping for QH format. */
-static unsigned64
-qh_vector_op(unsigned64 v1, unsigned64 v2, QH_FUNC func)
-{
- unsigned64 result = 0;
- int i;
- signed16 h, h1, h2;
-
- for (i = 0; i < 64; i += 16)
- {
- h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
- h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
- h = (*func)(h1, h2);
- result |= ((unsigned64)((unsigned16)h) << i);
- }
- return result;
-}
-
-static unsigned64
-qh_map_op(unsigned64 v1, signed16 h2, QH_FUNC func)
-{
- unsigned64 result = 0;
- int i;
- signed16 h, h1;
-
- for (i = 0; i < 64; i += 16)
- {
- h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
- h = (*func)(h1, h2);
- result |= ((unsigned64)((unsigned16)h) << i);
- }
- return result;
-}
-
-
-/* Vector operations for OB format. */
-
-static unsigned64
-ob_vector_op(unsigned64 v1, unsigned64 v2, OB_FUNC func)
-{
- unsigned64 result = 0;
- int i;
- unsigned8 b, b1, b2;
-
- for (i = 0; i < 64; i += 8)
- {
- b1 = v1 & 0xFF; v1 >>= 8;
- b2 = v2 & 0xFF; v2 >>= 8;
- b = (*func)(b1, b2);
- result |= ((unsigned64)b << i);
- }
- return result;
-}
-
-static unsigned64
-ob_map_op(unsigned64 v1, unsigned8 b2, OB_FUNC func)
-{
- unsigned64 result = 0;
- int i;
- unsigned8 b, b1;
-
- for (i = 0; i < 64; i += 8)
- {
- b1 = v1 & 0xFF; v1 >>= 8;
- b = (*func)(b1, b2);
- result |= ((unsigned64)b << i);
- }
- return result;
-}
-
-
-/* Primary entry for operations that update CPRs. */
-unsigned64
-mdmx_cpr_op(sim_cpu *cpu,
- address_word cia,
- int op,
- unsigned64 op1,
- int vt,
- MX_fmtsel fmtsel)
-{
- unsigned64 op2;
- unsigned64 result = 0;
-
- switch (MX_FMT (fmtsel))
- {
- case mdmx_qh:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = qh_map_op(op1, QH_ELEM(op2, fmtsel), qh_func[op]);
- break;
- case sel_vect:
- result = qh_vector_op(op1, ValueFPR(vt, fmt_mdmx), qh_func[op]);
- break;
- case sel_imm:
- result = qh_map_op(op1, vt, qh_func[op]);
- break;
- }
- break;
- case mdmx_ob:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = ob_map_op(op1, OB_ELEM(op2, fmtsel), ob_func[op]);
- break;
- case sel_vect:
- result = ob_vector_op(op1, ValueFPR(vt, fmt_mdmx), ob_func[op]);
- break;
- case sel_imm:
- result = ob_map_op(op1, vt, ob_func[op]);
- break;
- }
- break;
- default:
- Unpredictable ();
- }
-
- return result;
-}
-
-
-/* Operations that update CCs */
-
-static void
-qh_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
-{
- int i;
- signed16 h1, h2;
- int boolean;
-
- for (i = 0; i < 4; i++)
- {
- h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
- h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
- boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
- ((cond & MX_C_LT) && (h1 < h2));
- SETFCC(i, boolean);
- }
-}
-
-static void
-qh_map_test(sim_cpu *cpu, unsigned64 v1, signed16 h2, int cond)
-{
- int i;
- signed16 h1;
- int boolean;
-
- for (i = 0; i < 4; i++)
- {
- h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
- boolean = ((cond & MX_C_EQ) && (h1 == h2)) ||
- ((cond & MX_C_LT) && (h1 < h2));
- SETFCC(i, boolean);
- }
-}
-
-static void
-ob_vector_test(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int cond)
-{
- int i;
- unsigned8 b1, b2;
- int boolean;
-
- for (i = 0; i < 8; i++)
- {
- b1 = v1 & 0xFF; v1 >>= 8;
- b2 = v2 & 0xFF; v2 >>= 8;
- boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
- ((cond & MX_C_LT) && (b1 < b2));
- SETFCC(i, boolean);
- }
-}
-
-static void
-ob_map_test(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int cond)
-{
- int i;
- unsigned8 b1;
- int boolean;
-
- for (i = 0; i < 8; i++)
- {
- b1 = (unsigned8)(v1 & 0xFF); v1 >>= 8;
- boolean = ((cond & MX_C_EQ) && (b1 == b2)) ||
- ((cond & MX_C_LT) && (b1 < b2));
- SETFCC(i, boolean);
- }
-}
-
-
-void
-mdmx_cc_op(sim_cpu *cpu,
- address_word cia,
- int cond,
- unsigned64 v1,
- int vt,
- MX_fmtsel fmtsel)
-{
- unsigned64 op2;
-
- switch (MX_FMT (fmtsel))
- {
- case mdmx_qh:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- qh_map_test(cpu, v1, QH_ELEM(op2, fmtsel), cond);
- break;
- case sel_vect:
- qh_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
- break;
- case sel_imm:
- qh_map_test(cpu, v1, vt, cond);
- break;
- }
- break;
- case mdmx_ob:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- ob_map_test(cpu, v1, OB_ELEM(op2, fmtsel), cond);
- break;
- case sel_vect:
- ob_vector_test(cpu, v1, ValueFPR(vt, fmt_mdmx), cond);
- break;
- case sel_imm:
- ob_map_test(cpu, v1, vt, cond);
- break;
- }
- break;
- default:
- Unpredictable ();
- }
-}
-
-
-/* Pick operations. */
-
-static unsigned64
-qh_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
-{
- unsigned64 result = 0;
- int i, s;
- unsigned16 h;
-
- s = 0;
- for (i = 0; i < 4; i++)
- {
- h = ((GETFCC(i) == tf) ? (v1 & 0xFFFF) : (v2 & 0xFFFF));
- v1 >>= 16; v2 >>= 16;
- result |= ((unsigned64)h << s);
- s += 16;
- }
- return result;
-}
-
-static unsigned64
-qh_map_pick(sim_cpu *cpu, unsigned64 v1, signed16 h2, int tf)
-{
- unsigned64 result = 0;
- int i, s;
- unsigned16 h;
-
- s = 0;
- for (i = 0; i < 4; i++)
- {
- h = (GETFCC(i) == tf) ? (v1 & 0xFFFF) : (unsigned16)h2;
- v1 >>= 16;
- result |= ((unsigned64)h << s);
- s += 16;
- }
- return result;
-}
-
-static unsigned64
-ob_vector_pick(sim_cpu *cpu, unsigned64 v1, unsigned64 v2, int tf)
-{
- unsigned64 result = 0;
- int i, s;
- unsigned8 b;
-
- s = 0;
- for (i = 0; i < 8; i++)
- {
- b = (GETFCC(i) == tf) ? (v1 & 0xFF) : (v2 & 0xFF);
- v1 >>= 8; v2 >>= 8;
- result |= ((unsigned64)b << s);
- s += 8;
- }
- return result;
-}
-
-static unsigned64
-ob_map_pick(sim_cpu *cpu, unsigned64 v1, unsigned8 b2, int tf)
-{
- unsigned64 result = 0;
- int i, s;
- unsigned8 b;
-
- s = 0;
- for (i = 0; i < 8; i++)
- {
- b = (GETFCC(i) == tf) ? (v1 & 0xFF) : b2;
- v1 >>= 8;
- result |= ((unsigned64)b << s);
- s += 8;
- }
- return result;
-}
-
-
-unsigned64
-mdmx_pick_op(sim_cpu *cpu,
- address_word cia,
- int tf,
- unsigned64 v1,
- int vt,
- MX_fmtsel fmtsel)
-{
- unsigned64 result = 0;
- unsigned64 op2;
-
- switch (MX_FMT (fmtsel))
- {
- case mdmx_qh:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = qh_map_pick(cpu, v1, QH_ELEM(op2, fmtsel), tf);
- break;
- case sel_vect:
- result = qh_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
- break;
- case sel_imm:
- result = qh_map_pick(cpu, v1, vt, tf);
- break;
- }
- break;
- case mdmx_ob:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = ob_map_pick(cpu, v1, OB_ELEM(op2, fmtsel), tf);
- break;
- case sel_vect:
- result = ob_vector_pick(cpu, v1, ValueFPR(vt, fmt_mdmx), tf);
- break;
- case sel_imm:
- result = ob_map_pick(cpu, v1, vt, tf);
- break;
- }
- break;
- default:
- Unpredictable ();
- }
- return result;
-}
-
-
-/* Accumulators. */
-
-typedef void (*QH_ACC)(signed48 *a, signed16 ts, signed16 tt);
-
-static void
-AccAddAQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a += (signed48)ts + (signed48)tt;
-}
-
-static void
-AccAddLQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a = (signed48)ts + (signed48)tt;
-}
-
-static void
-AccMulAQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a += (signed48)ts * (signed48)tt;
-}
-
-static void
-AccMulLQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a = (signed48)ts * (signed48)tt;
-}
-
-static void
-SubMulAQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a -= (signed48)ts * (signed48)tt;
-}
-
-static void
-SubMulLQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a = -((signed48)ts * (signed48)tt);
-}
-
-static void
-AccSubAQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a += (signed48)ts - (signed48)tt;
-}
-
-static void
-AccSubLQH(signed48 *a, signed16 ts, signed16 tt)
-{
- *a = (signed48)ts - (signed48)tt;
-}
-
-
-typedef void (*OB_ACC)(signed24 *acc, unsigned8 ts, unsigned8 tt);
-
-static void
-AccAddAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a += (signed24)ts + (signed24)tt;
-}
-
-static void
-AccAddLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a = (signed24)ts + (signed24)tt;
-}
-
-static void
-AccMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a += (signed24)ts * (signed24)tt;
-}
-
-static void
-AccMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a = (signed24)ts * (signed24)tt;
-}
-
-static void
-SubMulAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a -= (signed24)ts * (signed24)tt;
-}
-
-static void
-SubMulLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a = -((signed24)ts * (signed24)tt);
-}
-
-static void
-AccSubAOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a += (signed24)ts - (signed24)tt;
-}
-
-static void
-AccSubLOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- *a = (signed24)ts - (signed24)tt;
-}
-
-static void
-AccAbsDiffOB(signed24 *a, unsigned8 ts, unsigned8 tt)
-{
- unsigned8 t = (ts >= tt ? ts - tt : tt - ts);
- *a += (signed24)t;
-}
-
-
-/* Dispatch tables for operations that update a CPR. */
-
-static const QH_ACC qh_acc[] = {
- AccAddAQH, AccAddAQH, AccMulAQH, AccMulLQH,
- SubMulAQH, SubMulLQH, AccSubAQH, AccSubLQH,
- NULL
-};
-
-static const OB_ACC ob_acc[] = {
- AccAddAOB, AccAddLOB, AccMulAOB, AccMulLOB,
- SubMulAOB, SubMulLOB, AccSubAOB, AccSubLOB,
- AccAbsDiffOB
-};
-
-
-static void
-qh_vector_acc(signed48 a[], unsigned64 v1, unsigned64 v2, QH_ACC acc)
-{
- int i;
- signed16 h1, h2;
-
- for (i = 0; i < 4; i++)
- {
- h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
- h2 = (signed16)(v2 & 0xFFFF); v2 >>= 16;
- (*acc)(&a[i], h1, h2);
- }
-}
-
-static void
-qh_map_acc(signed48 a[], unsigned64 v1, signed16 h2, QH_ACC acc)
-{
- int i;
- signed16 h1;
-
- for (i = 0; i < 4; i++)
- {
- h1 = (signed16)(v1 & 0xFFFF); v1 >>= 16;
- (*acc)(&a[i], h1, h2);
- }
-}
-
-static void
-ob_vector_acc(signed24 a[], unsigned64 v1, unsigned64 v2, OB_ACC acc)
-{
- int i;
- unsigned8 b1, b2;
-
- for (i = 0; i < 8; i++)
- {
- b1 = v1 & 0xFF; v1 >>= 8;
- b2 = v2 & 0xFF; v2 >>= 8;
- (*acc)(&a[i], b1, b2);
- }
-}
-
-static void
-ob_map_acc(signed24 a[], unsigned64 v1, unsigned8 b2, OB_ACC acc)
-{
- int i;
- unsigned8 b1;
-
- for (i = 0; i < 8; i++)
- {
- b1 = v1 & 0xFF; v1 >>= 8;
- (*acc)(&a[i], b1, b2);
- }
-}
-
-
-/* Primary entry for operations that accumulate */
-void
-mdmx_acc_op(sim_cpu *cpu,
- address_word cia,
- int op,
- unsigned64 op1,
- int vt,
- MX_fmtsel fmtsel)
-{
- unsigned64 op2;
-
- switch (MX_FMT (fmtsel))
- {
- case mdmx_qh:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- qh_map_acc(ACC.qh, op1, QH_ELEM(op2, fmtsel), qh_acc[op]);
- break;
- case sel_vect:
- qh_vector_acc(ACC.qh, op1, ValueFPR(vt, fmt_mdmx), qh_acc[op]);
- break;
- case sel_imm:
- qh_map_acc(ACC.qh, op1, vt, qh_acc[op]);
- break;
- }
- break;
- case mdmx_ob:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- ob_map_acc(ACC.ob, op1, OB_ELEM(op2, fmtsel), ob_acc[op]);
- break;
- case sel_vect:
- ob_vector_acc(ACC.ob, op1, ValueFPR(vt, fmt_mdmx), ob_acc[op]);
- break;
- case sel_imm:
- ob_map_acc(ACC.ob, op1, vt, ob_acc[op]);
- break;
- }
- break;
- default:
- Unpredictable ();
- }
-}
-
-
-/* Reading and writing accumulator (no conversion). */
-
-unsigned64
-mdmx_rac_op(sim_cpu *cpu,
- address_word cia,
- int op,
- int fmt)
-{
- unsigned64 result;
- unsigned int shift;
- int i;
-
- shift = op; /* L = 00, M = 01, H = 10. */
- result = 0;
-
- switch (fmt)
- {
- case MX_FMT_QH:
- shift <<= 4; /* 16 bits per element. */
- for (i = 3; i >= 0; --i)
- {
- result <<= 16;
- result |= ((ACC.qh[i] >> shift) & 0xFFFF);
- }
- break;
- case MX_FMT_OB:
- shift <<= 3; /* 8 bits per element. */
- for (i = 7; i >= 0; --i)
- {
- result <<= 8;
- result |= ((ACC.ob[i] >> shift) & 0xFF);
- }
- break;
- default:
- Unpredictable ();
- }
- return result;
-}
-
-void
-mdmx_wacl(sim_cpu *cpu,
- address_word cia,
- int fmt,
- unsigned64 vs,
- unsigned64 vt)
-{
- int i;
-
- switch (fmt)
- {
- case MX_FMT_QH:
- for (i = 0; i < 4; i++)
- {
- signed32 s = (signed16)(vs & 0xFFFF);
- ACC.qh[i] = ((signed48)s << 16) | (vt & 0xFFFF);
- vs >>= 16; vt >>= 16;
- }
- break;
- case MX_FMT_OB:
- for (i = 0; i < 8; i++)
- {
- signed16 s = (signed8)(vs & 0xFF);
- ACC.ob[i] = ((signed24)s << 8) | (vt & 0xFF);
- vs >>= 8; vt >>= 8;
- }
- break;
- default:
- Unpredictable ();
- }
-}
-
-void
-mdmx_wach(sim_cpu *cpu,
- address_word cia,
- int fmt,
- unsigned64 vs)
-{
- int i;
-
- switch (fmt)
- {
- case MX_FMT_QH:
- for (i = 0; i < 4; i++)
- {
- signed32 s = (signed16)(vs & 0xFFFF);
- ACC.qh[i] &= ~((signed48)0xFFFF << 32);
- ACC.qh[i] |= ((signed48)s << 32);
- vs >>= 16;
- }
- break;
- case MX_FMT_OB:
- for (i = 0; i < 8; i++)
- {
- ACC.ob[i] &= ~((signed24)0xFF << 16);
- ACC.ob[i] |= ((signed24)(vs & 0xFF) << 16);
- vs >>= 8;
- }
- break;
- default:
- Unpredictable ();
- }
-}
-
-
-/* Reading and writing accumulator (rounding conversions).
- Enumerating function guarantees s >= 0 for QH ops. */
-
-typedef signed16 (*QH_ROUND)(signed48 a, signed16 s);
-
-#define QH_BIT(n) ((unsigned48)1 << (n))
-#define QH_ONES(n) (((unsigned48)1 << (n))-1)
-
-static signed16
-RNASQH(signed48 a, signed16 s)
-{
- signed48 t;
- signed16 result = 0;
-
- if (s > 48)
- result = 0;
- else
- {
- t = (a >> s);
- if ((a & QH_BIT(47)) == 0)
- {
- if (s > 0 && ((a >> (s-1)) & 1) == 1)
- t++;
- if (t > QH_MAX)
- t = QH_MAX;
- }
- else
- {
- if (s > 0 && ((a >> (s-1)) & 1) == 1)
- {
- if (s > 1 && ((unsigned48)a & QH_ONES(s-1)) != 0)
- t++;
- }
- if (t < QH_MIN)
- t = QH_MIN;
- }
- result = (signed16)t;
- }
- return result;
-}
-
-static signed16
-RNAUQH(signed48 a, signed16 s)
-{
- unsigned48 t;
- signed16 result;
-
- if (s > 48)
- result = 0;
- else if (s == 48)
- result = ((unsigned48)a & MASK48) >> 47;
- else
- {
- t = ((unsigned48)a & MASK48) >> s;
- if (s > 0 && ((a >> (s-1)) & 1) == 1)
- t++;
- if (t > 0xFFFF)
- t = 0xFFFF;
- result = (signed16)t;
- }
- return result;
-}
-
-static signed16
-RNESQH(signed48 a, signed16 s)
-{
- signed48 t;
- signed16 result = 0;
-
- if (s > 47)
- result = 0;
- else
- {
- t = (a >> s);
- if (s > 0 && ((a >> (s-1)) & 1) == 1)
- {
- if (s == 1 || (a & QH_ONES(s-1)) == 0)
- t += t & 1;
- else
- t += 1;
- }
- if ((a & QH_BIT(47)) == 0)
- {
- if (t > QH_MAX)
- t = QH_MAX;
- }
- else
- {
- if (t < QH_MIN)
- t = QH_MIN;
- }
- result = (signed16)t;
- }
- return result;
-}
-
-static signed16
-RNEUQH(signed48 a, signed16 s)
-{
- unsigned48 t;
- signed16 result;
-
- if (s > 48)
- result = 0;
- else if (s == 48)
- result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
- else
- {
- t = ((unsigned48)a & MASK48) >> s;
- if (s > 0 && ((a >> (s-1)) & 1) == 1)
- {
- if (s > 1 && (a & QH_ONES(s-1)) != 0)
- t++;
- else
- t += t & 1;
- }
- if (t > 0xFFFF)
- t = 0xFFFF;
- result = (signed16)t;
- }
- return result;
-}
-
-static signed16
-RZSQH(signed48 a, signed16 s)
-{
- signed48 t;
- signed16 result = 0;
-
- if (s > 47)
- result = 0;
- else
- {
- t = (a >> s);
- if ((a & QH_BIT(47)) == 0)
- {
- if (t > QH_MAX)
- t = QH_MAX;
- }
- else
- {
- if (t < QH_MIN)
- t = QH_MIN;
- }
- result = (signed16)t;
- }
- return result;
-}
-
-static signed16
-RZUQH(signed48 a, signed16 s)
-{
- unsigned48 t;
- signed16 result = 0;
-
- if (s > 48)
- result = 0;
- else if (s == 48)
- result = ((unsigned48)a > QH_BIT(47) ? 1 : 0);
- else
- {
- t = ((unsigned48)a & MASK48) >> s;
- if (t > 0xFFFF)
- t = 0xFFFF;
- result = (signed16)t;
- }
- return result;
-}
-
-
-typedef unsigned8 (*OB_ROUND)(signed24 a, unsigned8 s);
-
-#define OB_BIT(n) ((unsigned24)1 << (n))
-#define OB_ONES(n) (((unsigned24)1 << (n))-1)
-
-static unsigned8
-RNAUOB(signed24 a, unsigned8 s)
-{
- unsigned8 result;
- unsigned24 t;
-
- if (s > 24)
- result = 0;
- else if (s == 24)
- result = ((unsigned24)a & MASK24) >> 23;
- else
- {
- t = ((unsigned24)a & MASK24) >> s;
- if (s > 0 && ((a >> (s-1)) & 1) == 1)
- t ++;
- result = OB_CLAMP(t);
- }
- return result;
-}
-
-static unsigned8
-RNEUOB(signed24 a, unsigned8 s)
-{
- unsigned8 result;
- unsigned24 t;
-
- if (s > 24)
- result = 0;
- else if (s == 24)
- result = (((unsigned24)a & MASK24) > OB_BIT(23) ? 1 : 0);
- else
- {
- t = ((unsigned24)a & MASK24) >> s;
- if (s > 0 && ((a >> (s-1)) & 1) == 1)
- {
- if (s > 1 && (a & OB_ONES(s-1)) != 0)
- t++;
- else
- t += t & 1;
- }
- result = OB_CLAMP(t);
- }
- return result;
-}
-
-static unsigned8
-RZUOB(signed24 a, unsigned8 s)
-{
- unsigned8 result;
- unsigned24 t;
-
- if (s >= 24)
- result = 0;
- else
- {
- t = ((unsigned24)a & MASK24) >> s;
- result = OB_CLAMP(t);
- }
- return result;
-}
-
-
-static const QH_ROUND qh_round[] = {
- RNASQH, RNAUQH, RNESQH, RNEUQH, RZSQH, RZUQH
-};
-
-static const OB_ROUND ob_round[] = {
- NULL, RNAUOB, NULL, RNEUOB, NULL, RZUOB
-};
-
-
-static unsigned64
-qh_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, QH_ROUND round)
-{
- unsigned64 result = 0;
- int i, s;
- signed16 h, h2;
-
- s = 0;
- for (i = 0; i < 4; i++)
- {
- h2 = (signed16)(v2 & 0xFFFF);
- if (h2 >= 0)
- h = (*round)(ACC.qh[i], h2);
- else
- {
- UnpredictableResult ();
- h = 0xdead;
- }
- v2 >>= 16;
- result |= ((unsigned64)((unsigned16)h) << s);
- s += 16;
- }
- return result;
-}
-
-static unsigned64
-qh_map_round(sim_cpu *cpu, address_word cia, signed16 h2, QH_ROUND round)
-{
- unsigned64 result = 0;
- int i, s;
- signed16 h;
-
- s = 0;
- for (i = 0; i < 4; i++)
- {
- if (h2 >= 0)
- h = (*round)(ACC.qh[i], h2);
- else
- {
- UnpredictableResult ();
- h = 0xdead;
- }
- result |= ((unsigned64)((unsigned16)h) << s);
- s += 16;
- }
- return result;
-}
-
-static unsigned64
-ob_vector_round(sim_cpu *cpu, address_word cia, unsigned64 v2, OB_ROUND round)
-{
- unsigned64 result = 0;
- int i, s;
- unsigned8 b, b2;
-
- s = 0;
- for (i = 0; i < 8; i++)
- {
- b2 = v2 & 0xFF; v2 >>= 8;
- b = (*round)(ACC.ob[i], b2);
- result |= ((unsigned64)b << s);
- s += 8;
- }
- return result;
-}
-
-static unsigned64
-ob_map_round(sim_cpu *cpu, address_word cia, unsigned8 b2, OB_ROUND round)
-{
- unsigned64 result = 0;
- int i, s;
- unsigned8 b;
-
- s = 0;
- for (i = 0; i < 8; i++)
- {
- b = (*round)(ACC.ob[i], b2);
- result |= ((unsigned64)b << s);
- s += 8;
- }
- return result;
-}
-
-
-unsigned64
-mdmx_round_op(sim_cpu *cpu,
- address_word cia,
- int rm,
- int vt,
- MX_fmtsel fmtsel)
-{
- unsigned64 op2;
- unsigned64 result = 0;
-
- switch (MX_FMT (fmtsel))
- {
- case mdmx_qh:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = qh_map_round(cpu, cia, QH_ELEM(op2, fmtsel), qh_round[rm]);
- break;
- case sel_vect:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = qh_vector_round(cpu, cia, op2, qh_round[rm]);
- break;
- case sel_imm:
- result = qh_map_round(cpu, cia, vt, qh_round[rm]);
- break;
- }
- break;
- case mdmx_ob:
- switch (MX_VT (fmtsel))
- {
- case sel_elem:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = ob_map_round(cpu, cia, OB_ELEM(op2, fmtsel), ob_round[rm]);
- break;
- case sel_vect:
- op2 = ValueFPR(vt, fmt_mdmx);
- result = ob_vector_round(cpu, cia, op2, ob_round[rm]);
- break;
- case sel_imm:
- result = ob_map_round(cpu, cia, vt, ob_round[rm]);
- break;
- }
- break;
- default:
- Unpredictable ();
- }
-
- return result;
-}
-
-
-/* Shuffle operation. */
-
-typedef struct {
- enum {vs, ss, vt} source;
- unsigned int index;
-} sh_map;
-
-static const sh_map ob_shuffle[][8] = {
- /* MDMX 2.0 encodings (3-4, 6-7). */
- /* vr5400 encoding (5), otherwise. */
- { }, /* RSVD */
- {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* RSVD */
- {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* RSVD */
- {{vs,0}, {ss,0}, {vs,1}, {ss,1}, {vs,2}, {ss,2}, {vs,3}, {ss,3}}, /* upsl */
- {{vt,1}, {vt,3}, {vt,5}, {vt,7}, {vs,1}, {vs,3}, {vs,5}, {vs,7}}, /* pach */
- {{vt,0}, {vt,2}, {vt,4}, {vt,6}, {vs,0}, {vs,2}, {vs,4}, {vs,6}}, /* pacl */
- {{vt,4}, {vs,4}, {vt,5}, {vs,5}, {vt,6}, {vs,6}, {vt,7}, {vs,7}}, /* mixh */
- {{vt,0}, {vs,0}, {vt,1}, {vs,1}, {vt,2}, {vs,2}, {vt,3}, {vs,3}} /* mixl */
-};
-
-static const sh_map qh_shuffle[][4] = {
- {{vt,2}, {vs,2}, {vt,3}, {vs,3}}, /* mixh */
- {{vt,0}, {vs,0}, {vt,1}, {vs,1}}, /* mixl */
- {{vt,1}, {vt,3}, {vs,1}, {vs,3}}, /* pach */
- { }, /* RSVD */
- {{vt,1}, {vs,0}, {vt,3}, {vs,2}}, /* bfla */
- { }, /* RSVD */
- {{vt,2}, {vt,3}, {vs,2}, {vs,3}}, /* repa */
- {{vt,0}, {vt,1}, {vs,0}, {vs,1}} /* repb */
-};
-
-
-unsigned64
-mdmx_shuffle(sim_cpu *cpu,
- address_word cia,
- int shop,
- unsigned64 op1,
- unsigned64 op2)
-{
- unsigned64 result = 0;
- int i, s;
- int op;
-
- if ((shop & 0x3) == 0x1) /* QH format. */
- {
- op = shop >> 2;
- s = 0;
- for (i = 0; i < 4; i++)
- {
- unsigned64 v;
-
- switch (qh_shuffle[op][i].source)
- {
- case vs:
- v = op1;
- break;
- case vt:
- v = op2;
- break;
- default:
- Unpredictable ();
- v = 0;
- }
- result |= (((v >> 16*qh_shuffle[op][i].index) & 0xFFFF) << s);
- s += 16;
- }
- }
- else if ((shop & 0x1) == 0x0) /* OB format. */
- {
- op = shop >> 1;
- s = 0;
- for (i = 0; i < 8; i++)
- {
- unsigned8 b;
- unsigned int ishift = 8*ob_shuffle[op][i].index;
-
- switch (ob_shuffle[op][i].source)
- {
- case vs:
- b = (op1 >> ishift) & 0xFF;
- break;
- case ss:
- b = ((op1 >> ishift) & 0x80) ? 0xFF : 0;
- break;
- case vt:
- b = (op2 >> ishift) & 0xFF;
- break;
- default:
- Unpredictable ();
- b = 0;
- }
- result |= ((unsigned64)b << s);
- s += 8;
- }
- }
- else
- Unpredictable ();
-
- return result;
-}