diff --git a/scripts/src/cpu.lua b/scripts/src/cpu.lua index 1b746fb59bc..054a2bbabee 100644 --- a/scripts/src/cpu.lua +++ b/scripts/src/cpu.lua @@ -221,6 +221,9 @@ if (CPUS["ADSP21062"]~=null) then MAME_DIR .. "src/devices/cpu/sharc/sharcmem.hxx", MAME_DIR .. "src/devices/cpu/sharc/sharcops.h", MAME_DIR .. "src/devices/cpu/sharc/sharcops.hxx", + MAME_DIR .. "src/devices/cpu/sharc/sharcdrc.cpp", + MAME_DIR .. "src/devices/cpu/sharc/sharcfe.cpp", + MAME_DIR .. "src/devices/cpu/sharc/sharcfe.h", } end diff --git a/src/devices/cpu/drcfe.cpp b/src/devices/cpu/drcfe.cpp index 6d2bd09cddf..87478de59e6 100644 --- a/src/devices/cpu/drcfe.cpp +++ b/src/devices/cpu/drcfe.cpp @@ -171,6 +171,7 @@ opcode_desc *drc_frontend::describe_one(offs_t curpc, const opcode_desc *prevdes desc->delayslots = 0; desc->skipslots = 0; desc->flags = 0; + desc->userflags = 0; desc->cycles = 0; memset(desc->regin, 0x00, sizeof(desc->regin)); memset(desc->regout, 0x00, sizeof(desc->regout)); diff --git a/src/devices/cpu/drcfe.h b/src/devices/cpu/drcfe.h index 67c67067221..09d86b2bd99 100644 --- a/src/devices/cpu/drcfe.h +++ b/src/devices/cpu/drcfe.h @@ -113,6 +113,7 @@ struct opcode_desc UINT8 delayslots; // number of delay slots (for branches) UINT8 skipslots; // number of skip slots (for branches) UINT32 flags; // OPFLAG_* opcode flags + UINT32 userflags; // core specific flags UINT32 cycles; // number of cycles needed to execute // register usage information diff --git a/src/devices/cpu/sharc/compute.hxx b/src/devices/cpu/sharc/compute.hxx index 880b368ad1f..4124fadf6a9 100644 --- a/src/devices/cpu/sharc/compute.hxx +++ b/src/devices/cpu/sharc/compute.hxx @@ -4,27 +4,27 @@ #include -#define CLEAR_ALU_FLAGS() (m_astat &= ~(AZ|AN|AV|AC|AS|AI)) +#define CLEAR_ALU_FLAGS() (m_core->astat &= ~(AZ|AN|AV|AC|AS|AI)) -#define SET_FLAG_AZ(r) { m_astat |= (((r) == 0) ? AZ : 0); } -#define SET_FLAG_AN(r) { m_astat |= (((r) & 0x80000000) ? AN : 0); } -#define SET_FLAG_AC_ADD(r,a,b) { m_astat |= (((UINT32)r < (UINT32)a) ? AC : 0); } -#define SET_FLAG_AV_ADD(r,a,b) { m_astat |= (((~((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); } -#define SET_FLAG_AC_SUB(r,a,b) { m_astat |= ((!((UINT32)a < (UINT32)b)) ? AC : 0); } -#define SET_FLAG_AV_SUB(r,a,b) { m_astat |= ((( ((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); } +#define SET_FLAG_AZ(r) { m_core->astat |= (((r) == 0) ? AZ : 0); } +#define SET_FLAG_AN(r) { m_core->astat |= (((r) & 0x80000000) ? AN : 0); } +#define SET_FLAG_AC_ADD(r,a,b) { m_core->astat |= (((UINT32)r < (UINT32)a) ? AC : 0); } +#define SET_FLAG_AV_ADD(r,a,b) { m_core->astat |= (((~((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); } +#define SET_FLAG_AC_SUB(r,a,b) { m_core->astat |= ((!((UINT32)a < (UINT32)b)) ? AC : 0); } +#define SET_FLAG_AV_SUB(r,a,b) { m_core->astat |= ((( ((a) ^ (b)) & ((a) ^ (r))) & 0x80000000) ? AV : 0); } #define IS_FLOAT_ZERO(r) ((((r) & 0x7fffffff) == 0)) #define IS_FLOAT_DENORMAL(r) ((((r) & 0x7f800000) == 0) && (((r) & 0x7fffff) != 0)) #define IS_FLOAT_NAN(r) ((((r) & 0x7f800000) == 0x7f800000) && (((r) & 0x7fffff) != 0)) #define IS_FLOAT_INFINITY(r) (((r) & 0x7fffffff) == 0x7f800000) -#define CLEAR_MULTIPLIER_FLAGS() (m_astat &= ~(MN|MV|MU|MI)) +#define CLEAR_MULTIPLIER_FLAGS() (m_core->astat &= ~(MN|MV|MU|MI)) -#define SET_FLAG_MN(r) { m_astat |= (((r) & 0x80000000) ? MN : 0); } -#define SET_FLAG_MV(r) { m_astat |= ((((UINT32)((r) >> 32) != 0) && ((UINT32)((r) >> 32) != 0xffffffff)) ? MV : 0); } +#define SET_FLAG_MN(r) { m_core->astat |= (((r) & 0x80000000) ? MN : 0); } +#define SET_FLAG_MV(r) { m_core->astat |= ((((UINT32)((r) >> 32) != 0) && ((UINT32)((r) >> 32) != 0xffffffff)) ? MV : 0); } /* TODO: MU needs 80-bit result */ -#define SET_FLAG_MU(r) { m_astat |= ((((UINT32)((r) >> 32) == 0) && ((UINT32)(r)) != 0) ? MU : 0); } +#define SET_FLAG_MU(r) { m_core->astat |= ((((UINT32)((r) >> 32) == 0) && ((UINT32)(r)) != 0) ? MU : 0); } #define FLOAT_SIGN 0x80000000 @@ -115,7 +115,7 @@ void adsp21062_device::compute_add(int rn, int rx, int ry) { UINT32 r = REG(rx) + REG(ry); - if (m_mode1 & MODE1_ALUSAT) + if (m_core->mode1 & MODE1_ALUSAT) fatalerror("SHARC: compute_add: ALU saturation not implemented!\n"); CLEAR_ALU_FLAGS(); @@ -125,7 +125,7 @@ void adsp21062_device::compute_add(int rn, int rx, int ry) SET_FLAG_AC_ADD(r, REG(rx), REG(ry)); REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx - Ry */ @@ -133,7 +133,7 @@ void adsp21062_device::compute_sub(int rn, int rx, int ry) { UINT32 r = REG(rx) - REG(ry); - if (m_mode1 & MODE1_ALUSAT) + if (m_core->mode1 & MODE1_ALUSAT) fatalerror("SHARC: compute_sub: ALU saturation not implemented!\n"); CLEAR_ALU_FLAGS(); @@ -143,16 +143,16 @@ void adsp21062_device::compute_sub(int rn, int rx, int ry) SET_FLAG_AC_SUB(r, REG(rx), REG(ry)); REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx + Ry + CI */ void adsp21062_device::compute_add_ci(int rn, int rx, int ry) { - int c = (m_astat & AC) ? 1 : 0; + int c = (m_core->astat & AC) ? 1 : 0; UINT32 r = REG(rx) + REG(ry) + c; - if (m_mode1 & MODE1_ALUSAT) + if (m_core->mode1 & MODE1_ALUSAT) fatalerror("SHARC: compute_add_ci: ALU saturation not implemented!\n"); CLEAR_ALU_FLAGS(); @@ -162,16 +162,16 @@ void adsp21062_device::compute_add_ci(int rn, int rx, int ry) SET_FLAG_AC_ADD(r, REG(rx), REG(ry)+c); REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx - Ry + CI - 1 */ void adsp21062_device::compute_sub_ci(int rn, int rx, int ry) { - int c = (m_astat & AC) ? 1 : 0; + int c = (m_core->astat & AC) ? 1 : 0; UINT32 r = REG(rx) - REG(ry) + c - 1; - if (m_mode1 & MODE1_ALUSAT) + if (m_core->mode1 & MODE1_ALUSAT) fatalerror("SHARC: compute_sub_ci: ALU saturation not implemented!\n"); CLEAR_ALU_FLAGS(); @@ -181,7 +181,7 @@ void adsp21062_device::compute_sub_ci(int rn, int rx, int ry) SET_FLAG_AC_SUB(r, REG(rx), REG(ry)+c-1); REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx AND Ry */ @@ -194,7 +194,7 @@ void adsp21062_device::compute_and(int rn, int rx, int ry) SET_FLAG_AZ(r); REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* COMP(Rx, Ry) */ @@ -204,21 +204,21 @@ void adsp21062_device::compute_comp(int rx, int ry) CLEAR_ALU_FLAGS(); if( REG(rx) == REG(ry) ) - m_astat |= AZ; + m_core->astat |= AZ; if( (INT32)REG(rx) < (INT32)REG(ry) ) - m_astat |= AN; + m_core->astat |= AN; // Update ASTAT compare accumulation register - comp_accum = (m_astat >> 24) & 0xff; + comp_accum = (m_core->astat >> 24) & 0xff; comp_accum >>= 1; - if ((m_astat & (AZ|AN)) == 0) + if ((m_core->astat & (AZ|AN)) == 0) { comp_accum |= 0x80; } - m_astat &= 0xffffff; - m_astat |= comp_accum << 24; + m_core->astat &= 0xffffff; + m_core->astat |= comp_accum << 24; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = PASS Rx */ @@ -229,11 +229,11 @@ void adsp21062_device::compute_pass(int rn, int rx) REG(rn) = REG(rx); if (REG(rn) == 0) - m_astat |= AZ; + m_core->astat |= AZ; if (REG(rn) & 0x80000000) - m_astat |= AN; + m_core->astat |= AN; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx XOR Ry */ @@ -245,7 +245,7 @@ void adsp21062_device::compute_xor(int rn, int rx, int ry) SET_FLAG_AZ(r); REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx OR Ry */ @@ -257,7 +257,7 @@ void adsp21062_device::compute_or(int rn, int rx, int ry) SET_FLAG_AZ(r); REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx + 1 */ @@ -273,7 +273,7 @@ void adsp21062_device::compute_inc(int rn, int rx) REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = Rx - 1 */ @@ -289,7 +289,7 @@ void adsp21062_device::compute_dec(int rn, int rx) REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = MIN(Rx, Ry) */ @@ -303,7 +303,7 @@ void adsp21062_device::compute_min(int rn, int rx, int ry) REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = MAX(Rx, Ry) */ @@ -317,7 +317,7 @@ void adsp21062_device::compute_max(int rn, int rx, int ry) REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = -Rx */ @@ -333,7 +333,7 @@ void adsp21062_device::compute_neg(int rn, int rx) REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rn = NOT Rx */ @@ -347,7 +347,7 @@ void adsp21062_device::compute_not(int rn, int rx) REG(rn) = r; - m_astat &= ~AF; + m_core->astat &= ~AF; } /*****************************************************************************/ @@ -364,13 +364,13 @@ UINT32 adsp21062_device::SCALB(SHARC_REG rx, int ry) if (exponent > 127) { // overflow - m_astat |= AV; + m_core->astat |= AV; return sign | FLOAT_INFINITY; } else if (exponent < -126) { // denormal - m_astat |= AZ; + m_core->astat |= AZ; return sign; } else @@ -389,12 +389,12 @@ void adsp21062_device::compute_float(int rn, int rx) // AN SET_FLAG_AN(REG(rn)); // AZ - m_astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0; /* TODO: AV flag */ - m_astat |= AF; + m_core->astat |= AF; } /* Rn = FIX Fx */ @@ -404,7 +404,7 @@ void adsp21062_device::compute_fix(int rn, int rx) SHARC_REG r_alu; r_alu.f = FREG(rx); - if (m_mode1 & MODE1_TRUNCATE) + if (m_core->mode1 & MODE1_TRUNCATE) { alu_i = (INT32)(r_alu.f); } @@ -418,13 +418,13 @@ void adsp21062_device::compute_fix(int rn, int rx) // AZ SET_FLAG_AZ(alu_i); // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; /* TODO: AV flag */ REG(rn) = alu_i; - m_astat |= AF; + m_core->astat |= AF; } /* Rn = FIX Fx BY Ry */ @@ -433,8 +433,8 @@ void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry) INT32 alu_i; SHARC_REG r_alu; - r_alu.r = SCALB(m_r[rx], ry); - if (m_mode1 & MODE1_TRUNCATE) + r_alu.r = SCALB(m_core->r[rx], ry); + if (m_core->mode1 & MODE1_TRUNCATE) { alu_i = (INT32)(r_alu.f); } @@ -448,13 +448,13 @@ void adsp21062_device::compute_fix_scaled(int rn, int rx, int ry) // AZ SET_FLAG_AZ(alu_i); // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; /* TODO: AV flag */ REG(rn) = alu_i; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = FLOAT Rx BY Ry */ @@ -471,11 +471,11 @@ void adsp21062_device::compute_float_scaled(int rn, int rx, int ry) // AN SET_FLAG_AN(REG(rn)); // AZ - m_astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(REG(rn)) || IS_FLOAT_ZERO(REG(rn))) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(REG(rn))) ? AUS : 0; - m_astat |= AF; + m_core->astat |= AF; } /* Rn = LOGB Fx */ @@ -490,20 +490,20 @@ void adsp21062_device::compute_logb(int rn, int rx) { REG(rn) = FLOAT_INFINITY; - m_astat |= AV; + m_core->astat |= AV; } else if (IS_FLOAT_ZERO(REG(rx))) { REG(rn) = FLOAT_SIGN | FLOAT_INFINITY; - m_astat |= AV; + m_core->astat |= AV; } else if (IS_FLOAT_NAN(REG(rx))) { REG(rn) = 0xffffffff; - m_astat |= AI; - m_stky |= AIS; + m_core->astat |= AI; + m_core->stky |= AIS; } else { @@ -517,7 +517,7 @@ void adsp21062_device::compute_logb(int rn, int rx) REG(rn) = exponent; } - m_astat |= AF; + m_core->astat |= AF; } /* Fn = SCALB Fx BY Fy */ @@ -529,25 +529,25 @@ void adsp21062_device::compute_scalb(int rn, int rx, int ry) if (IS_FLOAT_NAN(REG(rx))) { - m_astat |= AI; - m_stky |= AIS; + m_core->astat |= AI; + m_core->stky |= AIS; REG(rn) = 0xffffffff; } else { - r.r = SCALB(m_r[rx], ry); + r.r = SCALB(m_core->r[rx], ry); // AN SET_FLAG_AN(r.r); // AZ - m_astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0; + m_core->astat |= IS_FLOAT_ZERO(r.r) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; FREG(rn) = r.f; } - m_astat |= AF; + m_core->astat |= AF; } /* Fn = Fx + Fy */ @@ -558,20 +558,20 @@ void adsp21062_device::compute_fadd(int rn, int rx, int ry) CLEAR_ALU_FLAGS(); // AN - m_astat |= (r.f < 0.0f) ? AN : 0; + m_core->astat |= (r.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(rn) = r.f; - m_astat |= AF; + m_core->astat |= AF; } void adsp21062_device::compute_favg(int rn, int rx, int ry) @@ -581,20 +581,20 @@ void adsp21062_device::compute_favg(int rn, int rx, int ry) CLEAR_ALU_FLAGS(); // AN - m_astat |= (r.f < 0.0f) ? AN : 0; + m_core->astat |= (r.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(rn) = r.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = Fx - Fy */ @@ -605,20 +605,20 @@ void adsp21062_device::compute_fsub(int rn, int rx, int ry) CLEAR_ALU_FLAGS(); // AN - m_astat |= (r.f < 0.0f) ? AN : 0; + m_core->astat |= (r.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(rn) = r.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = -Fx */ @@ -629,17 +629,17 @@ void adsp21062_device::compute_fneg(int rn, int rx) CLEAR_ALU_FLAGS(); // AZ - m_astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0; // AN - m_astat |= (r.f < 0.0f) ? AN : 0; + m_core->astat |= (r.f < 0.0f) ? AN : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(rn) = r.f; - m_astat |= AF; + m_core->astat |= AF; } /* COMP(Fx, Fy) */ @@ -650,26 +650,26 @@ void adsp21062_device::compute_fcomp(int rx, int ry) CLEAR_ALU_FLAGS(); // AZ if( FREG(rx) == FREG(ry) ) - m_astat |= AZ; + m_core->astat |= AZ; // AN if( FREG(rx) < FREG(ry) ) - m_astat |= AN; + m_core->astat |= AN; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; // Update ASTAT compare accumulation register - comp_accum = (m_astat >> 24) & 0xff; + comp_accum = (m_core->astat >> 24) & 0xff; comp_accum >>= 1; - if ((m_astat & (AZ|AN)) == 0) + if ((m_core->astat & (AZ|AN)) == 0) { comp_accum |= 0x80; } - m_astat &= 0xffffff; - m_astat |= comp_accum << 24; - m_astat |= AF; + m_core->astat &= 0xffffff; + m_core->astat |= comp_accum << 24; + m_core->astat |= AF; } /* Fn = ABS(Fx + Fy) */ @@ -680,18 +680,18 @@ void adsp21062_device::compute_fabs_plus(int rn, int rx, int ry) CLEAR_ALU_FLAGS(); // AZ - m_astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(r.r) || IS_FLOAT_ZERO(r.r)) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(rn) = r.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = MAX(Fx, Fy) */ @@ -702,17 +702,17 @@ void adsp21062_device::compute_fmax(int rn, int rx, int ry) r_alu.f = MAX(FREG(rx), FREG(ry)); CLEAR_ALU_FLAGS(); - m_astat |= (r_alu.f < 0.0f) ? AN : 0; + m_core->astat |= (r_alu.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; /* TODO: AV flag */ FREG(rn) = r_alu.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = MIN(Fx, Fy) */ @@ -723,17 +723,17 @@ void adsp21062_device::compute_fmin(int rn, int rx, int ry) r_alu.f = MIN(FREG(rx), FREG(ry)); CLEAR_ALU_FLAGS(); - m_astat |= (r_alu.f < 0.0f) ? AN : 0; + m_core->astat |= (r_alu.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; /* TODO: AV flag */ FREG(rn) = r_alu.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = CLIP Fx BY Fy */ @@ -761,14 +761,14 @@ void adsp21062_device::compute_fclip(int rn, int rx, int ry) CLEAR_ALU_FLAGS(); SET_FLAG_AN(r_alu.r); // AZ - m_astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; FREG(rn) = r_alu.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = RECIPS Fx */ @@ -785,17 +785,17 @@ void adsp21062_device::compute_recips(int rn, int rx) r = 0xffffffff; // AI - m_astat |= AI; + m_core->astat |= AI; // AIS - m_stky |= AIS; + m_core->stky |= AIS; } else if (IS_FLOAT_ZERO(REG(rx))) { // +- Zero r = (REG(rx) & FLOAT_SIGN) | FLOAT_INFINITY; - m_astat |= AZ; + m_core->astat |= AZ; } else { @@ -820,17 +820,17 @@ void adsp21062_device::compute_recips(int rn, int rx) SET_FLAG_AN(REG(rx)); // AZ & AV - m_astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0; - m_astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0; + m_core->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; } // AF - m_astat |= AF; + m_core->astat |= AF; REG(rn) = r; } @@ -867,16 +867,16 @@ void adsp21062_device::compute_rsqrts(int rn, int rx) CLEAR_ALU_FLAGS(); // AN - m_astat |= (REG(rx) == 0x80000000) ? AN : 0; + m_core->astat |= (REG(rx) == 0x80000000) ? AN : 0; // AZ & AV - m_astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0; - m_astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0; + m_core->astat |= (IS_FLOAT_ZERO(r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(REG(rx))) ? AV : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || (REG(rx) & 0x80000000)) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || (REG(rx) & 0x80000000)) ? AI : 0; // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; // AF - m_astat |= AF; + m_core->astat |= AF; REG(rn) = r; } @@ -890,14 +890,14 @@ void adsp21062_device::compute_fpass(int rn, int rx) CLEAR_ALU_FLAGS(); // AN - m_astat |= (r.f < 0.0f) ? AN : 0; + m_core->astat |= (r.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; FREG(rn) = r.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fn = ABS Fx */ @@ -908,14 +908,14 @@ void adsp21062_device::compute_fabs(int rn, int rx) CLEAR_ALU_FLAGS(); // AN - m_astat |= (r.f < 0.0f) ? AN : 0; + m_core->astat |= (r.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r.r)) ? AZ : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx))) ? AI : 0; FREG(rn) = r.f; - m_astat |= AF; + m_core->astat |= AF; } /*****************************************************************************/ @@ -950,7 +950,7 @@ void adsp21062_device::compute_mul_ssin(int rn, int rx, int ry) /* MRF + (signed)Rx * (signed)Ry, integer, no rounding */ UINT32 adsp21062_device::compute_mrf_plus_mul_ssin(int rx, int ry) { - UINT64 r = m_mrf + ((INT64)(INT32)REG(rx) * (INT64)(INT32)REG(ry)); + UINT64 r = m_core->mrf + ((INT64)(INT32)REG(rx) * (INT64)(INT32)REG(ry)); CLEAR_MULTIPLIER_FLAGS(); SET_FLAG_MN((UINT32)r); @@ -963,7 +963,7 @@ UINT32 adsp21062_device::compute_mrf_plus_mul_ssin(int rx, int ry) /* MRB + (signed)Rx * (signed)Ry, integer, no rounding */ UINT32 adsp21062_device::compute_mrb_plus_mul_ssin(int rx, int ry) { - INT64 r = m_mrb + ((INT64)(INT32)REG(rx) * (INT64)(INT32)REG(ry)); + INT64 r = m_core->mrb + ((INT64)(INT32)REG(rx) * (INT64)(INT32)REG(ry)); CLEAR_MULTIPLIER_FLAGS(); SET_FLAG_MN((UINT32)r); @@ -994,11 +994,11 @@ void adsp21062_device::compute_multi_mr_to_reg(int ai, int rk) { switch(ai) { - case 0: SET_UREG(rk, (UINT32)(m_mrf)); break; - case 1: SET_UREG(rk, (UINT32)(m_mrf >> 32)); break; + case 0: SET_UREG(rk, (UINT32)(m_core->mrf)); break; + case 1: SET_UREG(rk, (UINT32)(m_core->mrf >> 32)); break; case 2: fatalerror("SHARC: tried to load MR2F\n"); break; - case 4: SET_UREG(rk, (UINT32)(m_mrb)); break; - case 5: SET_UREG(rk, (UINT32)(m_mrb >> 32)); break; + case 4: SET_UREG(rk, (UINT32)(m_core->mrb)); break; + case 5: SET_UREG(rk, (UINT32)(m_core->mrb >> 32)); break; case 6: fatalerror("SHARC: tried to load MR2B\n"); break; default: fatalerror("SHARC: unknown ai %d in mr_to_reg\n", ai); } @@ -1010,11 +1010,11 @@ void adsp21062_device::compute_multi_reg_to_mr(int ai, int rk) { switch(ai) { - case 0: m_mrf &= ~0xffffffff; m_mrf |= GET_UREG(rk); break; - case 1: m_mrf &= 0xffffffff; m_mrf |= (UINT64)(GET_UREG(rk)) << 32; break; + case 0: m_core->mrf &= ~0xffffffff; m_core->mrf |= GET_UREG(rk); break; + case 1: m_core->mrf &= 0xffffffff; m_core->mrf |= (UINT64)(GET_UREG(rk)) << 32; break; case 2: fatalerror("SHARC: tried to write MR2F\n"); break; - case 4: m_mrb &= ~0xffffffff; m_mrb |= GET_UREG(rk); break; - case 5: m_mrb &= 0xffffffff; m_mrb |= (UINT64)(GET_UREG(rk)) << 32; break; + case 4: m_core->mrb &= ~0xffffffff; m_core->mrb |= GET_UREG(rk); break; + case 5: m_core->mrb &= 0xffffffff; m_core->mrb |= (UINT64)(GET_UREG(rk)) << 32; break; case 6: fatalerror("SHARC: tried to write MR2B\n"); break; default: fatalerror("SHARC: unknown ai %d in reg_to_mr\n", ai); } @@ -1031,27 +1031,27 @@ void adsp21062_device::compute_dual_add_sub(int ra, int rs, int rx, int ry) CLEAR_ALU_FLAGS(); if (r_add == 0 || r_sub == 0) { - m_astat |= AZ; + m_core->astat |= AZ; } if (r_add & 0x80000000 || r_sub & 0x80000000) { - m_astat |= AN; + m_core->astat |= AN; } if (((~(REG(rx) ^ REG(ry)) & (REG(rx) ^ r_add)) & 0x80000000) || (( (REG(rx) ^ REG(ry)) & (REG(rx) ^ r_sub)) & 0x80000000)) { - m_astat |= AV; + m_core->astat |= AV; } if (((UINT32)r_add < (UINT32)REG(rx)) || (!((UINT32)r_sub < (UINT32)REG(rx)))) { - m_astat |= AC; + m_core->astat |= AC; } REG(ra) = r_add; REG(rs) = r_sub; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rm = (signed)Rxm * (signed)Rym, fractional, rounding, Ra = Rxa + Rya */ @@ -1076,7 +1076,7 @@ void adsp21062_device::compute_mul_ssfr_add(int rm, int rxm, int rym, int ra, in REG(rm) = r_mul; REG(ra) = r_add; - m_astat &= ~AF; + m_core->astat &= ~AF; } /* Rm = (signed)Rxm * (signed)Rym, fractional, rounding, Ra = Rxa - Rya */ @@ -1101,7 +1101,7 @@ void adsp21062_device::compute_mul_ssfr_sub(int rm, int rxm, int rym, int ra, in REG(rm) = r_mul; REG(ra) = r_sub; - m_astat &= ~AF; + m_core->astat &= ~AF; } @@ -1116,22 +1116,22 @@ void adsp21062_device::compute_dual_fadd_fsub(int ra, int rs, int rx, int ry) CLEAR_ALU_FLAGS(); // AN - m_astat |= ((r_add.f < 0.0f) || (r_sub.f < 0.0f)) ? AN : 0; + m_core->astat |= ((r_add.f < 0.0f) || (r_sub.f < 0.0f)) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) || + m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(rx)) || IS_FLOAT_NAN(REG(ry))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(ra) = r_add.f; FREG(rs) = r_sub.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fm = Fxm * Fym, Fa = Fxa + Fya */ @@ -1148,21 +1148,21 @@ void adsp21062_device::compute_fmul_fadd(int fm, int fxm, int fym, int fa, int f /* TODO: MI flag */ CLEAR_ALU_FLAGS(); - m_astat |= (r_add.f < 0.0f) ? AN : 0; + m_core->astat |= (r_add.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_add.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(fm) = r_mul.f; FREG(fa) = r_add.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fm = Fxm * Fym, Fa = Fxa - Fya */ @@ -1179,21 +1179,21 @@ void adsp21062_device::compute_fmul_fsub(int fm, int fxm, int fym, int fa, int f /* TODO: MI flag */ CLEAR_ALU_FLAGS(); - m_astat |= (r_sub.f < 0.0f) ? AN : 0; + m_core->astat |= (r_sub.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(fm) = r_mul.f; FREG(fa) = r_sub.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fm = Fxm * Fym, Fa = FLOAT Fxa BY Fya */ @@ -1214,16 +1214,16 @@ void adsp21062_device::compute_fmul_float_scaled(int fm, int fxm, int fym, int f /* TODO: MI flag */ CLEAR_ALU_FLAGS(); - m_astat |= (r_alu.f < 0.0f) ? AN : 0; + m_core->astat |= (r_alu.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r_alu.r) || IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_DENORMAL(r_alu.r) || IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; /* TODO: set AV if overflowed */ FREG(fm) = r_mul.f; FREG(fa) = r_alu.f; - m_astat |= AF; + m_core->astat |= AF; } /* Fm = Fxm * Fym, Fa = FIX Fxa BY Fya */ @@ -1233,9 +1233,9 @@ void adsp21062_device::compute_fmul_fix_scaled(int fm, int fxm, int fym, int fa, SHARC_REG r_mul, r_alu; r_mul.f = FREG(fxm) * FREG(fym); - r_alu.r = SCALB(m_r[fxa], fya); + r_alu.r = SCALB(m_core->r[fxa], fya); - if (m_mode1 & MODE1_TRUNCATE) + if (m_core->mode1 & MODE1_TRUNCATE) { alu_i = (INT32)(r_alu.f); } @@ -1255,14 +1255,14 @@ void adsp21062_device::compute_fmul_fix_scaled(int fm, int fxm, int fym, int fa, // AZ SET_FLAG_AZ(alu_i); // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0; /* TODO: AV flag */ FREG(fm) = r_mul.f; REG(fa) = alu_i; // TODO: check this, should be RA? - m_astat |= AF; + m_core->astat |= AF; } void adsp21062_device::compute_fmul_avg(int fm, int fxm, int fym, int fa, int fxa, int fya) @@ -1273,7 +1273,7 @@ void adsp21062_device::compute_fmul_avg(int fm, int fxm, int fym, int fa, int fx r_alu.f = (FREG(fxa) * FREG(fya))/((float) 2.0); /* TODO: are flags right for this? */ - if (m_mode1 & MODE1_TRUNCATE) + if (m_core->mode1 & MODE1_TRUNCATE) { alu_i = (INT32)(r_alu.f); } @@ -1293,14 +1293,14 @@ void adsp21062_device::compute_fmul_avg(int fm, int fxm, int fym, int fa, int fx // AZ SET_FLAG_AZ(alu_i); // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(fxa))) ? AI : 0; /* TODO: AV flag */ FREG(fm) = r_mul.f; REG(fa) = alu_i; - m_astat |= AF; + m_core->astat |= AF; } /* Fm = Fxm * Fym, Fa = MAX(Fxa, Fya) */ @@ -1318,18 +1318,18 @@ void adsp21062_device::compute_fmul_fmax(int fm, int fxm, int fym, int fa, int f /* TODO: MI flag */ CLEAR_ALU_FLAGS(); - m_astat |= (r_alu.f < 0.0f) ? AN : 0; + m_core->astat |= (r_alu.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; /* TODO: AV flag */ FREG(fm) = r_mul.f; FREG(fa) = r_alu.f; - m_astat |= AF; + m_core->astat |= AF; } @@ -1348,18 +1348,18 @@ void adsp21062_device::compute_fmul_fmin(int fm, int fxm, int fym, int fa, int f /* TODO: MI flag */ CLEAR_ALU_FLAGS(); - m_astat |= (r_alu.f < 0.0f) ? AN : 0; + m_core->astat |= (r_alu.f < 0.0f) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; + m_core->astat |= (IS_FLOAT_ZERO(r_alu.r)) ? AZ : 0; // AU - m_stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_alu.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; /* TODO: AV flag */ FREG(fm) = r_mul.f; FREG(fa) = r_alu.f; - m_astat |= AF; + m_core->astat |= AF; } @@ -1380,21 +1380,21 @@ void adsp21062_device::compute_fmul_dual_fadd_fsub(int fm, int fxm, int fym, int CLEAR_ALU_FLAGS(); // AN - m_astat |= ((r_add.r < 0.0f) || (r_sub.r < 0.0f)) ? AN : 0; + m_core->astat |= ((r_add.r < 0.0f) || (r_sub.r < 0.0f)) ? AN : 0; // AZ - m_astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) || + m_core->astat |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_ZERO(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r) || IS_FLOAT_ZERO(r_sub.r)) ? AZ : 0; // AUS - m_stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0; + m_core->stky |= (IS_FLOAT_DENORMAL(r_add.r) || IS_FLOAT_DENORMAL(r_sub.r)) ? AUS : 0; // AI - m_astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; + m_core->astat |= (IS_FLOAT_NAN(REG(fxa)) || IS_FLOAT_NAN(REG(fya))) ? AI : 0; /* TODO: AV flag */ // AIS - if (m_astat & AI) m_stky |= AIS; + if (m_core->astat & AI) m_core->stky |= AIS; FREG(fm) = r_mul.f; FREG(fa) = r_add.f; FREG(fs) = r_sub.f; - m_astat |= AF; + m_core->astat |= AF; } diff --git a/src/devices/cpu/sharc/sharc.cpp b/src/devices/cpu/sharc/sharc.cpp index 3c4cadf5386..f5336be8499 100644 --- a/src/devices/cpu/sharc/sharc.cpp +++ b/src/devices/cpu/sharc/sharc.cpp @@ -1,6 +1,6 @@ // license:BSD-3-Clause // copyright-holders:Ville Linde -/* Analog Devices ADSP-2106x SHARC emulator v2.0 +/* Analog Devices ADSP-2106x SHARC emulator v3.0 Written by Ville Linde */ @@ -8,6 +8,19 @@ #include "emu.h" #include "debugger.h" #include "sharc.h" +#include "sharcfe.h" + + +#define ENABLE_DRC 0 +#define DISABLE_FAST_REGISTERS 1 + + + +#define CACHE_SIZE (2 * 1024 * 1024) +#define COMPILE_BACKWARDS_BYTES 128 +#define COMPILE_FORWARDS_BYTES 512 +#define COMPILE_MAX_INSTRUCTIONS ((COMPILE_BACKWARDS_BYTES/4) + (COMPILE_FORWARDS_BYTES/4)) +#define COMPILE_MAX_SEQUENCE 64 enum @@ -20,7 +33,7 @@ enum SHARC_R8, SHARC_R9, SHARC_R10, SHARC_R11, SHARC_R12, SHARC_R13, SHARC_R14, SHARC_R15, SHARC_SYSCON, SHARC_SYSSTAT, SHARC_MRF, SHARC_MRB, - SHARC_STSTKP, SHARC_PCSTKP, SHARC_LSTKP, + SHARC_STSTKP, SHARC_PCSTKP, SHARC_LSTKP, SHARC_CURLCNTR, SHARC_FADDR, SHARC_DADDR, SHARC_I0, SHARC_I1, SHARC_I2, SHARC_I3, SHARC_I4, SHARC_I5, SHARC_I6, SHARC_I7, @@ -60,6 +73,9 @@ adsp21062_device::adsp21062_device(const machine_config &mconfig, const char *ta , m_program_config("program", ENDIANNESS_LITTLE, 64, 24, -3, ADDRESS_MAP_NAME(internal_pgm)) , m_data_config("data", ENDIANNESS_LITTLE, 32, 32, -2) , m_boot_mode(BOOT_MODE_HOST) + , m_cache(CACHE_SIZE + sizeof(sharc_internal_state)) + , m_drcuml(nullptr) + , m_drcfe(nullptr) { } @@ -73,27 +89,27 @@ offs_t adsp21062_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 void adsp21062_device::CHANGE_PC(UINT32 newpc) { - m_pc = newpc; - m_daddr = newpc; - m_faddr = newpc+1; - m_nfaddr = newpc+2; + m_core->pc = newpc; + m_core->daddr = newpc; + m_core->faddr = newpc+1; + m_core->nfaddr = newpc+2; } void adsp21062_device::CHANGE_PC_DELAYED(UINT32 newpc) { - m_nfaddr = newpc; + m_core->nfaddr = newpc; - m_delay_slot1 = m_pc; - m_delay_slot2 = m_daddr; + m_core->delay_slot1 = m_core->pc; + m_core->delay_slot2 = m_core->daddr; } TIMER_CALLBACK_MEMBER(adsp21062_device::sharc_iop_delayed_write_callback) { - switch (m_iop_delayed_reg) + switch (m_core->iop_delayed_reg) { case 0x1c: { - if (m_iop_delayed_data & 0x1) + if (m_core->iop_delayed_data & 0x1) { sharc_dma_exec(6); } @@ -102,25 +118,25 @@ TIMER_CALLBACK_MEMBER(adsp21062_device::sharc_iop_delayed_write_callback) case 0x1d: { - if (m_iop_delayed_data & 0x1) + if (m_core->iop_delayed_data & 0x1) { sharc_dma_exec(7); } break; } - default: fatalerror("SHARC: sharc_iop_delayed_write: unknown IOP register %02X\n", m_iop_delayed_reg); + default: fatalerror("SHARC: sharc_iop_delayed_write: unknown IOP register %02X\n", m_core->iop_delayed_reg); } - m_delayed_iop_timer->adjust(attotime::never, 0); + m_core->delayed_iop_timer->adjust(attotime::never, 0); } void adsp21062_device::sharc_iop_delayed_w(UINT32 reg, UINT32 data, int cycles) { - m_iop_delayed_reg = reg; - m_iop_delayed_data = data; + m_core->iop_delayed_reg = reg; + m_core->iop_delayed_data = data; - m_delayed_iop_timer->adjust(cycles_to_attotime(cycles), 0); + m_core->delayed_iop_timer->adjust(cycles_to_attotime(cycles), 0); } @@ -133,9 +149,9 @@ UINT32 adsp21062_device::sharc_iop_r(UINT32 address) case 0x37: // DMA status { - return m_dma_status; + return m_core->dma_status; } - default: fatalerror("sharc_iop_r: Unimplemented IOP reg %02X at %08X\n", address, m_pc); + default: fatalerror("sharc_iop_r: Unimplemented IOP reg %02X at %08X\n", address, m_core->pc); } } @@ -148,24 +164,24 @@ void adsp21062_device::sharc_iop_w(UINT32 address, UINT32 data) case 0x04: // External port DMA buffer 0 /* TODO: Last Bronx uses this to init the program, int_index however is 0? */ { - external_dma_write(m_extdma_shift,data); - m_extdma_shift++; - if(m_extdma_shift == 3) - m_extdma_shift = 0; + external_dma_write(m_core->extdma_shift,data); + m_core->extdma_shift++; + if(m_core->extdma_shift == 3) + m_core->extdma_shift = 0; #if 0 - UINT64 r = pm_read48(m_dma[6].int_index); + UINT64 r = pm_read48(m_core->dma[6].int_index); - r &= ~((UINT64)(0xffff) << (m_extdma_shift*16)); - r |= ((UINT64)data & 0xffff) << (m_extdma_shift*16); + r &= ~((UINT64)(0xffff) << (m_core->extdma_shift*16)); + r |= ((UINT64)data & 0xffff) << (m_core->extdma_shift*16); - pm_write48(m_dma[6].int_index, r); + pm_write48(m_core->dma[6].int_index, r); - m_extdma_shift++; - if (m_extdma_shift == 3) + m_core->extdma_shift++; + if (m_core->extdma_shift == 3) { - m_extdma_shift = 0; - m_dma[6].int_index ++; + m_core->extdma_shift = 0; + m_core->dma[6].int_index ++; } #endif } @@ -186,40 +202,40 @@ void adsp21062_device::sharc_iop_w(UINT32 address, UINT32 data) // DMA 6 case 0x1c: { - m_dma[6].control = data; + m_core->dma[6].control = data; sharc_iop_delayed_w(0x1c, data, 1); break; } case 0x20: break; - case 0x40: m_dma[6].int_index = data; return; - case 0x41: m_dma[6].int_modifier = data; return; - case 0x42: m_dma[6].int_count = data; return; - case 0x43: m_dma[6].chain_ptr = data; return; - case 0x44: m_dma[6].gen_purpose = data; return; - case 0x45: m_dma[6].ext_index = data; return; - case 0x46: m_dma[6].ext_modifier = data; return; - case 0x47: m_dma[6].ext_count = data; return; + case 0x40: m_core->dma[6].int_index = data; return; + case 0x41: m_core->dma[6].int_modifier = data; return; + case 0x42: m_core->dma[6].int_count = data; return; + case 0x43: m_core->dma[6].chain_ptr = data; return; + case 0x44: m_core->dma[6].gen_purpose = data; return; + case 0x45: m_core->dma[6].ext_index = data; return; + case 0x46: m_core->dma[6].ext_modifier = data; return; + case 0x47: m_core->dma[6].ext_count = data; return; // DMA 7 case 0x1d: { - m_dma[7].control = data; + m_core->dma[7].control = data; sharc_iop_delayed_w(0x1d, data, 30); break; } - case 0x48: m_dma[7].int_index = data; return; - case 0x49: m_dma[7].int_modifier = data; return; - case 0x4a: m_dma[7].int_count = data; return; - case 0x4b: m_dma[7].chain_ptr = data; return; - case 0x4c: m_dma[7].gen_purpose = data; return; - case 0x4d: m_dma[7].ext_index = data; return; - case 0x4e: m_dma[7].ext_modifier = data; return; - case 0x4f: m_dma[7].ext_count = data; return; + case 0x48: m_core->dma[7].int_index = data; return; + case 0x49: m_core->dma[7].int_modifier = data; return; + case 0x4a: m_core->dma[7].int_count = data; return; + case 0x4b: m_core->dma[7].chain_ptr = data; return; + case 0x4c: m_core->dma[7].gen_purpose = data; return; + case 0x4d: m_core->dma[7].ext_index = data; return; + case 0x4e: m_core->dma[7].ext_modifier = data; return; + case 0x4f: m_core->dma[7].ext_count = data; return; - default: fatalerror("sharc_iop_w: Unimplemented IOP reg %02X, %08X at %08X\n", address, data, m_pc); + default: fatalerror("sharc_iop_w: Unimplemented IOP reg %02X, %08X at %08X\n", address, data, m_core->pc); } } @@ -270,7 +286,7 @@ void adsp21062_device::external_iop_write(UINT32 address, UINT32 data) { if (data != 0) { - m_dma[6].control = data; + m_core->dma[6].control = data; } } else @@ -287,27 +303,27 @@ void adsp21062_device::external_dma_write(UINT32 address, UINT64 data) first internal RAM location, before they are used by the DMA controller. */ - switch ((m_dma[6].control >> 6) & 0x3) + switch ((m_core->dma[6].control >> 6) & 0x3) { case 2: // 16/48 packing { int shift = address % 3; - UINT64 r = pm_read48((m_dma[6].int_index & 0x1ffff) | 0x20000); + UINT64 r = pm_read48((m_core->dma[6].int_index & 0x1ffff) | 0x20000); r &= ~((UINT64)(0xffff) << (shift*16)); r |= (data & 0xffff) << (shift*16); - pm_write48((m_dma[6].int_index & 0x1ffff) | 0x20000, r); + pm_write48((m_core->dma[6].int_index & 0x1ffff) | 0x20000, r); if (shift == 2) { - m_dma[6].int_index += m_dma[6].int_modifier; + m_core->dma[6].int_index += m_core->dma[6].int_modifier; } break; } default: { - fatalerror("sharc_external_dma_write: unimplemented packing mode %d\n", (m_dma[6].control >> 6) & 0x3); + fatalerror("sharc_external_dma_write: unimplemented packing mode %d\n", (m_core->dma[6].control >> 6) & 0x3); } } } @@ -315,8 +331,12 @@ void adsp21062_device::external_dma_write(UINT32 address, UINT64 data) void adsp21062_device::device_start() { int saveindex; + + m_core = (sharc_internal_state *)m_cache.alloc_near(sizeof(sharc_internal_state)); + memset(m_core, 0, sizeof(sharc_internal_state)); m_program = &space(AS_PROGRAM); + m_direct = &m_program->direct(); m_data = &space(AS_DATA); build_opcode_table(); @@ -324,9 +344,107 @@ void adsp21062_device::device_start() m_internal_ram_block0 = &m_internal_ram[0]; m_internal_ram_block1 = &m_internal_ram[0x20000/2]; - m_delayed_iop_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(adsp21062_device::sharc_iop_delayed_write_callback), this)); + // init UML generator + UINT32 umlflags = 0; + m_drcuml = std::make_unique(*this, m_cache, umlflags, 1, 24, 0); - for (auto & elem : m_dma_op) + // add UML symbols + m_drcuml->symbol_add(&m_core->pc, sizeof(m_core->pc), "pc"); + m_drcuml->symbol_add(&m_core->icount, sizeof(m_core->icount), "icount"); + + for (int i=0; i < 16; i++) + { + char buf[10]; + sprintf(buf, "r%d", i); + m_drcuml->symbol_add(&m_core->r[i], sizeof(m_core->r[i]), buf); + + if (i < 8) + { + sprintf(buf, "dag_i%d", i); + m_drcuml->symbol_add(&m_core->dag1.i[i & 7], sizeof(m_core->dag1.i[i & 7]), buf); + sprintf(buf, "dag_m%d", i); + m_drcuml->symbol_add(&m_core->dag1.m[i & 7], sizeof(m_core->dag1.m[i & 7]), buf); + sprintf(buf, "dag_l%d", i); + m_drcuml->symbol_add(&m_core->dag1.l[i & 7], sizeof(m_core->dag1.l[i & 7]), buf); + sprintf(buf, "dag_b%d", i); + m_drcuml->symbol_add(&m_core->dag1.b[i & 7], sizeof(m_core->dag1.b[i & 7]), buf); + } + else + { + sprintf(buf, "dag_i%d", i); + m_drcuml->symbol_add(&m_core->dag2.i[i & 7], sizeof(m_core->dag2.i[i & 7]), buf); + sprintf(buf, "dag_m%d", i); + m_drcuml->symbol_add(&m_core->dag2.m[i & 7], sizeof(m_core->dag2.m[i & 7]), buf); + sprintf(buf, "dag_l%d", i); + m_drcuml->symbol_add(&m_core->dag2.l[i & 7], sizeof(m_core->dag2.l[i & 7]), buf); + sprintf(buf, "dag_b%d", i); + m_drcuml->symbol_add(&m_core->dag2.b[i & 7], sizeof(m_core->dag2.b[i & 7]), buf); + } + } + + m_drcuml->symbol_add(&m_core->astat, sizeof(m_core->astat), "astat"); + m_drcuml->symbol_add(&m_core->mode1, sizeof(m_core->mode1), "mode1"); + m_drcuml->symbol_add(&m_core->mode2, sizeof(m_core->mode2), "mode2"); + m_drcuml->symbol_add(&m_core->lcntr, sizeof(m_core->lcntr), "lcntr"); + m_drcuml->symbol_add(&m_core->curlcntr, sizeof(m_core->curlcntr), "curlcntr"); + m_drcuml->symbol_add(&m_core->imask, sizeof(m_core->imask), "imask"); + m_drcuml->symbol_add(&m_core->imaskp, sizeof(m_core->imaskp), "imaskp"); + m_drcuml->symbol_add(&m_core->irptl, sizeof(m_core->irptl), "irptl"); + m_drcuml->symbol_add(&m_core->ustat1, sizeof(m_core->ustat1), "ustat1"); + m_drcuml->symbol_add(&m_core->ustat2, sizeof(m_core->ustat2), "ustat2"); + m_drcuml->symbol_add(&m_core->stky, sizeof(m_core->stky), "stky"); + + m_drcuml->symbol_add(&m_core->astat_drc.az, sizeof(m_core->astat_drc.az), "astat_az"); + m_drcuml->symbol_add(&m_core->astat_drc.ac, sizeof(m_core->astat_drc.ac), "astat_ac"); + m_drcuml->symbol_add(&m_core->astat_drc.an, sizeof(m_core->astat_drc.an), "astat_an"); + m_drcuml->symbol_add(&m_core->astat_drc.av, sizeof(m_core->astat_drc.av), "astat_av"); + m_drcuml->symbol_add(&m_core->astat_drc.ai, sizeof(m_core->astat_drc.ai), "astat_ai"); + m_drcuml->symbol_add(&m_core->astat_drc.as, sizeof(m_core->astat_drc.as), "astat_as"); + m_drcuml->symbol_add(&m_core->astat_drc.mv, sizeof(m_core->astat_drc.mv), "astat_mv"); + m_drcuml->symbol_add(&m_core->astat_drc.mn, sizeof(m_core->astat_drc.mn), "astat_mn"); + m_drcuml->symbol_add(&m_core->astat_drc.mu, sizeof(m_core->astat_drc.mu), "astat_mu"); + m_drcuml->symbol_add(&m_core->astat_drc.mi, sizeof(m_core->astat_drc.mi), "astat_mi"); + m_drcuml->symbol_add(&m_core->astat_drc.sz, sizeof(m_core->astat_drc.sz), "astat_sz"); + m_drcuml->symbol_add(&m_core->astat_drc.sv, sizeof(m_core->astat_drc.sv), "astat_sv"); + m_drcuml->symbol_add(&m_core->astat_drc.ss, sizeof(m_core->astat_drc.ss), "astat_ss"); + + m_drcuml->symbol_add(&m_core->arg0, sizeof(m_core->arg0), "arg0"); + m_drcuml->symbol_add(&m_core->arg1, sizeof(m_core->arg1), "arg1"); + m_drcuml->symbol_add(&m_core->arg2, sizeof(m_core->arg2), "arg2"); + m_drcuml->symbol_add(&m_core->arg3, sizeof(m_core->arg3), "arg3"); + + m_drcuml->symbol_add(&m_core->dreg_temp, sizeof(m_core->dreg_temp), "dreg_temp"); + m_drcuml->symbol_add(&m_core->lstkp, sizeof(m_core->lstkp), "lstkp"); + m_drcuml->symbol_add(&m_core->px, sizeof(m_core->px), "px"); + + m_drcfe = std::make_unique(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, COMPILE_MAX_SEQUENCE); + + for (int i = 0; i < 16; i++) + { + m_regmap[i] = uml::mem(&m_core->r[i]); + } + + // I0-3 used by the DRC, rest can be assigned to fast registers + if (!DISABLE_FAST_REGISTERS) + { + drcbe_info beinfo; + m_drcuml->get_backend_info(beinfo); + if (beinfo.direct_iregs > 4) + m_regmap[0] = uml::I4; + if (beinfo.direct_iregs > 5) + m_regmap[1] = uml::I5; + if (beinfo.direct_iregs > 6) + m_regmap[2] = uml::I6; + if (beinfo.direct_iregs > 7) + m_regmap[3] = uml::I7; + } + + m_cache_dirty = true; + + + m_core->delayed_iop_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(adsp21062_device::sharc_iop_delayed_write_callback), this)); + + for (auto & elem : m_core->dma_op) { elem.src = 0; elem.dst = 0; @@ -343,32 +461,32 @@ void adsp21062_device::device_start() for (int i=0; i < 16; i++) { - m_r[i].r = 0; - m_reg_alt[i].r = 0; + m_core->r[i].r = 0; + m_core->reg_alt[i].r = 0; } - m_mrf = 0; - m_mrb = 0; - for (auto & elem : m_pcstack) + m_core->mrf = 0; + m_core->mrb = 0; + for (auto & elem : m_core->pcstack) { elem = 0; } for (int i=0; i < 6; i++) { - m_lcstack[i] = 0; - m_lastack[i] = 0; + m_core->lcstack[i] = 0; + m_core->lastack[i] = 0; } - m_pcstk = 0; - m_laddr.addr = m_laddr.code = m_laddr.loop_type = 0; - m_curlcntr = 0; - m_lcntr = 0; + m_core->pcstk = 0; + m_core->laddr.addr = m_core->laddr.code = m_core->laddr.loop_type = 0; + m_core->curlcntr = 0; + m_core->lcntr = 0; for (int i=0; i < 8; i++) { - m_dag1.i[i] = m_dag1.m[i] = m_dag1.b[i] = m_dag1.l[i] = 0; - m_dag2.i[i] = m_dag2.m[i] = m_dag2.b[i] = m_dag2.l[i] = 0; - m_dag1_alt.i[i] = m_dag1_alt.m[i] = m_dag1_alt.b[i] = m_dag1_alt.l[i] = 0; - m_dag2_alt.i[i] = m_dag2_alt.m[i] = m_dag2_alt.b[i] = m_dag2_alt.l[i] = 0; + m_core->dag1.i[i] = m_core->dag1.m[i] = m_core->dag1.b[i] = m_core->dag1.l[i] = 0; + m_core->dag2.i[i] = m_core->dag2.m[i] = m_core->dag2.b[i] = m_core->dag2.l[i] = 0; + m_core->dag1_alt.i[i] = m_core->dag1_alt.m[i] = m_core->dag1_alt.b[i] = m_core->dag1_alt.l[i] = 0; + m_core->dag2_alt.i[i] = m_core->dag2_alt.m[i] = m_core->dag2_alt.b[i] = m_core->dag2_alt.l[i] = 0; } - for (auto & elem : m_dma) + for (auto & elem : m_core->dma) { elem.control = 0; elem.int_index = 0; @@ -380,261 +498,265 @@ void adsp21062_device::device_start() elem.ext_modifier = 0; elem.ext_count = 0; } - m_mode1 = 0; - m_mode2 = 0; - m_astat = 0; - m_irptl = 0; - m_imask = 0; - m_imaskp = 0; - m_ustat1 = 0; - m_ustat2 = 0; - m_flag[0] = m_flag[1] = m_flag[2] = m_flag[3] = 0; - m_syscon = 0; - m_sysstat = 0; - for (auto & elem : m_status_stack) + m_core->mode1 = 0; + m_core->mode2 = 0; + m_core->astat = 0; + m_core->irptl = 0; + m_core->imask = 0; + m_core->imaskp = 0; + m_core->ustat1 = 0; + m_core->ustat2 = 0; + m_core->flag[0] = m_core->flag[1] = m_core->flag[2] = m_core->flag[3] = 0; + m_core->syscon = 0; + m_core->sysstat = 0; + for (auto & elem : m_core->status_stack) { elem.mode1 = 0; elem.astat = 0; } - m_status_stkp = 0; - m_px = 0; - m_opcode = 0; - m_irq_active = 0; - m_active_irq_num = 0; - m_dma_status = 0; - m_iop_delayed_reg = 0; - m_iop_delayed_data = 0; - m_delay_slot1 = 0; - m_delay_slot2 = 0; - m_systemreg_latency_cycles = 0; - m_systemreg_latency_reg = 0; - m_systemreg_latency_data = 0; - m_systemreg_previous_data = 0; - m_astat_old = 0; - m_astat_old_old = 0; - m_astat_old_old_old = 0; + m_core->status_stkp = 0; + m_core->px = 0; + m_core->opcode = 0; + m_core->irq_pending = 0; + m_core->active_irq_num = 0; + m_core->dma_status = 0; + m_core->iop_delayed_reg = 0; + m_core->iop_delayed_data = 0; + m_core->delay_slot1 = 0; + m_core->delay_slot2 = 0; + m_core->systemreg_latency_cycles = 0; + m_core->systemreg_latency_reg = 0; + m_core->systemreg_latency_data = 0; + m_core->systemreg_previous_data = 0; + m_core->astat_old = 0; + m_core->astat_old_old = 0; + m_core->astat_old_old_old = 0; - save_item(NAME(m_pc)); - save_pointer(NAME(&m_r[0].r), ARRAY_LENGTH(m_r)); - save_pointer(NAME(&m_reg_alt[0].r), ARRAY_LENGTH(m_reg_alt)); - save_item(NAME(m_mrf)); - save_item(NAME(m_mrb)); + m_core->fp0 = 0.0f; + m_core->fp1 = 1.0f; - save_item(NAME(m_pcstack)); - save_item(NAME(m_lcstack)); - save_item(NAME(m_lastack)); - save_item(NAME(m_lstkp)); + save_item(NAME(m_core->pc)); + save_pointer(NAME(&m_core->r[0].r), ARRAY_LENGTH(m_core->r)); + save_pointer(NAME(&m_core->reg_alt[0].r), ARRAY_LENGTH(m_core->reg_alt)); + save_item(NAME(m_core->mrf)); + save_item(NAME(m_core->mrb)); - save_item(NAME(m_faddr)); - save_item(NAME(m_daddr)); - save_item(NAME(m_pcstk)); - save_item(NAME(m_pcstkp)); - save_item(NAME(m_laddr.addr)); - save_item(NAME(m_laddr.code)); - save_item(NAME(m_laddr.loop_type)); - save_item(NAME(m_curlcntr)); - save_item(NAME(m_lcntr)); + save_item(NAME(m_core->pcstack)); + save_item(NAME(m_core->lcstack)); + save_item(NAME(m_core->lastack)); + save_item(NAME(m_core->lstkp)); - save_item(NAME(m_dag1.i)); - save_item(NAME(m_dag1.m)); - save_item(NAME(m_dag1.b)); - save_item(NAME(m_dag1.l)); - save_item(NAME(m_dag2.i)); - save_item(NAME(m_dag2.m)); - save_item(NAME(m_dag2.b)); - save_item(NAME(m_dag2.l)); - save_item(NAME(m_dag1_alt.i)); - save_item(NAME(m_dag1_alt.m)); - save_item(NAME(m_dag1_alt.b)); - save_item(NAME(m_dag1_alt.l)); - save_item(NAME(m_dag2_alt.i)); - save_item(NAME(m_dag2_alt.m)); - save_item(NAME(m_dag2_alt.b)); - save_item(NAME(m_dag2_alt.l)); + save_item(NAME(m_core->faddr)); + save_item(NAME(m_core->daddr)); + save_item(NAME(m_core->pcstk)); + save_item(NAME(m_core->pcstkp)); + save_item(NAME(m_core->laddr.addr)); + save_item(NAME(m_core->laddr.code)); + save_item(NAME(m_core->laddr.loop_type)); + save_item(NAME(m_core->curlcntr)); + save_item(NAME(m_core->lcntr)); - for (saveindex = 0; saveindex < ARRAY_LENGTH(m_dma); saveindex++) + save_item(NAME(m_core->dag1.i)); + save_item(NAME(m_core->dag1.m)); + save_item(NAME(m_core->dag1.b)); + save_item(NAME(m_core->dag1.l)); + save_item(NAME(m_core->dag2.i)); + save_item(NAME(m_core->dag2.m)); + save_item(NAME(m_core->dag2.b)); + save_item(NAME(m_core->dag2.l)); + save_item(NAME(m_core->dag1_alt.i)); + save_item(NAME(m_core->dag1_alt.m)); + save_item(NAME(m_core->dag1_alt.b)); + save_item(NAME(m_core->dag1_alt.l)); + save_item(NAME(m_core->dag2_alt.i)); + save_item(NAME(m_core->dag2_alt.m)); + save_item(NAME(m_core->dag2_alt.b)); + save_item(NAME(m_core->dag2_alt.l)); + + for (saveindex = 0; saveindex < ARRAY_LENGTH(m_core->dma); saveindex++) { - save_item(NAME(m_dma[saveindex].control), saveindex); - save_item(NAME(m_dma[saveindex].int_index), saveindex); - save_item(NAME(m_dma[saveindex].int_modifier), saveindex); - save_item(NAME(m_dma[saveindex].int_count), saveindex); - save_item(NAME(m_dma[saveindex].chain_ptr), saveindex); - save_item(NAME(m_dma[saveindex].gen_purpose), saveindex); - save_item(NAME(m_dma[saveindex].ext_index), saveindex); - save_item(NAME(m_dma[saveindex].ext_modifier), saveindex); - save_item(NAME(m_dma[saveindex].ext_count), saveindex); + save_item(NAME(m_core->dma[saveindex].control), saveindex); + save_item(NAME(m_core->dma[saveindex].int_index), saveindex); + save_item(NAME(m_core->dma[saveindex].int_modifier), saveindex); + save_item(NAME(m_core->dma[saveindex].int_count), saveindex); + save_item(NAME(m_core->dma[saveindex].chain_ptr), saveindex); + save_item(NAME(m_core->dma[saveindex].gen_purpose), saveindex); + save_item(NAME(m_core->dma[saveindex].ext_index), saveindex); + save_item(NAME(m_core->dma[saveindex].ext_modifier), saveindex); + save_item(NAME(m_core->dma[saveindex].ext_count), saveindex); } - save_item(NAME(m_mode1)); - save_item(NAME(m_mode2)); - save_item(NAME(m_astat)); - save_item(NAME(m_stky)); - save_item(NAME(m_irptl)); - save_item(NAME(m_imask)); - save_item(NAME(m_imaskp)); - save_item(NAME(m_ustat1)); - save_item(NAME(m_ustat2)); + save_item(NAME(m_core->mode1)); + save_item(NAME(m_core->mode2)); + save_item(NAME(m_core->astat)); + save_item(NAME(m_core->stky)); + save_item(NAME(m_core->irptl)); + save_item(NAME(m_core->imask)); + save_item(NAME(m_core->imaskp)); + save_item(NAME(m_core->ustat1)); + save_item(NAME(m_core->ustat2)); - save_item(NAME(m_flag)); + save_item(NAME(m_core->flag)); - save_item(NAME(m_syscon)); - save_item(NAME(m_sysstat)); + save_item(NAME(m_core->syscon)); + save_item(NAME(m_core->sysstat)); - for (saveindex = 0; saveindex < ARRAY_LENGTH(m_status_stack); saveindex++) + for (saveindex = 0; saveindex < ARRAY_LENGTH(m_core->status_stack); saveindex++) { - save_item(NAME(m_status_stack[saveindex].mode1), saveindex); - save_item(NAME(m_status_stack[saveindex].astat), saveindex); + save_item(NAME(m_core->status_stack[saveindex].mode1), saveindex); + save_item(NAME(m_core->status_stack[saveindex].astat), saveindex); } - save_item(NAME(m_status_stkp)); + save_item(NAME(m_core->status_stkp)); - save_item(NAME(m_px)); + save_item(NAME(m_core->px)); save_pointer(NAME(m_internal_ram), 2 * 0x10000); - save_item(NAME(m_opcode)); + save_item(NAME(m_core->opcode)); - save_item(NAME(m_nfaddr)); + save_item(NAME(m_core->nfaddr)); - save_item(NAME(m_idle)); - save_item(NAME(m_irq_active)); - save_item(NAME(m_active_irq_num)); + save_item(NAME(m_core->idle)); + save_item(NAME(m_core->irq_pending)); + save_item(NAME(m_core->active_irq_num)); - for (saveindex = 0; saveindex < ARRAY_LENGTH(m_dma_op); saveindex++) + for (saveindex = 0; saveindex < ARRAY_LENGTH(m_core->dma_op); saveindex++) { - save_item(NAME(m_dma_op[saveindex].src), saveindex); - save_item(NAME(m_dma_op[saveindex].dst), saveindex); - save_item(NAME(m_dma_op[saveindex].chain_ptr), saveindex); - save_item(NAME(m_dma_op[saveindex].src_modifier), saveindex); - save_item(NAME(m_dma_op[saveindex].dst_modifier), saveindex); - save_item(NAME(m_dma_op[saveindex].src_count), saveindex); - save_item(NAME(m_dma_op[saveindex].dst_count), saveindex); - save_item(NAME(m_dma_op[saveindex].pmode), saveindex); - save_item(NAME(m_dma_op[saveindex].chained_direction), saveindex); - save_item(NAME(m_dma_op[saveindex].active), saveindex); + save_item(NAME(m_core->dma_op[saveindex].src), saveindex); + save_item(NAME(m_core->dma_op[saveindex].dst), saveindex); + save_item(NAME(m_core->dma_op[saveindex].chain_ptr), saveindex); + save_item(NAME(m_core->dma_op[saveindex].src_modifier), saveindex); + save_item(NAME(m_core->dma_op[saveindex].dst_modifier), saveindex); + save_item(NAME(m_core->dma_op[saveindex].src_count), saveindex); + save_item(NAME(m_core->dma_op[saveindex].dst_count), saveindex); + save_item(NAME(m_core->dma_op[saveindex].pmode), saveindex); + save_item(NAME(m_core->dma_op[saveindex].chained_direction), saveindex); + save_item(NAME(m_core->dma_op[saveindex].active), saveindex); } - save_item(NAME(m_dma_status)); + save_item(NAME(m_core->dma_status)); - save_item(NAME(m_interrupt_active)); + save_item(NAME(m_core->interrupt_active)); - save_item(NAME(m_iop_delayed_reg)); - save_item(NAME(m_iop_delayed_data)); + save_item(NAME(m_core->iop_delayed_reg)); + save_item(NAME(m_core->iop_delayed_data)); - save_item(NAME(m_delay_slot1)); - save_item(NAME(m_delay_slot2)); + save_item(NAME(m_core->delay_slot1)); + save_item(NAME(m_core->delay_slot2)); - save_item(NAME(m_systemreg_latency_cycles)); - save_item(NAME(m_systemreg_latency_reg)); - save_item(NAME(m_systemreg_latency_data)); - save_item(NAME(m_systemreg_previous_data)); + save_item(NAME(m_core->systemreg_latency_cycles)); + save_item(NAME(m_core->systemreg_latency_reg)); + save_item(NAME(m_core->systemreg_latency_data)); + save_item(NAME(m_core->systemreg_previous_data)); - save_item(NAME(m_astat_old)); - save_item(NAME(m_astat_old_old)); - save_item(NAME(m_astat_old_old_old)); + save_item(NAME(m_core->astat_old)); + save_item(NAME(m_core->astat_old_old)); + save_item(NAME(m_core->astat_old_old_old)); - state_add( SHARC_PC, "PC", m_pc).formatstr("%08X"); - state_add( SHARC_PCSTK, "PCSTK", m_pcstk).formatstr("%08X"); - state_add( SHARC_PCSTKP, "PCSTKP", m_pcstkp).formatstr("%08X"); - state_add( SHARC_LSTKP, "LSTKP", m_lstkp).formatstr("%08X"); - state_add( SHARC_FADDR, "FADDR", m_faddr).formatstr("%08X"); - state_add( SHARC_DADDR, "DADDR", m_daddr).formatstr("%08X"); - state_add( SHARC_MODE1, "MODE1", m_mode1).formatstr("%08X"); - state_add( SHARC_MODE2, "MODE2", m_mode2).formatstr("%08X"); - state_add( SHARC_ASTAT, "ASTAT", m_astat).formatstr("%08X"); - state_add( SHARC_IRPTL, "IRPTL", m_irptl).formatstr("%08X"); - state_add( SHARC_IMASK, "IMASK", m_imask).formatstr("%08X"); - state_add( SHARC_USTAT1, "USTAT1", m_ustat1).formatstr("%08X"); - state_add( SHARC_USTAT2, "USTAT2", m_ustat2).formatstr("%08X"); - state_add( SHARC_STSTKP, "STSTKP", m_status_stkp).formatstr("%08X"); + state_add( SHARC_PC, "PC", m_core->pc).formatstr("%08X"); + state_add( SHARC_PCSTK, "PCSTK", m_core->pcstk).formatstr("%08X"); + state_add( SHARC_PCSTKP, "PCSTKP", m_core->pcstkp).formatstr("%08X"); + state_add( SHARC_LSTKP, "LSTKP", m_core->lstkp).formatstr("%08X"); + state_add( SHARC_FADDR, "FADDR", m_core->faddr).formatstr("%08X"); + state_add( SHARC_DADDR, "DADDR", m_core->daddr).formatstr("%08X"); + state_add( SHARC_MODE1, "MODE1", m_core->mode1).formatstr("%08X"); + state_add( SHARC_MODE2, "MODE2", m_core->mode2).formatstr("%08X"); + state_add( SHARC_ASTAT, "ASTAT", m_core->astat).formatstr("%08X"); + state_add( SHARC_IRPTL, "IRPTL", m_core->irptl).formatstr("%08X"); + state_add( SHARC_IMASK, "IMASK", m_core->imask).formatstr("%08X"); + state_add( SHARC_USTAT1, "USTAT1", m_core->ustat1).formatstr("%08X"); + state_add( SHARC_USTAT2, "USTAT2", m_core->ustat2).formatstr("%08X"); + state_add( SHARC_CURLCNTR, "CURLCNTR", m_core->curlcntr).formatstr("%08X"); + state_add( SHARC_STSTKP, "STSTKP", m_core->status_stkp).formatstr("%08X"); - state_add( SHARC_R0, "R0", m_r[0].r).formatstr("%08X"); - state_add( SHARC_R1, "R1", m_r[1].r).formatstr("%08X"); - state_add( SHARC_R2, "R2", m_r[2].r).formatstr("%08X"); - state_add( SHARC_R3, "R3", m_r[3].r).formatstr("%08X"); - state_add( SHARC_R4, "R4", m_r[4].r).formatstr("%08X"); - state_add( SHARC_R5, "R5", m_r[5].r).formatstr("%08X"); - state_add( SHARC_R6, "R6", m_r[6].r).formatstr("%08X"); - state_add( SHARC_R7, "R7", m_r[7].r).formatstr("%08X"); - state_add( SHARC_R8, "R8", m_r[8].r).formatstr("%08X"); - state_add( SHARC_R9, "R9", m_r[9].r).formatstr("%08X"); - state_add( SHARC_R10, "R10", m_r[10].r).formatstr("%08X"); - state_add( SHARC_R11, "R11", m_r[11].r).formatstr("%08X"); - state_add( SHARC_R12, "R12", m_r[12].r).formatstr("%08X"); - state_add( SHARC_R13, "R13", m_r[13].r).formatstr("%08X"); - state_add( SHARC_R14, "R14", m_r[14].r).formatstr("%08X"); - state_add( SHARC_R15, "R15", m_r[15].r).formatstr("%08X"); + state_add( SHARC_R0, "R0", m_core->r[0].r).formatstr("%08X"); + state_add( SHARC_R1, "R1", m_core->r[1].r).formatstr("%08X"); + state_add( SHARC_R2, "R2", m_core->r[2].r).formatstr("%08X"); + state_add( SHARC_R3, "R3", m_core->r[3].r).formatstr("%08X"); + state_add( SHARC_R4, "R4", m_core->r[4].r).formatstr("%08X"); + state_add( SHARC_R5, "R5", m_core->r[5].r).formatstr("%08X"); + state_add( SHARC_R6, "R6", m_core->r[6].r).formatstr("%08X"); + state_add( SHARC_R7, "R7", m_core->r[7].r).formatstr("%08X"); + state_add( SHARC_R8, "R8", m_core->r[8].r).formatstr("%08X"); + state_add( SHARC_R9, "R9", m_core->r[9].r).formatstr("%08X"); + state_add( SHARC_R10, "R10", m_core->r[10].r).formatstr("%08X"); + state_add( SHARC_R11, "R11", m_core->r[11].r).formatstr("%08X"); + state_add( SHARC_R12, "R12", m_core->r[12].r).formatstr("%08X"); + state_add( SHARC_R13, "R13", m_core->r[13].r).formatstr("%08X"); + state_add( SHARC_R14, "R14", m_core->r[14].r).formatstr("%08X"); + state_add( SHARC_R15, "R15", m_core->r[15].r).formatstr("%08X"); - state_add( SHARC_I0, "I0", m_dag1.i[0]).formatstr("%08X"); - state_add( SHARC_I1, "I1", m_dag1.i[1]).formatstr("%08X"); - state_add( SHARC_I2, "I2", m_dag1.i[2]).formatstr("%08X"); - state_add( SHARC_I3, "I3", m_dag1.i[3]).formatstr("%08X"); - state_add( SHARC_I4, "I4", m_dag1.i[4]).formatstr("%08X"); - state_add( SHARC_I5, "I5", m_dag1.i[5]).formatstr("%08X"); - state_add( SHARC_I6, "I6", m_dag1.i[6]).formatstr("%08X"); - state_add( SHARC_I7, "I7", m_dag1.i[7]).formatstr("%08X"); - state_add( SHARC_I8, "I8", m_dag2.i[0]).formatstr("%08X"); - state_add( SHARC_I9, "I9", m_dag2.i[1]).formatstr("%08X"); - state_add( SHARC_I10, "I10", m_dag2.i[2]).formatstr("%08X"); - state_add( SHARC_I11, "I11", m_dag2.i[3]).formatstr("%08X"); - state_add( SHARC_I12, "I12", m_dag2.i[4]).formatstr("%08X"); - state_add( SHARC_I13, "I13", m_dag2.i[5]).formatstr("%08X"); - state_add( SHARC_I14, "I14", m_dag2.i[6]).formatstr("%08X"); - state_add( SHARC_I15, "I15", m_dag2.i[7]).formatstr("%08X"); + state_add( SHARC_I0, "I0", m_core->dag1.i[0]).formatstr("%08X"); + state_add( SHARC_I1, "I1", m_core->dag1.i[1]).formatstr("%08X"); + state_add( SHARC_I2, "I2", m_core->dag1.i[2]).formatstr("%08X"); + state_add( SHARC_I3, "I3", m_core->dag1.i[3]).formatstr("%08X"); + state_add( SHARC_I4, "I4", m_core->dag1.i[4]).formatstr("%08X"); + state_add( SHARC_I5, "I5", m_core->dag1.i[5]).formatstr("%08X"); + state_add( SHARC_I6, "I6", m_core->dag1.i[6]).formatstr("%08X"); + state_add( SHARC_I7, "I7", m_core->dag1.i[7]).formatstr("%08X"); + state_add( SHARC_I8, "I8", m_core->dag2.i[0]).formatstr("%08X"); + state_add( SHARC_I9, "I9", m_core->dag2.i[1]).formatstr("%08X"); + state_add( SHARC_I10, "I10", m_core->dag2.i[2]).formatstr("%08X"); + state_add( SHARC_I11, "I11", m_core->dag2.i[3]).formatstr("%08X"); + state_add( SHARC_I12, "I12", m_core->dag2.i[4]).formatstr("%08X"); + state_add( SHARC_I13, "I13", m_core->dag2.i[5]).formatstr("%08X"); + state_add( SHARC_I14, "I14", m_core->dag2.i[6]).formatstr("%08X"); + state_add( SHARC_I15, "I15", m_core->dag2.i[7]).formatstr("%08X"); - state_add( SHARC_M0, "M0", m_dag1.m[0]).formatstr("%08X"); - state_add( SHARC_M1, "M1", m_dag1.m[1]).formatstr("%08X"); - state_add( SHARC_M2, "M2", m_dag1.m[2]).formatstr("%08X"); - state_add( SHARC_M3, "M3", m_dag1.m[3]).formatstr("%08X"); - state_add( SHARC_M4, "M4", m_dag1.m[4]).formatstr("%08X"); - state_add( SHARC_M5, "M5", m_dag1.m[5]).formatstr("%08X"); - state_add( SHARC_M6, "M6", m_dag1.m[6]).formatstr("%08X"); - state_add( SHARC_M7, "M7", m_dag1.m[7]).formatstr("%08X"); - state_add( SHARC_M8, "M8", m_dag2.m[0]).formatstr("%08X"); - state_add( SHARC_M9, "M9", m_dag2.m[1]).formatstr("%08X"); - state_add( SHARC_M10, "M10", m_dag2.m[2]).formatstr("%08X"); - state_add( SHARC_M11, "M11", m_dag2.m[3]).formatstr("%08X"); - state_add( SHARC_M12, "M12", m_dag2.m[4]).formatstr("%08X"); - state_add( SHARC_M13, "M13", m_dag2.m[5]).formatstr("%08X"); - state_add( SHARC_M14, "M14", m_dag2.m[6]).formatstr("%08X"); - state_add( SHARC_M15, "M15", m_dag2.m[7]).formatstr("%08X"); + state_add( SHARC_M0, "M0", m_core->dag1.m[0]).formatstr("%08X"); + state_add( SHARC_M1, "M1", m_core->dag1.m[1]).formatstr("%08X"); + state_add( SHARC_M2, "M2", m_core->dag1.m[2]).formatstr("%08X"); + state_add( SHARC_M3, "M3", m_core->dag1.m[3]).formatstr("%08X"); + state_add( SHARC_M4, "M4", m_core->dag1.m[4]).formatstr("%08X"); + state_add( SHARC_M5, "M5", m_core->dag1.m[5]).formatstr("%08X"); + state_add( SHARC_M6, "M6", m_core->dag1.m[6]).formatstr("%08X"); + state_add( SHARC_M7, "M7", m_core->dag1.m[7]).formatstr("%08X"); + state_add( SHARC_M8, "M8", m_core->dag2.m[0]).formatstr("%08X"); + state_add( SHARC_M9, "M9", m_core->dag2.m[1]).formatstr("%08X"); + state_add( SHARC_M10, "M10", m_core->dag2.m[2]).formatstr("%08X"); + state_add( SHARC_M11, "M11", m_core->dag2.m[3]).formatstr("%08X"); + state_add( SHARC_M12, "M12", m_core->dag2.m[4]).formatstr("%08X"); + state_add( SHARC_M13, "M13", m_core->dag2.m[5]).formatstr("%08X"); + state_add( SHARC_M14, "M14", m_core->dag2.m[6]).formatstr("%08X"); + state_add( SHARC_M15, "M15", m_core->dag2.m[7]).formatstr("%08X"); - state_add( SHARC_L0, "L0", m_dag1.l[0]).formatstr("%08X"); - state_add( SHARC_L1, "L1", m_dag1.l[1]).formatstr("%08X"); - state_add( SHARC_L2, "L2", m_dag1.l[2]).formatstr("%08X"); - state_add( SHARC_L3, "L3", m_dag1.l[3]).formatstr("%08X"); - state_add( SHARC_L4, "L4", m_dag1.l[4]).formatstr("%08X"); - state_add( SHARC_L5, "L5", m_dag1.l[5]).formatstr("%08X"); - state_add( SHARC_L6, "L6", m_dag1.l[6]).formatstr("%08X"); - state_add( SHARC_L7, "L7", m_dag1.l[7]).formatstr("%08X"); - state_add( SHARC_L8, "L8", m_dag2.l[0]).formatstr("%08X"); - state_add( SHARC_L9, "L9", m_dag2.l[1]).formatstr("%08X"); - state_add( SHARC_L10, "L10", m_dag2.l[2]).formatstr("%08X"); - state_add( SHARC_L11, "L11", m_dag2.l[3]).formatstr("%08X"); - state_add( SHARC_L12, "L12", m_dag2.l[4]).formatstr("%08X"); - state_add( SHARC_L13, "L13", m_dag2.l[5]).formatstr("%08X"); - state_add( SHARC_L14, "L14", m_dag2.l[6]).formatstr("%08X"); - state_add( SHARC_L15, "L15", m_dag2.l[7]).formatstr("%08X"); + state_add( SHARC_L0, "L0", m_core->dag1.l[0]).formatstr("%08X"); + state_add( SHARC_L1, "L1", m_core->dag1.l[1]).formatstr("%08X"); + state_add( SHARC_L2, "L2", m_core->dag1.l[2]).formatstr("%08X"); + state_add( SHARC_L3, "L3", m_core->dag1.l[3]).formatstr("%08X"); + state_add( SHARC_L4, "L4", m_core->dag1.l[4]).formatstr("%08X"); + state_add( SHARC_L5, "L5", m_core->dag1.l[5]).formatstr("%08X"); + state_add( SHARC_L6, "L6", m_core->dag1.l[6]).formatstr("%08X"); + state_add( SHARC_L7, "L7", m_core->dag1.l[7]).formatstr("%08X"); + state_add( SHARC_L8, "L8", m_core->dag2.l[0]).formatstr("%08X"); + state_add( SHARC_L9, "L9", m_core->dag2.l[1]).formatstr("%08X"); + state_add( SHARC_L10, "L10", m_core->dag2.l[2]).formatstr("%08X"); + state_add( SHARC_L11, "L11", m_core->dag2.l[3]).formatstr("%08X"); + state_add( SHARC_L12, "L12", m_core->dag2.l[4]).formatstr("%08X"); + state_add( SHARC_L13, "L13", m_core->dag2.l[5]).formatstr("%08X"); + state_add( SHARC_L14, "L14", m_core->dag2.l[6]).formatstr("%08X"); + state_add( SHARC_L15, "L15", m_core->dag2.l[7]).formatstr("%08X"); - state_add( SHARC_B0, "B0", m_dag1.b[0]).formatstr("%08X"); - state_add( SHARC_B1, "B1", m_dag1.b[1]).formatstr("%08X"); - state_add( SHARC_B2, "B2", m_dag1.b[2]).formatstr("%08X"); - state_add( SHARC_B3, "B3", m_dag1.b[3]).formatstr("%08X"); - state_add( SHARC_B4, "B4", m_dag1.b[4]).formatstr("%08X"); - state_add( SHARC_B5, "B5", m_dag1.b[5]).formatstr("%08X"); - state_add( SHARC_B6, "B6", m_dag1.b[6]).formatstr("%08X"); - state_add( SHARC_B7, "B7", m_dag1.b[7]).formatstr("%08X"); - state_add( SHARC_B8, "B8", m_dag2.b[0]).formatstr("%08X"); - state_add( SHARC_B9, "B9", m_dag2.b[1]).formatstr("%08X"); - state_add( SHARC_B10, "B10", m_dag2.b[2]).formatstr("%08X"); - state_add( SHARC_B11, "B11", m_dag2.b[3]).formatstr("%08X"); - state_add( SHARC_B12, "B12", m_dag2.b[4]).formatstr("%08X"); - state_add( SHARC_B13, "B13", m_dag2.b[5]).formatstr("%08X"); - state_add( SHARC_B14, "B14", m_dag2.b[6]).formatstr("%08X"); - state_add( SHARC_B15, "B15", m_dag2.b[7]).formatstr("%08X"); + state_add( SHARC_B0, "B0", m_core->dag1.b[0]).formatstr("%08X"); + state_add( SHARC_B1, "B1", m_core->dag1.b[1]).formatstr("%08X"); + state_add( SHARC_B2, "B2", m_core->dag1.b[2]).formatstr("%08X"); + state_add( SHARC_B3, "B3", m_core->dag1.b[3]).formatstr("%08X"); + state_add( SHARC_B4, "B4", m_core->dag1.b[4]).formatstr("%08X"); + state_add( SHARC_B5, "B5", m_core->dag1.b[5]).formatstr("%08X"); + state_add( SHARC_B6, "B6", m_core->dag1.b[6]).formatstr("%08X"); + state_add( SHARC_B7, "B7", m_core->dag1.b[7]).formatstr("%08X"); + state_add( SHARC_B8, "B8", m_core->dag2.b[0]).formatstr("%08X"); + state_add( SHARC_B9, "B9", m_core->dag2.b[1]).formatstr("%08X"); + state_add( SHARC_B10, "B10", m_core->dag2.b[2]).formatstr("%08X"); + state_add( SHARC_B11, "B11", m_core->dag2.b[3]).formatstr("%08X"); + state_add( SHARC_B12, "B12", m_core->dag2.b[4]).formatstr("%08X"); + state_add( SHARC_B13, "B13", m_core->dag2.b[5]).formatstr("%08X"); + state_add( SHARC_B14, "B14", m_core->dag2.b[6]).formatstr("%08X"); + state_add( SHARC_B15, "B15", m_core->dag2.b[7]).formatstr("%08X"); - state_add( STATE_GENPC, "GENPC", m_pc).noshow(); + state_add( STATE_GENPC, "GENPC", m_core->pc).noshow(); - m_icountptr = &m_icount; + m_icountptr = &m_core->icount; } void adsp21062_device::device_reset() @@ -645,27 +767,27 @@ void adsp21062_device::device_reset() { case BOOT_MODE_EPROM: { - m_dma[6].int_index = 0x20000; - m_dma[6].int_modifier = 1; - m_dma[6].int_count = 0x100; - m_dma[6].ext_index = 0x400000; - m_dma[6].ext_modifier = 1; - m_dma[6].ext_count = 0x600; - m_dma[6].control = 0x2a1; + m_core->dma[6].int_index = 0x20000; + m_core->dma[6].int_modifier = 1; + m_core->dma[6].int_count = 0x100; + m_core->dma[6].ext_index = 0x400000; + m_core->dma[6].ext_modifier = 1; + m_core->dma[6].ext_count = 0x600; + m_core->dma[6].control = 0x2a1; sharc_dma_exec(6); dma_op(6); - m_dma_op[6].timer->adjust(attotime::never, 0); + m_core->dma_op[6].timer->adjust(attotime::never, 0); break; } case BOOT_MODE_HOST: { - m_dma[6].int_index = 0x20000; - m_dma[6].int_modifier = 1; - m_dma[6].int_count = 0x100; - m_dma[6].control = 0xa1; + m_core->dma[6].int_index = 0x20000; + m_core->dma[6].int_modifier = 1; + m_core->dma[6].int_count = 0x100; + m_core->dma[6].control = 0xa1; break; } @@ -673,18 +795,18 @@ void adsp21062_device::device_reset() fatalerror("SHARC: Unimplemented boot mode %d\n", m_boot_mode); } - m_pc = 0x20004; - m_extdma_shift = 0; - m_daddr = m_pc + 1; - m_faddr = m_daddr + 1; - m_nfaddr = m_faddr+1; + m_core->pc = 0x20004; + m_core->extdma_shift = 0; + m_core->daddr = m_core->pc + 1; + m_core->faddr = m_core->daddr + 1; + m_core->nfaddr = m_core->faddr+1; - m_idle = 0; - m_stky = 0x5400000; + m_core->idle = 0; + m_core->stky = 0x5400000; - m_lstkp = 0; - m_pcstkp = 0; - m_interrupt_active = 0; + m_core->lstkp = 0; + m_core->pcstkp = 0; + m_core->interrupt_active = 0; } @@ -694,11 +816,11 @@ void adsp21062_device::execute_set_input(int irqline, int state) { if (state == ASSERT_LINE) { - m_irq_active |= 1 << (8-irqline); + m_core->irq_pending |= 1 << (8-irqline); } else { - m_irq_active &= ~(1 << (8-irqline)); + m_core->irq_pending &= ~(1 << (8-irqline)); } } else if (irqline >= SHARC_INPUT_FLAG0 && irqline <= SHARC_INPUT_FLAG3) @@ -712,9 +834,9 @@ void adsp21062_device::set_flag_input(int flag_num, int state) if (flag_num >= 0 && flag_num < 4) { // Check if flag is set to input in MODE2 (bit == 0) - if ((m_mode2 & (1 << (flag_num+15))) == 0) + if ((m_core->mode2 & (1 << (flag_num+15))) == 0) { - m_flag[flag_num] = state ? 1 : 0; + m_core->flag[flag_num] = state ? 1 : 0; } else { @@ -726,29 +848,29 @@ void adsp21062_device::set_flag_input(int flag_num, int state) void adsp21062_device::check_interrupts() { int i; - if ((m_imask & m_irq_active) && (m_mode1 & MODE1_IRPTEN) && !m_interrupt_active && - m_pc != m_delay_slot1 && m_pc != m_delay_slot2) + if ((m_core->imask & m_core->irq_pending) && (m_core->mode1 & MODE1_IRPTEN) && !m_core->interrupt_active && + m_core->pc != m_core->delay_slot1 && m_core->pc != m_core->delay_slot2) { int which = 0; for (i=0; i < 32; i++) { - if (m_irq_active & (1 << i)) + if (m_core->irq_pending & (1 << i)) { break; } which++; } - if (m_idle) + if (m_core->idle) { - PUSH_PC(m_pc+1); + PUSH_PC(m_core->pc+1); } else { - PUSH_PC(m_daddr); + PUSH_PC(m_core->daddr); } - m_irptl |= 1 << which; + m_core->irptl |= 1 << which; if (which >= 6 && which <= 8) { @@ -759,55 +881,63 @@ void adsp21062_device::check_interrupts() /* TODO: alter IMASKP */ - m_active_irq_num = which; - m_irq_active &= ~(1 << which); + m_core->active_irq_num = which; + m_core->irq_pending &= ~(1 << which); - m_interrupt_active = 1; + m_core->interrupt_active = 1; } } void adsp21062_device::execute_run() { - if (m_idle && m_irq_active == 0) +#if ENABLE_DRC + if (m_core->irq_pending != 0) { - m_icount = 0; - debugger_instruction_hook(this, m_daddr); + m_core->idle = 0; } - if (m_irq_active != 0) + execute_run_drc(); + return; +#else + if (m_core->idle && m_core->irq_pending == 0) + { + m_core->icount = 0; + debugger_instruction_hook(this, m_core->daddr); + } + if (m_core->irq_pending != 0) { check_interrupts(); - m_idle = 0; + m_core->idle = 0; } - while (m_icount > 0 && !m_idle) + while (m_core->icount > 0 && !m_core->idle) { - m_pc = m_daddr; - m_daddr = m_faddr; - m_faddr = m_nfaddr; - m_nfaddr++; + m_core->pc = m_core->daddr; + m_core->daddr = m_core->faddr; + m_core->faddr = m_core->nfaddr; + m_core->nfaddr++; - m_astat_old_old_old = m_astat_old_old; - m_astat_old_old = m_astat_old; - m_astat_old = m_astat; + m_core->astat_old_old_old = m_core->astat_old_old; + m_core->astat_old_old = m_core->astat_old; + m_core->astat_old = m_core->astat; - m_opcode = ROPCODE(m_pc); + debugger_instruction_hook(this, m_core->pc); - debugger_instruction_hook(this, m_pc); + m_core->opcode = ROPCODE(m_core->pc); // handle looping - if (m_pc == m_laddr.addr) + if (m_core->pc == m_core->laddr.addr) { - switch (m_laddr.loop_type) + switch (m_core->laddr.loop_type) { case 0: // arithmetic condition-based { - int condition = m_laddr.code; + int condition = m_core->laddr.code; { UINT32 looptop = TOP_PC(); - if (m_pc - looptop > 2) + if (m_core->pc - looptop > 2) { - m_astat = m_astat_old_old_old; + m_core->astat = m_core->astat_old_old_old; } } @@ -821,7 +951,7 @@ void adsp21062_device::execute_run() CHANGE_PC(TOP_PC()); } - m_astat = m_astat_old; + m_core->astat = m_core->astat_old; break; } case 1: // counter-based, length 1 @@ -836,9 +966,9 @@ void adsp21062_device::execute_run() } case 3: // counter-based, length >2 { - --m_lcstack[m_lstkp]; - --m_curlcntr; - if (m_curlcntr == 0) + --m_core->lcstack[m_core->lstkp]; + --m_core->curlcntr; + if (m_core->curlcntr == 0) { POP_LOOP(); POP_PC(); @@ -851,23 +981,24 @@ void adsp21062_device::execute_run() } } - (this->*m_sharc_op[(m_opcode >> 39) & 0x1ff])(); + (this->*m_sharc_op[(m_core->opcode >> 39) & 0x1ff])(); // System register latency effect - if (m_systemreg_latency_cycles > 0) + if (m_core->systemreg_latency_cycles > 0) { - --m_systemreg_latency_cycles; - if (m_systemreg_latency_cycles <= 0) + --m_core->systemreg_latency_cycles; + if (m_core->systemreg_latency_cycles <= 0) { systemreg_write_latency_effect(); } } - --m_icount; + --m_core->icount; }; +#endif } bool adsp21062_device::memory_read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value) diff --git a/src/devices/cpu/sharc/sharc.h b/src/devices/cpu/sharc/sharc.h index c658b3a9800..671076a87f7 100644 --- a/src/devices/cpu/sharc/sharc.h +++ b/src/devices/cpu/sharc/sharc.h @@ -5,6 +5,8 @@ #ifndef __SHARC_H__ #define __SHARC_H__ +#include "cpu/drcfe.h" +#include "cpu/drcuml.h" #define SHARC_INPUT_FLAG0 3 #define SHARC_INPUT_FLAG1 4 @@ -21,7 +23,7 @@ enum SHARC_BOOT_MODE }; -struct SHARC_DAG +struct alignas(16) SHARC_DAG { UINT32 i[8]; UINT32 m[8]; @@ -71,12 +73,73 @@ struct SHARC_DMA_OP }; +// STKY flags +#define AUS 0x1 /* ALU floating-point underflow */ +#define AVS 0x2 /* ALU floating-point overflow */ +#define AOS 0x4 /* ALU fixed-point overflow */ +#define AIS 0x20 /* ALU floating-point invalid operation */ + +// MODE1 flags +#define MODE1_BR8 0x1 /* Bit-reverse for I8 */ +#define MODE1_BR0 0x2 /* Bit-reverse for I0 */ +#define MODE1_SRCU 0x4 /* Alternate register select for computational units */ +#define MODE1_SRD1H 0x8 /* DAG alternate register select (7-4) */ +#define MODE1_SRD1L 0x10 /* DAG alternate register select (3-0) */ +#define MODE1_SRD2H 0x20 /* DAG alternate register select (15-12) */ +#define MODE1_SRD2L 0x40 /* DAG alternate register select (11-8) */ +#define MODE1_SRRFH 0x80 /* Register file alternate select for R(15-8) */ +#define MODE1_SRRFL 0x400 /* Register file alternate select for R(7-0) */ +#define MODE1_NESTM 0x800 /* Interrupt nesting enable */ +#define MODE1_IRPTEN 0x1000 /* Global interrupt enable */ +#define MODE1_ALUSAT 0x2000 /* Enable ALU fixed-point saturation */ +#define MODE1_SSE 0x4000 /* Enable short word sign extension */ +#define MODE1_TRUNCATE 0x8000 /* (1) Floating-point truncation / (0) round to nearest */ +#define MODE1_RND32 0x10000 /* (1) 32-bit floating-point rounding / (0) 40-bit rounding */ +#define MODE1_CSEL 0x60000 /* CSelect */ + +// MODE2 flags +#define MODE2_IRQ0E 0x1 /* IRQ0 (1) Edge sens. / (0) Level sens. */ +#define MODE2_IRQ1E 0x2 /* IRQ1 (1) Edge sens. / (0) Level sens. */ +#define MODE2_IRQ2E 0x4 /* IRQ2 (1) Edge sens. / (0) Level sens. */ +#define MODE2_CADIS 0x10 /* Cache disable */ +#define MODE2_TIMEN 0x20 /* Timer enable */ +#define MODE2_BUSLK 0x40 /* External bus lock */ +#define MODE2_FLG0O 0x8000 /* FLAG0 (1) Output / (0) Input */ +#define MODE2_FLG1O 0x10000 /* FLAG1 (1) Output / (0) Input */ +#define MODE2_FLG2O 0x20000 /* FLAG2 (1) Output / (0) Input */ +#define MODE2_FLG3O 0x40000 /* FLAG3 (1) Output / (0) Input */ +#define MODE2_CAFRZ 0x80000 /* Cache freeze */ + + +#define SIGN_EXTEND6(x) (((x) & 0x20) ? (0xffffffc0 | (x)) : (x)) +#define SIGN_EXTEND24(x) (((x) & 0x800000) ? (0xff000000 | (x)) : (x)) +#define MAKE_EXTRACT_MASK(start_bit, length) ((0xffffffff << start_bit) & (((UINT32)0xffffffff) >> (32 - (start_bit + length)))) + +#define OP_USERFLAG_COUNTER_LOOP 0x00000001 +#define OP_USERFLAG_COND_LOOP 0x00000002 +#define OP_USERFLAG_COND_FIELD 0x0000003c +#define OP_USERFLAG_COND_FIELD_SHIFT 2 +#define OP_USERFLAG_ASTAT_DELAY_COPY_AZ 0x00001000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_AN 0x00002000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_AC 0x00004000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_AV 0x00008000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_MV 0x00010000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_MN 0x00020000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_SV 0x00040000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_SZ 0x00080000 +#define OP_USERFLAG_ASTAT_DELAY_COPY_BTF 0x00100000 +#define OP_USERFLAG_ASTAT_DELAY_COPY 0x001ff000 + + #define MCFG_SHARC_BOOT_MODE(boot_mode) \ adsp21062_device::set_boot_mode(*device, boot_mode); +class sharc_frontend; class adsp21062_device : public cpu_device { + friend class sharc_frontend; + public: // construction/destruction adsp21062_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock); @@ -91,6 +154,92 @@ public: TIMER_CALLBACK_MEMBER(sharc_iop_delayed_write_callback); TIMER_CALLBACK_MEMBER(sharc_dma_callback); + void sharc_cfunc_unimplemented(); + void sharc_cfunc_read_iop(); + void sharc_cfunc_write_iop(); + void sharc_cfunc_pcstack_overflow(); + void sharc_cfunc_pcstack_underflow(); + void sharc_cfunc_loopstack_overflow(); + void sharc_cfunc_loopstack_underflow(); + void sharc_cfunc_statusstack_overflow(); + void sharc_cfunc_statusstack_underflow(); + + void sharc_cfunc_unimplemented_compute(); + void sharc_cfunc_unimplemented_shiftimm(); + void sharc_cfunc_write_snoop(); + + enum ASTAT_FLAGS + { + // ASTAT flags + AZ = 0x1, /* ALU result zero */ + AV = 0x2, /* ALU overflow */ + AN = 0x4, /* ALU result negative */ + AC = 0x8, /* ALU fixed-point carry */ + AS = 0x10, /* ALU X input sign */ + AI = 0x20, /* ALU floating-point invalid operation */ + MN = 0x40, /* Multiplier result negative */ + MV = 0x80, /* Multiplier overflow */ + MU = 0x100, /* Multiplier underflow */ + MI = 0x200, /* Multiplier floating-point invalid operation */ + AF = 0x400, + SV = 0x800, /* Shifter overflow */ + SZ = 0x1000, /* Shifter result zero */ + SS = 0x2000, /* Shifter input sign */ + BTF = 0x40000, /* Bit Test Flag */ + FLG0 = 0x80000, /* FLAG0 */ + FLG1 = 0x100000, /* FLAG1 */ + FLG2 = 0x200000, /* FLAG2 */ + FLG3 = 0x400000 /* FLAG3 */ + }; + + enum ASTAT_SHIFT + { + AZ_SHIFT = 0, + AV_SHIFT = 1, + AN_SHIFT = 2, + AC_SHIFT = 3, + AS_SHIFT = 4, + AI_SHIFT = 5, + MN_SHIFT = 6, + MV_SHIFT = 7, + MU_SHIFT = 8, + MI_SHIFT = 9, + AF_SHIFT = 10, + SV_SHIFT = 11, + SZ_SHIFT = 12, + SS_SHIFT = 13, + BTF_SHIFT = 18, + FLG0_SHIFT = 19, + FLG1_SHIFT = 20, + FLG2_SHIFT = 21, + FLG3_SHIFT = 22 + }; + + enum MODE1_DELAY_MODE + { + MODE1_WRITE_IMM, + MODE1_WRITE_REG, + MODE1_SET, + MODE1_CLEAR, + MODE1_TOGGLE, + }; + + enum MEM_ACCESSOR_TYPE + { + MEM_ACCESSOR_PM_READ48, + MEM_ACCESSOR_PM_WRITE48, + MEM_ACCESSOR_PM_READ32, + MEM_ACCESSOR_PM_WRITE32, + MEM_ACCESSOR_DM_READ32, + MEM_ACCESSOR_DM_WRITE32 + }; + + enum + { + EXCEPTION_INTERRUPT = 0, + EXCEPTION_COUNT + }; + protected: // device-level overrides virtual void device_start() override; @@ -109,10 +258,12 @@ protected: virtual bool memory_readop(offs_t offset, int size, UINT64 &value) override; // device_disasm_interface overrides - virtual UINT32 disasm_min_opcode_bytes() const override { return 1; } - virtual UINT32 disasm_max_opcode_bytes() const override { return 40; } + virtual UINT32 disasm_min_opcode_bytes() const override { return 6; } + virtual UINT32 disasm_max_opcode_bytes() const override { return 6; } virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) override; + direct_read_data *m_direct; + private: address_space_config m_program_config; address_space_config m_data_config; @@ -126,94 +277,178 @@ private: }; static const SHARC_OP s_sharc_opcode_table[]; - UINT32 m_pc; - SHARC_REG m_r[16]; - SHARC_REG m_reg_alt[16]; - UINT64 m_mrf; - UINT64 m_mrb; - - UINT32 m_pcstack[32]; - UINT32 m_lcstack[6]; - UINT32 m_lastack[6]; - UINT32 m_lstkp; - - UINT32 m_faddr; - UINT32 m_daddr; - UINT32 m_pcstk; - UINT32 m_pcstkp; - SHARC_LADDR m_laddr; - UINT32 m_curlcntr; - UINT32 m_lcntr; - UINT8 m_extdma_shift; - - /* Data Address Generator (DAG) */ - SHARC_DAG m_dag1; // (DM bus) - SHARC_DAG m_dag2; // (PM bus) - SHARC_DAG m_dag1_alt; - SHARC_DAG m_dag2_alt; - - SHARC_DMA_REGS m_dma[12]; - - /* System registers */ - UINT32 m_mode1; - UINT32 m_mode2; - UINT32 m_astat; - UINT32 m_stky; - UINT32 m_irptl; - UINT32 m_imask; - UINT32 m_imaskp; - UINT32 m_ustat1; - UINT32 m_ustat2; - - UINT32 m_flag[4]; - - UINT32 m_syscon; - UINT32 m_sysstat; - - struct + struct ASTAT_DRC { - UINT32 mode1; - UINT32 astat; - } m_status_stack[5]; - INT32 m_status_stkp; + union + { + struct + { + UINT32 az; + UINT32 av; + UINT32 an; + UINT32 ac; + UINT32 as; + UINT32 ai; + UINT32 mn; + UINT32 mv; + UINT32 mu; + UINT32 mi; + UINT32 sv; + UINT32 sz; + UINT32 ss; + UINT32 btf; + UINT32 af; + UINT32 cacc; + }; + UINT64 flags64[8]; + }; + }; - UINT64 m_px; + struct alignas(16) sharc_internal_state + { + SHARC_REG r[16]; + SHARC_REG reg_alt[16]; + + UINT32 pc; + UINT64 mrf; + UINT64 mrb; + + UINT32 pcstack[32]; + UINT32 lcstack[6]; + UINT32 lastack[6]; + UINT32 lstkp; + + UINT32 faddr; + UINT32 daddr; + UINT32 pcstk; + UINT32 pcstkp; + SHARC_LADDR laddr; + UINT32 curlcntr; + UINT32 lcntr; + UINT8 extdma_shift; + + /* Data Address Generator (DAG) */ + SHARC_DAG dag1; // (DM bus) + SHARC_DAG dag2; // (PM bus) + SHARC_DAG dag1_alt; + SHARC_DAG dag2_alt; + + SHARC_DMA_REGS dma[12]; + + /* System registers */ + UINT32 mode1; + UINT32 mode2; + UINT32 astat; + UINT32 stky; + UINT32 irptl; + UINT32 imask; + UINT32 imaskp; + UINT32 ustat1; + UINT32 ustat2; + + UINT32 flag[4]; + + UINT32 syscon; + UINT32 sysstat; + + struct + { + UINT32 mode1; + UINT32 astat; + } status_stack[5]; + INT32 status_stkp; + + UINT64 px; + + int icount; + UINT64 opcode; + + UINT32 nfaddr; + + INT32 idle; + INT32 irq_pending; + INT32 active_irq_num; + + SHARC_DMA_OP dma_op[12]; + UINT32 dma_status; + + INT32 interrupt_active; + + UINT32 iop_delayed_reg; + UINT32 iop_delayed_data; + emu_timer *delayed_iop_timer; + + UINT32 delay_slot1, delay_slot2; + + INT32 systemreg_latency_cycles; + INT32 systemreg_latency_reg; + UINT32 systemreg_latency_data; + UINT32 systemreg_previous_data; + + UINT32 astat_old; + UINT32 astat_old_old; + UINT32 astat_old_old_old; + + UINT32 arg0; + UINT32 arg1; + UINT32 arg2; + UINT32 arg3; + + UINT64 arg64; + UINT32 mode1_delay_data; + + ASTAT_DRC astat_drc; + ASTAT_DRC astat_drc_copy; + ASTAT_DRC astat_delay_copy; + UINT32 dreg_temp; + UINT32 jmpdest; + + float fp0; + float fp1; + + UINT32 force_recompile; + }; + + sharc_internal_state* m_core; + + SHARC_BOOT_MODE m_boot_mode; + + // UML stuff + drc_cache m_cache; + std::unique_ptr m_drcuml; + std::unique_ptr m_drcfe; + uml::parameter m_regmap[16]; + + uml::code_handle *m_entry; /* entry point */ + uml::code_handle *m_nocode; /* nocode exception handler */ + uml::code_handle *m_out_of_cycles; /* out of cycles exception handler */ + uml::code_handle *m_pm_read48; + uml::code_handle *m_pm_write48; + uml::code_handle *m_pm_read32; + uml::code_handle *m_pm_write32; + uml::code_handle *m_dm_read32; + uml::code_handle *m_dm_write32; + uml::code_handle *m_push_pc; + uml::code_handle *m_pop_pc; + uml::code_handle *m_push_loop; + uml::code_handle *m_pop_loop; + uml::code_handle *m_push_status; + uml::code_handle *m_pop_status; + uml::code_handle *m_exception[EXCEPTION_COUNT]; // exception handlers + uml::code_handle *m_swap_dag1_0_3; + uml::code_handle *m_swap_dag1_4_7; + uml::code_handle *m_swap_dag2_0_3; + uml::code_handle *m_swap_dag2_4_7; + uml::code_handle *m_swap_r0_7; + uml::code_handle *m_swap_r8_15; + + bool m_cache_dirty; UINT16 *m_internal_ram_block0, *m_internal_ram_block1; address_space *m_program; address_space *m_data; opcode_func m_sharc_op[512]; - int m_icount; - UINT64 m_opcode; - - UINT32 m_nfaddr; - - INT32 m_idle; - INT32 m_irq_active; - INT32 m_active_irq_num; - - SHARC_BOOT_MODE m_boot_mode; - - SHARC_DMA_OP m_dma_op[12]; - UINT32 m_dma_status; - - INT32 m_interrupt_active; - - UINT32 m_iop_delayed_reg; - UINT32 m_iop_delayed_data; - emu_timer *m_delayed_iop_timer; - - UINT32 m_delay_slot1, m_delay_slot2; - - INT32 m_systemreg_latency_cycles; - INT32 m_systemreg_latency_reg; - UINT32 m_systemreg_latency_data; - UINT32 m_systemreg_previous_data; - - UINT32 m_astat_old; - UINT32 m_astat_old_old; - UINT32 m_astat_old_old_old; UINT16 m_internal_ram[2 * 0x10000]; // 2x 128KB @@ -349,6 +584,59 @@ private: inline void compute_fmul_dual_fadd_fsub(int fm, int fxm, int fym, int fa, int fs, int fxa, int fya); void build_opcode_table(); + /* internal compiler state */ + struct compiler_state + { + UINT32 cycles; /* accumulated cycles */ + UINT8 checkints; /* need to check interrupts before next instruction */ + uml::code_label labelnum; /* index for local labels */ + struct + { + int counter; + int mode; + UINT32 data; + } mode1_delay; + }; + + void execute_run_drc(); + void flush_cache(); + void compile_block(offs_t pc); + void alloc_handle(drcuml_state *drcuml, uml::code_handle **handleptr, const char *name); + void static_generate_entry_point(); + void static_generate_nocode_handler(); + void static_generate_out_of_cycles(); + void static_generate_memory_accessor(MEM_ACCESSOR_TYPE type, const char *name, uml::code_handle *&handleptr); + void static_generate_exception(UINT8 exception, const char *name); + void static_generate_push_pc(); + void static_generate_pop_pc(); + void static_generate_push_loop(); + void static_generate_pop_loop(); + void static_generate_push_status(); + void static_generate_pop_status(); + void static_generate_mode1_ops(); + void load_fast_iregs(drcuml_block *block); + void save_fast_iregs(drcuml_block *block); + void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); + void generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, int allow_exception); + int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); + void generate_unimplemented_compute(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); + void generate_compute(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); + void generate_if_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int condition, int skip_label); + void generate_do_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int condition, int skip_label, ASTAT_DRC &astat); + void generate_shift_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int data, int shiftop, int rn, int rx); + void generate_call(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, bool delayslot); + void generate_jump(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, bool delayslot, bool loopabort, bool clearint); + void generate_write_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data); + void generate_set_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data); + void generate_clear_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data); + void generate_toggle_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data); + void generate_read_ureg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int ureg, bool has_compute); + void generate_write_ureg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int ureg, bool imm, UINT32 data); + void generate_update_circular_buffer(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int g, int i); + void generate_astat_copy(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc); + + bool if_condition_always_true(int condition); + UINT32 do_condition_astat_bits(int condition); }; diff --git a/src/devices/cpu/sharc/sharcdma.hxx b/src/devices/cpu/sharc/sharcdma.hxx index eacede6fb5b..9321dd88b05 100644 --- a/src/devices/cpu/sharc/sharcdma.hxx +++ b/src/devices/cpu/sharc/sharcdma.hxx @@ -21,80 +21,80 @@ void adsp21062_device::schedule_chained_dma_op(int channel, UINT32 dma_chain_ptr UINT32 ext_modifier = dm_read32(op_ptr - 6); UINT32 ext_count = dm_read32(op_ptr - 7); - if (m_dma_op[channel].active) + if (m_core->dma_op[channel].active) { - fatalerror("schedule_chained_dma_op: DMA operation already scheduled at %08X!\n", m_pc); + fatalerror("schedule_chained_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc); } if (chained_direction) // Transmit to external { - m_dma_op[channel].dst = ext_index; - m_dma_op[channel].dst_modifier = ext_modifier; - m_dma_op[channel].dst_count = ext_count; - m_dma_op[channel].src = int_index; - m_dma_op[channel].src_modifier = int_modifier; - m_dma_op[channel].src_count = int_count; + m_core->dma_op[channel].dst = ext_index; + m_core->dma_op[channel].dst_modifier = ext_modifier; + m_core->dma_op[channel].dst_count = ext_count; + m_core->dma_op[channel].src = int_index; + m_core->dma_op[channel].src_modifier = int_modifier; + m_core->dma_op[channel].src_count = int_count; } else // Receive from external { - m_dma_op[channel].src = ext_index; - m_dma_op[channel].src_modifier = ext_modifier; - m_dma_op[channel].src_count = ext_count; - m_dma_op[channel].dst = int_index; - m_dma_op[channel].dst_modifier = int_modifier; - m_dma_op[channel].dst_count = int_count; + m_core->dma_op[channel].src = ext_index; + m_core->dma_op[channel].src_modifier = ext_modifier; + m_core->dma_op[channel].src_count = ext_count; + m_core->dma_op[channel].dst = int_index; + m_core->dma_op[channel].dst_modifier = int_modifier; + m_core->dma_op[channel].dst_count = int_count; } - m_dma_op[channel].pmode = 0; - m_dma_op[channel].chain_ptr = chain_ptr; - m_dma_op[channel].chained_direction = chained_direction; + m_core->dma_op[channel].pmode = 0; + m_core->dma_op[channel].chain_ptr = chain_ptr; + m_core->dma_op[channel].chained_direction = chained_direction; - m_dma_op[channel].active = true; + m_core->dma_op[channel].active = true; - int cycles = m_dma_op[channel].src_count / 4; - m_dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); + int cycles = m_core->dma_op[channel].src_count / 4; + m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); // enable busy flag - m_dma_status |= (1 << channel); + m_core->dma_status |= (1 << channel); } void adsp21062_device::schedule_dma_op(int channel, UINT32 src, UINT32 dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode) { - if (m_dma_op[channel].active) + if (m_core->dma_op[channel].active) { - fatalerror("schedule_dma_op: DMA operation already scheduled at %08X!\n", m_pc); + fatalerror("schedule_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc); } - m_dma_op[channel].src = src; - m_dma_op[channel].dst = dst; - m_dma_op[channel].src_modifier = src_modifier; - m_dma_op[channel].dst_modifier = dst_modifier; - m_dma_op[channel].src_count = src_count; - m_dma_op[channel].dst_count = dst_count; - m_dma_op[channel].pmode = pmode; - m_dma_op[channel].chain_ptr = 0; + m_core->dma_op[channel].src = src; + m_core->dma_op[channel].dst = dst; + m_core->dma_op[channel].src_modifier = src_modifier; + m_core->dma_op[channel].dst_modifier = dst_modifier; + m_core->dma_op[channel].src_count = src_count; + m_core->dma_op[channel].dst_count = dst_count; + m_core->dma_op[channel].pmode = pmode; + m_core->dma_op[channel].chain_ptr = 0; - m_dma_op[channel].active = true; + m_core->dma_op[channel].active = true; int cycles = src_count / 4; - m_dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); + m_core->dma_op[channel].timer->adjust(cycles_to_attotime(cycles), channel); // enable busy flag - m_dma_status |= (1 << channel); + m_core->dma_status |= (1 << channel); } void adsp21062_device::dma_op(int channel) { int i; - UINT32 src = m_dma_op[channel].src; - UINT32 dst = m_dma_op[channel].dst; - int src_modifier = m_dma_op[channel].src_modifier; - int dst_modifier = m_dma_op[channel].dst_modifier; - int src_count = m_dma_op[channel].src_count; - //int dst_count = m_dma_op[channel].dst_count; - int pmode = m_dma_op[channel].pmode; + UINT32 src = m_core->dma_op[channel].src; + UINT32 dst = m_core->dma_op[channel].dst; + int src_modifier = m_core->dma_op[channel].src_modifier; + int dst_modifier = m_core->dma_op[channel].dst_modifier; + int src_count = m_core->dma_op[channel].src_count; + //int dst_count = m_core->dma_op[channel].dst_count; + int pmode = m_core->dma_op[channel].pmode; - //printf("dma_op: %08X, %08X, %08X, %08X, %08X, %08X, %d\n", src, dst, src_modifier, dst_modifier, src_count, dst_count, pmode); + //printf("dma_op: %08X, %08X, %08X, %08X, %08X, %d\n", src, dst, src_modifier, dst_modifier, src_count, pmode); switch (pmode) { @@ -148,19 +148,19 @@ void adsp21062_device::dma_op(int channel) if (channel == 6) { - m_irptl |= (1 << (channel+10)); + m_core->irptl |= (1 << (channel+10)); /* DMA interrupt */ - if (m_imask & (1 << (channel+10))) + if (m_core->imask & (1 << (channel+10))) { - m_irq_active |= 1 << (channel+10); + m_core->irq_pending |= 1 << (channel+10); } } // clear busy flag - m_dma_status &= ~(1 << channel); + m_core->dma_status &= ~(1 << channel); - m_dma_op[channel].active = false; + m_core->dma_op[channel].active = false; } void adsp21062_device::sharc_dma_exec(int channel) @@ -170,16 +170,16 @@ void adsp21062_device::sharc_dma_exec(int channel) UINT32 src_modifier, dst_modifier; int chen, tran, dtype, pmode, /*mswf, master,*/ ishake, intio/*, ext, flsh*/; - chen = (m_dma[channel].control >> 1) & 0x1; - tran = (m_dma[channel].control >> 2) & 0x1; - dtype = (m_dma[channel].control >> 5) & 0x1; - pmode = (m_dma[channel].control >> 6) & 0x3; - //mswf = (m_dma[channel].control >> 8) & 0x1; - //master = (m_dma[channel].control >> 9) & 0x1; - ishake = (m_dma[channel].control >> 10) & 0x1; - intio = (m_dma[channel].control >> 11) & 0x1; - //ext = (m_dma[channel].control >> 12) & 0x1; - //flsh = (m_dma[channel].control >> 13) & 0x1; + chen = (m_core->dma[channel].control >> 1) & 0x1; + tran = (m_core->dma[channel].control >> 2) & 0x1; + dtype = (m_core->dma[channel].control >> 5) & 0x1; + pmode = (m_core->dma[channel].control >> 6) & 0x3; + //mswf = (m_core->dma[channel].control >> 8) & 0x1; + //master = (m_core->dma[channel].control >> 9) & 0x1; + ishake = (m_core->dma[channel].control >> 10) & 0x1; + intio = (m_core->dma[channel].control >> 11) & 0x1; + //ext = (m_core->dma[channel].control >> 12) & 0x1; + //flsh = (m_core->dma[channel].control >> 13) & 0x1; if (ishake) fatalerror("SHARC: dma_exec: handshake not supported\n"); @@ -189,7 +189,7 @@ void adsp21062_device::sharc_dma_exec(int channel) if (chen) // Chained DMA { - UINT32 dma_chain_ptr = m_dma[channel].chain_ptr & 0x1ffff; + UINT32 dma_chain_ptr = m_core->dma[channel].chain_ptr & 0x1ffff; schedule_chained_dma_op(channel, dma_chain_ptr, tran); } @@ -197,21 +197,21 @@ void adsp21062_device::sharc_dma_exec(int channel) { if (tran) // Transmit to external { - dst = m_dma[channel].ext_index; - dst_modifier = m_dma[channel].ext_modifier; - dst_count = m_dma[channel].ext_count; - src = (m_dma[channel].int_index & 0x1ffff) | 0x20000; - src_modifier = m_dma[channel].int_modifier; - src_count = m_dma[channel].int_count; + dst = m_core->dma[channel].ext_index; + dst_modifier = m_core->dma[channel].ext_modifier; + dst_count = m_core->dma[channel].ext_count; + src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; + src_modifier = m_core->dma[channel].int_modifier; + src_count = m_core->dma[channel].int_count; } else // Receive from external { - src = m_dma[channel].ext_index; - src_modifier = m_dma[channel].ext_modifier; - src_count = m_dma[channel].ext_count; - dst = (m_dma[channel].int_index & 0x1ffff) | 0x20000; - dst_modifier = m_dma[channel].int_modifier; - dst_count = m_dma[channel].int_count; + src = m_core->dma[channel].ext_index; + src_modifier = m_core->dma[channel].ext_modifier; + src_count = m_core->dma[channel].ext_count; + dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000; + dst_modifier = m_core->dma[channel].int_modifier; + dst_count = m_core->dma[channel].int_count; } if (dtype) @@ -228,19 +228,19 @@ TIMER_CALLBACK_MEMBER(adsp21062_device::sharc_dma_callback) { int channel = param; - m_dma_op[channel].timer->adjust(attotime::never, 0); + m_core->dma_op[channel].timer->adjust(attotime::never, 0); - m_irptl |= (1 << (channel+10)); + m_core->irptl |= (1 << (channel+10)); // DMA interrupt - if (m_imask & (1 << (channel+10))) + if (m_core->imask & (1 << (channel+10))) { - m_irq_active |= 1 << (channel+10); + m_core->irq_pending |= 1 << (channel+10); } dma_op(channel); - if (m_dma_op[channel].chain_ptr != 0) + if (m_core->dma_op[channel].chain_ptr != 0) { - schedule_chained_dma_op(channel, m_dma_op[channel].chain_ptr, m_dma_op[channel].chained_direction); + schedule_chained_dma_op(channel, m_core->dma_op[channel].chain_ptr, m_core->dma_op[channel].chained_direction); } } diff --git a/src/devices/cpu/sharc/sharcdrc.cpp b/src/devices/cpu/sharc/sharcdrc.cpp new file mode 100644 index 00000000000..2f7f3e0fbcb --- /dev/null +++ b/src/devices/cpu/sharc/sharcdrc.cpp @@ -0,0 +1,4909 @@ +// license:BSD-3-Clause +// copyright-holders:Ville Linde + +/****************************************************************************** + + SHARC UML recompiler core + +******************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "sharc.h" +#include "sharcfe.h" +#include "cpu/drcfe.h" +#include "cpu/drcuml.h" +#include "cpu/drcumlsh.h" + +using namespace uml; + +#define USE_SWAPDQ 0 +#define WRITE_SNOOP 0 + + +// map variables +#define MAPVAR_PC M0 +#define MAPVAR_CYCLES M1 + +// exit codes +#define EXECUTE_OUT_OF_CYCLES 0 +#define EXECUTE_MISSING_CODE 1 +#define EXECUTE_UNMAPPED_CODE 2 +#define EXECUTE_RESET_CACHE 3 + + +#define REG(reg) m_regmap[reg] +#define DM_I(reg) mem(&m_core->dag1.i[reg]) +#define DM_M(reg) mem(&m_core->dag1.m[reg]) +#define DM_L(reg) mem(&m_core->dag1.l[reg]) +#define DM_B(reg) mem(&m_core->dag1.b[reg]) +#define PM_I(reg) mem(&m_core->dag2.i[reg]) +#define PM_M(reg) mem(&m_core->dag2.m[reg]) +#define PM_L(reg) mem(&m_core->dag2.l[reg]) +#define PM_B(reg) mem(&m_core->dag2.b[reg]) +#define ASTAT_AZ mem(&m_core->astat_drc.az) +#define ASTAT_AV mem(&m_core->astat_drc.av) +#define ASTAT_AN mem(&m_core->astat_drc.an) +#define ASTAT_AC mem(&m_core->astat_drc.ac) +#define ASTAT_AS mem(&m_core->astat_drc.as) +#define ASTAT_AI mem(&m_core->astat_drc.ai) +#define ASTAT_AF mem(&m_core->astat_drc.af) +#define ASTAT_MN mem(&m_core->astat_drc.mn) +#define ASTAT_MV mem(&m_core->astat_drc.mv) +#define ASTAT_MU mem(&m_core->astat_drc.mu) +#define ASTAT_MI mem(&m_core->astat_drc.mi) +#define ASTAT_SV mem(&m_core->astat_drc.sv) +#define ASTAT_SZ mem(&m_core->astat_drc.sz) +#define ASTAT_SS mem(&m_core->astat_drc.ss) +#define ASTAT_BTF mem(&m_core->astat_drc.btf) +#define FLAG0 mem(&m_core->flag[0]) +#define FLAG1 mem(&m_core->flag[1]) +#define FLAG2 mem(&m_core->flag[2]) +#define FLAG3 mem(&m_core->flag[3]) +#define CURLCNTR mem(&m_core->curlcntr) +#define LCNTR mem(&m_core->lcntr) +#define PCSTK mem(&m_core->pcstk) +#define PCSTKP mem(&m_core->pcstkp) +#define STKY mem(&m_core->stky) +#define LSTKP mem(&m_core->lstkp) +#define USTAT1 mem(&m_core->ustat1) +#define USTAT2 mem(&m_core->ustat2) +#define IRPTL mem(&m_core->irptl) +#define MODE1 mem(&m_core->mode1) +#define MODE2 mem(&m_core->mode2) +#define IMASK mem(&m_core->imask) +#define IMASKP mem(&m_core->imaskp) +#define MRF mem(&m_core->mrf) +#define MRB mem(&m_core->mrb) + +#define AZ_CALC_REQUIRED ((desc->regreq[0] & 0x00010000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AV_CALC_REQUIRED ((desc->regreq[0] & 0x00020000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AN_CALC_REQUIRED ((desc->regreq[0] & 0x00040000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AC_CALC_REQUIRED ((desc->regreq[0] & 0x00080000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AS_CALC_REQUIRED ((desc->regreq[0] & 0x00100000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AI_CALC_REQUIRED ((desc->regreq[0] & 0x00200000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define MN_CALC_REQUIRED ((desc->regreq[0] & 0x00400000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define MV_CALC_REQUIRED ((desc->regreq[0] & 0x00800000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define MU_CALC_REQUIRED ((desc->regreq[0] & 0x01000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define MI_CALC_REQUIRED ((desc->regreq[0] & 0x02000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define SV_CALC_REQUIRED ((desc->regreq[0] & 0x04000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define SZ_CALC_REQUIRED ((desc->regreq[0] & 0x08000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define SS_CALC_REQUIRED ((desc->regreq[0] & 0x10000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define BTF_CALC_REQUIRED ((desc->regreq[0] & 0x20000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) +#define AF_CALC_REQUIRED ((desc->regreq[0] & 0x40000000) || desc->flags & OPFLAG_IN_DELAY_SLOT) + + +#define IRAM_BLOCK0_START 0x20000 +#define IRAM_BLOCK0_END 0x27fff +#define IRAM_BLOCK1_START 0x28000 +#define IRAM_BLOCK1_END 0x3ffff +#define IRAM_SHORT_BLOCK0_START 0x40000 +#define IRAM_SHORT_BLOCK0_END 0x4ffff +#define IRAM_SHORT_BLOCK1_START 0x50000 +#define IRAM_SHORT_BLOCK1_END 0x7ffff +#define IOP_REGISTER_START 0x00000 +#define IOP_REGISTER_END 0x000ff +#define IRAM_END 0x7ffff + + +inline void adsp21062_device::alloc_handle(drcuml_state *drcuml, code_handle **handleptr, const char *name) +{ + if (*handleptr == nullptr) + *handleptr = drcuml->handle_alloc(name); +} + + + +static void cfunc_unimplemented(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_unimplemented(); +} + +static void cfunc_read_iop(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_read_iop(); +} + +static void cfunc_write_iop(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_write_iop(); +} + +static void cfunc_pcstack_overflow(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_pcstack_overflow(); +} + +static void cfunc_pcstack_underflow(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_pcstack_underflow(); +} + +static void cfunc_loopstack_overflow(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_loopstack_overflow(); +} + +static void cfunc_loopstack_underflow(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_loopstack_underflow(); +} + +static void cfunc_statusstack_overflow(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_statusstack_overflow(); +} + +static void cfunc_statusstack_underflow(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_statusstack_underflow(); +} + +static void cfunc_unimplemented_compute(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_unimplemented_compute(); +} + +static void cfunc_unimplemented_shiftimm(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_unimplemented_shiftimm(); +} + + +#if WRITE_SNOOP +void adsp21062_device::sharc_cfunc_write_snoop() +{ + printf("Write %08X to %08X at %08X\n", m_core->arg0, m_core->arg1, m_core->arg2); +} + +static void cfunc_write_snoop(void *param) +{ + adsp21062_device *sharc = (adsp21062_device *)param; + sharc->sharc_cfunc_write_snoop(); +} +#endif + + +void adsp21062_device::sharc_cfunc_unimplemented() +{ + UINT64 op = m_core->arg64; + fatalerror("PC=%08X: Unimplemented op %04X%08X\n", m_core->pc, (UINT32)(op >> 32), (UINT32)(op)); +} + +void adsp21062_device::sharc_cfunc_unimplemented_compute() +{ + UINT64 op = m_core->arg64; + fatalerror("PC=%08X: Unimplemented compute %04X%08X\n", m_core->pc, (UINT32)(op >> 32), (UINT32)(op)); +} + +void adsp21062_device::sharc_cfunc_unimplemented_shiftimm() +{ + UINT64 op = m_core->arg64; + fatalerror("PC=%08X: Unimplemented shiftimm %04X%08X\n", m_core->pc, (UINT32)(op >> 32), (UINT32)(op)); +} + +void adsp21062_device::sharc_cfunc_read_iop() +{ + m_core->arg1 = sharc_iop_r(m_core->arg0); +} + +void adsp21062_device::sharc_cfunc_write_iop() +{ + sharc_iop_w(m_core->arg0, m_core->arg1); +} + +void adsp21062_device::sharc_cfunc_pcstack_overflow() +{ + fatalerror("SHARC: PCStack overflow"); +} + +void adsp21062_device::sharc_cfunc_pcstack_underflow() +{ + fatalerror("SHARC: PCStack underflow"); +} + +void adsp21062_device::sharc_cfunc_loopstack_overflow() +{ + fatalerror("SHARC: Loop Stack overflow"); +} + +void adsp21062_device::sharc_cfunc_loopstack_underflow() +{ + fatalerror("SHARC: Loop Stack underflow"); +} + +void adsp21062_device::sharc_cfunc_statusstack_overflow() +{ + fatalerror("SHARC: Status Stack overflow"); +} + +void adsp21062_device::sharc_cfunc_statusstack_underflow() +{ + fatalerror("SHARC: Status Stack underflow"); +} + + +bool adsp21062_device::if_condition_always_true(int condition) +{ + if (condition == 0x1f || condition == 0x1e) + return true; + else + return false; +} + +UINT32 adsp21062_device::do_condition_astat_bits(int condition) +{ + UINT32 r = 0; + switch (condition) + { + case 0x00: r = AZ; break; // EQ + case 0x01: r = AZ | AN; break; // LT + case 0x02: r = AZ | AN; break; // LE + case 0x03: r = AC; break; // AC + case 0x04: r = AV; break; // AV + case 0x05: r = MV; break; // MV + case 0x06: r = MN; break; // MS + case 0x07: r = SV; break; // SV + case 0x08: r = SZ; break; // SZ + case 0x0d: r = BTF; break; // TF + case 0x10: r = AZ; break; // NOT EQUAL + case 0x11: r = AZ | AN; break; // GE + case 0x12: r = AZ | AN; break; // GT + case 0x13: r = AC; break; // NOT AC + case 0x14: r = AV; break; // NOT AV + case 0x15: r = MV; break; // NOT MV + case 0x16: r = MN; break; // NOT MS + case 0x17: r = SV; break; // NOT SV + case 0x18: r = SZ; break; // NOT SZ + case 0x1d: r = BTF; break; // NOT TF + } + + return r; +} + + +/*------------------------------------------------- +load_fast_iregs - load any fast integer +registers +-------------------------------------------------*/ + +inline void adsp21062_device::load_fast_iregs(drcuml_block *block) +{ + int regnum; + + for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) + { + if (m_regmap[regnum].is_int_register()) + { + UML_MOV(block, ireg(m_regmap[regnum].ireg() - REG_I0), mem(&m_core->r[regnum])); + } + } +} + + +/*------------------------------------------------- +save_fast_iregs - save any fast integer +registers +-------------------------------------------------*/ + +void adsp21062_device::save_fast_iregs(drcuml_block *block) +{ + int regnum; + + for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++) + { + if (m_regmap[regnum].is_int_register()) + { + UML_MOV(block, mem(&m_core->r[regnum]), ireg(m_regmap[regnum].ireg() - REG_I0)); + } + } +} + +void adsp21062_device::static_generate_memory_accessor(MEM_ACCESSOR_TYPE type, const char *name, code_handle *&handleptr) +{ + // I0 = read/write data + // I1 = address + // I2 is trashed + + void* block0 = &m_internal_ram_block0[0]; + void* block0_1 = &m_internal_ram_block0[1]; + void* block0_2 = &m_internal_ram_block0[2]; + void* block1 = &m_internal_ram_block1[0]; + void* block1_1 = &m_internal_ram_block1[1]; + void* block1_2 = &m_internal_ram_block1[2]; + + code_label label = 1; + + drcuml_block *block = m_drcuml->begin_block(1024); + + // add a global entry for this + alloc_handle(m_drcuml.get(), &handleptr, name); + UML_HANDLE(block, *handleptr); // handle *handleptr + + switch (type) + { + case MEM_ACCESSOR_PM_READ48: + UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START + UML_JMPc(block, COND_B, label); // jb label1 + UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END + UML_JMPc(block, COND_A, label); // ja label1 + + // 0x20000 ... 0x27fff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_DLOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // dload i0,[block0],i1,word,scale_x2 + UML_DSHL(block, I0, I0, 32); // dshl i0,i0,32 + UML_DLOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x2); // dload i2,[block0_1],i1,word,scale_x2 + UML_DSHL(block, I2, I2, 16); // dshl i2,i2,16 + UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 + UML_DLOAD(block, I2, block0_2, I1, SIZE_WORD, SCALE_x2); // dload i2,[block0_2],i1,word,scale_x2 + UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 + UML_RET(block); // ret + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START + UML_JMPc(block, COND_B, label); // jb label2 + UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END + UML_JMPc(block, COND_A, label); // ja label2 + + // 0x28000 ... 0x3ffff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_DLOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // dload i0,[block1],i1,word,scale_x2 + UML_DSHL(block, I0, I0, 32); // dshl i0,i0,32 + UML_DLOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x2); // dload i2,[block1_1],i1,word,scale_x2 + UML_DSHL(block, I2, I2, 16); // dshl i2,i2,16 + UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 + UML_DLOAD(block, I2, block1_2, I1, SIZE_WORD, SCALE_x2); // dload i2,[block1_2],i1,word,scale_x2 + UML_DOR(block, I0, I0, I2); // dor i0,i0,i2 + UML_RET(block); // ret + + UML_LABEL(block, label++); // label2: + break; + + case MEM_ACCESSOR_PM_WRITE48: + UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START + UML_JMPc(block, COND_B, label); // jb label1 + UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END + UML_JMPc(block, COND_A, label); // ja label1 + + // 0x20000 ... 0x27fff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_DSTORE(block, block0_2, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block0_2],i1,i0,word,scale_x2 + UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 + UML_DSTORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block0_1],i1,i0,word,scale_x2 + UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 + UML_DSTORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block0],i1,i0,word,scale_x2 + UML_MOV(block, mem(&m_core->force_recompile), 1); + UML_RET(block); // ret + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START + UML_JMPc(block, COND_B, label); // jb label2 + UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END + UML_JMPc(block, COND_A, label); // ja label2 + + // 0x28000 ... 0x3ffff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_DSTORE(block, block1_2, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block1_2],i1,i0,word,scale_x2 + UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 + UML_DSTORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block1_1],i1,i0,word,scale_x2 + UML_DSHR(block, I0, I0, 16); // dshr i0,i0,16 + UML_DSTORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2); // dstore [block1],i1,i0,word,scale_x2 + UML_RET(block); // ret + + UML_LABEL(block, label++); // label2: + break; + + case MEM_ACCESSOR_PM_READ32: + UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START + UML_JMPc(block, COND_B, label); // jb label1 + UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END + UML_JMPc(block, COND_A, label); // ja label1 + + // 0x20000 ... 0x27fff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // load i0,[block0],i1,word,scale_x2 + UML_SHL(block, I0, I0, 16); // shl i0,i0,16 + UML_LOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x2); // load i2,[block0_1],i1,word,scale_x2 + UML_OR(block, I0, I0, I2); // or i0,i0,i2 + UML_RET(block); // ret + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START + UML_JMPc(block, COND_B, label); // jb label2 + UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END + UML_JMPc(block, COND_A, label); // ja label2 + + // 0x28000 ... 0x3ffff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // load i0,[block1],i1,word,scale_x2 + UML_SHL(block, I0, I0, 16); // shl i0,i0,16 + UML_LOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x2); // load i2,[block1_1],i1,word,scale_x2 + UML_OR(block, I0, I0, I2); // or i0,i0,i2 + UML_RET(block); // ret + + UML_LABEL(block, label++); // label2: + break; + + case MEM_ACCESSOR_PM_WRITE32: + UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START + UML_JMPc(block, COND_B, label); // jb label1 + UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END + UML_JMPc(block, COND_A, label); // ja label1 + + // 0x20000 ... 0x27fff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_STORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x2); // store [block0_1],i1,i0,word,scale_x2 + UML_SHR(block, I0, I0, 16); // shr i0,i0,16 + UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2); // store [block0],i1,i0,word,scale_x2 + UML_RET(block); // ret + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START + UML_JMPc(block, COND_B, label); // jb label2 + UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END + UML_JMPc(block, COND_A, label); // ja label2 + + // 0x28000 ... 0x3ffff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff (block 1 is mirrored in 0x28000...2ffff, 0x30000...0x37fff and 0x38000...3ffff) + UML_MULS(block, I1, I1, I1, 3); // muls i1,3 + UML_STORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x2); // store [block1_1],i1,i0,word,scale_x2 + UML_SHR(block, I0, I0, 16); // shr i0,i0,16 + UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2); // store [block1],i1,i0,word,scale_x2 + UML_RET(block); // ret + + UML_LABEL(block, label++); // label2: + break; + + case MEM_ACCESSOR_DM_READ32: + UML_CMP(block, I1, IRAM_END); // cmp i1,IRAM_END + UML_JMPc(block, COND_BE, label); // jbe label1 + // 0x80000 ... + UML_SHL(block, I1, I1, 2); // shl i1,i1,2 + UML_READ(block, I0, I1, SIZE_DWORD, SPACE_DATA); // read i0,i1,dword,SPACE_DATA + UML_RET(block); + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START + UML_JMPc(block, COND_B, label); // jb label2 + UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END + UML_JMPc(block, COND_A, label); // ja label2 + // 0x20000 ... 0x27fff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x4); // load i0,[block0],i1,word,scale_x4 + UML_SHL(block, I0, I0, 16); // shl i0,i0,16 + UML_LOAD(block, I2, block0_1, I1, SIZE_WORD, SCALE_x4); // load i2,[block0_1],i1,word,scale_x4 + UML_OR(block, I0, I0, I2); // or i0,i0,i2 + UML_RET(block); + + UML_LABEL(block, label++); // label2: + UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START + UML_JMPc(block, COND_B, label); // jb label3 + UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END + UML_JMPc(block, COND_A, label); // ja label3 + // 0x28000 ... 0x3ffff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x4); // load i0,[block1],i1,word,scale_x4 + UML_SHL(block, I0, I0, 16); // shl i0,i0,16 + UML_LOAD(block, I2, block1_1, I1, SIZE_WORD, SCALE_x4); // load i2,[block1_1],i1,word,scale_x4 + UML_OR(block, I0, I0, I2); // or i0,i0,i2 + UML_RET(block); + + UML_LABEL(block, label++); // Label3: + UML_CMP(block, I1, IOP_REGISTER_END); // cmp i1,IOP_REGISTER_END + UML_JMPc(block, COND_A, label); // ja label4 + // IOP registers + UML_MOV(block, mem(&m_core->arg0), I1); // mov [m_core->arg0],i1 + UML_CALLC(block, cfunc_read_iop, this); // callc cfunc_read_iop + UML_MOV(block, I0, mem(&m_core->arg1)); // mov i0,[m_core->arg1] + UML_RET(block); + + UML_LABEL(block, label++); // label4: + UML_CMP(block, I1, IRAM_SHORT_BLOCK0_START); // cmp i1,IRAM_SHORT_BLOCK0_START + UML_JMPc(block, COND_B, label+1); // jb label6 + UML_CMP(block, I1, IRAM_SHORT_BLOCK0_END); // cmp i1,IRAM_SHORT_BLOCK0_END + UML_JMPc(block, COND_A, label+1); // ja label6 + // 0x40000 ... 0x4ffff + UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff + UML_XOR(block, I1, I1, 1); // xor i1,i1,1 + UML_TEST(block, mem(&m_core->mode1), 0x4000); // test [m_core->mode1],0x4000 + UML_JMPc(block, COND_Z, label); // jz label5 + UML_LOADS(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // loads i0,[block0],i1,word,scale_x2 + UML_RET(block); + UML_LABEL(block, label++); // label5: + UML_LOAD(block, I0, block0, I1, SIZE_WORD, SCALE_x2); // load i0,[block0],i1,word,scale_x2 + UML_RET(block); + + UML_LABEL(block, label++); // label6: + UML_CMP(block, I1, IRAM_SHORT_BLOCK1_START); // cmp i1,IRAM_SHORT_BLOCK1_START + UML_JMPc(block, COND_B, label+1); // jb label8 + UML_CMP(block, I1, IRAM_SHORT_BLOCK1_END); // cmp i1,IRAM_SHORT_BLOCK1_END + UML_JMPc(block, COND_A, label+1); // ja label8 + // 0x50000 ... 0x7ffff + UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff + UML_XOR(block, I1, I1, 1); // xor i1,i1,1 + UML_TEST(block, mem(&m_core->mode1), 0x4000); // test [m_core->mode1],0x4000 + UML_JMPc(block, COND_Z, label); // jz label7 + UML_LOADS(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // loads i0,[block1],i1,word,scale_x2 + UML_RET(block); + UML_LABEL(block, label++); // label7: + UML_LOAD(block, I0, block1, I1, SIZE_WORD, SCALE_x2); // load i0,[block1],i1,word,scale_x2 + UML_RET(block); + + UML_LABEL(block, label++); // label8: + break; + + case MEM_ACCESSOR_DM_WRITE32: +#if WRITE_SNOOP + //UML_CMP(block, I1, 0x283eb); + UML_CMP(block, I1, 0x2400047); + UML_JMPc(block, COND_NE, label); + UML_MOV(block, mem(&m_core->arg0), I0); + UML_MOV(block, mem(&m_core->arg1), I1); + UML_MOV(block, mem(&m_core->arg2), mem(&m_core->pc)); + UML_CALLC(block, cfunc_write_snoop, this); + UML_LABEL(block, label++); +#endif + + + UML_CMP(block, I1, IRAM_END); // cmp i1,IRAM_END + UML_JMPc(block, COND_BE, label); // jbe label1 + // 0x80000 ... + UML_SHL(block, I1, I1, 2); // shl i1,i1,2 + UML_WRITE(block, I1, I0, SIZE_DWORD, SPACE_DATA); // write i1,i0,dword,SPACE_DATA + UML_RET(block); + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I1, IRAM_BLOCK0_START); // cmp i1,IRAM_BLOCK0_START + UML_JMPc(block, COND_B, label); // jb label2 + UML_CMP(block, I1, IRAM_BLOCK0_END); // cmp i1,IRAM_BLOCK0_END + UML_JMPc(block, COND_A, label); // ja label2 + // 0x20000 ... 0x27fff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_STORE(block, block0_1, I1, I0, SIZE_WORD, SCALE_x4); // store [block0_1],i1,i0,word,scale_x4 + UML_SHR(block, I0, I0, 16); // shr i0,i0,16 + UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x4); // store [block0],i1,i0,word,scale_x4 + UML_RET(block); + + UML_LABEL(block, label++); // label2: + UML_CMP(block, I1, IRAM_BLOCK1_START); // cmp i1,IRAM_BLOCK1_START + UML_JMPc(block, COND_B, label); // jb label3 + UML_CMP(block, I1, IRAM_BLOCK1_END); // cmp i1,IRAM_BLOCK1_END + UML_JMPc(block, COND_A, label); // ja label3 + // 0x28000 ... 0x3ffff + UML_AND(block, I1, I1, 0x7fff); // and i1,i1,0x7fff + UML_STORE(block, block1_1, I1, I0, SIZE_WORD, SCALE_x4); // store [block1_1],i1,i0,word,scale_x4 + UML_SHR(block, I0, I0, 16); // shr i0,i0,16 + UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x4); // store [block1],i1,i0,word,scale_x4 + UML_RET(block); + + UML_LABEL(block, label++); // Label3: + UML_CMP(block, I1, IOP_REGISTER_END); // cmp i1,IOP_REGISTER_END + UML_JMPc(block, COND_A, label); // ja label4 + // IOP registers + UML_MOV(block, mem(&m_core->arg0), I1); // mov [m_core->arg0],i1 + UML_MOV(block, mem(&m_core->arg1), I0); // mov [m_core->arg1],i0 + UML_CALLC(block, cfunc_write_iop, this); // callc cfunc_write_iop + UML_RET(block); + + UML_LABEL(block, label++); // label4: + UML_CMP(block, I1, IRAM_SHORT_BLOCK0_START); // cmp i1,IRAM_SHORT_BLOCK0_START + UML_JMPc(block, COND_B, label); // jb label5 + UML_CMP(block, I1, IRAM_SHORT_BLOCK0_END); // cmp i1,IRAM_SHORT_BLOCK0_END + UML_JMPc(block, COND_A, label); // ja label5 + // 0x40000 ... 0x4ffff + UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff + UML_XOR(block, I1, I1, 1); // xor i1,i1,1 + UML_STORE(block, block0, I1, I0, SIZE_WORD, SCALE_x2); // store [block0],i1,i0,word,scale_x2 + UML_RET(block); + + UML_LABEL(block, label++); // label5: + UML_CMP(block, I1, IRAM_SHORT_BLOCK1_START); // cmp i1,IRAM_SHORT_BLOCK1_START + UML_JMPc(block, COND_B, label); // jb label6 + UML_CMP(block, I1, IRAM_SHORT_BLOCK1_END); // cmp i1,IRAM_SHORT_BLOCK1_END + UML_JMPc(block, COND_A, label); // ja label6 + // 0x50000 ... 0x7ffff + UML_AND(block, I1, I1, 0xffff); // and i1,i1,0xffff + UML_XOR(block, I1, I1, 1); // xor i1,i1,1 + UML_STORE(block, block1, I1, I0, SIZE_WORD, SCALE_x2); // store [block1],i1,i0,word,scale_x2 + UML_RET(block); + + UML_LABEL(block, label++); // label6: + break; + } + + UML_RET(block); + + block->end(); +} + +void adsp21062_device::static_generate_push_pc() +{ + // Push contents of I0 to PC stack + // Trashes I1 + + code_label label = 1; + drcuml_block *block = m_drcuml->begin_block(32); + + // add a global entry for this + alloc_handle(m_drcuml.get(), &m_push_pc, "push_pc"); + UML_HANDLE(block, *m_push_pc); // handle *m_push_pc + + UML_MOV(block, I1, PCSTKP); // mov i1,PCSTKP + UML_ADD(block, I1, I1, 1); // add i1,i1,1 + UML_CMP(block, I1, 32); // cmp i1,32 + UML_JMPc(block, COND_L,label); // jl label1 + UML_CALLC(block, cfunc_pcstack_overflow, this); // callc cfunc_pcstack_overflow + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I1, 0); // cmp i1,0 + UML_JMPc(block, COND_E, label); // je label2 + UML_AND(block, STKY, STKY, ~0x400000); // and STKY,~0x400000 + UML_JMP(block, label + 1); // jmp label3 + UML_LABEL(block, label++); // label2: + UML_OR(block, STKY, STKY, 0x400000); // or STKY,0x400000 + + UML_LABEL(block, label++); // label3: + UML_MOV(block, PCSTK, I0); // mov PCSTK,pc + UML_STORE(block, &m_core->pcstack, I1, I0, SIZE_DWORD, SCALE_x4); // store [m_core->pcstack],i1,i0,dword,scale_x4 + UML_MOV(block, PCSTKP, I1); // mov PCSTKP,i1 + + UML_RET(block); + + block->end(); +} + +void adsp21062_device::static_generate_pop_pc() +{ + // Pop PC stack into I0 + // Trashes I1 + + code_label label = 1; + drcuml_block *block = m_drcuml->begin_block(32); + + // add a global entry for this + alloc_handle(m_drcuml.get(), &m_pop_pc, "pop_pc"); + UML_HANDLE(block, *m_pop_pc); // handle *m_pop_pc + + UML_MOV(block, I1, PCSTKP); // mov i0,PCSTKP + UML_LOAD(block, I0, &m_core->pcstack, I1, SIZE_DWORD, SCALE_x4); // load i1,[m_core->pcstack],i0,dword,scale_x4 + UML_CMP(block, I1, 0); // cmp i1,0 + UML_JMPc(block, COND_NE, label); // jne label1 + UML_CALLC(block, cfunc_pcstack_underflow, this); // callc cfunc_pcstack_underflow + + UML_LABEL(block, label++); // label1: + UML_SUB(block, I1, I1, 1); // sub i1,i1,1 + UML_CMP(block, I1, 0); // cmp i1,0 + UML_JMPc(block, COND_E, label); // je label2 + UML_AND(block, STKY, STKY, ~0x400000); // and STKY,~0x400000 + UML_JMP(block, label + 1); // jmp label3 + UML_LABEL(block, label++); // label2: + UML_OR(block, STKY, STKY, 0x400000); // or STKY,0x400000 + + UML_LABEL(block, label++); // label3: + UML_MOV(block, PCSTKP, I1); // mov PCSTKP,i1 + UML_MOV(block, PCSTK, I0); // mov PCSTK,i0 + + UML_RET(block); + + block->end(); +} + +void adsp21062_device::static_generate_push_loop() +{ + // I0 = counter + // I1 = type/condition/addr + // Trashes I2 + + code_label label = 1; + drcuml_block *block = m_drcuml->begin_block(32); + + // add a global entry for this + alloc_handle(m_drcuml.get(), &m_push_loop, "push_loop"); + UML_HANDLE(block, *m_push_loop); // handle *m_push_loop + + UML_MOV(block, I2, LSTKP); // mov i2,LSTKP + UML_ADD(block, I2, I2, 1); // add i2,1 + UML_CMP(block, I2, 6); // cmp i2,6 + UML_JMPc(block, COND_L, label); // jl label1 + UML_CALLC(block, cfunc_loopstack_overflow, this); // callc cfunc_loopstack_overflow + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I2, 0); // cmp i2,0 + UML_JMPc(block, COND_E, label); // je label2 + UML_AND(block, STKY, STKY, ~0x4000000); // and STKY,~0x4000000 + UML_JMP(block, label + 1); // jmp label3 + UML_LABEL(block, label++); // label2: + UML_OR(block, STKY, STKY, 0x4000000); // or STKY,0x4000000 + + UML_LABEL(block, label++); // label3: + + UML_STORE(block, m_core->lcstack, I2, I0, SIZE_DWORD, SCALE_x4); // store m_core->lcstack,i2,i0,dword,scale_x4 + UML_STORE(block, m_core->lastack, I2, I1, SIZE_DWORD, SCALE_x4); // store m_core->lastack,i2,i1,dword,scale_x4 + UML_MOV(block, CURLCNTR, I0); // mov CURLCNTR,i0 + UML_MOV(block, LSTKP, I2); // mov LSTKP,i2 + + UML_RET(block); + + block->end(); +} + +void adsp21062_device::static_generate_pop_loop() +{ + // Trashes I0,I2 + + code_label label = 1; + drcuml_block *block = m_drcuml->begin_block(32); + + // add a global entry for this + alloc_handle(m_drcuml.get(), &m_pop_loop, "pop_loop"); + UML_HANDLE(block, *m_pop_loop); // handle *m_pop_loop + + UML_MOV(block, I2, LSTKP); // mov i2,LSTKP + UML_CMP(block, I2, 0); // cmp i2,0 + UML_JMPc(block, COND_NE, label); // jne label1 + UML_CALLC(block, cfunc_loopstack_underflow, this); // callc cfunc_loopstack_underflow + + UML_LABEL(block, label++); // label1: + UML_SUB(block, I2, I2, 1); // sub i2,i2,1 + UML_CMP(block, I2, 0); // cmp i2,0 + UML_JMPc(block, COND_E, label); // je label2 + UML_AND(block, STKY, STKY, ~0x4000000); // and STKY,~0x4000000 + UML_JMP(block, label + 1); // jmp label3 + UML_LABEL(block, label++); // label2: + UML_OR(block, STKY, STKY, 0x4000000); // or STKY,0x4000000 + + UML_LABEL(block, label++); // label3: + UML_LOAD(block, I0, m_core->lcstack, I2, SIZE_DWORD, SCALE_x4); // load i0,m_core->lcstack,i2,dword,scale_x4 + UML_MOV(block, CURLCNTR, I0); // mov CURLCNTR,i0 + UML_MOV(block, LSTKP, I2); // mov LSTKP,i2 + + UML_RET(block); + + block->end(); +} + +void adsp21062_device::static_generate_push_status() +{ + // Trashes I2 + + code_label label = 1; + drcuml_block *block = m_drcuml->begin_block(32); + + // add a global entry for this + alloc_handle(m_drcuml.get(), &m_push_status, "push_status"); + UML_HANDLE(block, *m_push_status); // handle *m_push_status + + UML_MOV(block, I2, mem(&m_core->status_stkp)); // mov i2,[status_stkp] + UML_ADD(block, I2, I2, 1); // add i2,1 + UML_CMP(block, I2, 5); // cmp i2,5 + UML_JMPc(block, COND_L, label); // jl label1 + UML_CALLC(block, cfunc_statusstack_overflow, this); // callc cfunc_statusstack_overflow + + UML_LABEL(block, label++); // label1: + UML_CMP(block, I2, 0); // cmp i2,0 + UML_JMPc(block, COND_E, label); // je label2 + UML_AND(block, STKY, STKY, ~0x1000000); // and STKY,~0x1000000 + UML_JMP(block, label + 1); // jmp label3 + UML_LABEL(block, label++); // label2: + UML_OR(block, STKY, STKY, 0x1000000); // or STKY,0x1000000 + + UML_LABEL(block, label++); // label3: + UML_MOV(block, mem(&m_core->status_stkp), I2); // mov [status_stkp],i2 + + //TODO: load MODE1 + //TODO: load ASTAT + + UML_RET(block); + + block->end(); +} + +void adsp21062_device::static_generate_pop_status() +{ + // Trashes I2 + + code_label label = 1; + drcuml_block *block = m_drcuml->begin_block(32); + + // add a global entry for this + alloc_handle(m_drcuml.get(), &m_pop_status, "pop_status"); + UML_HANDLE(block, *m_pop_status); // handle *m_pop_status + + //TODO: store MODE1 + //TODO: store ASTAT + + UML_MOV(block, I2, mem(&m_core->status_stkp)); // mov i2,[status_stkp] + UML_CMP(block, I2, 0); // cmp i2,0 + UML_JMPc(block, COND_NE, label); // jl label1 + UML_CALLC(block, cfunc_statusstack_underflow, this); // callc cfunc_statusstack_underflow + + UML_LABEL(block, label++); // label1: + UML_SUB(block, I2, I2, 1); // sub i2,1 + UML_CMP(block, I2, 0); // cmp i2,0 + UML_JMPc(block, COND_E, label); // je label2 + UML_AND(block, STKY, STKY, ~0x1000000); // and STKY,~0x1000000 + UML_JMP(block, label + 1); // jmp label3 + UML_LABEL(block, label++); // label2: + UML_OR(block, STKY, STKY, 0x1000000); // or STKY,0x1000000 + + UML_LABEL(block, label++); // label3: + UML_MOV(block, mem(&m_core->status_stkp), I2); // mov [status_stkp],i2 + + UML_RET(block); + + block->end(); +} + + +void adsp21062_device::static_generate_exception(UINT8 exception, const char *name) +{ + code_handle *&exception_handle = m_exception[exception]; + + code_label label = 1; + + code_label label_nopush = label++; + + /* begin generating */ + drcuml_block *block = m_drcuml->begin_block(1024); + + /* add a global entry for this */ + alloc_handle(m_drcuml.get(), &exception_handle, name); + UML_HANDLE(block, *exception_handle); // handle name + + UML_AND(block, I3, mem(&m_core->irq_pending), IMASK); // and i3,[irq_pending],IMASK + UML_TZCNT(block, I3, I3); // tzcnt i3,i3 + + UML_MOV(block, I2, 1); // mov i2,1 + UML_SHL(block, I2, I2, I3); // shl i2,i2,i3 + UML_OR(block, IRPTL, IRPTL, I2); // or IRPTL,i2 + UML_XOR(block, mem(&m_core->irq_pending), mem(&m_core->irq_pending), I2); // xor [irq_pending],i2 + UML_MOV(block, mem(&m_core->active_irq_num), I3); // mov [active_irq_num],i3 + UML_MOV(block, mem(&m_core->interrupt_active), 1); // mov [interrupt_active],1 + + UML_CALLH(block, *m_push_pc); // callh m_push_pc + + UML_CMP(block, I3, 6); // cmp i3,6 + UML_JMPc(block, COND_L, label_nopush); // jl label_nopush + UML_CMP(block, I3, 8); // cmp i3,8 + UML_JMPc(block, COND_G, label_nopush); // jg label_nopush + UML_CALLH(block, *m_push_status); // callh m_push_status + + UML_LABEL(block, label_nopush); // label_nopush: + UML_SHL(block, I0, I3, 2); // shl i0,i3,2 + UML_ADD(block, I0, I0, 0x20000); // add i0,0x20000 + UML_HASHJMP(block, 0, I0, *m_nocode); // hashjmp i0,m_nocode + + block->end(); +} + + +void adsp21062_device::static_generate_mode1_ops() +{ + drcuml_block *block; + + // TODO: these could be further optimized with 64-bit or 128-bit swaps + // e.g SWAP128 instruction (swap 128 bits between 2 memory locations) + + block = m_drcuml->begin_block(128); + alloc_handle(m_drcuml.get(), &m_swap_dag1_0_3, "swap_dag1_0_3"); + UML_HANDLE(block, *m_swap_dag1_0_3); // handle name +#if !USE_SWAPDQ + for (int i = 0; i < 4; i++) + { + UML_MOV(block, I0, mem(&m_core->dag1.i[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.i[i])); + UML_MOV(block, mem(&m_core->dag1.i[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.i[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag1.m[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.m[i])); + UML_MOV(block, mem(&m_core->dag1.m[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.m[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag1.l[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.l[i])); + UML_MOV(block, mem(&m_core->dag1.l[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.l[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag1.b[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.b[i])); + UML_MOV(block, mem(&m_core->dag1.b[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.b[i]), I0); + } +#else + UML_SWAPDQ(block, mem(&m_core->dag1.i[0]), mem(&m_core->dag1_alt.i[0])); + UML_SWAPDQ(block, mem(&m_core->dag1.m[0]), mem(&m_core->dag1_alt.m[0])); + UML_SWAPDQ(block, mem(&m_core->dag1.l[0]), mem(&m_core->dag1_alt.l[0])); + UML_SWAPDQ(block, mem(&m_core->dag1.b[0]), mem(&m_core->dag1_alt.b[0])); +#endif + UML_RET(block); + block->end(); + + block = m_drcuml->begin_block(128); + alloc_handle(m_drcuml.get(), &m_swap_dag1_4_7, "swap_dag1_4_7"); + UML_HANDLE(block, *m_swap_dag1_4_7); // handle name +#if !USE_SWAPDQ + for (int i = 4; i < 8; i++) + { + UML_MOV(block, I0, mem(&m_core->dag1.i[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.i[i])); + UML_MOV(block, mem(&m_core->dag1.i[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.i[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag1.m[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.m[i])); + UML_MOV(block, mem(&m_core->dag1.m[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.m[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag1.l[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.l[i])); + UML_MOV(block, mem(&m_core->dag1.l[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.l[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag1.b[i])); + UML_MOV(block, I1, mem(&m_core->dag1_alt.b[i])); + UML_MOV(block, mem(&m_core->dag1.b[i]), I1); + UML_MOV(block, mem(&m_core->dag1_alt.b[i]), I0); + } +#else + UML_SWAPDQ(block, mem(&m_core->dag1.i[4]), mem(&m_core->dag1_alt.i[4])); + UML_SWAPDQ(block, mem(&m_core->dag1.m[4]), mem(&m_core->dag1_alt.m[4])); + UML_SWAPDQ(block, mem(&m_core->dag1.l[4]), mem(&m_core->dag1_alt.l[4])); + UML_SWAPDQ(block, mem(&m_core->dag1.b[4]), mem(&m_core->dag1_alt.b[4])); +#endif + UML_RET(block); + block->end(); + + block = m_drcuml->begin_block(128); + alloc_handle(m_drcuml.get(), &m_swap_dag2_0_3, "swap_dag2_0_3"); + UML_HANDLE(block, *m_swap_dag2_0_3); // handle name +#if !USE_SWAPDQ + for (int i = 0; i < 4; i++) + { + UML_MOV(block, I0, mem(&m_core->dag2.i[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.i[i])); + UML_MOV(block, mem(&m_core->dag2.i[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.i[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag2.m[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.m[i])); + UML_MOV(block, mem(&m_core->dag2.m[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.m[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag2.l[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.l[i])); + UML_MOV(block, mem(&m_core->dag2.l[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.l[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag2.b[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.b[i])); + UML_MOV(block, mem(&m_core->dag2.b[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.b[i]), I0); + } +#else + UML_SWAPDQ(block, mem(&m_core->dag2.i[0]), mem(&m_core->dag2_alt.i[0])); + UML_SWAPDQ(block, mem(&m_core->dag2.m[0]), mem(&m_core->dag2_alt.m[0])); + UML_SWAPDQ(block, mem(&m_core->dag2.l[0]), mem(&m_core->dag2_alt.l[0])); + UML_SWAPDQ(block, mem(&m_core->dag2.b[0]), mem(&m_core->dag2_alt.b[0])); +#endif + UML_RET(block); + block->end(); + + block = m_drcuml->begin_block(128); + alloc_handle(m_drcuml.get(), &m_swap_dag2_4_7, "swap_dag2_4_7"); + UML_HANDLE(block, *m_swap_dag2_4_7); // handle name +#if !USE_SWAPDQ + for (int i = 4; i < 8; i++) + { + UML_MOV(block, I0, mem(&m_core->dag2.i[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.i[i])); + UML_MOV(block, mem(&m_core->dag2.i[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.i[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag2.m[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.m[i])); + UML_MOV(block, mem(&m_core->dag2.m[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.m[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag2.l[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.l[i])); + UML_MOV(block, mem(&m_core->dag2.l[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.l[i]), I0); + UML_MOV(block, I0, mem(&m_core->dag2.b[i])); + UML_MOV(block, I1, mem(&m_core->dag2_alt.b[i])); + UML_MOV(block, mem(&m_core->dag2.b[i]), I1); + UML_MOV(block, mem(&m_core->dag2_alt.b[i]), I0); + } +#else + UML_SWAPDQ(block, mem(&m_core->dag2.i[4]), mem(&m_core->dag2_alt.i[4])); + UML_SWAPDQ(block, mem(&m_core->dag2.m[4]), mem(&m_core->dag2_alt.m[4])); + UML_SWAPDQ(block, mem(&m_core->dag2.l[4]), mem(&m_core->dag2_alt.l[4])); + UML_SWAPDQ(block, mem(&m_core->dag2.b[4]), mem(&m_core->dag2_alt.b[4])); +#endif + UML_RET(block); + block->end(); + + block = m_drcuml->begin_block(64); + alloc_handle(m_drcuml.get(), &m_swap_r0_7, "swap_r0_7"); + UML_HANDLE(block, *m_swap_r0_7); // handle name +#if !USE_SWAPDQ + for (int i = 0; i < 8; i++) + { + UML_MOV(block, I0, mem(&m_core->r[i])); + UML_MOV(block, I1, mem(&m_core->reg_alt[i])); + UML_MOV(block, mem(&m_core->r[i]), I1); + UML_MOV(block, mem(&m_core->reg_alt[i]), I0); + } +#else + UML_SWAPDQ(block, mem(&m_core->r[0]), mem(&m_core->reg_alt[0])); + UML_SWAPDQ(block, mem(&m_core->r[4]), mem(&m_core->reg_alt[4])); +#endif + UML_RET(block); + block->end(); + + block = m_drcuml->begin_block(64); + alloc_handle(m_drcuml.get(), &m_swap_r8_15, "swap_r8_15"); + UML_HANDLE(block, *m_swap_r8_15); // handle name +#if !USE_SWAPDQ + for (int i = 8; i < 16; i++) + { + UML_MOV(block, I0, mem(&m_core->r[i])); + UML_MOV(block, I1, mem(&m_core->reg_alt[i])); + UML_MOV(block, mem(&m_core->r[i]), I1); + UML_MOV(block, mem(&m_core->reg_alt[i]), I0); + } +#else + UML_SWAPDQ(block, mem(&m_core->r[8]), mem(&m_core->reg_alt[8])); + UML_SWAPDQ(block, mem(&m_core->r[12]), mem(&m_core->reg_alt[12])); +#endif + UML_RET(block); + block->end(); +} + + + + +void adsp21062_device::execute_run_drc() +{ + drcuml_state *drcuml = m_drcuml.get(); + int execute_result; + +// if (m_cache_dirty) +// printf("SHARC cache reset\n"); + + /* reset the cache if dirty */ + if (m_cache_dirty) + flush_cache(); + + m_cache_dirty = false; + m_core->force_recompile = 0; + + /* execute */ + do + { + execute_result = drcuml->execute(*m_entry); + + /* if we need to recompile, do it */ + if (execute_result == EXECUTE_MISSING_CODE) + { + compile_block(m_core->pc); + } + else if (execute_result == EXECUTE_UNMAPPED_CODE) + { + fatalerror("Attempted to execute unmapped code at PC=%08X\n", m_core->pc); + } + else if (execute_result == EXECUTE_RESET_CACHE) + { + flush_cache(); + } + } while (execute_result != EXECUTE_OUT_OF_CYCLES); +} + + +void adsp21062_device::compile_block(offs_t pc) +{ + compiler_state compiler = { 0 }; + + const opcode_desc *seqhead, *seqlast; + const opcode_desc *desclist; + bool override = false; + + drcuml_block *block; + + desclist = m_drcfe->describe_code(pc); + + bool succeeded = false; + while (!succeeded) + { + try + { + block = m_drcuml->begin_block(4096); + + for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next()) + { + const opcode_desc *curdesc; + UINT32 nextpc; + + /* determine the last instruction in this sequence */ + for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next()) + if (seqlast->flags & OPFLAG_END_SEQUENCE) + break; + assert(seqlast != nullptr); + + /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */ + if (override || m_drcuml->hash_exists(0, seqhead->pc)) + UML_HASH(block, 0, seqhead->pc); // hash mode,pc + + /* if we already have a hash, and this is the first sequence, assume that we */ + /* are recompiling due to being out of sync and allow future overrides */ + else if (seqhead == desclist) + { + override = true; + UML_HASH(block, 0, seqhead->pc); // hash mode,pc + } + + /* otherwise, redispatch to that fixed PC and skip the rest of the processing */ + else + { + UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc + UML_HASHJMP(block, 0, seqhead->pc, *m_nocode); // hashjmp <0>,seqhead->pc,nocode + continue; + } + + /* label this instruction, if it may be jumped to locally */ + if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET) + UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc + + /* iterate over instructions in the sequence and compile them */ + for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next()) + generate_sequence_instruction(block, &compiler, curdesc); + + /* if we need to return to the start, do it */ + if (seqlast->flags & OPFLAG_RETURN_TO_START) + nextpc = pc; + /* otherwise we just go to the next instruction */ + else + nextpc = seqlast->pc + (seqlast->skipslots + 1); + + + // force recompilation at end of block, if needed + UML_CMP(block, mem(&m_core->force_recompile), 0); + UML_JMPc(block, COND_Z, compiler.labelnum); + UML_MOV(block, mem(&m_cache_dirty), 1); + UML_MOV(block, mem(&m_core->icount), 0); + UML_LABEL(block, compiler.labelnum++); + + + /* count off cycles and go there */ + generate_update_cycles(block, &compiler, nextpc, TRUE); // + + if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc) + UML_HASHJMP(block, 0, nextpc, *m_nocode); // hashjmp ,nextpc,nocode + } + + block->end(); + succeeded = true; + } + catch (drcuml_block::abort_compilation &) + { + flush_cache(); + } + } +} + + +void adsp21062_device::flush_cache() +{ + /* empty the transient cache contents */ + m_drcuml->reset(); + + m_drcfe->flush(); + + try + { + // generate the entry point and out-of-cycles handlers + static_generate_entry_point(); + static_generate_nocode_handler(); + static_generate_out_of_cycles(); + + // generate utility functions + static_generate_push_pc(); + static_generate_pop_pc(); + static_generate_push_loop(); + static_generate_pop_loop(); + static_generate_push_status(); + static_generate_pop_status(); + static_generate_mode1_ops(); + + // generate exception handlers + static_generate_exception(EXCEPTION_INTERRUPT, "exception_interrupt"); + + // generate memory accessors + static_generate_memory_accessor(MEM_ACCESSOR_PM_READ48, "pm_read48", m_pm_read48); + static_generate_memory_accessor(MEM_ACCESSOR_PM_WRITE48, "pm_write48", m_pm_write48); + static_generate_memory_accessor(MEM_ACCESSOR_PM_READ32, "pm_read32", m_pm_read32); + static_generate_memory_accessor(MEM_ACCESSOR_PM_WRITE32, "pm_write32", m_pm_write32); + static_generate_memory_accessor(MEM_ACCESSOR_DM_READ32, "dm_read32", m_dm_read32); + static_generate_memory_accessor(MEM_ACCESSOR_DM_WRITE32, "dm_write32", m_dm_write32); + } + catch (drcuml_block::abort_compilation &) + { + fatalerror("Error generating SHARC static handlers\n"); + } +} + + +void adsp21062_device::static_generate_entry_point() +{ + code_label skip = 1; + drcuml_block *block; + + /* begin generating */ + block = m_drcuml->begin_block(20); + + /* forward references */ + alloc_handle(m_drcuml.get(), &m_nocode, "nocode"); + alloc_handle(m_drcuml.get(), &m_exception[EXCEPTION_INTERRUPT], "exception_interrupt"); + + alloc_handle(m_drcuml.get(), &m_entry, "entry"); + UML_HANDLE(block, *m_entry); // handle entry + + load_fast_iregs(block); // + + /* check for interrupts */ + UML_CMP(block, mem(&m_core->irq_pending), 0); // cmp [irq_pending],0 + UML_JMPc(block, COND_E, skip); // je skip + UML_CMP(block, mem(&m_core->interrupt_active), 0); // cmp [interrupt_active],0 + UML_JMPc(block, COND_NE, skip); // jne skip + UML_TEST(block, mem(&m_core->irq_pending), IMASK); // test [irq_pending],IMASK + UML_JMPc(block, COND_Z, skip); // jz skip + UML_TEST(block, mem(&m_core->mode1), MODE1_IRPTEN); // test MODE1,MODE1_IRPTEN + UML_JMPc(block, COND_Z, skip); // jz skip + + UML_MOV(block, I0, mem(&m_core->pc)); // mov i0,nextpc + UML_MOV(block, I1, 0); // mov i1,0 + UML_CALLH(block, *m_exception[EXCEPTION_INTERRUPT]); // callh m_exception[EXCEPTION_INTERRUPT] + + UML_LABEL(block, skip); + + /* generate a hash jump via the current mode and PC */ + UML_HASHJMP(block, 0, mem(&m_core->pc), *m_nocode); // hashjmp ,,nocode + + block->end(); +} + + +void adsp21062_device::static_generate_nocode_handler() +{ + drcuml_block *block; + + /* begin generating */ + block = m_drcuml->begin_block(10); + + /* generate a hash jump via the current mode and PC */ + alloc_handle(m_drcuml.get(), &m_nocode, "nocode"); + UML_HANDLE(block, *m_nocode); // handle nocode + UML_GETEXP(block, I0); // getexp i0 + UML_MOV(block, mem(&m_core->pc), I0); // mov [pc],i0 + save_fast_iregs(block); // + UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE + + block->end(); +} + +void adsp21062_device::static_generate_out_of_cycles() +{ + drcuml_block *block; + + /* begin generating */ + block = m_drcuml->begin_block(10); + + /* generate a hash jump via the current mode and PC */ + alloc_handle(m_drcuml.get(), &m_out_of_cycles, "out_of_cycles"); + UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles + UML_GETEXP(block, I0); // getexp i0 + UML_MOV(block, mem(&m_core->pc), I0); // mov ,i0 + save_fast_iregs(block); // + UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES + + block->end(); +} + + +void adsp21062_device::generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) +{ + /* add an entry for the log */ +// if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP)) +// log_add_disasm_comment(block, desc->pc, desc->opptr.l[0]); + + /* set the PC map variable */ + UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc + + /* accumulate total cycles */ + compiler->cycles += desc->cycles; + + /* update the icount map variable */ + UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles + + /* if we are debugging, call the debugger */ + if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0) + { + UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc + save_fast_iregs(block); // + UML_DEBUG(block, desc->pc); // debug desc->pc + } + + /* if we hit an unmapped address, fatal error */ + if (desc->flags & OPFLAG_COMPILER_UNMAPPED) + { + UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc + save_fast_iregs(block); // + UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE + } + + /* if this is an invalid opcode, generate the exception now */ +// if (desc->flags & OPFLAG_INVALID_OPCODE) +// UML_EXH(block, *m_exception[EXCEPTION_PROGRAM], 0x80000); // exh exception_program,0x80000 + + /* unless this is a virtual no-op, it's a regular instruction */ + if (!(desc->flags & OPFLAG_VIRTUAL_NOOP)) + { + /* compile the instruction */ + if (!generate_opcode(block, compiler, desc)) + { + UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc + UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); // dmov [arg64],*desc->opptr.q + UML_CALLC(block, cfunc_unimplemented, this); // callc cfunc_unimplemented,ppc + } + } + + + // insert delayed MODE1 operation if needed + if (compiler->mode1_delay.counter > 0) + { + compiler->mode1_delay.counter--; + if (compiler->mode1_delay.counter <= 0) + { + switch (compiler->mode1_delay.mode) + { + case MODE1_WRITE_IMM: + generate_write_mode1_imm(block, compiler, desc, compiler->mode1_delay.data); + break; + case MODE1_WRITE_REG: + fatalerror("MODE1 delay REG"); + break; + case MODE1_SET: + generate_set_mode1_imm(block, compiler, desc, compiler->mode1_delay.data); + break; + case MODE1_CLEAR: + generate_clear_mode1_imm(block, compiler, desc, compiler->mode1_delay.data); + break; + case MODE1_TOGGLE: + fatalerror("MODE1 delay TOGGLE"); + break; + } + } + } + + + // insert loop check at this instruction if needed + if (desc->userflags & OP_USERFLAG_COUNTER_LOOP) + { + code_label label_expire = compiler->labelnum++; + UML_MOV(block, I1, mem(&m_core->lstkp)); // mov i1,[m_core->lstkp] + UML_LOAD(block, I0, m_core->lcstack, I1, SIZE_DWORD, SCALE_x4); // load i0,m_core->lcstack,i1,dword,scale_x4 + UML_SUB(block, I0, I0, 1); // sub i0,1 + UML_STORE(block, m_core->lcstack, I1, I0, SIZE_DWORD, SCALE_x4); // store m_core->lcstack,i1,i0,dword,scale_x4 + UML_SUB(block, CURLCNTR, CURLCNTR, 1); // sub CURLCNTR,1 + UML_JMPc(block, COND_E, label_expire); // jne label_expire + + generate_jump(block, compiler, desc, false, false, false); + + UML_LABEL(block, label_expire); // label_expire: + UML_CALLH(block, *m_pop_pc); // callh m_pop_pc + UML_CALLH(block, *m_pop_loop); // callh m_pop_loop + } + if (desc->userflags & OP_USERFLAG_COND_LOOP) + { + code_label label_expire = compiler->labelnum++; + + int condition = (desc->userflags & OP_USERFLAG_COND_FIELD) >> OP_USERFLAG_COND_FIELD_SHIFT; + generate_do_condition(block, compiler, desc, condition, label_expire, m_core->astat_delay_copy); + + generate_jump(block, compiler, desc, false, false, false); + + UML_LABEL(block, label_expire); + UML_CALLH(block, *m_pop_pc); + UML_CALLH(block, *m_pop_loop); + } + + // copy ASTAT bits over for conditional loop + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY) + { + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AZ) + UML_MOV(block, mem(&m_core->astat_delay_copy.az), mem(&m_core->astat_drc.az)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AN) + UML_MOV(block, mem(&m_core->astat_delay_copy.an), mem(&m_core->astat_drc.an)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AV) + UML_MOV(block, mem(&m_core->astat_delay_copy.av), mem(&m_core->astat_drc.av)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_AC) + UML_MOV(block, mem(&m_core->astat_delay_copy.ac), mem(&m_core->astat_drc.ac)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MN) + UML_MOV(block, mem(&m_core->astat_delay_copy.mn), mem(&m_core->astat_drc.mn)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_MV) + UML_MOV(block, mem(&m_core->astat_delay_copy.mv), mem(&m_core->astat_drc.mv)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SV) + UML_MOV(block, mem(&m_core->astat_delay_copy.sv), mem(&m_core->astat_drc.sv)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_SZ) + UML_MOV(block, mem(&m_core->astat_delay_copy.sz), mem(&m_core->astat_drc.sz)); + if (desc->userflags & OP_USERFLAG_ASTAT_DELAY_COPY_BTF) + UML_MOV(block, mem(&m_core->astat_delay_copy.btf), mem(&m_core->astat_drc.btf)); + } +} + +void adsp21062_device::generate_update_cycles(drcuml_block *block, compiler_state *compiler, uml::parameter param, int allow_exception) +{ + /* check full interrupts if pending */ + if (compiler->checkints) + { + code_label skip = compiler->labelnum++; + compiler->checkints = FALSE; + + UML_CMP(block, mem(&m_core->irq_pending), 0); // cmp [irq_pending],0 + UML_JMPc(block, COND_E, skip); // je skip + UML_CMP(block, mem(&m_core->interrupt_active), 0); // cmp [interrupt_active],0 + UML_JMPc(block, COND_NE, skip); // jne skip + UML_TEST(block, mem(&m_core->irq_pending), IMASK); // test [irq_pending],IMASK + UML_JMPc(block, COND_Z, skip); // jz skip + UML_TEST(block, mem(&m_core->mode1), MODE1_IRPTEN); // test MODE1,MODE1_IRPTEN + UML_JMPc(block, COND_Z, skip); // jz skip + + UML_MOV(block, I0, param); // mov i0,nextpc + UML_MOV(block, I1, compiler->cycles); // mov i1,cycles + UML_CALLH(block, *m_exception[EXCEPTION_INTERRUPT]); // callh m_exception[EXCEPTION_INTERRUPT] + + UML_LABEL(block, skip); + } + + /* account for cycles */ + if (compiler->cycles > 0) + { + UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), MAPVAR_CYCLES); // sub icount,icount,cycles + UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0 + if (allow_exception) + UML_EXHc(block, COND_S, *m_out_of_cycles, param); // exh out_of_cycles,nextpc + } + compiler->cycles = 0; +} + +void adsp21062_device::generate_write_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data) +{ + code_label skip; + + // TODO: swap effects + if (data & 0x1) + fatalerror("generate_write_mode1_imm: tried to enable I8 bit reversing"); + if (data & 0x2) + fatalerror("generate_write_mode1_imm: tried to enable I0 bit reversing"); + if (data & 0x4) + fatalerror("generate_write_mode1_imm: tried to enable MR alternate"); + + // DAG1 regs 4-7 + skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x8); + UML_JMPc(block, (data & 0x8) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same + UML_CALLH(block, *m_swap_dag1_4_7); + UML_LABEL(block, skip); + + // DAG1 regs 0-3 + skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x10); + UML_JMPc(block, (data & 0x10) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same + UML_CALLH(block, *m_swap_dag1_0_3); + UML_LABEL(block, skip); + + // DAG2 regs 4-7 + skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x20); + UML_JMPc(block, (data & 0x20) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same + UML_CALLH(block, *m_swap_dag2_4_7); + UML_LABEL(block, skip); + + // DAG2 regs 0-3 + skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x40); + UML_JMPc(block, (data & 0x40) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same + UML_CALLH(block, *m_swap_dag2_0_3); + UML_LABEL(block, skip); + + // REG 8-15 + skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x80); + UML_JMPc(block, (data & 0x80) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same + UML_CALLH(block, *m_swap_r8_15); + UML_LABEL(block, skip); + + // REG 0-7 + skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x400); + UML_JMPc(block, (data & 0x400) ? COND_NZ : COND_Z, skip); // don't swap if the bits are same + UML_CALLH(block, *m_swap_r0_7); + UML_LABEL(block, skip); + + UML_MOV(block, MODE1, data); +} + +void adsp21062_device::generate_set_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data) +{ + if (data & 0x1) + fatalerror("generate_set_mode1_imm: tried to enable I8 bit reversing"); + if (data & 0x2) + fatalerror("generate_set_mode1_imm: tried to enable I0 bit reversing"); + if (data & 0x4) + fatalerror("generate_set_mode1_imm: tried to enable MR alternate"); + if (data & 0x8) // DAG1 regs 4-7 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x8); + UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 + UML_CALLH(block, *m_swap_dag1_4_7); + UML_LABEL(block, skip); + } + if (data & 0x10) // DAG1 regs 0-3 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x10); + UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 + UML_CALLH(block, *m_swap_dag1_0_3); + UML_LABEL(block, skip); + } + if (data & 0x20) // DAG2 regs 4-7 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x20); + UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 + UML_CALLH(block, *m_swap_dag2_4_7); + UML_LABEL(block, skip); + } + if (data & 0x40) // DAG1 regs 0-3 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x40); + UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 + UML_CALLH(block, *m_swap_dag2_0_3); + UML_LABEL(block, skip); + } + if (data & 0x80) // REG 8-15 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x80); + UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 + UML_CALLH(block, *m_swap_r8_15); + UML_LABEL(block, skip); + } + if (data & 0x400) // REG 0-7 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x400); + UML_JMPc(block, COND_NZ, skip); // don't swap if the bit is already 1 + UML_CALLH(block, *m_swap_r0_7); + UML_LABEL(block, skip); + } + + UML_OR(block, MODE1, MODE1, data); +} + +void adsp21062_device::generate_clear_mode1_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 data) +{ + if (data & 0x1) + fatalerror("generate_clear_mode1_imm: tried to disable I8 bit reversing"); + if (data & 0x2) + fatalerror("generate_clear_mode1_imm: tried to disable I0 bit reversing"); + if (data & 0x4) + fatalerror("generate_clear_mode1_imm: tried to disable MR alternate"); + if (data & 0x8) // DAG1 regs 4-7 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x8); + UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 + UML_CALLH(block, *m_swap_dag1_4_7); + UML_LABEL(block, skip); + } + if (data & 0x10) // DAG1 regs 0-3 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x10); + UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 + UML_CALLH(block, *m_swap_dag1_0_3); + UML_LABEL(block, skip); + } + if (data & 0x20) // DAG2 regs 4-7 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x20); + UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 + UML_CALLH(block, *m_swap_dag2_4_7); + UML_LABEL(block, skip); + } + if (data & 0x40) // DAG1 regs 0-3 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x40); + UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 + UML_CALLH(block, *m_swap_dag2_0_3); + UML_LABEL(block, skip); + } + if (data & 0x80) // REG 8-15 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x80); + UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 + UML_CALLH(block, *m_swap_r8_15); + UML_LABEL(block, skip); + } + if (data & 0x400) // REG 0-7 + { + code_label skip = compiler->labelnum++; + UML_TEST(block, MODE1, 0x400); + UML_JMPc(block, COND_Z, skip); // don't swap if the bit is already 0 + UML_CALLH(block, *m_swap_r0_7); + UML_LABEL(block, skip); + } + + UML_AND(block, MODE1, MODE1, ~data); +} + + + +void adsp21062_device::generate_update_circular_buffer(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int g, int i) +{ + // TODO +} + +void adsp21062_device::generate_astat_copy(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) +{ + UML_MOV(block, mem(&m_core->astat_drc_copy.az), ASTAT_AZ); + UML_MOV(block, mem(&m_core->astat_drc_copy.av), ASTAT_AV); + UML_MOV(block, mem(&m_core->astat_drc_copy.an), ASTAT_AN); + UML_MOV(block, mem(&m_core->astat_drc_copy.av), ASTAT_AV); + UML_MOV(block, mem(&m_core->astat_drc_copy.as), ASTAT_AS); + UML_MOV(block, mem(&m_core->astat_drc_copy.ai), ASTAT_AI); + UML_MOV(block, mem(&m_core->astat_drc_copy.af), ASTAT_AF); + UML_MOV(block, mem(&m_core->astat_drc_copy.mn), ASTAT_MN); + UML_MOV(block, mem(&m_core->astat_drc_copy.mv), ASTAT_MV); + UML_MOV(block, mem(&m_core->astat_drc_copy.mu), ASTAT_MU); + UML_MOV(block, mem(&m_core->astat_drc_copy.mi), ASTAT_MI); + UML_MOV(block, mem(&m_core->astat_drc_copy.sv), ASTAT_SV); + UML_MOV(block, mem(&m_core->astat_drc_copy.sz), ASTAT_SZ); + UML_MOV(block, mem(&m_core->astat_drc_copy.ss), ASTAT_SS); + UML_MOV(block, mem(&m_core->astat_drc_copy.btf), ASTAT_BTF); + UML_MOV(block, mem(&m_core->astat_drc_copy.cacc), mem(&m_core->astat_drc.cacc)); +} + + + +void adsp21062_device::generate_call(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, bool delayslot) +{ + // I0 = target pc for dynamic branches + + compiler_state compiler_temp = *compiler; + + // save branch target + if (desc->targetpc == BRANCH_TARGET_DYNAMIC) + { + UML_MOV(block, mem(&m_core->jmpdest), I0); // mov [jmpdest],i0 + } + + // compile delay slots if needed + if (delayslot) + { + generate_sequence_instruction(block, &compiler_temp, desc->delay.first()); + generate_sequence_instruction(block, &compiler_temp, desc->delay.last()); + } + + if (delayslot) + UML_MOV(block, I0, desc->pc + 3); + else + UML_MOV(block, I0, desc->pc + 1); + UML_CALLH(block, *m_push_pc); + + // update cycles and hash jump + if (desc->targetpc != BRANCH_TARGET_DYNAMIC) + { + generate_update_cycles(block, &compiler_temp, desc->targetpc, TRUE); + if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + UML_JMP(block, desc->targetpc | 0x80000000); // jmp targetpc | 0x80000000 + else + UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp 0,targetpc,nocode + } + else + { + generate_update_cycles(block, &compiler_temp, mem(&m_core->jmpdest), TRUE); + UML_HASHJMP(block, 0, mem(&m_core->jmpdest), *m_nocode); // hashjmp 0,jmpdest,nocode + } + + // update compiler label + compiler->labelnum = compiler_temp.labelnum; + + /* reset the mapvar to the current cycles and account for skipped slots */ + compiler->cycles += desc->skipslots; + UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles +} + +void adsp21062_device::generate_jump(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, bool delayslot, bool loopabort, bool clearint) +{ + // I0 = target pc for dynamic branches + + compiler_state compiler_temp = *compiler; + + // save branch target + if (desc->targetpc == BRANCH_TARGET_DYNAMIC) + { + UML_MOV(block, mem(&m_core->jmpdest), I0); // mov [jmpdest],i0 + } + + // compile delay slots if needed + if (delayslot) + { + generate_sequence_instruction(block, &compiler_temp, desc->delay.first()); + generate_sequence_instruction(block, &compiler_temp, desc->delay.last()); + } + + // update cycles and hash jump + if (desc->targetpc != BRANCH_TARGET_DYNAMIC) + { + generate_update_cycles(block, &compiler_temp, desc->targetpc, TRUE); + if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + UML_JMP(block, desc->targetpc | 0x80000000); // jmp targetpc | 0x80000000 + else + UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp 0,targetpc,nocode + } + else + { + generate_update_cycles(block, &compiler_temp, mem(&m_core->jmpdest), TRUE); + UML_HASHJMP(block, 0, mem(&m_core->jmpdest), *m_nocode); // hashjmp 0,jmpdest,nocode + } + + // update compiler label + compiler->labelnum = compiler_temp.labelnum; + + /* reset the mapvar to the current cycles and account for skipped slots */ + compiler->cycles += desc->skipslots; + UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles +} + +/*------------------------------------------------- +generate_write_ureg - UREG is read into I0 +-------------------------------------------------*/ + +void adsp21062_device::generate_read_ureg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int ureg, bool has_compute) +{ + // UREG is read into I0 + + switch (ureg) + { + // REG 0-15 + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + UML_MOV(block, I0, REG(ureg & 0xf)); + break; + // I0-7 + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + UML_MOV(block, I0, mem(&m_core->dag1.i[ureg & 7])); + break; + // I8-15 + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: + UML_MOV(block, I0, mem(&m_core->dag2.i[ureg & 7])); + break; + // M0-7 + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + UML_MOV(block, I0, mem(&m_core->dag1.m[ureg & 7])); + break; + // M8-15 + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + UML_MOV(block, I0, mem(&m_core->dag2.m[ureg & 7])); + break; + // L0-7 + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + UML_MOV(block, I0, mem(&m_core->dag1.l[ureg & 7])); + break; + // L8-15 + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + UML_MOV(block, I0, mem(&m_core->dag2.l[ureg & 7])); + break; + // B0-7 + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + UML_MOV(block, I0, mem(&m_core->dag1.b[ureg & 7])); + break; + // B8-15 + case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: + UML_MOV(block, I0, mem(&m_core->dag2.b[ureg & 7])); + break; + + case 0x64: // PCSTK + fatalerror("generate_read_ureg: PCSTK"); + break; + case 0x70: // USTAT1 + UML_MOV(block, I0, mem(&m_core->ustat1)); + break; + case 0x71: // USTAT2 + UML_MOV(block, I0, mem(&m_core->ustat2)); + break; + case 0x79: // IRPTL + UML_MOV(block, I0, mem(&m_core->irptl)); + break; + case 0x7a: // MODE2 + UML_MOV(block, I0, mem(&m_core->mode2)); + break; + case 0x7b: // MODE1 + UML_MOV(block, I0, mem(&m_core->mode1)); + break; + case 0x7c: // ASTAT + // construct from bits + if (!has_compute) + { + // no compute, just read normally from ASTAT + UML_XOR(block, I0, I0, I0); + UML_OR(block, I0, I0, ASTAT_AZ); + UML_SHL(block, I1, ASTAT_AV, 1); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_AN, 2); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_AC, 3); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_AS, 4); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_AI, 5); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_MN, 6); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_MV, 7); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_MU, 8); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_MI, 9); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_AF, 10); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_SV, 11); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_SZ, 12); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_SS, 13); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, ASTAT_BTF, 18); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG0, 19); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG1, 20); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG2, 21); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG3, 22); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc.cacc), 24); + UML_OR(block, I0, I0, I1); + } + else + { + // read from ASTAT copy if this opcode also does compute + UML_XOR(block, I0, I0, I0); + UML_OR(block, I0, I0, mem(&m_core->astat_drc_copy.az)); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.av), 1); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.an), 2); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.ac), 3); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.as), 4); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.ai), 5); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mn), 6); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mv), 7); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mu), 8); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.mi), 9); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.af), 10); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.sv), 11); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.sz), 12); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.ss), 13); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.btf), 18); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG0, 19); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG1, 20); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG2, 21); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, FLAG3, 22); + UML_OR(block, I0, I0, I1); + UML_SHL(block, I1, mem(&m_core->astat_drc_copy.cacc), 24); + UML_OR(block, I0, I0, I1); + } + break; + case 0x7d: // IMASK + UML_MOV(block, I0, mem(&m_core->imask)); + break; + case 0x7e: // STKY + UML_MOV(block, I0, mem(&m_core->stky)); + break; + case 0xdb: // PX + UML_DMOV(block, I0, mem(&m_core->px)); // NOTE: this returns 64 bits + break; + case 0xdc: // PX1 (bits 0-15 of PX) + UML_MOV(block, I0, mem(&m_core->px)); + UML_AND(block, I0, I0, 0xffff); + break; + case 0xdd: // PX2 (bits 16-47 of PX) + UML_DMOV(block, I0, mem(&m_core->px)); + UML_DSHR(block, I0, I0, 16); + UML_DAND(block, I0, I0, 0xffffffff); + break; + + default: + fatalerror("generate_read_ureg %02X", ureg); + break; + } +} + + +/*------------------------------------------------- + generate_write_ureg - contents of register I0 or 32-bit immediate data are written into UREG +-------------------------------------------------*/ + +void adsp21062_device::generate_write_ureg(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int ureg, bool imm, UINT32 data) +{ + switch (ureg) + { + // REG 0-15 + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + UML_MOV(block, REG(ureg & 0xf), imm ? data : I0); + break; + // I0-7 + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + UML_MOV(block, DM_I(ureg & 7), imm ? data : I0); + break; + // I8-15 + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: + UML_MOV(block, PM_I(ureg & 7), imm ? data : I0); + break; + // M0-7 + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + UML_MOV(block, DM_M(ureg & 7), imm ? data : I0); + break; + // M8-15 + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + UML_MOV(block, PM_M(ureg & 7), imm ? data : I0); + break; + // L0-7 + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + UML_MOV(block, DM_L(ureg & 7), imm ? data : I0); + break; + // L8-15 + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + UML_MOV(block, PM_L(ureg & 7), imm ? data : I0); + break; + // B0-7 + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + // Note: loading B also loads the same value in I + UML_MOV(block, DM_B(ureg & 7), imm ? data : I0); + UML_MOV(block, DM_I(ureg & 7), imm ? data : I0); + break; + // B8-15 + case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: + // Note: loading B also loads the same value in I + UML_MOV(block, PM_B(ureg & 7), imm ? data : I0); + UML_MOV(block, PM_B(ureg & 7), imm ? data : I0); + break; + + case 0x64: // PCSTK + fatalerror("generate_write_ureg: PCSTK"); + break; + case 0x70: // USTAT1 + UML_MOV(block, mem(&m_core->ustat1), imm ? data : I0); + break; + case 0x71: // USTAT2 + UML_MOV(block, mem(&m_core->ustat2), imm ? data : I0); + break; + case 0x79: // IRPTL + UML_MOV(block, mem(&m_core->irptl), imm ? data : I0); + break; + case 0x7a: // MODE2 + UML_MOV(block, mem(&m_core->mode2), imm ? data : I0); + break; + case 0x7b: // MODE1 + // MODE1 needs to be written delayed + if (imm) + { + compiler->mode1_delay.counter = 2; + compiler->mode1_delay.data = data; + compiler->mode1_delay.mode = MODE1_WRITE_IMM; + } + else + { + compiler->mode1_delay.counter = 2; + compiler->mode1_delay.mode = MODE1_WRITE_REG; + UML_MOV(block, mem(&m_core->mode1_delay_data), I0); + } + break; + case 0x7c: // ASTAT + // TODO: needs bit break up + fatalerror("generate_write_ureg: ASTAT"); + break; + case 0x7d: // IMASK + UML_MOV(block, mem(&m_core->imask), imm ? data : I0); + break; + case 0x7e: // STKY + UML_MOV(block, mem(&m_core->stky), imm ? data : I0); + break; + case 0xdb: // PX + if (imm) + { + fatalerror("generate_write_ureg %02X with immediate!", ureg); + } + else + { + UML_DMOV(block, mem(&m_core->px), I0); + } + break; + case 0xdc: // PX1 (bits 0-15 of PX) + if (imm) + { + UML_DAND(block, mem(&m_core->px), mem(&m_core->px), ~0xffff); + UML_DOR(block, mem(&m_core->px), mem(&m_core->px), (UINT64)(data)); + } + else + { + UML_DAND(block, mem(&m_core->px), mem(&m_core->px), ~0xffff); + UML_DXOR(block, I1, I1, I1); + UML_DAND(block, I1, I0, 0xffff); + UML_DOR(block, mem(&m_core->px), mem(&m_core->px), I1); + } + break; + case 0xdd: // PX2 (bits 16-47 of PX) + if (imm) + { + UML_DAND(block, mem(&m_core->px), mem(&m_core->px), 0xffff); + UML_DOR(block, mem(&m_core->px), mem(&m_core->px), (UINT64)(data) << 16); + } + else + { + UML_DAND(block, mem(&m_core->px), mem(&m_core->px), 0xffff); + UML_DSHL(block, I0, I0, 16); + UML_DOR(block, mem(&m_core->px), mem(&m_core->px), I0); + } + break; + + default: + fatalerror("generate_write_ureg %02X", ureg); + break; + } +} + +int adsp21062_device::generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) +{ + UINT64 opcode = desc->opptr.q[0]; + + switch ((opcode >> 45) & 7) + { + case 0: // subops + { + UINT32 subop = (opcode >> 40) & 0x1f; + switch (subop) + { + case 0x00: // NOP / idle |000|00000| + if (opcode & U64(0x008000000000)) + { + // IDLE + UML_MOV(block, mem(&m_core->idle), 1); + UML_MOV(block, mem(&m_core->icount), 0); + return TRUE; + } + else + { + // NOP + return TRUE; + } + break; + + case 0x01: // compute |000|00001| + { + int cond = (opcode >> 33) & 0x1f; + + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + + generate_compute(block, compiler, desc); + + if (has_condition) + UML_LABEL(block, skip_label); + return TRUE; + } + + case 0x02: // immediate shift |000|00010| + { + int shiftop = (opcode >> 16) & 0x3f; + int rn = (opcode >> 4) & 0xf; + int rx = (opcode & 0xf); + int cond = (opcode >> 33) & 0x1f; + int data = ((opcode >> 8) & 0xff) | ((opcode >> 19) & 0xf00); + + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + + generate_shift_imm(block, compiler, desc, data, shiftop, rn, rx); + + if (has_condition) + UML_LABEL(block, skip_label); + return TRUE; + } + + case 0x04: // compute / modify |000|00100| + { + int cond = (opcode >> 33) & 0x1f; + int compute = opcode & 0x7fffff; + int g = (opcode >> 38) & 0x1; + int m = (opcode >> 27) & 0x7; + int i = (opcode >> 30) & 0x7; + + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + + generate_compute(block, compiler, desc); + + if (g) + { + // PM + UML_ADD(block, PM_I(i), PM_I(i), PM_M(m)); + } + else + { + // DM + UML_ADD(block, DM_I(i), DM_I(i), DM_M(m)); + } + + generate_update_circular_buffer(block, compiler, desc, g, i); + + if (has_condition) + UML_LABEL(block, skip_label); + + return TRUE; + } + + case 0x06: // direct jump|call |000|00110| + { + int b = (opcode >> 39) & 0x1; + int j = (opcode >> 26) & 0x1; + int la = (opcode >> 38) & 0x1; + int ci = (opcode >> 24) & 0x1; + int cond = (opcode >> 33) & 0x1f; + + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + if (b) // call + { + generate_call(block, compiler, desc, j != 0); + } + else // jump + { + generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); + } + if (has_condition) + UML_LABEL(block, skip_label); + return TRUE; + } + + case 0x07: // direct jump|call |000|00111| + { + int b = (opcode >> 39) & 0x1; + int j = (opcode >> 26) & 0x1; + int la = (opcode >> 38) & 0x1; + int ci = (opcode >> 24) & 0x1; + int cond = (opcode >> 33) & 0x1f; + + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + if (b) // call + { + generate_call(block, compiler, desc, j != 0); + } + else // jump + { + generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); + } + if (has_condition) + UML_LABEL(block, skip_label); + return TRUE; + } + + case 0x08: // indirect jump|call / compute |000|01000| + { + int la = (opcode >> 38) & 0x1; + int ci = (opcode >> 24) & 0x1; + int b = (opcode >> 39) & 0x1; + int j = (opcode >> 26) & 0x1; + int e = (opcode >> 25) & 0x1; + int pmi = (opcode >> 30) & 0x7; + int pmm = (opcode >> 27) & 0x7; + int cond = (opcode >> 33) & 0x1f; + int compute = opcode & 0x7fffff; + + if (e) + { + // IF ... ELSE + + int label_else = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, label_else); + + UML_ADD(block, I0, PM_I(pmi), PM_M(pmm)); + + if (b) // call + { + generate_call(block, compiler, desc, j != 0); + } + else // jump + { + generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); + } + + UML_LABEL(block, label_else); + generate_compute(block, compiler, desc); + } + else + { + // IF + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + generate_compute(block, compiler, desc); + + UML_ADD(block, I0, PM_I(pmi), PM_M(pmm)); + + if (b) // call + { + generate_call(block, compiler, desc, j != 0); + } + else // jump + { + generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); + } + + if (has_condition) + UML_LABEL(block, skip_label); + } + + return TRUE; + } + + case 0x09: // indirect jump|call / compute |000|01001| + { + int la = (opcode >> 38) & 0x1; + int ci = (opcode >> 24) & 0x1; + int b = (opcode >> 39) & 0x1; + int j = (opcode >> 26) & 0x1; + int e = (opcode >> 25) & 0x1; + int cond = (opcode >> 33) & 0x1f; + int compute = opcode & 0x7fffff; + + if (e) + { + // IF ... ELSE + + int label_else = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, label_else); + + if (b) // call + { + generate_call(block, compiler, desc, j != 0); + } + else // jump + { + generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); + } + + UML_LABEL(block, label_else); + generate_compute(block, compiler, desc); + } + else + { + // IF + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + generate_compute(block, compiler, desc); + + if (b) // call + { + generate_call(block, compiler, desc, j != 0); + } + else // jump + { + generate_jump(block, compiler, desc, j != 0, la != 0, ci != 0); + } + + if (has_condition) + UML_LABEL(block, skip_label); + } + + return TRUE; + } + + case 0x0a: // return from subroutine / compute |000|01010| + { + int cond = (opcode >> 33) & 0x1f; + int j = (opcode >> 26) & 0x1; + int e = (opcode >> 25) & 0x1; + //int lr = (opcode >> 24) & 0x1; + int compute = opcode & 0x7fffff; + + // TODO: loop re-entry + + if (e) + { + // IF ... ELSE + + int label_else = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, label_else); + + UML_CALLH(block, *m_pop_pc); + generate_jump(block, compiler, desc, j != 0, false, false); + + UML_LABEL(block, label_else); + generate_compute(block, compiler, desc); + } + else + { + // IF + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + generate_compute(block, compiler, desc); + + UML_CALLH(block, *m_pop_pc); + generate_jump(block, compiler, desc, j != 0, false, false); + + if (has_condition) + UML_LABEL(block, skip_label); + } + + return TRUE; + } + + case 0x0b: // return from interrupt / compute |000|01011| + { + int cond = (opcode >> 33) & 0x1f; + int j = (opcode >> 26) & 0x1; + int e = (opcode >> 25) & 0x1; + int compute = opcode & 0x7fffff; + + + code_label skip_pop = compiler->labelnum++; + + UML_MOV(block, mem(&m_core->interrupt_active), 0); // mov [interrupt_active],0 + UML_MOV(block, I0, 1); // mov i0,1 + UML_SHL(block, I0, I0, mem(&m_core->active_irq_num)); // shl i0,[active_irq_num] + UML_XOR(block, IRPTL, IRPTL, I0); // xor IRPTL,i0 + UML_CMP(block, mem(&m_core->status_stkp), 0); // cmp [status_stkp],0 + UML_JMPc(block, COND_Z, skip_pop); // jz skip_pop + UML_CALLH(block, *m_pop_status); // callh m_pop_status + + UML_LABEL(block, skip_pop); // skip_pop: + + // TODO: check interrupts + + if (e) + { + // IF ... ELSE + + code_label label_else = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, label_else); + + UML_CALLH(block, *m_pop_pc); + generate_jump(block, compiler, desc, j != 0, false, false); + + UML_LABEL(block, label_else); + generate_compute(block, compiler, desc); + } + else + { + // IF + bool has_condition = !if_condition_always_true(cond); + code_label skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + generate_compute(block, compiler, desc); + + UML_CALLH(block, *m_pop_pc); + generate_jump(block, compiler, desc, j != 0, false, false); + + if (has_condition) + UML_LABEL(block, skip_label); + } + + return TRUE; + } + + case 0x0c: // do until counter expired |000|01100| + { + UINT16 data = (UINT16)(opcode >> 24); + int offset = SIGN_EXTEND24(opcode & 0xffffff); + UINT32 address = desc->pc + offset; + + UML_MOV(block, LCNTR, data); + if (data > 0) + { + // push pc + UML_MOV(block, I0, desc->pc + 1); + UML_CALLH(block, *m_push_pc); + + // push loop + UML_MOV(block, I0, data); + UML_MOV(block, I1, address); + UML_CALLH(block, *m_push_loop); + } + return TRUE; + } + + case 0x0d: // do until counter expired |000|01101| + { + int ureg = (opcode >> 32) & 0xff; + int offset = SIGN_EXTEND24(opcode & 0xffffff); + UINT32 address = desc->pc + offset; + + generate_read_ureg(block, compiler, desc, ureg, false); + + UML_AND(block, I3, I0, 0xffff); + UML_MOV(block, LCNTR, I3); + + // push pc + UML_MOV(block, I0, desc->pc + 1); + UML_CALLH(block, *m_push_pc); + + // push loop + UML_MOV(block, I0, I3); + UML_MOV(block, I1, address); + UML_CALLH(block, *m_push_loop); + return TRUE; + } + + case 0x0e: // do until |000|01110| + { + int offset = SIGN_EXTEND24(opcode & 0xffffff); + UINT32 address = desc->pc + offset; + + // push pc + UML_MOV(block, I0, desc->pc + 1); + UML_CALLH(block, *m_push_pc); + + // push loop + UML_MOV(block, I0, 0); + UML_MOV(block, I1, address); + UML_CALLH(block, *m_push_loop); + return TRUE; + } + + case 0x0f: // immediate data -> ureg |000|01111| + { + int ureg = (opcode >> 32) & 0xff; + UINT32 data = (UINT32)opcode; + + generate_write_ureg(block, compiler, desc, ureg, true, data); + return TRUE; + } + + case 0x10: // ureg <-> DM|PM (direct) |000|100|G|D| + case 0x11: + case 0x12: + case 0x13: + { + int ureg = (opcode >> 32) & 0xff; + UINT32 address = (UINT32)(opcode); + int d = (opcode >> 40) & 1; + int g = (opcode >> 41) & 1; + + UML_MOV(block, I1, address); + if (d) + { + generate_read_ureg(block, compiler, desc, ureg, false); + + // write + if (g) + { + // PM + if (ureg == 0xdb) // PX is 48-bit + UML_CALLH(block, *m_pm_write48); + else + UML_CALLH(block, *m_pm_write32); + } + else + { + // DM + UML_CALLH(block, *m_dm_write32); + } + } + else + { + // read + if (g) + { + // PM + if (ureg == 0xdb) // PX is 48-bit + UML_CALLH(block, *m_pm_read48); + else + UML_CALLH(block, *m_pm_read32); + } + else + { + // DM + UML_CALLH(block, *m_dm_read32); + } + + generate_write_ureg(block, compiler, desc, ureg, false, 0); + } + return TRUE; + } + + case 0x14: // system register bit manipulation |000|10100| + { + int bop = (opcode >> 37) & 0x7; + int sreg = (opcode >> 32) & 0xf; + UINT32 data = (UINT32)opcode; + + switch (bop) + { + case 0: // SET + { + switch (sreg) + { + case 0x0: // USTAT1 + UML_OR(block, USTAT1, USTAT1, data); + break; + case 0x1: // USTAT2 + UML_OR(block, USTAT2, USTAT2, data); + break; + case 0x9: // IRPTL + UML_OR(block, IRPTL, IRPTL, data); + break; + case 0xa: // MODE2 + UML_OR(block, MODE2, MODE2, data); + break; + case 0xb: // MODE1 + compiler->mode1_delay.counter = 2; + compiler->mode1_delay.data = data; + compiler->mode1_delay.mode = MODE1_SET; + break; + case 0xc: // ASTAT + return FALSE; + case 0xd: // IMASK + UML_OR(block, IMASK, IMASK, data); + break; + case 0xe: // STKY + UML_OR(block, STKY, STKY, data); + break; + case 0xf: // IMASKP + UML_OR(block, IMASKP, IMASKP, data); + break; + + default: + return FALSE; + } + return TRUE; + } + case 1: // CLEAR + { + switch (sreg) + { + case 0x0: // USTAT1 + UML_AND(block, USTAT1, USTAT1, ~data); + break; + case 0x1: // USTAT2 + UML_AND(block, USTAT2, USTAT2, ~data); + break; + case 0x9: // IRPTL + UML_AND(block, IRPTL, IRPTL, ~data); + break; + case 0xa: // MODE2 + UML_AND(block, MODE2, MODE2, ~data); + break; + case 0xb: // MODE1 + compiler->mode1_delay.counter = 2; + compiler->mode1_delay.data = data; + compiler->mode1_delay.mode = MODE1_CLEAR; + break; + case 0xc: // ASTAT + return FALSE; + case 0xd: // IMASK + UML_AND(block, IMASK, IMASK, ~data); + break; + case 0xe: // STKY + UML_AND(block, STKY, STKY, ~data); + break; + case 0xf: // IMASKP + UML_AND(block, IMASKP, IMASKP, ~data); + break; + + default: + return FALSE; + } + return TRUE; + } + case 2: // TOGGLE + { + switch (sreg) + { + case 0x0: // USTAT1 + UML_XOR(block, USTAT1, USTAT1, data); + break; + case 0x1: // USTAT2 + UML_XOR(block, USTAT2, USTAT2, data); + break; + case 0x9: // IRPTL + UML_XOR(block, IRPTL, IRPTL, data); + break; + case 0xa: // MODE2 + UML_XOR(block, MODE2, MODE2, data); + break; + case 0xb: // MODE1 + compiler->mode1_delay.counter = 2; + compiler->mode1_delay.data = data; + compiler->mode1_delay.mode = MODE1_TOGGLE; + break; + case 0xc: // ASTAT + return FALSE; + case 0xd: // IMASK + UML_XOR(block, IMASK, IMASK, data); + break; + case 0xe: // STKY + UML_XOR(block, STKY, STKY, data); + break; + case 0xf: // IMASKP + UML_XOR(block, IMASKP, IMASKP, data); + break; + + default: + return FALSE; + } + return TRUE; + } + case 4: // TEST + { + switch (sreg) + { + case 0x0: // USTAT1 + UML_AND(block, I0, USTAT1, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + case 0x1: // USTAT2 + UML_AND(block, I0, USTAT2, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + case 0x9: // IRPTL + UML_AND(block, I0, IRPTL, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + case 0xa: // MODE2 + UML_AND(block, I0, MODE2, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + case 0xb: // MODE1 + UML_AND(block, I0, MODE1, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + case 0xc: // ASTAT + return FALSE; + case 0xd: // IMASK + UML_AND(block, I0, IMASK, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + case 0xe: // STKY + UML_AND(block, I0, STKY, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + case 0xf: // IMASKP + UML_AND(block, I0, IMASKP, data); + UML_CMP(block, I0, data); + UML_SETc(block, COND_E, ASTAT_BTF); + break; + + default: + return FALSE; + } + return TRUE; + } + case 5: // XOR + { + return FALSE; + } + + default: + return FALSE; + } + return TRUE; + } + + case 0x16: // I register modify / bit-reverse |000|10110| + { + if (opcode & U64(0x008000000000)) // bit reverse + { + return FALSE; + } + else // modify + { + int g = (opcode >> 38) & 0x1; + int i = (opcode >> 32) & 0x7; + INT32 data = (INT32)(opcode); + + if (g) + { + // PM + UML_ADD(block, PM_I(i), PM_I(i), data); + } + else + { + // DM + UML_ADD(block, DM_I(i), DM_I(i), data); + } + generate_update_circular_buffer(block, compiler, desc, g, i); + return TRUE; + } + } + + case 0x17: // push|pop stacks / flush cache |000|10111| + return FALSE; + + case 0x18: // cjump |000|11000| + return FALSE; + + case 0x19: // rframe |000|11001| + return FALSE; + + default: + return FALSE; + } + break; + } + + case 1: // compute / dreg <-> DM / dreg <-> PM |001| + { + return FALSE; + } + + case 2: // compute / ureg <-> DM|PM, register modify |010| + { + int u = (opcode >> 44) & 0x1; + int i = (opcode >> 41) & 0x7; + int m = (opcode >> 38) & 0x7; + int cond = (opcode >> 33) & 0x1f; + int g = (opcode >> 32) & 0x1; + int d = (opcode >> 31) & 0x1; + int ureg = (opcode >> 23) & 0xff; + int compute = opcode & 0x7fffff; + + bool ureg_is_dreg = (ureg >= 0 && ureg < 16); + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + bool ureg_is_astat = (ureg == 0x7c); + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + + if (d) + { + // UREG -> DM|PM + bool temp_ureg = false; + + // save UREG if compute writes to it + if (compute != 0 && ureg_is_dreg && desc->regout[0] & (1 << (ureg & 0xf))) + { + UML_MOV(block, mem(&m_core->dreg_temp), REG(ureg & 0xf)); + temp_ureg = true; + } + + // save a copy of ASTAT if we need to read it + if (ureg_is_astat) + generate_astat_copy(block, compiler, desc); + + // compute + generate_compute(block, compiler, desc); + + // transfer + UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] + if (u == 0) // pre-modify without update + UML_ADD(block, I1, I1, (g) ? PM_M(m) : DM_M(m)); // add i1,i1,dm|pm[m] + if (temp_ureg) + UML_MOV(block, I0, mem(&m_core->dreg_temp)); // mov i0,[m_core->dreg_temp] + else + generate_read_ureg(block, compiler, desc, ureg, ureg_is_astat); + + if (ureg == 0xdb && (g)) // PX is 48-bit when writing to PM + UML_CALLH(block, *m_pm_write48); // callh pm_write48 + else + UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 + } + else + { + // DM|PM -> UREG + + // compute + generate_compute(block, compiler, desc); + + // transfer + UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] + if (u == 0) // pre-modify without update + UML_ADD(block, I1, I1, (g) ? PM_M(m) : DM_M(m)); // add i1,i1,dm|pm[m] + + if (ureg == 0xdb && (g)) // PX is 48-bit when reading from PM + UML_CALLH(block, *m_pm_read48); // callh pm_read48 + else + UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 + generate_write_ureg(block, compiler, desc, ureg, false, 0); + } + + if (u != 0) // post-modify with update + { + if (g) + UML_ADD(block, PM_I(i), PM_I(i), PM_M(m)); // add pm[i],pm[m] + else + UML_ADD(block, DM_I(i), DM_I(i), DM_M(m)); // add dm[i],dm[m] + + generate_update_circular_buffer(block, compiler, desc, g, i); + } + + if (has_condition) + UML_LABEL(block, skip_label); + + return TRUE; + } + + case 3: + { + if (opcode & U64(0x100000000000)) // compute / ureg <-> ureg |011|1| + { + int src_ureg = (opcode >> 36) & 0xff; + int dst_ureg = (opcode >> 23) & 0xff; + int cond = (opcode >> 31) & 0x1f; + int compute = opcode & 0x7fffff; + + bool has_condition = !if_condition_always_true(cond); + bool src_is_dreg = (src_ureg >= 0 && src_ureg < 16); + int skip_label = 0; + + bool src_ureg_is_astat = (src_ureg == 0x7c); + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + + bool temp_ureg = false; + // save UREG if compute writes to it + if (compute != 0 && src_is_dreg && desc->regout[0] & (1 << (src_ureg & 0xf))) + { + UML_MOV(block, mem(&m_core->dreg_temp), REG(src_ureg & 0xf)); + temp_ureg = true; + } + + // save a copy of ASTAT if we need to read it + if (src_ureg_is_astat) + generate_astat_copy(block, compiler, desc); + + generate_compute(block, compiler, desc); + + if (temp_ureg) + { + UML_MOV(block, I0, mem(&m_core->dreg_temp)); + } + else + { + generate_read_ureg(block, compiler, desc, src_ureg, src_ureg_is_astat); + } + generate_write_ureg(block, compiler, desc, dst_ureg, false, 0); + + if (has_condition) + UML_LABEL(block, skip_label); + + return TRUE; + } + else // compute / dreg <-> DM|PM, immediate modify |011|0| + { + int cond = (opcode >> 33) & 0x1f; + int u = (opcode >> 38) & 0x1; + int d = (opcode >> 39) & 0x1; + int g = (opcode >> 40) & 0x1; + int dreg = (opcode >> 23) & 0xf; + int i = (opcode >> 41) & 0x7; + int mod = SIGN_EXTEND6((opcode >> 27) & 0x3f); + int compute = opcode & 0x7fffff; + + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + if (d) + { + // DREG -> DM|PM + bool temp_dreg = false; + + // save dreg if compute writes to it + if (compute != 0 && desc->regout[0] & (1 << dreg)) + { + UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); + temp_dreg = true; + } + // compute + generate_compute(block, compiler, desc); + + // transfer + UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] + if (u == 0) // pre-modify without update + UML_ADD(block, I1, I1, mod); // add i1,i1,mod + if (temp_dreg) + UML_MOV(block, I0, mem(&m_core->dreg_temp)); // mov i0,[m_core->dreg_temp] + else + UML_MOV(block, I0, REG(dreg)); // mov i0,reg[dreg] + UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 + } + else + { + // DM|PM -> DREG + + // compute + generate_compute(block, compiler, desc); + + // transfer + UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] + if (u == 0) // pre-modify without update + UML_ADD(block, I1, I1, mod); // add i1,i1,mod + UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 + UML_MOV(block, REG(dreg), I0); // mov reg[dreg],i0 + } + + if (u != 0) // post-modify with update + { + if (g) + UML_ADD(block, PM_I(i), PM_I(i), mod); // add pm[i],mod + else + UML_ADD(block, DM_I(i), DM_I(i), mod); // add dm[i],mod + + generate_update_circular_buffer(block, compiler, desc, g, i); + } + if (has_condition) + UML_LABEL(block, skip_label); + + return TRUE; + } + break; + } + + case 4: + { + if (opcode & U64(0x100000000000)) // immediate data -> DM|PM |100|1| + { + return FALSE; + } + else // immediate shift / dreg <-> DM|PM |100|0| + { + int i = (opcode >> 41) & 0x7; + int m = (opcode >> 38) & 0x7; + int g = (opcode >> 32) & 0x1; + int d = (opcode >> 31) & 0x1; + int dreg = (opcode >> 23) & 0xf; + int cond = (opcode >> 33) & 0x1f; + int data = ((opcode >> 8) & 0xff) | ((opcode >> 19) & 0xf00); + int shiftop = (opcode >> 16) & 0x3f; + int rn = (opcode >> 4) & 0xf; + int rx = (opcode & 0xf); + + bool has_condition = !if_condition_always_true(cond); + int skip_label = 0; + + if (has_condition) + { + skip_label = compiler->labelnum++; + generate_if_condition(block, compiler, desc, cond, skip_label); + } + if (d) + { + // DREG -> DM|PM + bool temp_dreg = false; + + // save dreg if shiftop writes to it + if (desc->regout[0] & (1 << dreg)) + { + UML_MOV(block, mem(&m_core->dreg_temp), REG(dreg)); + temp_dreg = true; + } + // shiftop + generate_shift_imm(block, compiler, desc, data, shiftop, rn, rx); + + // transfer + UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] + if (temp_dreg) + UML_MOV(block, I0, mem(&m_core->dreg_temp)); // mov i0,[m_core->dreg_temp] + else + UML_MOV(block, I0, REG(dreg)); // mov i0,reg[dreg] + UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 + } + else + { + // DM|PM -> DREG + + // shiftop + generate_shift_imm(block, compiler, desc, data, shiftop, rn, rx); + + // transfer + UML_MOV(block, I1, (g) ? PM_I(i) : DM_I(i)); // mov i1,dm|pm[i] + UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 + UML_MOV(block, REG(dreg), I0); // mov reg[dreg],i0 + } + + // update I + if (g) + UML_ADD(block, PM_I(i), PM_I(i), PM_M(m)); + else + UML_ADD(block, DM_I(i), DM_I(i), DM_M(m)); + + generate_update_circular_buffer(block, compiler, desc, g, i); + + if (has_condition) + UML_LABEL(block, skip_label); + + return TRUE; + } + break; + } + + case 5: // ureg <-> DM|PM (indirect) |101| + { + int g = (opcode >> 44) & 1; + int d = (opcode >> 40) & 1; + int i = (opcode >> 41) & 0x7; + int ureg = (opcode >> 32) & 0xff; + UINT32 offset = (UINT32)opcode; + + if (d) + { + // UREG -> DM|PM + UML_ADD(block, I1, (g) ? PM_I(i) : DM_I(i), offset); // add i1,dm|pm[i],offset + + generate_read_ureg(block, compiler, desc, ureg, false); + + if (ureg == 0xdb && (g)) // PX is 48-bit when writing to PM + UML_CALLH(block, *m_pm_write48); // callh pm_write48 + else + UML_CALLH(block, (g) ? *m_pm_write32 : *m_dm_write32); // callh dm|pm_write32 + } + else + { + // DM|PM -> UREG + UML_ADD(block, I1, (g) ? PM_I(i) : DM_I(i), offset); // add i1,dm|pm[i],offset + + if (ureg == 0xdb && (g)) // PX is 48-bit when reading from PM + UML_CALLH(block, *m_pm_read48); // callh pm_read48 + else + UML_CALLH(block, (g) ? *m_pm_read32 : *m_dm_read32); // callh dm|pm_read32 + + generate_write_ureg(block, compiler, desc, ureg, false, 0); + } + return TRUE; + } + + case 6: // indirect jump / compute / dreg <-> DM |110| + { + return FALSE; + } + + case 7: // indirect jump / compute / dreg <-> DM |111| + { + return FALSE; + } + } + + return FALSE; +} + +void adsp21062_device::generate_unimplemented_compute(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) +{ + UML_MOV(block, mem(&m_core->pc), desc->pc); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_CALLC(block, cfunc_unimplemented_compute, this); +} + +void adsp21062_device::generate_compute(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) +{ + UINT64 opcode = desc->opptr.q[0]; + if ((opcode & 0x7fffff) == 0) + return; + + int rs = (opcode >> 12) & 0xf; + int rn = (opcode >> 8) & 0xf; + int ra = rn; + int rx = (opcode >> 4) & 0xf; + int ry = (opcode >> 0) & 0xf; + int ps = (opcode >> 16) & 0xf; + + if (opcode & 0x400000) // multi-function operation + { + UINT32 multiop = (opcode >> 16) & 0x3f; + int fm = rs; + int fa = rn; + int fxm = (opcode >> 6) & 0x3; // registers 0 - 3 + int fym = ((opcode >> 4) & 0x3) + 4; // registers 4 - 7 + int fxa = ((opcode >> 2) & 0x3) + 8; // registers 8 - 11 + int fya = (opcode & 0x3) + 12; // registers 12 - 15 + + switch (multiop) + { + case 0x00: // Rn = MRxx + { + generate_unimplemented_compute(block, compiler, desc); + return; + } + + case 0x01: // MRxx = Rn + { + int ai = rs; + switch (ai) + { + case 0x00: // MR0F + UML_DAND(block, MRF, MRF, U64(0xffffffff00000000)); + UML_AND(block, I0, REG(rn), 0xffffffff); + UML_DOR(block, MRF, MRF, I0); + break; + case 0x01: // MR1F + UML_DAND(block, MRF, MRF, U64(0x00000000ffffffff)); + UML_DSHL(block, I0, REG(rn), 32); + UML_DOR(block, MRF, MRF, I0); + break; + case 0x04: // MR0B + UML_DAND(block, MRB, MRB, U64(0xffffffff00000000)); + UML_AND(block, I0, REG(rn), 0xffffffff); + UML_DOR(block, MRB, MRB, I0); + break; + case 0x05: // MR1B + UML_DAND(block, MRB, MRB, U64(0x00000000ffffffff)); + UML_DSHL(block, I0, REG(rn), 32); + UML_DOR(block, MRB, MRB, I0); + break; + + case 0x02: // MR2F + case 0x06: // MR2B + generate_unimplemented_compute(block, compiler, desc); + return; + } + return; + } + + case 0x07: // Ra = Rx + Ry, Rs = Rx - Ry + case 0x0f: // Fa = Fx + Fy, Fs = Fx - Fy + case 0x04: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 + case 0x05: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 + case 0x06: // Rm = R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 + case 0x08: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 + case 0x09: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 + case 0x0a: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 + case 0x0c: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 + case 0x0d: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 + case 0x0e: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 + case 0x10: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 + case 0x11: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 + case 0x12: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 + case 0x14: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 + case 0x15: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 + case 0x16: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 + generate_unimplemented_compute(block, compiler, desc); + return; + + case 0x1c: // Fm = F3-0 * F7-4, Fa = (F11-8 + F15-12) / 2 + generate_unimplemented_compute(block, compiler, desc); + return; + + case 0x1d: // Fm = F3-0 * F7-4, Fa = ABS F11-8 + generate_unimplemented_compute(block, compiler, desc); + return; + + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12, Rs = R11-8 - R15-12 + generate_unimplemented_compute(block, compiler, desc); + return; + + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12, Fs = F11-8 - F15-12 + // TODO: denormals + UML_FSCOPYI(block, F0, REG(fxm)); + UML_FSCOPYI(block, F1, REG(fym)); + UML_FSCOPYI(block, F2, REG(fxa)); + UML_FSCOPYI(block, F3, REG(fya)); + UML_FSMUL(block, F0, F0, F1); + UML_FSADD(block, F4, F2, F3); + UML_FSSUB(block, F5, F2, F3); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F4, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F5, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, I0); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, I1); + if (AZ_CALC_REQUIRED) UML_OR(block, ASTAT_AZ, ASTAT_AZ, I0); + if (AN_CALC_REQUIRED) UML_OR(block, ASTAT_AN, ASTAT_AN, I1); + + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + + UML_ICOPYFS(block, REG(fm), F0); + UML_ICOPYFS(block, REG(fa), F4); + UML_ICOPYFS(block, REG(ps), F5); + return; + + case 0x18: // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12 + // TODO: denormals + UML_FSCOPYI(block, F0, REG(fxm)); + UML_FSCOPYI(block, F1, REG(fym)); + UML_FSCOPYI(block, F2, REG(fxa)); + UML_FSCOPYI(block, F3, REG(fya)); + UML_FSMUL(block, F0, F0, F1); + UML_FSADD(block, F2, F2, F3); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F2, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + + UML_ICOPYFS(block, REG(fm), F0); + UML_ICOPYFS(block, REG(fa), F2); + return; + + case 0x19: // Fm = F3-0 * F7-4, Fa = F11-8 - F15-12 + // TODO: denormals + UML_FSCOPYI(block, F0, REG(fxm)); + UML_FSCOPYI(block, F1, REG(fym)); + UML_FSCOPYI(block, F2, REG(fxa)); + UML_FSCOPYI(block, F3, REG(fya)); + UML_FSMUL(block, F0, F0, F1); + UML_FSSUB(block, F2, F2, F3); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F2, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + + UML_ICOPYFS(block, REG(fm), F0); + UML_ICOPYFS(block, REG(fa), F2); + return; + + case 0x1a: // Fm = F3-0 * F7-4, Fa = FLOAT F11-8 BY R15-12 + { + code_label denormal = compiler->labelnum++; + code_label end = compiler->labelnum++; + + // TODO: denormals + UML_FSCOPYI(block, F0, REG(fxm)); + UML_FSCOPYI(block, F1, REG(fym)); + UML_FSMUL(block, F0, F0, F1); + + UML_FSFRINT(block, F2, REG(fxa), SIZE_DWORD); + UML_ICOPYFS(block, I1, F2); + UML_AND(block, I0, I1, 0x7f800000); + UML_AND(block, I1, I1, 0x807fffff); + UML_SHR(block, I0, I0, 23); + UML_SUB(block, I0, I0, 127); + UML_ADD(block, I0, I0, REG(fya)); + UML_CMP(block, I0, -126); + UML_JMPc(block, COND_L, denormal); + + UML_ADD(block, I0, I0, 127); + UML_AND(block, I0, I0, 0xff); + UML_SHL(block, I0, I0, 23); + UML_OR(block, I0, I0, I1); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + UML_JMP(block, end); + + UML_LABEL(block, denormal); + UML_AND(block, I0, I1, 0x80000000); + if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); + if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + + UML_LABEL(block, end); + + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + + UML_ICOPYFS(block, REG(fm), F0); + UML_MOV(block, REG(fa), I0); + return; + } + + case 0x1b: // Fm = F3-0 * F7-4, Fa = FIX F11-8 BY R15-12 + { + code_label denormal = compiler->labelnum++; + code_label end = compiler->labelnum++; + + // TODO: denormals + UML_FSCOPYI(block, F0, REG(fxm)); + UML_FSCOPYI(block, F1, REG(fym)); + UML_FSMUL(block, F0, F0, F1); + + UML_MOV(block, I1, REG(fxa)); + UML_AND(block, I0, I1, 0x7f800000); + UML_AND(block, I1, I1, 0x807fffff); + UML_SHR(block, I0, I0, 23); + UML_SUB(block, I0, I0, 127); + UML_ADD(block, I0, I0, REG(fya)); + UML_CMP(block, I0, -126); + UML_JMPc(block, COND_L, denormal); + + UML_ADD(block, I0, I0, 127); + UML_AND(block, I0, I0, 0xff); + UML_SHL(block, I0, I0, 23); + UML_OR(block, I0, I0, I1); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + UML_JMP(block, end); + + UML_LABEL(block, denormal); + UML_AND(block, I0, I1, 0x80000000); + if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); + if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + + UML_LABEL(block, end); + + UML_FSCOPYI(block, F2, I0); + UML_TEST(block, MODE1, MODE1_TRUNCATE); + UML_JMPc(block, COND_Z, compiler->labelnum); + UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_TRUNC); + UML_JMP(block, compiler->labelnum + 1); + UML_LABEL(block, compiler->labelnum++); + UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_ROUND); + UML_LABEL(block, compiler->labelnum++); + + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + + UML_ICOPYFS(block, REG(fm), F0); + UML_MOV(block, REG(fa), I0); + return; + } + + case 0x1e: // Fm = F3-0 * F7-4, Fa = MAX(F11-8, F15-12) + // TODO: denormals + UML_FSCOPYI(block, F0, REG(fxm)); + UML_FSCOPYI(block, F1, REG(fym)); + UML_FSCOPYI(block, F2, REG(fxa)); + UML_FSCOPYI(block, F3, REG(fya)); + UML_FSMUL(block, F0, F0, F1); + + UML_FSMOV(block, F4, F2); + UML_FSCMP(block, F2, F3); + UML_FSMOVc(block, COND_C, F4, F3); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F4, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + + UML_ICOPYFS(block, REG(fm), F0); + UML_ICOPYFS(block, REG(fa), F4); + return; + + case 0x1f: // Fm = F3-0 * F7-4, Fa = MIN(F11-8, F15-12) + // TODO: denormals + UML_FSCOPYI(block, F0, REG(fxm)); + UML_FSCOPYI(block, F1, REG(fym)); + UML_FSCOPYI(block, F2, REG(fxa)); + UML_FSCOPYI(block, F3, REG(fya)); + UML_FSMUL(block, F0, F0, F1); + + UML_FSMOV(block, F4, F2); + UML_FSCMP(block, F3, F2); + UML_FSMOVc(block, COND_C, F4, F3); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F4, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + + UML_ICOPYFS(block, REG(fm), F0); + UML_ICOPYFS(block, REG(fa), F4); + return; + + default: + generate_unimplemented_compute(block, compiler, desc); + return; + } + } + else // single-function operation + { + UINT32 operation = (opcode >> 12) & 0xff; + + switch ((opcode >> 20) & 3) + { + case 0: // ALU operations + { + switch (operation) + { + case 0x09: // Rn = (Rx + Ry) / 2 + case 0x61: // Rn = MIN(Rx, Ry) + case 0x63: // Rn = CLIP Rx BY Ry + case 0x92: // Fn = ABS(Fx - Fy) + case 0x89: // Fn = (Fx + Fy) / 2 + case 0xdd: // Rn = TRUNC Fx BY Ry + case 0xe3: // Fn = CLIP Fx BY Fy + case 0xe0: // Fn = Fx COPYSIGN Fy + case 0x05: // Rn = Rx + Ry + CI + case 0x06: // Rn = Rx - Ry + CI - 1 + case 0x25: // Rn = Rx + CI + case 0x26: // Rn = Rx + CI - 1 + case 0x30: // Rn = ABS Rx + case 0x43: // Rn = NOT Rx + case 0xb0: // Fn = ABS(Fx) + case 0xa5: // Fn = RND Fx + case 0xad: // Rn = MANT Fx + case 0xc9: // Rn = FIX Fx + case 0xcd: // Rn = TRUNC Fx + generate_unimplemented_compute(block, compiler, desc); + return; + + case 0x01: // Rn = Rx + Ry + UML_ADD(block, REG(rn), REG(rx), REG(ry)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); + if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x02: // Rn = Rx - Ry + UML_SUB(block, REG(rn), REG(rx), REG(ry)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); + if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x0a: // COMP(Rx, Ry) + UML_CMP(block, REG(rx), REG(ry)); + UML_SETc(block, COND_Z, I0); + UML_SETc(block, COND_L, I1); + UML_MOV(block, ASTAT_AZ, I0); + UML_MOV(block, ASTAT_AN, I1); + UML_XOR(block, I0, I0, 1); + UML_XOR(block, I1, I1, 1); + UML_AND(block, I0, I0, I1); + UML_SHL(block, I0, I0, 7); + + UML_MOV(block, I2, mem(&m_core->astat_drc.cacc)); + UML_SHR(block, I2, I2, 1); + UML_OR(block, I2, I2, I0); + UML_MOV(block, mem(&m_core->astat_drc.cacc), I2); + + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x21: // Rn = PASS Rx + UML_MOV(block, REG(rn), REG(rx)); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_CMP(block, REG(rn), 0); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x22: // Rn = -Rx + UML_SUB(block, REG(rn), 0, REG(rx)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); + if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x29: // Rn = Rx + 1 + UML_ADD(block, REG(rn), REG(rx), 1); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); + if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x2a: // Rn = Rx - 1 + UML_SUB(block, REG(rn), REG(rx), 1); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); + if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x40: // Rn = Rx AND Ry + UML_AND(block, REG(rn), REG(rx), REG(ry)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x41: // Rn = Rx OR Ry + UML_OR(block, REG(rn), REG(rx), REG(ry)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x42: // Rn = Rx XOR Ry + UML_XOR(block, REG(rn), REG(rx), REG(ry)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x62: // Rn = MAX(Rx, Ry) + UML_MOV(block, REG(rn), REG(rx)); + UML_CMP(block, REG(rx), REG(ry)); + UML_MOVc(block, COND_L, REG(rn), REG(ry)); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_CMP(block, REG(rn), 0); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: + { + /* Fixed-point Dual Add/Subtract */ + UML_ADD(block, I0, REG(rx), REG(ry)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, ASTAT_AV); + if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AC); + UML_SUB(block, I1, REG(rx), REG(ry)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, mem(&m_core->arg0)); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, mem(&m_core->arg1)); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_V, mem(&m_core->arg2)); + if (AC_CALC_REQUIRED) UML_SETc(block, COND_C, mem(&m_core->arg3)); + if (AZ_CALC_REQUIRED) UML_OR(block, ASTAT_AZ, ASTAT_AZ, mem(&m_core->arg0)); + if (AN_CALC_REQUIRED) UML_OR(block, ASTAT_AN, ASTAT_AN, mem(&m_core->arg1)); + if (AV_CALC_REQUIRED) UML_OR(block, ASTAT_AV, ASTAT_AV, mem(&m_core->arg2)); + if (AC_CALC_REQUIRED) UML_OR(block, ASTAT_AC, ASTAT_AC, mem(&m_core->arg3)); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + UML_MOV(block, REG(ra), I0); + UML_MOV(block, REG(rs), I1); + return; + } + + case 0x81: // Fn = Fx + Fy + // TODO: denormals + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSCOPYI(block, F1, REG(ry)); + UML_FSADD(block, F0, F0, F1); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + UML_ICOPYFS(block, REG(rn), F0); + return; + + case 0x82: // Fn = Fx - Fy + // TODO: denormals + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSCOPYI(block, F1, REG(ry)); + UML_FSSUB(block, F0, F0, F1); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + UML_ICOPYFS(block, REG(rn), F0); + return; + + case 0x8a: // COMP(Fx, Fy) + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSCOPYI(block, F1, REG(ry)); + UML_FSCMP(block, F0, F1); + UML_SETc(block, COND_Z, I0); + UML_SETc(block, COND_C, I1); + UML_MOV(block, ASTAT_AZ, I0); + UML_MOV(block, ASTAT_AN, I1); + UML_XOR(block, I0, I0, 1); + UML_XOR(block, I1, I1, 1); + UML_AND(block, I0, I0, I1); + UML_SHL(block, I0, I0, 7); + + UML_MOV(block, I2, mem(&m_core->astat_drc.cacc)); + UML_SHR(block, I2, I2, 1); + UML_OR(block, I2, I2, I0); + UML_MOV(block, mem(&m_core->astat_drc.cacc), I2); + + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + return; + + case 0x91: // Fn = ABS(Fx + Fy) + // TODO: denormals + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSCOPYI(block, F1, REG(ry)); + UML_FSADD(block, F0, F0, F1); + UML_FSABS(block, F0, F0); + UML_ICOPYFS(block, REG(rn), F0); + if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 0); // TODO + if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + return; + + case 0xa1: // Fn = PASS Fx + UML_MOV(block, REG(rn), REG(rx)); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + { + UML_FSCOPYI(block, F0, REG(rn)); + UML_FSCMP(block, F0, mem(&m_core->fp0)); + } + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + return; + + case 0xa2: // Fn = -Fx + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSNEG(block, F0, F0); + UML_ICOPYFS(block, REG(rn), F0); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + return; + + case 0xbd: // Fn = SCALB Fx BY Ry + // TODO: source = nan, result = denormal + UML_MOV(block, I1, REG(rx)); + UML_AND(block, I0, I1, 0x7f800000); + UML_AND(block, I1, I1, 0x807fffff); + UML_SHR(block, I0, I0, 23); + UML_SUB(block, I0, I0, 127); + UML_ADD(block, I0, I0, REG(ry)); + UML_ADD(block, I0, I0, 127); + UML_AND(block, I0, I0, 0xff); + UML_SHL(block, I0, I0, 23); + UML_OR(block, REG(rn), I0, I1); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + return; + + case 0xc1: // Rn = LOGB Fx + // TODO: source = zero, infinity, nan + UML_SHR(block, I0, REG(rx), 23); + UML_AND(block, I0, I0, 0xff); + UML_SUB(block, REG(rn), I0, 127); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0xc4: // Fn = RECIPS Fx + // TODO: denormals + // TODO: use the bit accurate method from interpreter? + UML_FSCOPYI(block, F0, REG(rx)); + if (AN_CALC_REQUIRED || AV_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AV); + UML_FSCMP(block, F0, mem(&m_core->fp0)); + UML_JMPc(block, COND_Z, compiler->labelnum); + UML_FSRECIP(block, F0, F0); + UML_LABEL(block, compiler->labelnum++); + if (AZ_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + UML_ICOPYFS(block, REG(rn), F0); + return; + + case 0xc5: // Fn = RSQRTS Fx + // TODO: denormals + // TODO: use the bit accurate method from interpreter? + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSCMP(block, F0, mem(&m_core->fp0)); + UML_JMPc(block, COND_Z, compiler->labelnum); + UML_FSRSQRT(block, F0, F0); + UML_LABEL(block, compiler->labelnum++); + UML_ICOPYFS(block, REG(rn), F0); + // TODO: flags! + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + return; + + case 0xca: // Fn = FLOAT Rx + UML_FSFRINT(block, F0, REG(rx), SIZE_DWORD); + UML_ICOPYFS(block, REG(rn), F0); + if (AZ_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + return; + + case 0xd9: // Rn = FIX Fx BY Ry + { + code_label denormal = compiler->labelnum++; + code_label end = compiler->labelnum++; + + UML_MOV(block, I1, REG(rx)); + UML_AND(block, I0, I1, 0x7f800000); + UML_AND(block, I1, I1, 0x807fffff); + UML_SHR(block, I0, I0, 23); + UML_SUB(block, I0, I0, 127); + UML_ADD(block, I0, I0, REG(ry)); + UML_CMP(block, I0, -126); + UML_JMPc(block, COND_L, denormal); + + UML_ADD(block, I0, I0, 127); + UML_AND(block, I0, I0, 0xff); + UML_SHL(block, I0, I0, 23); + UML_OR(block, I0, I0, I1); + + UML_FSCOPYI(block, F2, I0); + UML_TEST(block, MODE1, MODE1_TRUNCATE); + UML_JMPc(block, COND_Z, compiler->labelnum); + UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_TRUNC); + UML_JMP(block, compiler->labelnum + 1); + UML_LABEL(block, compiler->labelnum++); + UML_FSTOINT(block, I0, F2, SIZE_DWORD, ROUND_ROUND); + UML_LABEL(block, compiler->labelnum++); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_CMP(block, I0, 0); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + UML_MOV(block, REG(rn), I0); + UML_JMP(block, end); + + UML_LABEL(block, denormal); + UML_AND(block, I0, I1, 0x80000000); + if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); + if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + UML_MOV(block, REG(rn), I0); + + UML_LABEL(block, end); + return; + } + + case 0xda: // Fn = FLOAT Rx BY Ry + { + code_label denormal = compiler->labelnum++; + code_label end = compiler->labelnum++; + UML_FSFRINT(block, F0, REG(rx), SIZE_DWORD); + UML_ICOPYFS(block, I1, F0); + UML_AND(block, I0, I1, 0x7f800000); + UML_AND(block, I1, I1, 0x807fffff); + UML_SHR(block, I0, I0, 23); + UML_SUB(block, I0, I0, 127); + UML_ADD(block, I0, I0, REG(ry)); + UML_CMP(block, I0, -126); + UML_JMPc(block, COND_L, denormal); + + UML_ADD(block, I0, I0, 127); + UML_AND(block, I0, I0, 0xff); + UML_SHL(block, I0, I0, 23); + UML_OR(block, REG(rn), I0, I1); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_S, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + UML_JMP(block, end); + + UML_LABEL(block, denormal); + UML_AND(block, I0, I1, 0x80000000); + if (AZ_CALC_REQUIRED) UML_MOV(block, ASTAT_AZ, 1); + if (AN_CALC_REQUIRED) UML_MOV(block, ASTAT_AN, 0); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); + UML_MOV(block, REG(rn), I0); + + UML_LABEL(block, end); + return; + } + + case 0xe1: // Fn = MIN(Fx, Fy) + UML_FSCOPYI(block, F2, REG(rx)); + UML_FSCOPYI(block, F3, REG(ry)); + UML_FSMOV(block, F4, F2); + UML_FSCMP(block, F3, F2); + UML_FSMOVc(block, COND_C, F4, F3); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F4, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + UML_ICOPYFS(block, REG(rn), F4); + return; + + case 0xe2: // Fn = MAX(Fx, Fy) + UML_FSCOPYI(block, F2, REG(rx)); + UML_FSCOPYI(block, F3, REG(ry)); + UML_FSMOV(block, F4, F2); + UML_FSCMP(block, F2, F3); + UML_FSMOVc(block, COND_C, F4, F3); + + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F4, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + UML_ICOPYFS(block, REG(rn), F4); + return; + + case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: + { + /* Floating-point Dual Add/Subtract */ + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSCOPYI(block, F1, REG(ry)); + UML_FSADD(block, F2, F0, F1); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F2, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_AZ); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_AN); + UML_FSSUB(block, F3, F0, F1); + if (AZ_CALC_REQUIRED || AN_CALC_REQUIRED) + UML_FSCMP(block, F2, mem(&m_core->fp0)); + if (AZ_CALC_REQUIRED) UML_SETc(block, COND_Z, I0); + if (AN_CALC_REQUIRED) UML_SETc(block, COND_C, I1); + if (AZ_CALC_REQUIRED) UML_OR(block, ASTAT_AZ, ASTAT_AZ, I0); + if (AN_CALC_REQUIRED) UML_OR(block, ASTAT_AN, ASTAT_AN, I1); + if (AV_CALC_REQUIRED) UML_MOV(block, ASTAT_AV, 0); // TODO + if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0); + if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); + if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO + UML_ICOPYFS(block, REG(ra), F2); + UML_ICOPYFS(block, REG(rs), F3); + return; + } + + default: + generate_unimplemented_compute(block, compiler, desc); + return; + } + break; + } + + case 1: // multiplier operations + { + switch (operation) + { + case 0x48: // Rn = Rx * Ry (UUF) + case 0x49: // Rn = Rx * Ry (UUFR) + case 0x50: // Rn = Rx * Ry (SUI) + case 0x58: // Rn = Rx * Ry (SUF) + case 0x59: // Rn = Rx * Ry (SUFR) + case 0x60: // Rn = Rx * Ry (USI) + case 0x68: // Rn = Rx * Ry (USF) + case 0x69: // Rn = Rx * Ry (USFR) + case 0x70: // Rn = Rx * Ry (SSI) + case 0x78: // Rn = Rx * Ry (SSF) + case 0x79: // Rn = Rx * Ry (SSFR) + case 0x44: // MRF = Rx * Ry (UUI) + case 0x4c: // MRF = Rx * Ry (UUF) + case 0x4d: // MRF = Rx * Ry (UUFR) + case 0x54: // MRF = Rx * Ry (SUI) + case 0x5c: // MRF = Rx * Ry (SUF) + case 0x5d: // MRF = Rx * Ry (SUFR) + case 0x64: // MRF = Rx * Ry (USI) + case 0x6c: // MRF = Rx * Ry (USF) + case 0x6d: // MRF = Rx * Ry (USFR) + case 0x74: // MRF = Rx * Ry (SSI) + case 0x7c: // MRF = Rx * Ry (SSF) + case 0x7d: // MRF = Rx * Ry (SSFR) + case 0x46: // MRB = Rx * Ry (UUI) + case 0x4e: // MRB = Rx * Ry (UUF) + case 0x4f: // MRB = Rx * Ry (UUFR) + case 0x56: // MRB = Rx * Ry (SUI) + case 0x5e: // MRB = Rx * Ry (SUF) + case 0x5f: // MRB = Rx * Ry (SUFR) + case 0x66: // MRB = Rx * Ry (USI) + case 0x6e: // MRB = Rx * Ry (USF) + case 0x6f: // MRB = Rx * Ry (USFR) + case 0x76: // MRB = Rx * Ry (SSI) + case 0x7e: // MRB = Rx * Ry (SSF) + case 0x7f: // MRB = Rx * Ry (SSFR) + case 0x80: // Rn = MRF + Rx * Ry (UUI) + case 0x88: // Rn = MRF + Rx * Ry (UUF) + case 0x89: // Rn = MRF + Rx * Ry (UUFR) + case 0x90: // Rn = MRF + Rx * Ry (SUI) + case 0x98: // Rn = MRF + Rx * Ry (SUF) + case 0x99: // Rn = MRF + Rx * Ry (SUFR) + case 0xa0: // Rn = MRF + Rx * Ry (USI) + case 0xa8: // Rn = MRF + Rx * Ry (USF) + case 0xa9: // Rn = MRF + Rx * Ry (USFR) + case 0xb8: // Rn = MRF + Rx * Ry (SSF) + case 0xb9: // Rn = MRF + Rx * Ry (SSFR) + case 0x82: // Rn = MRB + Rx * Ry (UUI) + case 0x8a: // Rn = MRB + Rx * Ry (UUF) + case 0x8b: // Rn = MRB + Rx * Ry (UUFR) + case 0x92: // Rn = MRB + Rx * Ry (SUI) + case 0x9a: // Rn = MRB + Rx * Ry (SUF) + case 0x9b: // Rn = MRB + Rx * Ry (SUFR) + case 0xa2: // Rn = MRB + Rx * Ry (USI) + case 0xaa: // Rn = MRB + Rx * Ry (USF) + case 0xab: // Rn = MRB + Rx * Ry (USFR) + case 0xba: // Rn = MRB + Rx * Ry (SSF) + case 0xbb: // Rn = MRB + Rx * Ry (SSFR) + case 0x84: // MRF = MRF + Rx * Ry (UUI) + case 0x8c: // MRF = MRF + Rx * Ry (UUF) + case 0x8d: // MRF = MRF + Rx * Ry (UUFR) + case 0x94: // MRF = MRF + Rx * Ry (SUI) + case 0x9c: // MRF = MRF + Rx * Ry (SUF) + case 0x9d: // MRF = MRF + Rx * Ry (SUFR) + case 0xa4: // MRF = MRF + Rx * Ry (USI) + case 0xac: // MRF = MRF + Rx * Ry (USF) + case 0xad: // MRF = MRF + Rx * Ry (USFR) + case 0xb4: // MRF = MRF + Rx * Ry (SSI) + case 0xbc: // MRF = MRF + Rx * Ry (SSF) + case 0xbd: // MRF = MRF + Rx * Ry (SSFR) + case 0x86: // MRB = MRB + Rx * Ry (UUI) + case 0x8e: // MRB = MRB + Rx * Ry (UUF) + case 0x8f: // MRB = MRB + Rx * Ry (UUFR) + case 0x96: // MRB = MRB + Rx * Ry (SUI) + case 0x9e: // MRB = MRB + Rx * Ry (SUF) + case 0x9f: // MRB = MRB + Rx * Ry (SUFR) + case 0xa6: // MRB = MRB + Rx * Ry (USI) + case 0xae: // MRB = MRB + Rx * Ry (USF) + case 0xaf: // MRB = MRB + Rx * Ry (USFR) + case 0xb6: // MRB = MRB + Rx * Ry (SSI) + case 0xbe: // MRB = MRB + Rx * Ry (SSF) + case 0xbf: // MRB = MRB + Rx * Ry (SSFR) + case 0xc0: // Rn = MRF - Rx * Ry (UUI) + case 0xc8: // Rn = MRF - Rx * Ry (UUF) + case 0xc9: // Rn = MRF - Rx * Ry (UUFR) + case 0xd0: // Rn = MRF - Rx * Ry (SUI) + case 0xd8: // Rn = MRF - Rx * Ry (SUF) + case 0xd9: // Rn = MRF - Rx * Ry (SUFR) + case 0xe0: // Rn = MRF - Rx * Ry (USI) + case 0xe8: // Rn = MRF - Rx * Ry (USF) + case 0xe9: // Rn = MRF - Rx * Ry (USFR) + case 0xf0: // Rn = MRF - Rx * Ry (SSI) + case 0xf8: // Rn = MRF - Rx * Ry (SSF) + case 0xf9: // Rn = MRF - Rx * Ry (SSFR) + case 0xc2: // Rn = MRB - Rx * Ry (UUI) + case 0xca: // Rn = MRB - Rx * Ry (UUF) + case 0xcb: // Rn = MRB - Rx * Ry (UUFR) + case 0xd2: // Rn = MRB - Rx * Ry (SUI) + case 0xda: // Rn = MRB - Rx * Ry (SUF) + case 0xdb: // Rn = MRB - Rx * Ry (SUFR) + case 0xe2: // Rn = MRB - Rx * Ry (USI) + case 0xea: // Rn = MRB - Rx * Ry (USF) + case 0xeb: // Rn = MRB - Rx * Ry (USFR) + case 0xf2: // Rn = MRB - Rx * Ry (SSI) + case 0xfa: // Rn = MRB - Rx * Ry (SSF) + case 0xfb: // Rn = MRB - Rx * Ry (SSFR) + case 0xc4: // MRF = MRF - Rx * Ry (UUI) + case 0xcc: // MRF = MRF - Rx * Ry (UUF) + case 0xcd: // MRF = MRF - Rx * Ry (UUFR) + case 0xd4: // MRF = MRF - Rx * Ry (SUI) + case 0xdc: // MRF = MRF - Rx * Ry (SUF) + case 0xdd: // MRF = MRF - Rx * Ry (SUFR) + case 0xe4: // MRF = MRF - Rx * Ry (USI) + case 0xec: // MRF = MRF - Rx * Ry (USF) + case 0xed: // MRF = MRF - Rx * Ry (USFR) + case 0xf4: // MRF = MRF - Rx * Ry (SSI) + case 0xfc: // MRF = MRF - Rx * Ry (SSF) + case 0xfd: // MRF = MRF - Rx * Ry (SSFR) + case 0xc6: // MRB = MRB - Rx * Ry (UUI) + case 0xce: // MRB = MRB - Rx * Ry (UUF) + case 0xcf: // MRB = MRB - Rx * Ry (UUFR) + case 0xd6: // MRB = MRB - Rx * Ry (SUI) + case 0xde: // MRB = MRB - Rx * Ry (SUF) + case 0xdf: // MRB = MRB - Rx * Ry (SUFR) + case 0xe6: // MRB = MRB - Rx * Ry (USI) + case 0xee: // MRB = MRB - Rx * Ry (USF) + case 0xef: // MRB = MRB - Rx * Ry (USFR) + case 0xf6: // MRB = MRB - Rx * Ry (SSI) + case 0xfe: // MRB = MRB - Rx * Ry (SSF) + case 0xff: // MRB = MRB - Rx * Ry (SSFR) + case 0x00: // Rn = SAT MRF (UI) + case 0x01: // Rn = SAT MRF (SI) + case 0x08: // Rn = SAT MRF (UF) + case 0x09: // Rn = SAT MRF (SF) + case 0x02: // Rn = SAT MRB (UI) + case 0x03: // Rn = SAT MRB (SI) + case 0x0a: // Rn = SAT MRB (UF) + case 0x0b: // Rn = SAT MRB (SF) + case 0x04: // MRF = SAT MRF (UI) + case 0x05: // MRF = SAT MRF (SI) + case 0x0c: // MRF = SAT MRF (UF) + case 0x0d: // MRF = SAT MRF (SF) + case 0x06: // MRB = SAT MRB (UI) + case 0x07: // MRB = SAT MRB (SI) + case 0x0e: // MRB = SAT MRB (UF) + case 0x0f: // MRB = SAT MRB (SF) + case 0x18: // Rn = RND MRF (U) + case 0x19: // Rn = RND MRF (S) + case 0x1a: // Rn = RND MRB (U) + case 0x1b: // Rn = RND MRB (S) + case 0x1c: // MRF = RND MRF (U) + case 0x1d: // MRF = RND MRF (S) + case 0x1e: // MRB = RND MRB (U) + case 0x1f: // MRB = RND MRB (S) + generate_unimplemented_compute(block, compiler, desc); + return; + + case 0x14: // MRF = 0 + UML_DMOV(block, mem(&m_core->mrf), 0); + if (MN_CALC_REQUIRED) UML_MOV(block, ASTAT_MN, 0); + if (MV_CALC_REQUIRED) UML_MOV(block, ASTAT_MV, 0); + if (MU_CALC_REQUIRED) UML_MOV(block, ASTAT_MU, 0); + if (MI_CALC_REQUIRED) UML_MOV(block, ASTAT_MI, 0); + return; + + case 0x16: // MRB = 0 + UML_DMOV(block, mem(&m_core->mrb), 0); + if (MN_CALC_REQUIRED) UML_MOV(block, ASTAT_MN, 0); + if (MV_CALC_REQUIRED) UML_MOV(block, ASTAT_MV, 0); + if (MU_CALC_REQUIRED) UML_MOV(block, ASTAT_MU, 0); + if (MI_CALC_REQUIRED) UML_MOV(block, ASTAT_MI, 0); + return; + + case 0x30: // Fn = Fx * Fy + UML_FSCOPYI(block, F0, REG(rx)); + UML_FSCOPYI(block, F1, REG(ry)); + UML_FSMUL(block, F0, F0, F1); + UML_ICOPYFS(block, REG(rn), F0); + if (MN_CALC_REQUIRED) + UML_FSCMP(block, F0, mem(&m_core->fp0)); + if (MN_CALC_REQUIRED) UML_SETc(block, COND_C, ASTAT_MN); + // TODO: MV, MU, MI flags + return; + + case 0x40: // Rn = Rx * Ry (UUI) + UML_MULU(block, I0, I0, REG(rx), REG(ry)); + UML_MOV(block, REG(rn), I0); + // TODO: flags + return; + + case 0xb0: // Rn = MRF + Rx * Ry (SSI) + UML_DSEXT(block, I0, REG(rx), SIZE_DWORD); + UML_DSEXT(block, I1, REG(ry), SIZE_DWORD); + UML_DMULS(block, I0, I0, I0, I1); + UML_DADD(block, I0, I0, mem(&m_core->mrf)); + UML_MOV(block, REG(rn), I0); + // TODO: flags! + return; + + case 0xb2: // Rn = MRB + Rx * Ry (SSI) + UML_DSEXT(block, I0, REG(rx), SIZE_DWORD); + UML_DSEXT(block, I1, REG(ry), SIZE_DWORD); + UML_DMULS(block, I0, I0, I0, I1); + UML_DADD(block, I0, I0, mem(&m_core->mrb)); + UML_MOV(block, REG(rn), I0); + // TODO: flags! + return; + + default: + generate_unimplemented_compute(block, compiler, desc); + return; + } + break; + } + + case 2: // shifter operations + { + switch (operation) + { + case 0x00: // Rn = LSHIFT Rx BY Ry | + case 0x04: // Rn = ASHIFT Rx BY Ry | + case 0xc4: // Rn = BCLR Rx BY Ry | + case 0x44: // Rn = FDEP Rx BY Ry | : + case 0x4c: // Rn = FDEP Rx BY Ry | : (SE) + case 0x48: // Rn = FEXT Rx BY Ry | : (SE) + case 0x24: // Rn = Rn OR ASHIFT Rx BY Ry | + case 0x64: // Rn = Rn OR FDEP Rx BY Ry | : + case 0x6c: // Rn = Rn OR FDEP Rx BY Ry | : (SE) + case 0x80: // Rn = EXP Rx + case 0x84: // Rn = EXP Rx (EX) + case 0x88: // Rn = LEFTZ Rx + case 0x8c: // Rn = LEFTO Rx + case 0x90: // Rn = FPACK Fx + case 0x94: // Fn = FUNPACK Rx + generate_unimplemented_compute(block, compiler, desc); + return; + + case 0x08: // Rn = ROT Rx BY Ry | + { + code_label shift_neg = compiler->labelnum++; + code_label shift_end = compiler->labelnum++; + + UML_MOV(block, I0, REG(ry)); + UML_CMP(block, I0, 0); + UML_JMPc(block, COND_L, shift_neg); + UML_ROL(block, I1, REG(rx), I0); + UML_JMP(block, shift_end); + UML_LABEL(block, shift_neg); + UML_SUB(block, I2, 0, I0); + UML_ROR(block, I1, REG(rx), I2); + UML_LABEL(block, shift_end); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + UML_MOV(block, REG(rn), I1); + return; + } + + case 0x20: // Rn = Rn OR LSHIFT Rx BY Ry | + { + code_label shift_neg = compiler->labelnum++; + code_label shift_end = compiler->labelnum++; + + UML_MOV(block, I0, REG(ry)); + UML_CMP(block, I0, 0); + UML_JMPc(block, COND_L, shift_neg); + UML_SHL(block, I1, REG(rx), I0); + UML_JMP(block, shift_end); + UML_LABEL(block, shift_neg); + UML_SUB(block, I2, 0, I0); + UML_SHR(block, I1, REG(rx), I2); + UML_LABEL(block, shift_end); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED) + { + UML_CMP(block, I0, 0); + UML_SETc(block, COND_NZ, ASTAT_SV); + } + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + UML_OR(block, REG(rn), REG(rn), I1); + + return; + } + + case 0x40: // Rn = FEXT Rx BY Ry | : + // extraction mask + UML_MOV(block, I0, REG(ry)); + UML_SHR(block, I1, I0, 6); + UML_AND(block, I1, I1, 0x3f); // i1 = len6 + UML_AND(block, I0, I0, 0x3f); // i0 = bit6 + UML_MOV(block, I3, 0xffffffff); + UML_SUB(block, I2, 32, I1); + UML_SHR(block, I3, I3, I2); + UML_SHL(block, I3, I3, I0); + + UML_AND(block, I2, REG(rx), I3); + UML_SHR(block, REG(rn), I2, I0); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED) + { + UML_ADD(block, I0, I0, I1); + UML_CMP(block, I0, 32); + UML_SETc(block, COND_G, ASTAT_SV); + } + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0xc0: // Rn = BSET Rx BY Ry | + { + UML_MOV(block, I0, REG(ry)); + UML_MOV(block, I1, 1); + UML_SHL(block, I1, I1, I0); + UML_OR(block, REG(rn), REG(rn), I1); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED) + { + UML_CMP(block, I0, 31); + UML_SETc(block, COND_G, ASTAT_SV); + } + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + } + + case 0xcc: // BTST Rx BY Ry | + { + UML_MOV(block, I0, REG(ry)); + UML_MOV(block, I1, 1); + UML_SHL(block, I1, I1, I0); + UML_TEST(block, REG(rx), I1); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED) + UML_CMP(block, I0, 31); + if (SV_CALC_REQUIRED) UML_SETc(block, COND_G, ASTAT_SV); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + } + + default: + generate_unimplemented_compute(block, compiler, desc); + return; + } + break; + } + + default: + generate_unimplemented_compute(block, compiler, desc); + return; + } + } +} + +void adsp21062_device::generate_if_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int condition, int skip_label) +{ + // Jump to skip_label if condition is not true + code_label not_skip; + + switch (condition) + { + case 0x00: /* EQ */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x01: /* LT */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NE, skip_label); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x02: /* LE */ + not_skip = compiler->labelnum++; + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, not_skip); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_NZ, not_skip); + UML_JMP(block, skip_label); + UML_LABEL(block, not_skip); + break; + case 0x03: /* AC */ + UML_TEST(block, ASTAT_AC, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x04: /* AV */ + UML_TEST(block, ASTAT_AV, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x05: /* MV */ + UML_TEST(block, ASTAT_MV, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x06: /* MS */ + UML_TEST(block, ASTAT_MN, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x07: /* SV */ + UML_TEST(block, ASTAT_SV, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x08: /* SZ */ + UML_TEST(block, ASTAT_SZ, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x09: /* FLAG0 */ + UML_CMP(block, FLAG0, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x0a: /* FLAG1 */ + UML_CMP(block, FLAG1, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x0b: /* FLAG2 */ + UML_CMP(block, FLAG2, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x0c: /* FLAG3 */ + UML_CMP(block, FLAG3, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x0d: /* TF */ + UML_TEST(block, ASTAT_BTF, 1); + UML_JMPc(block, COND_E, skip_label); + case 0x0e: /* BM */ + UML_JMP(block, skip_label); + case 0x0f: /* NOT LCE */ + UML_CMP(block, CURLCNTR, 1); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x10: /* NOT EQUAL */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x11: /* GE */ + not_skip = compiler->labelnum++; + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, not_skip); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_Z, not_skip); + UML_JMP(block, skip_label); + UML_LABEL(block, not_skip); + break; + case 0x12: /* GT */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, skip_label); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x13: /* NOT AC */ + UML_TEST(block, ASTAT_AC, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x14: /* NOT AV */ + UML_TEST(block, ASTAT_AV, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x15: /* NOT MV */ + UML_TEST(block, ASTAT_MV, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x16: /* NOT MS */ + UML_TEST(block, ASTAT_MN, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x17: /* NOT SV */ + UML_TEST(block, ASTAT_SV, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x18: /* NOT SZ */ + UML_TEST(block, ASTAT_SZ, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x19: /* NOT FLAG0 */ + UML_CMP(block, FLAG0, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x1a: /* NOT FLAG1 */ + UML_CMP(block, FLAG1, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x1b: /* NOT FLAG2 */ + UML_CMP(block, FLAG2, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x1c: /* NOT FLAG3 */ + UML_CMP(block, FLAG3, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x1d: /* NOT TF */ + UML_TEST(block, ASTAT_BTF, 1); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x1e: /* NOT BM */ + fatalerror("generate_if_condition 0x1e"); // should not happen + break; + case 0x1f: /* TRUE */ + fatalerror("generate_if_condition 0x1f"); // should not happen + break; + } +} + +void adsp21062_device::generate_do_condition(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int condition, int skip_label, ASTAT_DRC &astat) +{ + // Jump to skip_label if condition is true + code_label not_skip; + + UML_JMP(block, skip_label); + return; + + switch (condition) + { + case 0x00: /* EQ */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x01: /* LT */ + not_skip = compiler->labelnum++; + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, not_skip); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_Z, not_skip); + UML_JMP(block, skip_label); + UML_LABEL(block, not_skip); + break; + case 0x02: /* LE */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, skip_label); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x03: /* AC */ + UML_TEST(block, ASTAT_AC, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x04: /* AV */ + UML_TEST(block, ASTAT_AV, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x05: /* MV */ + UML_TEST(block, ASTAT_MV, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x06: /* MS */ + UML_TEST(block, ASTAT_MN, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x07: /* SV */ + UML_TEST(block, ASTAT_SV, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x08: /* SZ */ + UML_TEST(block, ASTAT_SZ, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x09: /* FLAG0 */ + UML_CMP(block, FLAG0, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x0a: /* FLAG1 */ + UML_CMP(block, FLAG1, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x0b: /* FLAG2 */ + UML_CMP(block, FLAG2, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x0c: /* FLAG3 */ + UML_CMP(block, FLAG3, 0); + UML_JMPc(block, COND_NE, skip_label); + break; + case 0x0d: /* TF */ + UML_TEST(block, ASTAT_BTF, 1); + UML_JMPc(block, COND_NZ, skip_label); + break; + case 0x0e: /* BM */ + // infinite loop + break; + case 0x0f: /* LCE */ + fatalerror("generate_do_condition 0x0f"); // this should only be used with counter loops + break; + case 0x10: /* NOT EQUAL */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x11: /* GE */ + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, skip_label); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x12: /* GT */ + not_skip = compiler->labelnum++; + UML_TEST(block, ASTAT_AZ, 1); + UML_JMPc(block, COND_NZ, not_skip); + UML_TEST(block, ASTAT_AN, 1); + UML_JMPc(block, COND_NZ, not_skip); + UML_JMP(block, skip_label); + UML_LABEL(block, not_skip); + break; + case 0x13: /* NOT AC */ + UML_TEST(block, ASTAT_AC, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x14: /* NOT AV */ + UML_TEST(block, ASTAT_AV, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x15: /* NOT MV */ + UML_TEST(block, ASTAT_MV, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x16: /* NOT MS */ + UML_TEST(block, ASTAT_MN, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x17: /* NOT SV */ + UML_TEST(block, ASTAT_SV, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x18: /* NOT SZ */ + UML_TEST(block, ASTAT_SZ, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x19: /* NOT FLAG0 */ + UML_CMP(block, FLAG0, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x1a: /* NOT FLAG1 */ + UML_CMP(block, FLAG1, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x1b: /* NOT FLAG2 */ + UML_CMP(block, FLAG2, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x1c: /* NOT FLAG3 */ + UML_CMP(block, FLAG3, 0); + UML_JMPc(block, COND_E, skip_label); + break; + case 0x1d: /* NOT TF */ + UML_TEST(block, ASTAT_BTF, 1); + UML_JMPc(block, COND_Z, skip_label); + break; + case 0x1e: /* NOT BM */ + // always true + UML_JMP(block, skip_label); + break; + case 0x1f: /* FALSE (FOREVER) */ + // infinite loop + break; + } +} + +void adsp21062_device::generate_shift_imm(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int data, int shiftop, int rn, int rx) +{ + INT8 shift = data & 0xff; + int bit = data & 0x3f; + int len = (data >> 6) & 0x3f; + + switch (shiftop) + { + case 0x01: // ASHIFT Rx BY + case 0x11: // FDEP Rx BY : + case 0x13: // FDEP Rx BY : (SE) + case 0x1b: // Rn = Rn OR FDEP Rx BY : (SE) + UML_MOV(block, mem(&m_core->pc), desc->pc); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_CALLC(block, cfunc_unimplemented_shiftimm, this); + break; + + case 0x00: // LSHIFT Rx BY + if (abs(shift) >= 32) + { + UML_MOV(block, REG(rn), 0); + if (SZ_CALC_REQUIRED) UML_MOV(block, ASTAT_SZ, 1); + if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 1); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + } + else + { + if (shift < 0) + UML_SHR(block, REG(rn), REG(rx), -shift); + else + UML_SHL(block, REG(rn), REG(rx), shift); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && shift != 0) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && shift == 0) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + } + return; + + case 0x02: // ROT Rx BY + UML_ROL(block, REG(rn), REG(rx), (shift < 0) ? 31 - ((-shift) & 0x1f) : shift & 0x1f); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0x08: // Rn = Rn OR LSHIFT Rx BY + if (abs(shift) >= 32) + { + UML_MOV(block, I0, 0); + if (SZ_CALC_REQUIRED) UML_MOV(block, ASTAT_SZ, 1); + if (SV_CALC_REQUIRED) UML_MOV(block, ASTAT_SV, 1); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + UML_OR(block, REG(rn), REG(rn), I0); + } + else + { + if (shift < 0) + UML_SHR(block, I0, REG(rx), -shift); + else + UML_SHL(block, I0, REG(rx), shift); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && shift != 0) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && shift == 0) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + UML_OR(block, REG(rn), REG(rn), I0); + } + return; + + case 0x10: // FEXT Rx BY : + if (bit == 0) + { + UML_AND(block, REG(rn), REG(rx), MAKE_EXTRACT_MASK(bit, len)); + } + else + { + UML_AND(block, I0, REG(rx), MAKE_EXTRACT_MASK(bit, len)); + UML_SHR(block, REG(rn), I0, bit); + } + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && (bit + len) > 32) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && (bit + len) <= 32) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0x12: // FEXT Rx BY : (SE) + UML_AND(block, I0, REG(rx), MAKE_EXTRACT_MASK(bit, len)); + UML_SHL(block, I0, I0, 32 - (bit + len)); + UML_SAR(block, REG(rn), I0, 32 - (bit + len) + bit); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && (bit + len) > 32) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && (bit + len) <= 32) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0x19: // Rn = Rn OR FDEP Rx BY : + UML_AND(block, I0, REG(rx), MAKE_EXTRACT_MASK(0, len)); + if (bit > 0) + UML_SHL(block, I0, I0, bit); + UML_OR(block, REG(rn), REG(rn), I0); + + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && (bit + len) > 32) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && (bit + len) <= 32) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0x30: // BSET Rx BY + UML_OR(block, REG(rn), REG(rx), 1 << data); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0x31: // BCLR Rx By + UML_AND(block, REG(rn), REG(rx), ~(1 << data)); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0x32: // BTGL Rx BY + UML_XOR(block, REG(rn), REG(rx), 1 << data); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + case 0x33: // BTST Rx BY + UML_TEST(block, REG(rx), 1 << data); + if (SZ_CALC_REQUIRED) UML_SETc(block, COND_Z, ASTAT_SZ); + if (SV_CALC_REQUIRED && data > 31) UML_MOV(block, ASTAT_SV, 1); + if (SV_CALC_REQUIRED && data <= 31) UML_MOV(block, ASTAT_SV, 0); + if (SS_CALC_REQUIRED) UML_MOV(block, ASTAT_SS, 0); + return; + + default: + UML_MOV(block, mem(&m_core->pc), desc->pc); + UML_DMOV(block, mem(&m_core->arg64), desc->opptr.q[0]); + UML_CALLC(block, cfunc_unimplemented_compute, this); + return; + } +} \ No newline at end of file diff --git a/src/devices/cpu/sharc/sharcdsm.cpp b/src/devices/cpu/sharc/sharcdsm.cpp index af754afe66b..b65bbeb71ea 100644 --- a/src/devices/cpu/sharc/sharcdsm.cpp +++ b/src/devices/cpu/sharc/sharcdsm.cpp @@ -88,14 +88,14 @@ static void compute(UINT32 opcode) case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: { - print("R%d = R%d * R%d (SSFR), R%d = R%d + R%d, R%d = R%d - R%d", rm, rxm, rym+4, ra, rxa+8, rya+12, rs, rxa+8, rya+12); + print("R%d = R%d * R%d (SSFR), R%d = R%d + R%d, R%d = R%d - R%d", rm, rxm, rym+4, ra, rxa+8, rya+12, (opcode >> 16) & 0xf, rxa+8, rya+12); break; } case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: { - print("F%d = F%d * F%d, F%d = F%d + F%d, F%d = F%d - F%d", rm, rxm, rym+4, ra, rxa+8, rya+12, rs, rxa+8, rya+12); + print("F%d = F%d * F%d, F%d = F%d + F%d, F%d = F%d - F%d", rm, rxm, rym+4, ra, rxa+8, rya+12, (opcode >> 16) & 0xf, rxa+8, rya+12); break; } diff --git a/src/devices/cpu/sharc/sharcfe.cpp b/src/devices/cpu/sharc/sharcfe.cpp new file mode 100644 index 00000000000..37e361a70c8 --- /dev/null +++ b/src/devices/cpu/sharc/sharcfe.cpp @@ -0,0 +1,1830 @@ +// license:BSD-3-Clause +// copyright-holders:Ville Linde + +/****************************************************************************** + + Front-end for SHARC recompiler + +******************************************************************************/ + +#include "emu.h" +#include "sharcfe.h" + +#define REG_USED(desc,x) do { (desc).regin[0] |= 1 << (x); } while(0) +#define REG_MODIFIED(desc,x) do { (desc).regout[0] |= 1 << (x); } while(0) + +//#define ASTAT_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) +//#define ASTAT_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) + +#define AZ_USED(desc) do { (desc).regin[0] |= 1 << 16; } while(0) +#define AZ_MODIFIED(desc) do { (desc).regout[0] |= 1 << 16; } while(0) +#define AV_USED(desc) do { (desc).regin[0] |= 1 << 17; } while(0) +#define AV_MODIFIED(desc) do { (desc).regout[0] |= 1 << 17; } while(0) +#define AN_USED(desc) do { (desc).regin[0] |= 1 << 18; } while(0) +#define AN_MODIFIED(desc) do { (desc).regout[0] |= 1 << 18; } while(0) +#define AC_USED(desc) do { (desc).regin[0] |= 1 << 19; } while(0) +#define AC_MODIFIED(desc) do { (desc).regout[0] |= 1 << 19; } while(0) +#define AS_USED(desc) do { (desc).regin[0] |= 1 << 20; } while(0) +#define AS_MODIFIED(desc) do { (desc).regout[0] |= 1 << 20; } while(0) +#define AI_USED(desc) do { (desc).regin[0] |= 1 << 21; } while(0) +#define AI_MODIFIED(desc) do { (desc).regout[0] |= 1 << 21; } while(0) +#define MN_USED(desc) do { (desc).regin[0] |= 1 << 22; } while(0) +#define MN_MODIFIED(desc) do { (desc).regout[0] |= 1 << 22; } while(0) +#define MV_USED(desc) do { (desc).regin[0] |= 1 << 23; } while(0) +#define MV_MODIFIED(desc) do { (desc).regout[0] |= 1 << 23; } while(0) +#define MU_USED(desc) do { (desc).regin[0] |= 1 << 24; } while(0) +#define MU_MODIFIED(desc) do { (desc).regout[0] |= 1 << 24; } while(0) +#define MI_USED(desc) do { (desc).regin[0] |= 1 << 25; } while(0) +#define MI_MODIFIED(desc) do { (desc).regout[0] |= 1 << 25; } while(0) +#define SV_USED(desc) do { (desc).regin[0] |= 1 << 26; } while(0) +#define SV_MODIFIED(desc) do { (desc).regout[0] |= 1 << 26; } while(0) +#define SZ_USED(desc) do { (desc).regin[0] |= 1 << 27; } while(0) +#define SZ_MODIFIED(desc) do { (desc).regout[0] |= 1 << 27; } while(0) +#define SS_USED(desc) do { (desc).regin[0] |= 1 << 28; } while(0) +#define SS_MODIFIED(desc) do { (desc).regout[0] |= 1 << 28; } while(0) +#define BTF_USED(desc) do { (desc).regin[0] |= 1 << 29; } while(0) +#define BTF_MODIFIED(desc) do { (desc).regout[0] |= 1 << 29; } while(0) +#define AF_USED(desc) do { (desc).regin[0] |= 1 << 30; } while(0) +#define AF_MODIFIED(desc) do { (desc).regout[0] |= 1 << 30; } while(0) + +#define ALU_FLAGS_MODIFIED(desc) do { AZ_MODIFIED(desc);AN_MODIFIED(desc);AV_MODIFIED(desc);AC_MODIFIED(desc);AS_MODIFIED(desc);AI_MODIFIED(desc); } while(0) +#define MULT_FLAGS_MODIFIED(desc) do { MN_MODIFIED(desc);MV_MODIFIED(desc);MU_MODIFIED(desc);MI_MODIFIED(desc); } while(0) +#define SHIFT_FLAGS_MODIFIED(desc) do { SZ_MODIFIED(desc);SV_MODIFIED(desc);SS_MODIFIED(desc); } while(0) + + +#define PM_I_USED(desc,x) do { (desc).regin[1] |= 1 << (x); } while(0) +#define PM_I_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << (x); } while(0) +#define PM_M_USED(desc,x) do { (desc).regin[1] |= 1 << ((x) + 8); } while(0) +#define PM_M_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << ((x) + 8); } while(0) +#define PM_B_USED(desc,x) do { (desc).regin[1] |= 1 << ((x) + 16); } while(0) +#define PM_B_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << ((x) + 16); } while(0) +#define PM_L_USED(desc,x) do { (desc).regin[1] |= 1 << ((x) + 24); } while(0) +#define PM_L_MODIFIED(desc,x) do { (desc).regout[1] |= 1 << ((x) + 24); } while(0) + +#define DM_I_USED(desc,x) do { (desc).regin[2] |= 1 << (x); } while(0) +#define DM_I_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << (x); } while(0) +#define DM_M_USED(desc,x) do { (desc).regin[2] |= 1 << ((x) + 8); } while(0) +#define DM_M_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << ((x) + 8); } while(0) +#define DM_B_USED(desc,x) do { (desc).regin[2] |= 1 << ((x) + 16); } while(0) +#define DM_B_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << ((x) + 16); } while(0) +#define DM_L_USED(desc,x) do { (desc).regin[2] |= 1 << ((x) + 24); } while(0) +#define DM_L_MODIFIED(desc,x) do { (desc).regout[2] |= 1 << ((x) + 24); } while(0) + + +sharc_frontend::sharc_frontend(adsp21062_device *sharc, UINT32 window_start, UINT32 window_end, UINT32 max_sequence) + : drc_frontend(*sharc, window_start, window_end, max_sequence), + m_sharc(sharc) +{ + m_loopmap = std::make_unique(0x20000); +} + + + +void sharc_frontend::flush() +{ + LOOP_ENTRY* map = m_loopmap.get(); + + memset(map, 0, sizeof(LOOP_ENTRY) * 0x20000); +} + +void sharc_frontend::add_loop_entry(UINT32 pc, UINT8 type, UINT32 start_pc, UINT8 looptype, UINT8 condition) +{ + UINT32 l2 = pc >> 17; + UINT32 l1 = pc & 0x1ffff; + + if (l2 != 0x1) + fatalerror("sharc_frontend::add_loop_entry: PC = %08X", pc); + + LOOP_ENTRY* map = m_loopmap.get(); + UINT32 current_type = map[l1].entrytype; + if (current_type & type) + { + // check for mismatch if the entry is already used + if (map[l1].start_pc != start_pc || + map[l1].looptype != looptype || + map[l1].condition != condition) + { + fatalerror("sharc_frontend::add_loop_entry: existing entry does match: start_pc %08X/%08X, looptype %02X/%02X, cond %02X/%02X", start_pc, map[l1].start_pc, looptype, map[l1].looptype, condition, map[l1].condition); + } + } + + current_type |= type; + + map[l1].entrytype = current_type; + map[l1].looptype = looptype; + map[l1].condition = condition; + map[l1].start_pc = start_pc; +} + +void sharc_frontend::insert_loop(const LOOP_DESCRIPTOR &loopdesc) +{ + add_loop_entry(loopdesc.start_pc, LOOP_ENTRY_START, loopdesc.start_pc, loopdesc.type, loopdesc.condition); + add_loop_entry(loopdesc.end_pc, LOOP_ENTRY_EVALUATION, loopdesc.start_pc, loopdesc.type, loopdesc.condition); + if (loopdesc.astat_check_pc != 0xffffffff) + add_loop_entry(loopdesc.astat_check_pc, LOOP_ENTRY_ASTAT_CHECK, loopdesc.start_pc, loopdesc.type, loopdesc.condition); +} + +bool sharc_frontend::is_loop_evaluation(UINT32 pc) +{ + UINT32 l2 = pc >> 17; + UINT32 l1 = pc & 0x1ffff; + + if (l2 != 0x1) + return false; + + LOOP_ENTRY* map = m_loopmap.get(); + if (map[l1].entrytype & LOOP_ENTRY_EVALUATION) + return true; + + return false; +} + +bool sharc_frontend::is_loop_start(UINT32 pc) +{ + UINT32 l2 = pc >> 17; + UINT32 l1 = pc & 0x1ffff; + + if (l2 != 0x1) + return false; + + LOOP_ENTRY* map = m_loopmap.get(); + if (map[l1].entrytype & LOOP_ENTRY_START) + return true; + + return false; +} + +bool sharc_frontend::is_astat_delay_check(UINT32 pc) +{ + UINT32 l2 = pc >> 17; + UINT32 l1 = pc & 0x1ffff; + + if (l2 != 0x1) + return false; + + LOOP_ENTRY* map = m_loopmap.get(); + if (map[l1].entrytype & LOOP_ENTRY_ASTAT_CHECK) + return true; + + return false; +} + + +bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev) +{ + //UINT64 opcode = desc.opptr.q[0] = m_sharc.m_direct->read_qword(desc.physpc, 0); + UINT64 opcode = desc.opptr.q[0] = m_sharc->pm_read48(desc.physpc); + + desc.length = 1; + desc.cycles = 1; + + // handle looping + /* + if (m_loop.size() > 0) + { + for (int i = 0; i < m_loop.size(); i++) + { + LOOP_DESCRIPTOR &loop = m_loop.at(i); + if (loop.start_pc == desc.pc) + { + desc.flags |= OPFLAG_IS_BRANCH_TARGET; + } + if (loop.astat_check_pc == desc.pc) + { + if (loop.type == LOOP_TYPE_CONDITIONAL) + { + UINT32 flags = m_sharc->do_condition_astat_bits(loop.condition); + if (flags & adsp21062_device::ASTAT_FLAGS::AZ) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AZ; + if (flags & adsp21062_device::ASTAT_FLAGS::AN) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AN; + if (flags & adsp21062_device::ASTAT_FLAGS::AV) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AV; + if (flags & adsp21062_device::ASTAT_FLAGS::AC) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AC; + if (flags & adsp21062_device::ASTAT_FLAGS::MN) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_MN; + if (flags & adsp21062_device::ASTAT_FLAGS::MV) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_MV; + if (flags & adsp21062_device::ASTAT_FLAGS::SV) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_SV; + if (flags & adsp21062_device::ASTAT_FLAGS::SZ) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_SZ; + if (flags & adsp21062_device::ASTAT_FLAGS::BTF) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_BTF; + } + } + if (loop.end_pc == desc.pc) + { + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.targetpc = loop.start_pc; + if (loop.type == LOOP_TYPE_COUNTER) + { + desc.userflags |= OP_USERFLAG_COUNTER_LOOP; + } + else if (loop.type == LOOP_TYPE_CONDITIONAL) + { + desc.userflags |= OP_USERFLAG_COND_LOOP; + desc.userflags |= (loop.condition << 2) & OP_USERFLAG_COND_FIELD; + } + m_loop.erase(m_loop.begin()+i); + break; + } + } + }*/ + + if (is_astat_delay_check(desc.pc)) + { + LOOP_ENTRY* map = m_loopmap.get(); + int index = desc.pc & 0x1ffff; + + if (map[index].looptype == LOOP_TYPE_CONDITIONAL) + { + UINT32 flags = m_sharc->do_condition_astat_bits(map[index].condition); + if (flags & adsp21062_device::ASTAT_FLAGS::AZ) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AZ; + if (flags & adsp21062_device::ASTAT_FLAGS::AN) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AN; + if (flags & adsp21062_device::ASTAT_FLAGS::AV) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AV; + if (flags & adsp21062_device::ASTAT_FLAGS::AC) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_AC; + if (flags & adsp21062_device::ASTAT_FLAGS::MN) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_MN; + if (flags & adsp21062_device::ASTAT_FLAGS::MV) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_MV; + if (flags & adsp21062_device::ASTAT_FLAGS::SV) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_SV; + if (flags & adsp21062_device::ASTAT_FLAGS::SZ) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_SZ; + if (flags & adsp21062_device::ASTAT_FLAGS::BTF) desc.userflags |= OP_USERFLAG_ASTAT_DELAY_COPY_BTF; + } + } + + if (is_loop_start(desc.pc)) + { + desc.flags |= OPFLAG_IS_BRANCH_TARGET; + } + + if (is_loop_evaluation(desc.pc)) + { + LOOP_ENTRY* map = m_loopmap.get(); + int index = desc.pc & 0x1ffff; + + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + desc.targetpc = map[index].start_pc; + if (map[index].looptype == LOOP_TYPE_COUNTER) + { + desc.userflags |= OP_USERFLAG_COUNTER_LOOP; + } + else if (map[index].looptype == LOOP_TYPE_CONDITIONAL) + { + desc.userflags |= OP_USERFLAG_COND_LOOP; + desc.userflags |= (map[index].condition << 2) & OP_USERFLAG_COND_FIELD; + } + } + + + switch ((opcode >> 45) & 7) + { + case 0: // subops + { + UINT32 subop = (opcode >> 40) & 0x1f; + switch (subop) + { + case 0x00: // NOP / idle |000|00000| + if (opcode & U64(0x008000000000)) + { + // IDLE + desc.flags |= OPFLAG_END_SEQUENCE; + } + else + { + // NOP + } + break; + + case 0x01: // compute |000|00001| + { + int cond = (opcode >> 33) & 0x1f; + describe_if_condition(desc, cond); + + if (!describe_compute(desc, opcode)) + return false; + break; + } + + case 0x02: // immediate shift |000|00010| + { + int shiftop = (opcode >> 16) & 0x3f; + int rn = (opcode >> 4) & 0xf; + int rx = (opcode & 0xf); + int cond = (opcode >> 33) & 0x1f; + + describe_if_condition(desc, cond); + + if (!describe_shiftop_imm(desc, shiftop, rn, rx)) + return false; + break; + } + + case 0x04: // compute / modify |000|00100| + { + int g = (opcode >> 38) & 0x1; + int m = (opcode >> 27) & 0x7; + int i = (opcode >> 30) & 0x7; + int cond = (opcode >> 33) & 0x1f; + + describe_if_condition(desc, cond); + + if (!describe_compute(desc, opcode)) + return false; + + if (g) + { + // PM + PM_I_USED(desc, i); + PM_I_MODIFIED(desc, i); + PM_M_USED(desc, m); + } + else + { + // DM + DM_I_USED(desc, i); + DM_I_MODIFIED(desc, i); + DM_M_USED(desc, m); + } + break; + } + + case 0x06: // direct jump|call |000|00110| + { + int j = (opcode >> 26) & 0x1; + int cond = (opcode >> 33) & 0x1f; + UINT32 address = opcode & 0xffffff; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + desc.targetpc = address; + desc.delayslots = (j) ? 2 : 0; + break; + } + + case 0x07: // direct jump|call |000|00111| + { + int j = (opcode >> 26) & 0x1; + int cond = (opcode >> 33) & 0x1f; + UINT32 address = opcode & 0xffffff; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + desc.targetpc = desc.pc + SIGN_EXTEND24(address); + desc.delayslots = (j) ? 2 : 0; + break; + } + + case 0x08: // indirect jump|call / compute |000|01000| + { + int j = (opcode >> 26) & 0x1; + int pmi = (opcode >> 30) & 0x7; + int pmm = (opcode >> 27) & 0x7; + int cond = (opcode >> 33) & 0x1f; + + if (!describe_compute(desc, opcode)) + return false; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + PM_I_USED(desc, pmi); + PM_M_USED(desc, pmm); + + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = (j) ? 2 : 0; + break; + } + + case 0x09: // indirect jump|call / compute |000|01001| + { + int j = (opcode >> 26) & 0x1;; + int cond = (opcode >> 33) & 0x1f; + + if (!describe_compute(desc, opcode)) + return false; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + desc.targetpc = desc.pc + SIGN_EXTEND6((opcode >> 27) & 0x3f); + desc.delayslots = (j) ? 2 : 0; + + break; + } + + case 0x0a: // return from subroutine / compute |000|01010| + { + int cond = (opcode >> 33) & 0x1f; + int j = (opcode >> 26) & 0x1; + + if (!describe_compute(desc, opcode)) + return false; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = (j) ? 2 : 0; + break; + } + + case 0x0b: // return from interrupt / compute |000|01011| + { + int cond = (opcode >> 33) & 0x1f; + int j = (opcode >> 26) & 0x1; + + if (!describe_compute(desc, opcode)) + return false; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = (j) ? 2 : 0; + break; + } + + case 0x0c: // do until counter expired |000|01100| + { + int offset = SIGN_EXTEND24(opcode & 0xffffff); + + LOOP_DESCRIPTOR loop; + loop.start_pc = desc.pc + 1; + loop.end_pc = desc.pc + offset; + loop.astat_check_pc = 0xffffffff; + loop.type = LOOP_TYPE_COUNTER; + loop.condition = 0; + + insert_loop(loop); + break; + } + + case 0x0d: // do until counter expired |000|01101| + { + int ureg = (opcode >> 32) & 0xff; + if (!describe_ureg_access(desc, ureg, UREG_READ)) + return false; + + int offset = SIGN_EXTEND24(opcode & 0xffffff); + + LOOP_DESCRIPTOR loop; + loop.start_pc = desc.pc + 1; + loop.end_pc = desc.pc + offset; + loop.astat_check_pc = 0xffffffff; + loop.type = LOOP_TYPE_COUNTER; + loop.condition = 0; + + insert_loop(loop); + break; + } + + case 0x0e: // do until |000|01110| + { + int offset = SIGN_EXTEND24(opcode & 0xffffff); + int cond = (opcode >> 33) & 0x1f; + + LOOP_DESCRIPTOR loop; + loop.start_pc = desc.pc + 1; + loop.end_pc = desc.pc + offset; + loop.type = LOOP_TYPE_CONDITIONAL; + loop.condition = cond; + + loop.astat_check_pc = loop.end_pc - 2; + if (loop.astat_check_pc < loop.start_pc) + fatalerror("describe_compute: conditional loop < 2 at %08X", desc.pc); + + insert_loop(loop); + break; + } + + case 0x0f: // immediate data -> ureg |000|01111| + { + int ureg = (opcode >> 32) & 0xff; + if (!describe_ureg_access(desc, ureg, UREG_WRITE)) + return false; + break; + } + + case 0x10: // ureg <-> DM|PM (direct) |000|100|G|D| + case 0x11: + case 0x12: + case 0x13: + { + int ureg = (opcode >> 32) & 0xff; + int d = (opcode >> 40) & 1; + if (d) + { + if (!describe_ureg_access(desc, ureg, UREG_READ)) + return false; + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + if (!describe_ureg_access(desc, ureg, UREG_WRITE)) + return false; + desc.flags |= OPFLAG_READS_MEMORY; + } + break; + } + + case 0x14: // system register bit manipulation |000|10100| + { + int bop = (opcode >> 37) & 0x7; + int sreg = (opcode >> 32) & 0xf; + UINT32 data = (UINT32)(opcode); + + switch (bop) + { + case 0: // SET + case 1: // CLEAR + case 2: // TOGGLE + if (sreg == 0x7c) // ASTAT + { + if (data & adsp21062_device::AZ) + { + AZ_USED(desc); AZ_MODIFIED(desc); + } + if (data & adsp21062_device::AV) + { + AV_USED(desc); AV_MODIFIED(desc); + } + if (data & adsp21062_device::AN) + { + AN_USED(desc); AN_MODIFIED(desc); + } + if (data & adsp21062_device::AC) + { + AC_USED(desc); AC_MODIFIED(desc); + } + if (data & adsp21062_device::AS) + { + AS_USED(desc); AS_MODIFIED(desc); + } + if (data & adsp21062_device::AI) + { + AI_USED(desc); AI_MODIFIED(desc); + } + if (data & adsp21062_device::MN) + { + MN_USED(desc); MN_MODIFIED(desc); + } + if (data & adsp21062_device::MV) + { + MV_USED(desc); MV_MODIFIED(desc); + } + if (data & adsp21062_device::MU) + { + MU_USED(desc); MU_MODIFIED(desc); + } + if (data & adsp21062_device::MI) + { + MI_USED(desc); MI_MODIFIED(desc); + } + if (data & adsp21062_device::SV) + { + SV_USED(desc); SV_MODIFIED(desc); + } + if (data & adsp21062_device::SZ) + { + SZ_USED(desc); SZ_MODIFIED(desc); + } + if (data & adsp21062_device::SS) + { + SS_USED(desc); SS_MODIFIED(desc); + } + if (data & adsp21062_device::BTF) + { + BTF_USED(desc); BTF_MODIFIED(desc); + } + if (data & adsp21062_device::AF) + { + AF_USED(desc); AF_MODIFIED(desc); + } + } + break; + + case 4: // TEST + case 5: // XOR + BTF_MODIFIED(desc); + break; + + default: + fatalerror("sharc_frontend::describe: system reg bit manipulation %d", bop); + return false; + } + break; + } + + case 0x16: // I register modify / bit-reverse |000|10110| + { + if (opcode & U64(0x008000000000)) // bit reverse + { + fatalerror("sharc_frontend::describe: bit reverse unimplemented"); + } + else // modify + { + int g = (opcode >> 38) & 0x1; + int i = (opcode >> 32) & 0x7; + + if (g) + PM_I_USED(desc, i); + else + DM_I_USED(desc, i); + } + break; + } + + case 0x17: // push|pop stacks / flush cache |000|10111| + break; + + case 0x18: // cjump |000|11000| + fatalerror("sharc_frontend::describe: cjump unimplemented"); + break; + + case 0x19: // rframe |000|11001| + fatalerror("sharc_frontend::describe: rframe unimplemented"); + break; + + default: + fatalerror("sharc_frontend::describe: unknown subop %02X in opcode %04X%08X", subop, (UINT16)(opcode >> 32), (UINT32)(opcode)); + return false; + } + break; + } + + case 1: // compute / dreg <-> DM / dreg <-> PM |001| + { + if (!describe_compute(desc, opcode)) + return false; + + int pm_dreg = (opcode >> 23) & 0xf; + int pmm = (opcode >> 27) & 0x7; + int pmi = (opcode >> 30) & 0x7; + int dm_dreg = (opcode >> 33) & 0xf; + int dmm = (opcode >> 38) & 0x7; + int dmi = (opcode >> 41) & 0x7; + int pmd = (opcode >> 37) & 0x1; + int dmd = (opcode >> 44) & 0x1; + + PM_I_USED(desc, pmi); + PM_I_MODIFIED(desc, pmi); + PM_M_USED(desc, pmm); + + if (pmd) + { + REG_USED(desc, pm_dreg); + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + REG_MODIFIED(desc, pm_dreg); + desc.flags |= OPFLAG_READS_MEMORY; + } + + DM_I_USED(desc, dmi); + DM_I_MODIFIED(desc, dmi); + DM_M_USED(desc, dmm); + + if (dmd) + { + REG_USED(desc, dm_dreg); + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + REG_MODIFIED(desc, dm_dreg); + desc.flags |= OPFLAG_READS_MEMORY; + } + break; + } + + case 2: // compute / ureg <-> DM|PM, register modify |010| + { + if (!describe_compute(desc, opcode)) + return false; + + int i = (opcode >> 41) & 0x7; + int m = (opcode >> 38) & 0x7; + int cond = (opcode >> 33) & 0x1f; + int g = (opcode >> 32) & 0x1; + int d = (opcode >> 31) & 0x1; + int ureg = (opcode >> 23) & 0xff; + + describe_if_condition(desc, cond); + + if (d) + { + if (!describe_ureg_access(desc, ureg, UREG_READ)) + return false; + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + if (!describe_ureg_access(desc, ureg, UREG_WRITE)) + return false; + desc.flags |= OPFLAG_READS_MEMORY; + } + + if (g) + { + // PM + PM_I_USED(desc, i); + PM_M_USED(desc, m); + } + else + { + // DM + DM_I_USED(desc, i); + DM_M_USED(desc, m); + } + + break; + } + + case 3: + { + if (!describe_compute(desc, opcode)) + return false; + + if (opcode & U64(0x100000000000)) // compute / ureg <-> ureg |011|1| + { + int src_ureg = (opcode >> 36) & 0xff; + int dst_ureg = (opcode >> 23) & 0xff; + int cond = (opcode >> 31) & 0x1f; + + describe_if_condition(desc, cond); + + if (!describe_ureg_access(desc, src_ureg, UREG_READ)) + return false; + if (!describe_ureg_access(desc, dst_ureg, UREG_WRITE)) + return false; + } + else // compute / dreg <-> DM|PM, immediate modify |011|0| + { + int u = (opcode >> 38) & 0x1; + int d = (opcode >> 39) & 0x1; + int g = (opcode >> 40) & 0x1; + int dreg = (opcode >> 23) & 0xf; + int i = (opcode >> 41) & 0x7; + int cond = (opcode >> 33) & 0x1f; + + describe_if_condition(desc, cond); + + if (d) + { + REG_USED(desc, dreg); + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + REG_MODIFIED(desc, dreg); + desc.flags |= OPFLAG_READS_MEMORY; + } + + if (g) + { + // PM + PM_I_USED(desc, i); + + if (u) // post-modify with update + { + PM_I_MODIFIED(desc, i); + } + } + else + { + // DM + DM_I_USED(desc, i); + + if (u) // post-modify with update + { + DM_I_MODIFIED(desc, i); + } + } + } + break; + } + + case 4: + { + if (opcode & U64(0x100000000000)) // immediate data -> DM|PM |100|1| + { + int i = (opcode >> 41) & 0x7; + int m = (opcode >> 38) & 0x7; + int g = (opcode >> 37) & 0x1; + + desc.flags |= OPFLAG_WRITES_MEMORY; + + if (g) + { + // PM + PM_I_USED(desc, i); + PM_I_MODIFIED(desc, i); + PM_M_USED(desc, m); + } + else + { + // DM + DM_I_USED(desc, i); + DM_I_MODIFIED(desc, i); + DM_M_USED(desc, m); + } + } + else // immediate shift / dreg <-> DM|PM |100|0| + { + int i = (opcode >> 41) & 0x7; + int m = (opcode >> 38) & 0x7; + int g = (opcode >> 32) & 0x1; + int d = (opcode >> 31) & 0x1; + int dreg = (opcode >> 23) & 0xf; + int shiftop = (opcode >> 16) & 0x3f; + int rn = (opcode >> 4) & 0xf; + int rx = (opcode & 0xf); + int cond = (opcode >> 33) & 0x1f; + + describe_if_condition(desc, cond); + + if (!describe_shiftop_imm(desc, shiftop, rn, rx)) + return false; + + if (d) + { + REG_USED(desc, dreg); + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + REG_MODIFIED(desc, dreg); + desc.flags |= OPFLAG_READS_MEMORY; + } + + if (g) + { + // PM + PM_I_USED(desc, i); + PM_I_MODIFIED(desc, i); + PM_M_USED(desc, m); + } + else + { + // DM + DM_I_USED(desc, i); + DM_I_MODIFIED(desc, i); + DM_M_USED(desc, m); + } + } + break; + } + + case 5: // ureg <-> DM|PM (indirect) |101| + { + int ureg = (opcode >> 32) & 0xff; + int d = (opcode >> 40) & 1; + int i = (opcode >> 41) & 0x7; + int g = (opcode >> 44) & 1; + + if (d) + { + if (!describe_ureg_access(desc, ureg, UREG_READ)) + return false; + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + if (!describe_ureg_access(desc, ureg, UREG_WRITE)) + return false; + desc.flags |= OPFLAG_READS_MEMORY; + } + + if (g) + PM_I_USED(desc, i); + else + DM_I_USED(desc, i); + break; + } + + case 6: // indirect jump / compute / dreg <-> DM |110| + { + int d = (opcode >> 44) & 0x1; + int dmi = (opcode >> 41) & 0x7; + int dmm = (opcode >> 38) & 0x7; + int pmi = (opcode >> 30) & 0x7; + int pmm = (opcode >> 27) & 0x7; + int cond = (opcode >> 33) & 0x1f; + int dreg = (opcode >> 23) & 0xf; + + if (!describe_compute(desc, opcode)) + return false; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + PM_I_USED(desc, pmi); + PM_M_USED(desc, pmm); + DM_I_USED(desc, dmi); + DM_I_MODIFIED(desc, dmi); + DM_M_USED(desc, dmm); + + if (d) + { + REG_USED(desc, dreg); + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + REG_MODIFIED(desc, dreg); + desc.flags |= OPFLAG_READS_MEMORY; + } + + desc.targetpc = BRANCH_TARGET_DYNAMIC; + desc.delayslots = 0; + break; + } + + case 7: // indirect jump / compute / dreg <-> DM |111| + { + int d = (opcode >> 44) & 0x1; + int dmi = (opcode >> 41) & 0x7; + int dmm = (opcode >> 38) & 0x7; + int cond = (opcode >> 33) & 0x1f; + int dreg = (opcode >> 23) & 0xf; + + if (!describe_compute(desc, opcode)) + return false; + + if (m_sharc->if_condition_always_true(cond)) + desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE; + else + desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH; + + describe_if_condition(desc, cond); + + DM_I_USED(desc, dmi); + DM_I_MODIFIED(desc, dmi); + DM_M_USED(desc, dmm); + + if (d) + { + REG_USED(desc, dreg); + desc.flags |= OPFLAG_WRITES_MEMORY; + } + else + { + REG_MODIFIED(desc, dreg); + desc.flags |= OPFLAG_READS_MEMORY; + } + + desc.targetpc = desc.pc + SIGN_EXTEND6((opcode >> 27) & 0x3f); + desc.delayslots = 0; + break; + } + } + + return true; +} + +bool sharc_frontend::describe_compute(opcode_desc &desc, UINT64 opcode) +{ + // skip if no-op + if ((opcode & 0x7fffff) == 0) + return true; + + int rs = (opcode >> 12) & 0xf; + int rn = (opcode >> 8) & 0xf; + int ra = rn; + int rx = (opcode >> 4) & 0xf; + int ry = (opcode >> 0) & 0xf; + + if (opcode & 0x400000) // multi-function operation + { + UINT32 multiop = (opcode >> 16) & 0x3f; + int fm = rs; + int fa = rn; + int fxm = (opcode >> 6) & 0x3; // registers 0 - 3 + int fym = ((opcode >> 4) & 0x3) + 4; // registers 4 - 7 + int fxa = ((opcode >> 2) & 0x3) + 8; // registers 8 - 11 + int fya = (opcode & 0x3) + 12; // registers 12 - 15 + + switch (multiop) + { + case 0x00: // Rn = MRxx + REG_MODIFIED(desc, rn); + break; + case 0x01: // MRxx = Rn + REG_USED(desc, rn); + break; + + case 0x07: // Ra = Rx + Ry, Rs = Rx - Ry + case 0x0f: // Fa = Fx + Fy, Fs = Fx - Fy + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, ra); + REG_MODIFIED(desc, rs); + ALU_FLAGS_MODIFIED(desc); + break; + + case 0x04: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 + case 0x05: // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 + case 0x06: // Rm = R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + REG_MODIFIED(desc, fm); + REG_MODIFIED(desc, fa); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x08: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 + case 0x09: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 + case 0x0a: // MRF = MRF + R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x0c: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 + case 0x0d: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 + case 0x0e: // Rm = MRF + R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + REG_MODIFIED(desc, fm); + REG_MODIFIED(desc, fa); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x10: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 + R15-12 + case 0x11: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = R11-8 - R15-12 + case 0x12: // MRF = MRF - R3-0 * R7-4 (SSF), Ra = (R11-8 + R15-12) / 2 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x14: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12 + case 0x15: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = R11-8 - R15-12 + case 0x16: // Rm = MRF - R3-0 * R7-4 (SSFR), Ra = (R11-8 + R15-12) / 2 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + REG_MODIFIED(desc, fm); + REG_MODIFIED(desc, fa); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x18: // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12 + case 0x19: // Fm = F3-0 * F7-4, Fa = F11-8 - F15-12 + case 0x1a: // Fm = F3-0 * F7-4, Fa = FLOAT F11-8 BY R15-12 + case 0x1b: // Fm = F3-0 * F7-4, Fa = FIX F11-8 BY R15-12 + case 0x1c: // Fm = F3-0 * F7-4, Fa = (F11-8 + F15-12) / 2 + case 0x1e: // Fm = F3-0 * F7-4, Fa = MAX(F11-8, F15-12) + case 0x1f: // Fm = F3-0 * F7-4, Fa = MIN(F11-8, F15-12) + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + REG_MODIFIED(desc, fm); + REG_MODIFIED(desc, fa); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x1d: // Fm = F3-0 * F7-4, Fa = ABS F11-8 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_MODIFIED(desc, fm); + REG_MODIFIED(desc, fa); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + // Rm = R3-0 * R7-4 (SSFR), Ra = R11-8 + R15-12, Rs = R11-8 - R15-12 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + REG_MODIFIED(desc, fm); + REG_MODIFIED(desc, fa); + REG_MODIFIED(desc, (opcode >> 16) & 0xf); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + // Fm = F3-0 * F7-4, Fa = F11-8 + F15-12, Fs = F11-8 - F15-12 + REG_USED(desc, fxm); + REG_USED(desc, fym); + REG_USED(desc, fxa); + REG_USED(desc, fya); + REG_MODIFIED(desc, fm); + REG_MODIFIED(desc, fa); + REG_MODIFIED(desc, (opcode >> 16) & 0xf); + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + break; + + default: + fatalerror("sharc_frontend::describe_compute: unknown multiop %02X in opcode %04X%08X at %08X", multiop, (UINT16)(opcode >> 32), (UINT32)(opcode), desc.pc); + return false; + } + } + else // single-function operation + { + UINT32 operation = (opcode >> 12) & 0xff; + + switch ((opcode >> 20) & 3) + { + case 0: // ALU operations + { + switch (operation) + { + case 0x01: // Rn = Rx + Ry + case 0x02: // Rn = Rx - Ry + case 0x09: // Rn = (Rx + Ry) / 2 + case 0x40: // Rn = Rx AND Ry + case 0x41: // Rn = Rx OR Ry + case 0x42: // Rn = Rx XOR Ry + case 0x61: // Rn = MIN(Rx, Ry) + case 0x62: // Rn = MAX(Rx, Ry) + case 0x63: // Rn = CLIP Rx BY Ry + case 0x81: // Fn = Fx + Fy + case 0x82: // Fn = Fx - Fy + case 0x91: // Fn = ABS(Fx + Fy) + case 0x92: // Fn = ABS(Fx - Fy) + case 0x89: // Fn = (Fx + Fy) / 2 + case 0xbd: // Fn = SCALB Fx BY Ry + case 0xd9: // Rn = FIX Fx BY Ry + case 0xdd: // Rn = TRUNC Fx BY Ry + case 0xda: // Fn = FLOAT Rx BY Ry + case 0xe1: // Fn = MIN(Fx, Fy) + case 0xe2: // Fn = MAX(Fx, Fy) + case 0xe3: // Fn = CLIP Fx BY Fy + case 0xe0: // Fn = Fx COPYSIGN Fy + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + ALU_FLAGS_MODIFIED(desc); + break; + + case 0x05: // Rn = Rx + Ry + CI + case 0x06: // Rn = Rx - Ry + CI - 1 + case 0x25: // Rn = Rx + CI + case 0x26: // Rn = Rx + CI - 1 + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + AC_USED(desc); + ALU_FLAGS_MODIFIED(desc); + break; + + case 0x0a: // COMP(Rx, Ry) + case 0x8a: // COMP(Fx, Fy) + REG_USED(desc, rx); + REG_USED(desc, ry); + ALU_FLAGS_MODIFIED(desc); + break; + + case 0x29: // Rn = Rx + 1 + case 0x2a: // Rn = Rx - 1 + case 0x22: // Rn = -Rx + case 0x30: // Rn = ABS Rx + case 0x21: // Rn = PASS Rx + case 0x43: // Rn = NOT Rx + case 0xb0: // Fn = ABS(Fx) + case 0xa1: // Fn = PASS Fx + case 0xa2: // Fn = -Fx + case 0xa5: // Fn = RND Fx + case 0xad: // Rn = MANT Fx + case 0xc1: // Rn = LOGB Fx + case 0xc9: // Rn = FIX Fx + case 0xcd: // Rn = TRUNC Fx + case 0xca: // Fn = FLOAT Rx + case 0xc4: // Fn = RECIPS Fx + case 0xc5: // Fn = RSQRTS Fx + REG_USED(desc, rx); + REG_MODIFIED(desc, rn); + ALU_FLAGS_MODIFIED(desc); + break; + + case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x75: case 0x76: case 0x77: + case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: case 0x7d: case 0x7e: case 0x7f: + { + /* Fixed-point Dual Add/Subtract */ + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + REG_MODIFIED(desc, ra); + ALU_FLAGS_MODIFIED(desc); + break; + } + + case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: + case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: + { + /* Floating-point Dual Add/Subtract */ + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + REG_MODIFIED(desc, ra); + ALU_FLAGS_MODIFIED(desc); + break; + } + + default: + fatalerror("sharc_frontend::describe_compute: unknown ALU op %02X in opcode %04X%08X at %08X", operation, (UINT16)(opcode >> 32), (UINT32)(opcode), desc.pc); + return false; + } + break; + } + + case 1: // multiplier operations + { + switch (operation) + { + case 0x40: // Rn = Rx * Ry (UUI) + case 0x48: // Rn = Rx * Ry (UUF) + case 0x49: // Rn = Rx * Ry (UUFR) + case 0x50: // Rn = Rx * Ry (SUI) + case 0x58: // Rn = Rx * Ry (SUF) + case 0x59: // Rn = Rx * Ry (SUFR) + case 0x60: // Rn = Rx * Ry (USI) + case 0x68: // Rn = Rx * Ry (USF) + case 0x69: // Rn = Rx * Ry (USFR) + case 0x70: // Rn = Rx * Ry (SSI) + case 0x78: // Rn = Rx * Ry (SSF) + case 0x79: // Rn = Rx * Ry (SSFR) + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x44: // MRF = Rx * Ry (UUI) + case 0x4c: // MRF = Rx * Ry (UUF) + case 0x4d: // MRF = Rx * Ry (UUFR) + case 0x54: // MRF = Rx * Ry (SUI) + case 0x5c: // MRF = Rx * Ry (SUF) + case 0x5d: // MRF = Rx * Ry (SUFR) + case 0x64: // MRF = Rx * Ry (USI) + case 0x6c: // MRF = Rx * Ry (USF) + case 0x6d: // MRF = Rx * Ry (USFR) + case 0x74: // MRF = Rx * Ry (SSI) + case 0x7c: // MRF = Rx * Ry (SSF) + case 0x7d: // MRF = Rx * Ry (SSFR) + // TODO: track MRF? + REG_USED(desc, rx); + REG_USED(desc, ry); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x46: // MRB = Rx * Ry (UUI) + case 0x4e: // MRB = Rx * Ry (UUF) + case 0x4f: // MRB = Rx * Ry (UUFR) + case 0x56: // MRB = Rx * Ry (SUI) + case 0x5e: // MRB = Rx * Ry (SUF) + case 0x5f: // MRB = Rx * Ry (SUFR) + case 0x66: // MRB = Rx * Ry (USI) + case 0x6e: // MRB = Rx * Ry (USF) + case 0x6f: // MRB = Rx * Ry (USFR) + case 0x76: // MRB = Rx * Ry (SSI) + case 0x7e: // MRB = Rx * Ry (SSF) + case 0x7f: // MRB = Rx * Ry (SSFR) + // TODO: track MRB? + REG_USED(desc, rx); + REG_USED(desc, ry); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x80: // Rn = MRF + Rx * Ry (UUI) + case 0x88: // Rn = MRF + Rx * Ry (UUF) + case 0x89: // Rn = MRF + Rx * Ry (UUFR) + case 0x90: // Rn = MRF + Rx * Ry (SUI) + case 0x98: // Rn = MRF + Rx * Ry (SUF) + case 0x99: // Rn = MRF + Rx * Ry (SUFR) + case 0xa0: // Rn = MRF + Rx * Ry (USI) + case 0xa8: // Rn = MRF + Rx * Ry (USF) + case 0xa9: // Rn = MRF + Rx * Ry (USFR) + case 0xb0: // Rn = MRF + Rx * Ry (SSI) + case 0xb8: // Rn = MRF + Rx * Ry (SSF) + case 0xb9: // Rn = MRF + Rx * Ry (SSFR) + // TODO: track MRF? + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x82: // Rn = MRB + Rx * Ry (UUI) + case 0x8a: // Rn = MRB + Rx * Ry (UUF) + case 0x8b: // Rn = MRB + Rx * Ry (UUFR) + case 0x92: // Rn = MRB + Rx * Ry (SUI) + case 0x9a: // Rn = MRB + Rx * Ry (SUF) + case 0x9b: // Rn = MRB + Rx * Ry (SUFR) + case 0xa2: // Rn = MRB + Rx * Ry (USI) + case 0xaa: // Rn = MRB + Rx * Ry (USF) + case 0xab: // Rn = MRB + Rx * Ry (USFR) + case 0xb2: // Rn = MRB + Rx * Ry (SSI) + case 0xba: // Rn = MRB + Rx * Ry (SSF) + case 0xbb: // Rn = MRB + Rx * Ry (SSFR) + // TODO: track MRB? + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x84: // MRF = MRF + Rx * Ry (UUI) + case 0x8c: // MRF = MRF + Rx * Ry (UUF) + case 0x8d: // MRF = MRF + Rx * Ry (UUFR) + case 0x94: // MRF = MRF + Rx * Ry (SUI) + case 0x9c: // MRF = MRF + Rx * Ry (SUF) + case 0x9d: // MRF = MRF + Rx * Ry (SUFR) + case 0xa4: // MRF = MRF + Rx * Ry (USI) + case 0xac: // MRF = MRF + Rx * Ry (USF) + case 0xad: // MRF = MRF + Rx * Ry (USFR) + case 0xb4: // MRF = MRF + Rx * Ry (SSI) + case 0xbc: // MRF = MRF + Rx * Ry (SSF) + case 0xbd: // MRF = MRF + Rx * Ry (SSFR) + // TODO: track MRF? + REG_USED(desc, rx); + REG_USED(desc, ry); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x86: // MRB = MRB + Rx * Ry (UUI) + case 0x8e: // MRB = MRB + Rx * Ry (UUF) + case 0x8f: // MRB = MRB + Rx * Ry (UUFR) + case 0x96: // MRB = MRB + Rx * Ry (SUI) + case 0x9e: // MRB = MRB + Rx * Ry (SUF) + case 0x9f: // MRB = MRB + Rx * Ry (SUFR) + case 0xa6: // MRB = MRB + Rx * Ry (USI) + case 0xae: // MRB = MRB + Rx * Ry (USF) + case 0xaf: // MRB = MRB + Rx * Ry (USFR) + case 0xb6: // MRB = MRB + Rx * Ry (SSI) + case 0xbe: // MRB = MRB + Rx * Ry (SSF) + case 0xbf: // MRB = MRB + Rx * Ry (SSFR) + break; + // TODO: track MRB? + REG_USED(desc, rx); + REG_USED(desc, ry); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0xc0: // Rn = MRF - Rx * Ry (UUI) + case 0xc8: // Rn = MRF - Rx * Ry (UUF) + case 0xc9: // Rn = MRF - Rx * Ry (UUFR) + case 0xd0: // Rn = MRF - Rx * Ry (SUI) + case 0xd8: // Rn = MRF - Rx * Ry (SUF) + case 0xd9: // Rn = MRF - Rx * Ry (SUFR) + case 0xe0: // Rn = MRF - Rx * Ry (USI) + case 0xe8: // Rn = MRF - Rx * Ry (USF) + case 0xe9: // Rn = MRF - Rx * Ry (USFR) + case 0xf0: // Rn = MRF - Rx * Ry (SSI) + case 0xf8: // Rn = MRF - Rx * Ry (SSF) + case 0xf9: // Rn = MRF - Rx * Ry (SSFR) + // TODO: track MRF? + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0xc2: // Rn = MRB - Rx * Ry (UUI) + case 0xca: // Rn = MRB - Rx * Ry (UUF) + case 0xcb: // Rn = MRB - Rx * Ry (UUFR) + case 0xd2: // Rn = MRB - Rx * Ry (SUI) + case 0xda: // Rn = MRB - Rx * Ry (SUF) + case 0xdb: // Rn = MRB - Rx * Ry (SUFR) + case 0xe2: // Rn = MRB - Rx * Ry (USI) + case 0xea: // Rn = MRB - Rx * Ry (USF) + case 0xeb: // Rn = MRB - Rx * Ry (USFR) + case 0xf2: // Rn = MRB - Rx * Ry (SSI) + case 0xfa: // Rn = MRB - Rx * Ry (SSF) + case 0xfb: // Rn = MRB - Rx * Ry (SSFR) + // TODO: track MRB? + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0xc4: // MRF = MRF - Rx * Ry (UUI) + case 0xcc: // MRF = MRF - Rx * Ry (UUF) + case 0xcd: // MRF = MRF - Rx * Ry (UUFR) + case 0xd4: // MRF = MRF - Rx * Ry (SUI) + case 0xdc: // MRF = MRF - Rx * Ry (SUF) + case 0xdd: // MRF = MRF - Rx * Ry (SUFR) + case 0xe4: // MRF = MRF - Rx * Ry (USI) + case 0xec: // MRF = MRF - Rx * Ry (USF) + case 0xed: // MRF = MRF - Rx * Ry (USFR) + case 0xf4: // MRF = MRF - Rx * Ry (SSI) + case 0xfc: // MRF = MRF - Rx * Ry (SSF) + case 0xfd: // MRF = MRF - Rx * Ry (SSFR) + // TODO: track MRF? + REG_USED(desc, rx); + REG_USED(desc, ry); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0xc6: // MRB = MRB - Rx * Ry (UUI) + case 0xce: // MRB = MRB - Rx * Ry (UUF) + case 0xcf: // MRB = MRB - Rx * Ry (UUFR) + case 0xd6: // MRB = MRB - Rx * Ry (SUI) + case 0xde: // MRB = MRB - Rx * Ry (SUF) + case 0xdf: // MRB = MRB - Rx * Ry (SUFR) + case 0xe6: // MRB = MRB - Rx * Ry (USI) + case 0xee: // MRB = MRB - Rx * Ry (USF) + case 0xef: // MRB = MRB - Rx * Ry (USFR) + case 0xf6: // MRB = MRB - Rx * Ry (SSI) + case 0xfe: // MRB = MRB - Rx * Ry (SSF) + case 0xff: // MRB = MRB - Rx * Ry (SSFR) + // TODO: track MRB? + REG_USED(desc, rx); + REG_USED(desc, ry); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x00: // Rn = SAT MRF (UI) + case 0x01: // Rn = SAT MRF (SI) + case 0x08: // Rn = SAT MRF (UF) + case 0x09: // Rn = SAT MRF (SF) + // TODO: track MRF? + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x02: // Rn = SAT MRB (UI) + case 0x03: // Rn = SAT MRB (SI) + case 0x0a: // Rn = SAT MRB (UF) + case 0x0b: // Rn = SAT MRB (SF) + // TODO: track MRB? + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x04: // MRF = SAT MRF (UI) + case 0x05: // MRF = SAT MRF (SI) + case 0x0c: // MRF = SAT MRF (UF) + case 0x0d: // MRF = SAT MRF (SF) + // TODO: track MRF? + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x06: // MRB = SAT MRB (UI) + case 0x07: // MRB = SAT MRB (SI) + case 0x0e: // MRB = SAT MRB (UF) + case 0x0f: // MRB = SAT MRB (SF) + // TODO: track MRB? + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x18: // Rn = RND MRF (U) + case 0x19: // Rn = RND MRF (S) + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x1a: // Rn = RND MRB (U) + case 0x1b: // Rn = RND MRB (S) + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x1c: // MRF = RND MRF (U) + case 0x1d: // MRF = RND MRF (S) + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x1e: // MRB = RND MRB (U) + case 0x1f: // MRB = RND MRB (S) + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x14: // MRF = 0 + MULT_FLAGS_MODIFIED(desc); + break; + case 0x16: // MRB = 0 + MULT_FLAGS_MODIFIED(desc); + break; + + case 0x30: // Fn = Fx * Fy + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + MULT_FLAGS_MODIFIED(desc); + break; + + default: + fatalerror("sharc_frontend::describe_compute: unknown mult op %02X in opcode %04X%08X at %08X", operation, (UINT16)(opcode >> 32), (UINT32)(opcode), desc.pc); + } + break; + } + + case 2: // shifter operations + { + switch (operation) + { + case 0x00: // Rn = LSHIFT Rx BY Ry | + case 0x04: // Rn = ASHIFT Rx BY Ry | + case 0x08: // Rn = ROT Rx BY Ry | + case 0xc4: // Rn = BCLR Rx BY Ry | + case 0xc0: // Rn = BSET Rx BY Ry | + case 0x44: // Rn = FDEP Rx BY Ry | : + case 0x4c: // Rn = FDEP Rx BY Ry | : (SE) + case 0x40: // Rn = FEXT Rx BY Ry | : + case 0x48: // Rn = FEXT Rx BY Ry | : (SE) + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_MODIFIED(desc, rn); + SHIFT_FLAGS_MODIFIED(desc); + break; + + case 0x20: // Rn = Rn OR LSHIFT Rx BY Ry | + case 0x24: // Rn = Rn OR ASHIFT Rx BY Ry | + case 0x64: // Rn = Rn OR FDEP Rx BY Ry | : + case 0x6c: // Rn = Rn OR FDEP Rx BY Ry | : (SE) + REG_USED(desc, rx); + REG_USED(desc, ry); + REG_USED(desc, rn); + REG_MODIFIED(desc, rn); + SHIFT_FLAGS_MODIFIED(desc); + break; + + case 0xcc: // BTST Rx BY Ry | + REG_USED(desc, rx); + REG_USED(desc, ry); + SHIFT_FLAGS_MODIFIED(desc); + break; + + case 0x80: // Rn = EXP Rx + case 0x84: // Rn = EXP Rx (EX) + case 0x88: // Rn = LEFTZ Rx + case 0x8c: // Rn = LEFTO Rx + case 0x90: // Rn = FPACK Fx + case 0x94: // Fn = FUNPACK Rx + REG_USED(desc, rx); + REG_MODIFIED(desc, rn); + SHIFT_FLAGS_MODIFIED(desc); + break; + + default: + fatalerror("sharc_frontend::describe_compute: unknown shift op %02X in opcode %04X%08X at %08X", operation, (UINT16)(opcode >> 32), (UINT32)(opcode), desc.pc); + } + break; + } + + default: + fatalerror("sharc_frontend::describe_compute: unknown operation type in opcode %04X%08X at %08X", (UINT16)(opcode >> 32), (UINT32)(opcode), desc.pc); + return false; + } + } + + return true; +} + +bool sharc_frontend::describe_ureg_access(opcode_desc &desc, int reg, UREG_ACCESS access) +{ + switch (reg) + { + case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: + case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: + if (access == UREG_READ) + REG_USED(desc, reg); + else + REG_MODIFIED(desc, reg); + break; + + case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: + if (access == UREG_READ) + DM_I_USED(desc, reg & 7); + else + DM_I_MODIFIED(desc, reg & 7); + break; + case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f: + if (access == UREG_READ) + PM_I_USED(desc, reg & 7); + else + PM_I_MODIFIED(desc, reg & 7); + break; + + case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: + if (access == UREG_READ) + DM_M_USED(desc, reg & 7); + else + DM_M_MODIFIED(desc, reg & 7); + break; + case 0x28: case 0x29: case 0x2a: case 0x2b: case 0x2c: case 0x2d: case 0x2e: case 0x2f: + if (access == UREG_READ) + PM_M_USED(desc, reg & 7); + else + PM_M_MODIFIED(desc, reg & 7); + break; + + case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37: + if (access == UREG_READ) + DM_L_USED(desc, reg & 7); + else + DM_L_MODIFIED(desc, reg & 7); + break; + case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: + if (access == UREG_READ) + PM_L_USED(desc, reg & 7); + else + PM_L_MODIFIED(desc, reg & 7); + break; + + case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x45: case 0x46: case 0x47: + if (access == UREG_READ) + DM_B_USED(desc, reg & 7); + else + DM_B_MODIFIED(desc, reg & 7); + break; + case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: + if (access == UREG_READ) + PM_B_USED(desc, reg & 7); + else + PM_B_MODIFIED(desc, reg & 7); + break; + + case 0x60: // FADDR + break; + case 0x61: // DADDR + break; + case 0x63: // PC + break; + case 0x64: // PCSTK + break; + case 0x65: // PCSTKP + break; + case 0x66: // LADDR + break; + case 0x67: // CURLCNTR + break; + case 0x68: // LCNTR + break; + case 0x70: // USTAT1 + break; + case 0x71: // USTAT2 + break; + case 0x79: // IRPTL + break; + case 0x7a: // MODE1 + break; + case 0x7b: // MODE2 + break; + + case 0x7c: // ASTAT + if (access == UREG_READ) + { + AZ_USED(desc); + AN_USED(desc); + AV_USED(desc); + AC_USED(desc); + AS_USED(desc); + AI_USED(desc); + MN_USED(desc); + MV_USED(desc); + MU_USED(desc); + MI_USED(desc); + SV_USED(desc); + SZ_USED(desc); + SS_USED(desc); + BTF_USED(desc); + AF_USED(desc); + } + else + { + ALU_FLAGS_MODIFIED(desc); + MULT_FLAGS_MODIFIED(desc); + SHIFT_FLAGS_MODIFIED(desc); + BTF_MODIFIED(desc); + AF_MODIFIED(desc); + } + break; + + case 0x7d: // IMASK + break; + case 0x7e: // STKY + break; + case 0x7f: // IMASKP + break; + case 0xdb: // PX + break; + case 0xdc: // PX1 + break; + case 0xdd: // PX2 + break; + + default: + fatalerror("sharc_frontend::describe_ureg_access: unknown UREG %02X", reg); + return false; + } + + return true; +} + +bool sharc_frontend::describe_shiftop_imm(opcode_desc &desc, int shiftop, int rn, int rx) +{ + switch (shiftop) + { + case 0x00: // LSHIFT Rx BY + case 0x01: // ASHIFT Rx BY + case 0x02: // ROT Rx BY + case 0x10: // FEXT Rx BY + case 0x11: // FDEP Rx BY + case 0x12: // FEXT Rx BY : (SE) + case 0x13: // FDEP Rx BY : (SE) + case 0x30: // BSET Rx BY + case 0x31: // BCLR Rx By + case 0x32: // BTGL Rx BY + REG_USED(desc, rx); + REG_MODIFIED(desc, rn); + SHIFT_FLAGS_MODIFIED(desc); + break; + + case 0x08: // Rn = Rn OR LSHIFT Rx BY + case 0x19: // Rn = Rn OR FDEP Rx BY : + case 0x1b: // Rn = Rn OR FDEP Rx BY : (SE) + REG_USED(desc, rx); + REG_USED(desc, rn); + REG_MODIFIED(desc, rn); + SHIFT_FLAGS_MODIFIED(desc); + break; + + case 0x33: // BTST Rx BY + REG_USED(desc, rx); + SHIFT_FLAGS_MODIFIED(desc); + break; + + default: + fatalerror("sharc_frontend::describe_shiftop_imm: unknown op %02X at %08X", shiftop, desc.pc); + return false; + } + + return true; +} + +void sharc_frontend::describe_if_condition(opcode_desc &desc, int condition) +{ + switch (condition) + { + case 0x00: AZ_USED(desc); break; /* EQ */ + case 0x01: AZ_USED(desc); AN_USED(desc); break; /* LT */ + case 0x02: AZ_USED(desc); AN_USED(desc); break; /* LE */ + case 0x03: AC_USED(desc); break; /* AC */ + case 0x04: AV_USED(desc); break; /* AV */ + case 0x05: MV_USED(desc); break; /* MV */ + case 0x06: MN_USED(desc); break; /* MS */ + case 0x07: SV_USED(desc); break; /* SV */ + case 0x08: SZ_USED(desc); break; /* SZ */ + case 0x0d: BTF_USED(desc); break; /* TF */ + case 0x10: AZ_USED(desc); break; /* NOT EQUAL */ + case 0x11: AZ_USED(desc); AN_USED(desc); break; /* GE */ + case 0x12: AZ_USED(desc); AN_USED(desc); break; /* GT */ + case 0x13: AC_USED(desc); break; /* NOT AC */ + case 0x14: AV_USED(desc); break; /* NOT AV */ + case 0x15: MV_USED(desc); break; /* NOT MV */ + case 0x16: MN_USED(desc); break; /* NOT MS */ + case 0x17: SV_USED(desc); break; /* NOT SV */ + case 0x18: SZ_USED(desc); break; /* NOT SZ */ + case 0x1d: BTF_USED(desc); break; /* NOT TF */ + } +} \ No newline at end of file diff --git a/src/devices/cpu/sharc/sharcfe.h b/src/devices/cpu/sharc/sharcfe.h new file mode 100644 index 00000000000..b383e122606 --- /dev/null +++ b/src/devices/cpu/sharc/sharcfe.h @@ -0,0 +1,81 @@ +// license:BSD-3-Clause +// copyright-holders:Ville Linde + +/****************************************************************************** + + Front-end for SHARC recompiler + +******************************************************************************/ + +#pragma once + +#include "sharc.h" +#include "cpu/drcfe.h" + +#ifndef __SHARCFE_H__ +#define __SHARCFE_H__ + +class sharc_frontend : public drc_frontend +{ +public: + sharc_frontend(adsp21062_device *sharc, UINT32 window_start, UINT32 window_end, UINT32 max_sequence); + void flush(); + + enum UREG_ACCESS + { + UREG_READ, + UREG_WRITE + }; + + enum LOOP_TYPE + { + LOOP_TYPE_COUNTER, + LOOP_TYPE_CONDITIONAL + }; + + enum LOOP_ENTRY_TYPE + { + LOOP_ENTRY_START = 0x1, + LOOP_ENTRY_EVALUATION = 0x2, + LOOP_ENTRY_ASTAT_CHECK = 0x4, + }; + + struct LOOP_ENTRY + { + UINT16 entrytype; + UINT8 looptype; + UINT8 condition; + UINT32 start_pc; + }; + + struct LOOP_DESCRIPTOR + { + UINT32 start_pc; + UINT32 end_pc; + UINT32 astat_check_pc; + LOOP_TYPE type; + int condition; + }; + +protected: + // required overrides + virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override; + +private: + bool describe_compute(opcode_desc &desc, UINT64 opcode); + bool describe_ureg_access(opcode_desc &desc, int reg, UREG_ACCESS access); + bool describe_shiftop_imm(opcode_desc &desc, int shiftop, int rn, int rx); + void describe_if_condition(opcode_desc &desc, int condition); + + void insert_loop(const LOOP_DESCRIPTOR &loopdesc); + void add_loop_entry(UINT32 pc, UINT8 type, UINT32 start_pc, UINT8 looptype, UINT8 condition); + bool is_loop_evaluation(UINT32 pc); + bool is_loop_start(UINT32 pc); + bool is_astat_delay_check(UINT32 pc); + + adsp21062_device *m_sharc; + + std::unique_ptr m_loopmap; +}; + +#endif /* __SHARCFE_H__ */ diff --git a/src/devices/cpu/sharc/sharcmem.hxx b/src/devices/cpu/sharc/sharcmem.hxx index 3427e0346b8..f48c1ba3608 100644 --- a/src/devices/cpu/sharc/sharcmem.hxx +++ b/src/devices/cpu/sharc/sharcmem.hxx @@ -20,12 +20,13 @@ UINT32 adsp21062_device::pm_read32(UINT32 address) (m_internal_ram_block1[addr + 1]); } else { - fatalerror("SHARC: PM Bus Read32 %08X at %08X\n", address, m_pc); + fatalerror("SHARC: PM Bus Read32 %08X at %08X\n", address, m_core->pc); } } void adsp21062_device::pm_write32(UINT32 address, UINT32 data) { +// printf("PM Write32 %08X, %08X at %08X\n", data, address, m_core->pc); if (address >= 0x20000 && address < 0x28000) { UINT32 addr = (address & 0x7fff) * 3; @@ -44,7 +45,8 @@ void adsp21062_device::pm_write32(UINT32 address, UINT32 data) return; } else { - fatalerror("SHARC: PM Bus Write32 %08X, %08X at %08X\n", address, data, m_pc); + debugger_break(machine()); + //fatalerror("SHARC: PM Bus Write32 %08X, %08X at %08X\n", address, data, m_core->pc); } } @@ -68,7 +70,7 @@ UINT64 adsp21062_device::pm_read48(UINT32 address) ((UINT64)(m_internal_ram_block1[addr + 2]) << 0); } else { - fatalerror("SHARC: PM Bus Read48 %08X at %08X\n", address, m_pc); + fatalerror("SHARC: PM Bus Read48 %08X at %08X\n", address, m_core->pc); } return 0; @@ -76,6 +78,7 @@ UINT64 adsp21062_device::pm_read48(UINT32 address) void adsp21062_device::pm_write48(UINT32 address, UINT64 data) { +// printf("PM Write48 %08X%08X, %08X at %08X\n", (UINT32)(data >> 32), (UINT32)(data), address, m_core->pc); if ((address >= 0x20000 && address < 0x28000)) { UINT32 addr = (address & 0x7fff) * 3; @@ -96,7 +99,7 @@ void adsp21062_device::pm_write48(UINT32 address, UINT64 data) return; } else { - fatalerror("SHARC: PM Bus Write48 %08X, %04X%08X at %08X\n", address, (UINT16)(data >> 32),(UINT32)data, m_pc); + fatalerror("SHARC: PM Bus Write48 %08X, %04X%08X at %08X\n", address, (UINT16)(data >> 32),(UINT32)data, m_core->pc); } } @@ -128,7 +131,7 @@ UINT32 adsp21062_device::dm_read32(UINT32 address) UINT32 addr = address & 0xffff; UINT16 r = m_internal_ram_block0[addr ^ 1]; - if (m_mode1 & 0x4000) + if (m_core->mode1 & 0x4000) { // sign-extend return (INT32)(INT16)(r); @@ -144,7 +147,7 @@ UINT32 adsp21062_device::dm_read32(UINT32 address) UINT32 addr = address & 0xffff; UINT16 r = m_internal_ram_block1[addr ^ 1]; - if (m_mode1 & 0x4000) + if (m_core->mode1 & 0x4000) { // sign-extend return (INT32)(INT16)(r); diff --git a/src/devices/cpu/sharc/sharcops.hxx b/src/devices/cpu/sharc/sharcops.hxx index 5bcc9765f1c..0400319d10e 100644 --- a/src/devices/cpu/sharc/sharcops.hxx +++ b/src/devices/cpu/sharc/sharcops.hxx @@ -3,14 +3,14 @@ #define SIGN_EXTEND6(x) (((x) & 0x20) ? (0xffffffc0 | (x)) : (x)) #define SIGN_EXTEND24(x) (((x) & 0x800000) ? (0xff000000 | (x)) : (x)) -#define PM_REG_I(x) (m_dag2.i[x]) -#define PM_REG_M(x) (m_dag2.m[x]) -#define PM_REG_B(x) (m_dag2.b[x]) -#define PM_REG_L(x) (m_dag2.l[x]) -#define DM_REG_I(x) (m_dag1.i[x]) -#define DM_REG_M(x) (m_dag1.m[x]) -#define DM_REG_B(x) (m_dag1.b[x]) -#define DM_REG_L(x) (m_dag1.l[x]) +#define PM_REG_I(x) (m_core->dag2.i[x]) +#define PM_REG_M(x) (m_core->dag2.m[x]) +#define PM_REG_B(x) (m_core->dag2.b[x]) +#define PM_REG_L(x) (m_core->dag2.l[x]) +#define DM_REG_I(x) (m_core->dag1.i[x]) +#define DM_REG_M(x) (m_core->dag1.m[x]) +#define DM_REG_B(x) (m_core->dag1.b[x]) +#define DM_REG_L(x) (m_core->dag1.l[x]) // ASTAT flags #define AZ 0x1 /* ALU result zero */ @@ -33,44 +33,6 @@ #define FLG2 0x200000 /* FLAG2 */ #define FLG3 0x400000 /* FLAG3 */ -// STKY flags -#define AUS 0x1 /* ALU floating-point underflow */ -#define AVS 0x2 /* ALU floating-point overflow */ -#define AOS 0x4 /* ALU fixed-point overflow */ -#define AIS 0x20 /* ALU floating-point invalid operation */ - -// MODE1 flags -#define MODE1_BR8 0x1 /* Bit-reverse for I8 */ -#define MODE1_BR0 0x2 /* Bit-reverse for I0 */ -#define MODE1_SRCU 0x4 /* Alternate register select for computational units */ -#define MODE1_SRD1H 0x8 /* DAG alternate register select (7-4) */ -#define MODE1_SRD1L 0x10 /* DAG alternate register select (3-0) */ -#define MODE1_SRD2H 0x20 /* DAG alternate register select (15-12) */ -#define MODE1_SRD2L 0x40 /* DAG alternate register select (11-8) */ -#define MODE1_SRRFH 0x80 /* Register file alternate select for R(15-8) */ -#define MODE1_SRRFL 0x400 /* Register file alternate select for R(7-0) */ -#define MODE1_NESTM 0x800 /* Interrupt nesting enable */ -#define MODE1_IRPTEN 0x1000 /* Global interrupt enable */ -#define MODE1_ALUSAT 0x2000 /* Enable ALU fixed-point saturation */ -#define MODE1_SSE 0x4000 /* Enable short word sign extension */ -#define MODE1_TRUNCATE 0x8000 /* (1) Floating-point truncation / (0) round to nearest */ -#define MODE1_RND32 0x10000 /* (1) 32-bit floating-point rounding / (0) 40-bit rounding */ -#define MODE1_CSEL 0x60000 /* CSelect */ - -// MODE2 flags -#define MODE2_IRQ0E 0x1 /* IRQ0 (1) Edge sens. / (0) Level sens. */ -#define MODE2_IRQ1E 0x2 /* IRQ1 (1) Edge sens. / (0) Level sens. */ -#define MODE2_IRQ2E 0x4 /* IRQ2 (1) Edge sens. / (0) Level sens. */ -#define MODE2_CADIS 0x10 /* Cache disable */ -#define MODE2_TIMEN 0x20 /* Timer enable */ -#define MODE2_BUSLK 0x40 /* External bus lock */ -#define MODE2_FLG0O 0x8000 /* FLAG0 (1) Output / (0) Input */ -#define MODE2_FLG1O 0x10000 /* FLAG1 (1) Output / (0) Input */ -#define MODE2_FLG2O 0x20000 /* FLAG2 (1) Output / (0) Input */ -#define MODE2_FLG3O 0x40000 /* FLAG3 (1) Output / (0) Input */ -#define MODE2_CAFRZ 0x80000 /* Cache freeze */ - - #define REG_PC 0x63 #define REG_PCSTK 0x64 #define REG_PCSTKP 0x65 @@ -89,8 +51,8 @@ -#define REG(x) (m_r[x].r) -#define FREG(x) (m_r[x].f) +#define REG(x) (m_core->r[x].r) +#define FREG(x) (m_core->r[x].f) #define UPDATE_CIRCULAR_BUFFER_PM(x) \ { \ @@ -127,16 +89,16 @@ void adsp21062_device::add_systemreg_write_latency_effect(int sysreg, UINT32 data, UINT32 prev_data) { - if (m_systemreg_latency_cycles > 0) + if (m_core->systemreg_latency_cycles > 0) { - //fatalerror("SHARC: add_systemreg_write_latency_effect: already scheduled! (reg: %02X, data: %08X, PC: %08X)\n", systemreg_latency_reg, systemreg_latency_data, m_pc); + //fatalerror("SHARC: add_systemreg_write_latency_effect: already scheduled! (reg: %02X, data: %08X, PC: %08X)\n", systemreg_latency_reg, systemreg_latency_data, m_core->pc); systemreg_write_latency_effect(); } - m_systemreg_latency_cycles = 2; - m_systemreg_latency_reg = sysreg; - m_systemreg_latency_data = data; - m_systemreg_previous_data = prev_data; + m_core->systemreg_latency_cycles = 2; + m_core->systemreg_latency_reg = sysreg; + m_core->systemreg_latency_data = data; + m_core->systemreg_previous_data = prev_data; } void adsp21062_device::swap_register(UINT32 *a, UINT32 *b) @@ -149,15 +111,15 @@ void adsp21062_device::swap_register(UINT32 *a, UINT32 *b) void adsp21062_device::systemreg_write_latency_effect() { int i; - UINT32 data = m_systemreg_latency_data; - UINT32 old_data = m_systemreg_previous_data; + UINT32 data = m_core->systemreg_latency_data; + UINT32 old_data = m_core->systemreg_previous_data; - switch(m_systemreg_latency_reg) + switch(m_core->systemreg_latency_reg) { case 0xb: /* MODE1 */ { UINT32 oldreg = old_data; - m_mode1 = data; + m_core->mode1 = data; if ((data & 0x1) != (oldreg & 0x1)) { @@ -174,96 +136,96 @@ void adsp21062_device::systemreg_write_latency_effect() if ((data & 0x8) != (oldreg & 0x8)) /* Switch DAG1 7-4 */ { - swap_register(&m_dag1.i[4], &m_dag1_alt.i[4]); - swap_register(&m_dag1.i[5], &m_dag1_alt.i[5]); - swap_register(&m_dag1.i[6], &m_dag1_alt.i[6]); - swap_register(&m_dag1.i[7], &m_dag1_alt.i[7]); - swap_register(&m_dag1.m[4], &m_dag1_alt.m[4]); - swap_register(&m_dag1.m[5], &m_dag1_alt.m[5]); - swap_register(&m_dag1.m[6], &m_dag1_alt.m[6]); - swap_register(&m_dag1.m[7], &m_dag1_alt.m[7]); - swap_register(&m_dag1.l[4], &m_dag1_alt.l[4]); - swap_register(&m_dag1.l[5], &m_dag1_alt.l[5]); - swap_register(&m_dag1.l[6], &m_dag1_alt.l[6]); - swap_register(&m_dag1.l[7], &m_dag1_alt.l[7]); - swap_register(&m_dag1.b[4], &m_dag1_alt.b[4]); - swap_register(&m_dag1.b[5], &m_dag1_alt.b[5]); - swap_register(&m_dag1.b[6], &m_dag1_alt.b[6]); - swap_register(&m_dag1.b[7], &m_dag1_alt.b[7]); + swap_register(&m_core->dag1.i[4], &m_core->dag1_alt.i[4]); + swap_register(&m_core->dag1.i[5], &m_core->dag1_alt.i[5]); + swap_register(&m_core->dag1.i[6], &m_core->dag1_alt.i[6]); + swap_register(&m_core->dag1.i[7], &m_core->dag1_alt.i[7]); + swap_register(&m_core->dag1.m[4], &m_core->dag1_alt.m[4]); + swap_register(&m_core->dag1.m[5], &m_core->dag1_alt.m[5]); + swap_register(&m_core->dag1.m[6], &m_core->dag1_alt.m[6]); + swap_register(&m_core->dag1.m[7], &m_core->dag1_alt.m[7]); + swap_register(&m_core->dag1.l[4], &m_core->dag1_alt.l[4]); + swap_register(&m_core->dag1.l[5], &m_core->dag1_alt.l[5]); + swap_register(&m_core->dag1.l[6], &m_core->dag1_alt.l[6]); + swap_register(&m_core->dag1.l[7], &m_core->dag1_alt.l[7]); + swap_register(&m_core->dag1.b[4], &m_core->dag1_alt.b[4]); + swap_register(&m_core->dag1.b[5], &m_core->dag1_alt.b[5]); + swap_register(&m_core->dag1.b[6], &m_core->dag1_alt.b[6]); + swap_register(&m_core->dag1.b[7], &m_core->dag1_alt.b[7]); } if ((data & 0x10) != (oldreg & 0x10)) /* Switch DAG1 3-0 */ { - swap_register(&m_dag1.i[0], &m_dag1_alt.i[0]); - swap_register(&m_dag1.i[1], &m_dag1_alt.i[1]); - swap_register(&m_dag1.i[2], &m_dag1_alt.i[2]); - swap_register(&m_dag1.i[3], &m_dag1_alt.i[3]); - swap_register(&m_dag1.m[0], &m_dag1_alt.m[0]); - swap_register(&m_dag1.m[1], &m_dag1_alt.m[1]); - swap_register(&m_dag1.m[2], &m_dag1_alt.m[2]); - swap_register(&m_dag1.m[3], &m_dag1_alt.m[3]); - swap_register(&m_dag1.l[0], &m_dag1_alt.l[0]); - swap_register(&m_dag1.l[1], &m_dag1_alt.l[1]); - swap_register(&m_dag1.l[2], &m_dag1_alt.l[2]); - swap_register(&m_dag1.l[3], &m_dag1_alt.l[3]); - swap_register(&m_dag1.b[0], &m_dag1_alt.b[0]); - swap_register(&m_dag1.b[1], &m_dag1_alt.b[1]); - swap_register(&m_dag1.b[2], &m_dag1_alt.b[2]); - swap_register(&m_dag1.b[3], &m_dag1_alt.b[3]); + swap_register(&m_core->dag1.i[0], &m_core->dag1_alt.i[0]); + swap_register(&m_core->dag1.i[1], &m_core->dag1_alt.i[1]); + swap_register(&m_core->dag1.i[2], &m_core->dag1_alt.i[2]); + swap_register(&m_core->dag1.i[3], &m_core->dag1_alt.i[3]); + swap_register(&m_core->dag1.m[0], &m_core->dag1_alt.m[0]); + swap_register(&m_core->dag1.m[1], &m_core->dag1_alt.m[1]); + swap_register(&m_core->dag1.m[2], &m_core->dag1_alt.m[2]); + swap_register(&m_core->dag1.m[3], &m_core->dag1_alt.m[3]); + swap_register(&m_core->dag1.l[0], &m_core->dag1_alt.l[0]); + swap_register(&m_core->dag1.l[1], &m_core->dag1_alt.l[1]); + swap_register(&m_core->dag1.l[2], &m_core->dag1_alt.l[2]); + swap_register(&m_core->dag1.l[3], &m_core->dag1_alt.l[3]); + swap_register(&m_core->dag1.b[0], &m_core->dag1_alt.b[0]); + swap_register(&m_core->dag1.b[1], &m_core->dag1_alt.b[1]); + swap_register(&m_core->dag1.b[2], &m_core->dag1_alt.b[2]); + swap_register(&m_core->dag1.b[3], &m_core->dag1_alt.b[3]); } if ((data & 0x20) != (oldreg & 0x20)) /* Switch DAG2 15-12 */ { - swap_register(&m_dag2.i[4], &m_dag2_alt.i[4]); - swap_register(&m_dag2.i[5], &m_dag2_alt.i[5]); - swap_register(&m_dag2.i[6], &m_dag2_alt.i[6]); - swap_register(&m_dag2.i[7], &m_dag2_alt.i[7]); - swap_register(&m_dag2.m[4], &m_dag2_alt.m[4]); - swap_register(&m_dag2.m[5], &m_dag2_alt.m[5]); - swap_register(&m_dag2.m[6], &m_dag2_alt.m[6]); - swap_register(&m_dag2.m[7], &m_dag2_alt.m[7]); - swap_register(&m_dag2.l[4], &m_dag2_alt.l[4]); - swap_register(&m_dag2.l[5], &m_dag2_alt.l[5]); - swap_register(&m_dag2.l[6], &m_dag2_alt.l[6]); - swap_register(&m_dag2.l[7], &m_dag2_alt.l[7]); - swap_register(&m_dag2.b[4], &m_dag2_alt.b[4]); - swap_register(&m_dag2.b[5], &m_dag2_alt.b[5]); - swap_register(&m_dag2.b[6], &m_dag2_alt.b[6]); - swap_register(&m_dag2.b[7], &m_dag2_alt.b[7]); + swap_register(&m_core->dag2.i[4], &m_core->dag2_alt.i[4]); + swap_register(&m_core->dag2.i[5], &m_core->dag2_alt.i[5]); + swap_register(&m_core->dag2.i[6], &m_core->dag2_alt.i[6]); + swap_register(&m_core->dag2.i[7], &m_core->dag2_alt.i[7]); + swap_register(&m_core->dag2.m[4], &m_core->dag2_alt.m[4]); + swap_register(&m_core->dag2.m[5], &m_core->dag2_alt.m[5]); + swap_register(&m_core->dag2.m[6], &m_core->dag2_alt.m[6]); + swap_register(&m_core->dag2.m[7], &m_core->dag2_alt.m[7]); + swap_register(&m_core->dag2.l[4], &m_core->dag2_alt.l[4]); + swap_register(&m_core->dag2.l[5], &m_core->dag2_alt.l[5]); + swap_register(&m_core->dag2.l[6], &m_core->dag2_alt.l[6]); + swap_register(&m_core->dag2.l[7], &m_core->dag2_alt.l[7]); + swap_register(&m_core->dag2.b[4], &m_core->dag2_alt.b[4]); + swap_register(&m_core->dag2.b[5], &m_core->dag2_alt.b[5]); + swap_register(&m_core->dag2.b[6], &m_core->dag2_alt.b[6]); + swap_register(&m_core->dag2.b[7], &m_core->dag2_alt.b[7]); } if ((data & 0x40) != (oldreg & 0x40)) /* Switch DAG2 11-8 */ { - swap_register(&m_dag2.i[0], &m_dag2_alt.i[0]); - swap_register(&m_dag2.i[1], &m_dag2_alt.i[1]); - swap_register(&m_dag2.i[2], &m_dag2_alt.i[2]); - swap_register(&m_dag2.i[3], &m_dag2_alt.i[3]); - swap_register(&m_dag2.m[0], &m_dag2_alt.m[0]); - swap_register(&m_dag2.m[1], &m_dag2_alt.m[1]); - swap_register(&m_dag2.m[2], &m_dag2_alt.m[2]); - swap_register(&m_dag2.m[3], &m_dag2_alt.m[3]); - swap_register(&m_dag2.l[0], &m_dag2_alt.l[0]); - swap_register(&m_dag2.l[1], &m_dag2_alt.l[1]); - swap_register(&m_dag2.l[2], &m_dag2_alt.l[2]); - swap_register(&m_dag2.l[3], &m_dag2_alt.l[3]); - swap_register(&m_dag2.b[0], &m_dag2_alt.b[0]); - swap_register(&m_dag2.b[1], &m_dag2_alt.b[1]); - swap_register(&m_dag2.b[2], &m_dag2_alt.b[2]); - swap_register(&m_dag2.b[3], &m_dag2_alt.b[3]); + swap_register(&m_core->dag2.i[0], &m_core->dag2_alt.i[0]); + swap_register(&m_core->dag2.i[1], &m_core->dag2_alt.i[1]); + swap_register(&m_core->dag2.i[2], &m_core->dag2_alt.i[2]); + swap_register(&m_core->dag2.i[3], &m_core->dag2_alt.i[3]); + swap_register(&m_core->dag2.m[0], &m_core->dag2_alt.m[0]); + swap_register(&m_core->dag2.m[1], &m_core->dag2_alt.m[1]); + swap_register(&m_core->dag2.m[2], &m_core->dag2_alt.m[2]); + swap_register(&m_core->dag2.m[3], &m_core->dag2_alt.m[3]); + swap_register(&m_core->dag2.l[0], &m_core->dag2_alt.l[0]); + swap_register(&m_core->dag2.l[1], &m_core->dag2_alt.l[1]); + swap_register(&m_core->dag2.l[2], &m_core->dag2_alt.l[2]); + swap_register(&m_core->dag2.l[3], &m_core->dag2_alt.l[3]); + swap_register(&m_core->dag2.b[0], &m_core->dag2_alt.b[0]); + swap_register(&m_core->dag2.b[1], &m_core->dag2_alt.b[1]); + swap_register(&m_core->dag2.b[2], &m_core->dag2_alt.b[2]); + swap_register(&m_core->dag2.b[3], &m_core->dag2_alt.b[3]); } if ((data & 0x80) != (oldreg & 0x80)) { for (i=8; i<16; i++) - swap_register((UINT32*)&m_r[i].r, (UINT32*)&m_reg_alt[i].r); + swap_register((UINT32*)&m_core->r[i].r, (UINT32*)&m_core->reg_alt[i].r); } if ((data & 0x400) != (oldreg & 0x400)) { for (i=0; i<8; i++) - swap_register((UINT32*)&m_r[i].r, (UINT32*)&m_reg_alt[i].r); + swap_register((UINT32*)&m_core->r[i].r, (UINT32*)&m_core->reg_alt[i].r); } break; } - default: fatalerror("SHARC: systemreg_latency_op: unknown register %02X at %08X\n", m_systemreg_latency_reg, m_pc); + default: fatalerror("SHARC: systemreg_latency_op: unknown register %02X at %08X\n", m_core->systemreg_latency_reg, m_core->pc); } - m_systemreg_latency_reg = -1; + m_core->systemreg_latency_reg = -1; } UINT32 adsp21062_device::GET_UREG(int ureg) @@ -273,18 +235,18 @@ UINT32 adsp21062_device::GET_UREG(int ureg) { case 0x0: /* R0 - R15 */ { - return m_r[reg].r; + return m_core->r[reg].r; } case 0x1: { if (reg & 0x8) /* I8 - I15 */ { - return m_dag2.i[reg & 0x7]; + return m_core->dag2.i[reg & 0x7]; } else /* I0 - I7 */ { - return m_dag1.i[reg & 0x7]; + return m_core->dag1.i[reg & 0x7]; } } @@ -292,14 +254,14 @@ UINT32 adsp21062_device::GET_UREG(int ureg) { if (reg & 0x8) /* M8 - M15 */ { - INT32 r = m_dag2.m[reg & 0x7]; + INT32 r = m_core->dag2.m[reg & 0x7]; if (r & 0x800000) r |= 0xff000000; return r; } else /* M0 - M7 */ { - return m_dag1.m[reg & 0x7]; + return m_core->dag1.m[reg & 0x7]; } } @@ -307,11 +269,11 @@ UINT32 adsp21062_device::GET_UREG(int ureg) { if (reg & 0x8) /* L8 - L15 */ { - return m_dag2.l[reg & 0x7]; + return m_core->dag2.l[reg & 0x7]; } else /* L0 - L7 */ { - return m_dag1.l[reg & 0x7]; + return m_core->dag1.l[reg & 0x7]; } } @@ -319,11 +281,11 @@ UINT32 adsp21062_device::GET_UREG(int ureg) { if (reg & 0x8) /* B8 - B15 */ { - return m_dag2.b[reg & 0x7]; + return m_core->dag2.b[reg & 0x7]; } else /* B0 - B7 */ { - return m_dag1.b[reg & 0x7]; + return m_core->dag1.b[reg & 0x7]; } } @@ -331,8 +293,8 @@ UINT32 adsp21062_device::GET_UREG(int ureg) { switch(reg) { - case 0x4: return m_pcstack[m_pcstkp]; /* PCSTK */ - default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + case 0x4: return m_core->pcstack[m_core->pcstkp]; /* PCSTK */ + default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } break; } @@ -341,24 +303,24 @@ UINT32 adsp21062_device::GET_UREG(int ureg) { switch(reg) { - case 0x0: return m_ustat1; /* USTAT1 */ - case 0x1: return m_ustat2; /* USTAT2 */ - case 0x9: return m_irptl; /* IRPTL */ - case 0xa: return m_mode2; /* MODE2 */ - case 0xb: return m_mode1; /* MODE1 */ + case 0x0: return m_core->ustat1; /* USTAT1 */ + case 0x1: return m_core->ustat2; /* USTAT2 */ + case 0x9: return m_core->irptl; /* IRPTL */ + case 0xa: return m_core->mode2; /* MODE2 */ + case 0xb: return m_core->mode1; /* MODE1 */ case 0xc: /* ASTAT */ { - UINT32 r = m_astat; + UINT32 r = m_core->astat; r &= ~0x00780000; - r |= (m_flag[0] << 19); - r |= (m_flag[1] << 20); - r |= (m_flag[2] << 21); - r |= (m_flag[3] << 22); + r |= (m_core->flag[0] << 19); + r |= (m_core->flag[1] << 20); + r |= (m_core->flag[2] << 21); + r |= (m_core->flag[3] << 22); return r; } - case 0xd: return m_imask; /* IMASK */ - case 0xe: return m_stky; /* STKY */ - default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + case 0xd: return m_core->imask; /* IMASK */ + case 0xe: return m_core->stky; /* STKY */ + default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } break; } @@ -368,15 +330,15 @@ UINT32 adsp21062_device::GET_UREG(int ureg) switch(reg) { /* PX needs to be handled separately if the whole 48 bits are needed */ - case 0xb: return (UINT32)(m_px); /* PX */ - case 0xc: return (UINT16)(m_px); /* PX1 */ - case 0xd: return (UINT32)(m_px >> 16); /* PX2 */ - default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + case 0xb: return (UINT32)(m_core->px); /* PX */ + case 0xc: return (UINT16)(m_core->px); /* PX1 */ + case 0xd: return (UINT32)(m_core->px >> 16); /* PX2 */ + default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } break; } - default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + default: fatalerror("SHARC: GET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } } @@ -386,39 +348,39 @@ void adsp21062_device::SET_UREG(int ureg, UINT32 data) switch((ureg >> 4) & 0xf) { case 0x0: /* R0 - R15 */ - m_r[reg].r = data; + m_core->r[reg].r = data; break; case 0x1: if (reg & 0x8) /* I8 - I15 */ { - m_dag2.i[reg & 0x7] = data; + m_core->dag2.i[reg & 0x7] = data; } else /* I0 - I7 */ { - m_dag1.i[reg & 0x7] = data; + m_core->dag1.i[reg & 0x7] = data; } break; case 0x2: if (reg & 0x8) /* M8 - M15 */ { - m_dag2.m[reg & 0x7] = data; + m_core->dag2.m[reg & 0x7] = data; } else /* M0 - M7 */ { - m_dag1.m[reg & 0x7] = data; + m_core->dag1.m[reg & 0x7] = data; } break; case 0x3: if (reg & 0x8) /* L8 - L15 */ { - m_dag2.l[reg & 0x7] = data; + m_core->dag2.l[reg & 0x7] = data; } else /* L0 - L7 */ { - m_dag1.l[reg & 0x7] = data; + m_core->dag1.l[reg & 0x7] = data; } break; @@ -426,73 +388,73 @@ void adsp21062_device::SET_UREG(int ureg, UINT32 data) // Note: loading B also loads the same value in I if (reg & 0x8) /* B8 - B15 */ { - m_dag2.b[reg & 0x7] = data; - m_dag2.i[reg & 0x7] = data; + m_core->dag2.b[reg & 0x7] = data; + m_core->dag2.i[reg & 0x7] = data; } else /* B0 - B7 */ { - m_dag1.b[reg & 0x7] = data; - m_dag1.i[reg & 0x7] = data; + m_core->dag1.b[reg & 0x7] = data; + m_core->dag1.i[reg & 0x7] = data; } break; case 0x6: switch (reg) { - case 0x5: m_pcstkp = data; break; /* PCSTKP */ - case 0x8: m_lcntr = data; break; /* LCNTR */ - default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + case 0x5: m_core->pcstkp = data; break; /* PCSTKP */ + case 0x8: m_core->lcntr = data; break; /* LCNTR */ + default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } break; case 0x7: /* system regs */ switch(reg) { - case 0x0: m_ustat1 = data; break; /* USTAT1 */ - case 0x1: m_ustat2 = data; break; /* USTAT2 */ + case 0x0: m_core->ustat1 = data; break; /* USTAT1 */ + case 0x1: m_core->ustat2 = data; break; /* USTAT2 */ - case 0x9: m_irptl = data; break; /* IRPTL */ - case 0xa: m_mode2 = data; break; /* MODE2 */ + case 0x9: m_core->irptl = data; break; /* IRPTL */ + case 0xa: m_core->mode2 = data; break; /* MODE2 */ case 0xb: /* MODE1 */ { - add_systemreg_write_latency_effect(reg, data, m_mode1); - m_mode1 = data; + add_systemreg_write_latency_effect(reg, data, m_core->mode1); + m_core->mode1 = data; break; } - case 0xc: m_astat = data; break; /* ASTAT */ + case 0xc: m_core->astat = data; break; /* ASTAT */ case 0xd: /* IMASK */ { check_interrupts(); - m_imask = data; + m_core->imask = data; break; } - case 0xe: m_stky = data; break; /* STKY */ - default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + case 0xe: m_core->stky = data; break; /* STKY */ + default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } break; case 0xd: switch(reg) { - case 0xc: m_px &= U64(0xffffffffffff0000); m_px |= (data & 0xffff); break; /* PX1 */ - case 0xd: m_px &= U64(0x000000000000ffff); m_px |= (UINT64)data << 16; break; /* PX2 */ - default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + case 0xc: m_core->px &= U64(0xffffffffffff0000); m_core->px |= (data & 0xffff); break; /* PX1 */ + case 0xd: m_core->px &= U64(0x000000000000ffff); m_core->px |= (UINT64)data << 16; break; /* PX2 */ + default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } break; - default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_pc); + default: fatalerror("SHARC: SET_UREG: unknown register %08X at %08X\n", ureg, m_core->pc); } } /*****************************************************************************/ -#define SET_FLAG_SV_LSHIFT(x, shift) if((x) & ((UINT32)0xffffffff << shift)) m_astat |= SV -#define SET_FLAG_SV_RSHIFT(x, shift) if((x) & ((UINT32)0xffffffff >> shift)) m_astat |= SV +#define SET_FLAG_SV_LSHIFT(x, shift) if((x) & ((UINT32)0xffffffff << shift)) m_core->astat |= SV +#define SET_FLAG_SV_RSHIFT(x, shift) if((x) & ((UINT32)0xffffffff >> shift)) m_core->astat |= SV -#define SET_FLAG_SZ(x) if((x) == 0) m_astat |= SZ +#define SET_FLAG_SZ(x) if((x) == 0) m_core->astat |= SZ #define MAKE_EXTRACT_MASK(start_bit, length) ((0xffffffff << start_bit) & (((UINT32)0xffffffff) >> (32 - (start_bit + length)))) @@ -502,7 +464,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx int bit = data & 0x3f; int len = (data >> 6) & 0x3f; - m_astat &= ~(SZ|SV|SS); + m_core->astat &= ~(SZ|SV|SS); switch(shiftop) { @@ -514,7 +476,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx REG(rn) = (shift < 32) ? (REG(rx) << shift) : 0; if (shift > 0) { - m_astat |= SV; + m_core->astat |= SV; } } SET_FLAG_SZ(REG(rn)); @@ -532,7 +494,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx REG(rn) = (shift < 32) ? ((INT32)REG(rx) << shift) : 0; if (shift > 0) { - m_astat |= SV; + m_core->astat |= SV; } } SET_FLAG_SZ(REG(rn)); @@ -566,7 +528,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx r = (shift < 32) ? (REG(rx) << shift) : 0; if (shift > 0) { - m_astat |= SV; + m_core->astat |= SV; } } SET_FLAG_SZ(r); @@ -583,7 +545,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx SET_FLAG_SZ(REG(rn)); if (bit+len > 32) { - m_astat |= SV; + m_core->astat |= SV; } break; } @@ -602,7 +564,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx SET_FLAG_SZ(REG(rn)); if (bit+len > 32) { - m_astat |= SV; + m_core->astat |= SV; } break; } @@ -618,7 +580,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx SET_FLAG_SZ(REG(rn)); if (bit+len > 32) { - m_astat |= SV; + m_core->astat |= SV; } break; } @@ -632,7 +594,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx SET_FLAG_SZ(REG(rn)); if (bit+len > 32) { - m_astat |= SV; + m_core->astat |= SV; } break; } @@ -646,7 +608,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx } else { - m_astat |= SV; + m_core->astat |= SV; } SET_FLAG_SZ(REG(rn)); break; @@ -661,7 +623,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx } else { - m_astat |= SV; + m_core->astat |= SV; } SET_FLAG_SZ(REG(rn)); break; @@ -676,7 +638,7 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx } else { - m_astat |= SV; + m_core->astat |= SV; } SET_FLAG_SZ(REG(rn)); break; @@ -692,12 +654,12 @@ void adsp21062_device::SHIFT_OPERATION_IMM(int shiftop, int data, int rn, int rx } else { - m_astat |= SZ | SV; + m_core->astat |= SZ | SV; } break; } - default: fatalerror("SHARC: unimplemented shift operation %02X at %08X\n", shiftop, m_pc); + default: fatalerror("SHARC: unimplemented shift operation %02X at %08X\n", shiftop, m_core->pc); } } @@ -795,7 +757,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) } default: - fatalerror("SHARC: compute: multi-function opcode %02X not implemented ! (%08X, %08X)\n", multiop, m_pc, opcode); + fatalerror("SHARC: compute: multi-function opcode %02X not implemented ! (%08X, %08X)\n", multiop, m_core->pc, opcode); break; } } @@ -863,7 +825,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) break; } - default: fatalerror("SHARC: compute: unimplemented ALU operation %02X (%08X, %08X)\n", op, m_pc, opcode); + default: fatalerror("SHARC: compute: unimplemented ALU operation %02X (%08X, %08X)\n", op, m_core->pc, opcode); } break; } @@ -874,8 +836,8 @@ void adsp21062_device::COMPUTE(UINT32 opcode) { switch(op) { - case 0x14: m_mrf = 0; break; - case 0x16: m_mrb = 0; break; + case 0x14: m_core->mrf = 0; break; + case 0x16: m_core->mrb = 0; break; case 0x30: compute_fmul(rn, rx, ry); break; case 0x40: compute_mul_uuin(rn, rx, ry); break; @@ -885,7 +847,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) case 0xb2: REG(rn) = compute_mrb_plus_mul_ssin(rx, ry); break; default: - fatalerror("SHARC: compute: multiplier operation %02X not implemented ! (%08X, %08X)\n", op, m_pc, opcode); + fatalerror("SHARC: compute: multiplier operation %02X not implemented ! (%08X, %08X)\n", op, m_core->pc, opcode); break; } break; @@ -895,7 +857,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) /* Shifter operations */ case 2: { - m_astat &= ~(SZ|SV|SS); + m_core->astat &= ~(SZ|SV|SS); op >>= 2; switch(op) @@ -912,7 +874,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) REG(rn) = (shift < 32) ? (REG(rx) << shift) : 0; if (shift > 0) { - m_astat |= SV; + m_core->astat |= SV; } } SET_FLAG_SZ(REG(rn)); @@ -935,7 +897,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) (((UINT32)REG(rx) >> (32-s)) & ((UINT32)(0xffffffff) >> (32-s))); if (shift > 0) { - m_astat |= SV; + m_core->astat |= SV; } } SET_FLAG_SZ(REG(rn)); @@ -951,7 +913,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) REG(rn) = REG(rn) | ((shift < 32) ? (REG(rx) << shift) : 0); if (shift > 0) { - m_astat |= SV; + m_core->astat |= SV; } } SET_FLAG_SZ(REG(rn)); @@ -968,7 +930,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) SET_FLAG_SZ(REG(rn)); if (bit+len > 32) { - m_astat |= SV; + m_core->astat |= SV; } break; } @@ -986,7 +948,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) SET_FLAG_SZ(REG(rn)); if (bit+len > 32) { - m_astat |= SV; + m_core->astat |= SV; } break; } @@ -1002,7 +964,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) SET_FLAG_SZ(REG(rn)); if (bit+len > 32) { - m_astat |= SV; + m_core->astat |= SV; } break; } @@ -1017,7 +979,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) } else { - m_astat |= SV; + m_core->astat |= SV; } SET_FLAG_SZ(REG(rn)); break; @@ -1033,7 +995,7 @@ void adsp21062_device::COMPUTE(UINT32 opcode) } else { - m_astat |= SV; + m_core->astat |= SV; } SET_FLAG_SZ(REG(rn)); break; @@ -1050,13 +1012,13 @@ void adsp21062_device::COMPUTE(UINT32 opcode) } else { - m_astat |= SZ | SV; + m_core->astat |= SZ | SV; } break; } default: - fatalerror("SHARC: compute: shift operation %02X not implemented ! (%08X, %08X)\n", op, m_pc, opcode); + fatalerror("SHARC: compute: shift operation %02X not implemented ! (%08X, %08X)\n", op, m_core->pc, opcode); } break; } @@ -1069,143 +1031,143 @@ void adsp21062_device::COMPUTE(UINT32 opcode) void adsp21062_device::PUSH_PC(UINT32 pc) { - m_pcstkp++; - if(m_pcstkp >= 32) + m_core->pcstkp++; + if(m_core->pcstkp >= 32) { fatalerror("SHARC: PC Stack overflow!\n"); } - if (m_pcstkp == 0) + if (m_core->pcstkp == 0) { - m_stky |= 0x400000; + m_core->stky |= 0x400000; } else { - m_stky &= ~0x400000; + m_core->stky &= ~0x400000; } - m_pcstk = pc; - m_pcstack[m_pcstkp] = pc; + m_core->pcstk = pc; + m_core->pcstack[m_core->pcstkp] = pc; } UINT32 adsp21062_device::POP_PC() { - m_pcstk = m_pcstack[m_pcstkp]; + m_core->pcstk = m_core->pcstack[m_core->pcstkp]; - if(m_pcstkp == 0) + if(m_core->pcstkp == 0) { fatalerror("SHARC: PC Stack underflow!\n"); } - m_pcstkp--; + m_core->pcstkp--; - if (m_pcstkp == 0) + if (m_core->pcstkp == 0) { - m_stky |= 0x400000; + m_core->stky |= 0x400000; } else { - m_stky &= ~0x400000; + m_core->stky &= ~0x400000; } - return m_pcstk; + return m_core->pcstk; } UINT32 adsp21062_device::TOP_PC() { - return m_pcstack[m_pcstkp]; + return m_core->pcstack[m_core->pcstkp]; } void adsp21062_device::PUSH_LOOP(UINT32 addr, UINT32 code, UINT32 type, UINT32 count) { - m_lstkp++; - if(m_lstkp >= 6) + m_core->lstkp++; + if(m_core->lstkp >= 6) { fatalerror("SHARC: Loop Stack overflow!\n"); } - if (m_lstkp == 0) + if (m_core->lstkp == 0) { - m_stky |= 0x4000000; + m_core->stky |= 0x4000000; } else { - m_stky &= ~0x4000000; + m_core->stky &= ~0x4000000; } - m_lcstack[m_lstkp] = count; - m_lastack[m_lstkp] = (type << 30) | (code << 24) | addr; - m_curlcntr = count; + m_core->lcstack[m_core->lstkp] = count; + m_core->lastack[m_core->lstkp] = (type << 30) | (code << 24) | addr; + m_core->curlcntr = count; - m_laddr.addr = addr; - m_laddr.code = code; - m_laddr.loop_type = type; + m_core->laddr.addr = addr; + m_core->laddr.code = code; + m_core->laddr.loop_type = type; } void adsp21062_device::POP_LOOP() { - if(m_lstkp == 0) + if(m_core->lstkp == 0) { fatalerror("SHARC: Loop Stack underflow!\n"); } - m_lstkp--; + m_core->lstkp--; - if (m_lstkp == 0) + if (m_core->lstkp == 0) { - m_stky |= 0x4000000; + m_core->stky |= 0x4000000; } else { - m_stky &= ~0x4000000; + m_core->stky &= ~0x4000000; } - m_curlcntr = m_lcstack[m_lstkp]; + m_core->curlcntr = m_core->lcstack[m_core->lstkp]; - m_laddr.addr = m_lastack[m_lstkp] & 0xffffff; - m_laddr.code = (m_lastack[m_lstkp] >> 24) & 0x1f; - m_laddr.loop_type = (m_lastack[m_lstkp] >> 30) & 0x3; + m_core->laddr.addr = m_core->lastack[m_core->lstkp] & 0xffffff; + m_core->laddr.code = (m_core->lastack[m_core->lstkp] >> 24) & 0x1f; + m_core->laddr.loop_type = (m_core->lastack[m_core->lstkp] >> 30) & 0x3; } void adsp21062_device::PUSH_STATUS_STACK() { - m_status_stkp++; - if (m_status_stkp >= 5) + m_core->status_stkp++; + if (m_core->status_stkp >= 5) { fatalerror("SHARC: Status stack overflow!\n"); } - if (m_status_stkp == 0) + if (m_core->status_stkp == 0) { - m_stky |= 0x1000000; + m_core->stky |= 0x1000000; } else { - m_stky &= ~0x1000000; + m_core->stky &= ~0x1000000; } - m_status_stack[m_status_stkp].mode1 = GET_UREG(REG_MODE1); - m_status_stack[m_status_stkp].astat = GET_UREG(REG_ASTAT); + m_core->status_stack[m_core->status_stkp].mode1 = GET_UREG(REG_MODE1); + m_core->status_stack[m_core->status_stkp].astat = GET_UREG(REG_ASTAT); } void adsp21062_device::POP_STATUS_STACK() { - SET_UREG(REG_MODE1, m_status_stack[m_status_stkp].mode1); - SET_UREG(REG_ASTAT, m_status_stack[m_status_stkp].astat); + SET_UREG(REG_MODE1, m_core->status_stack[m_core->status_stkp].mode1); + SET_UREG(REG_ASTAT, m_core->status_stack[m_core->status_stkp].astat); - m_status_stkp--; - if (m_status_stkp < 0) + m_core->status_stkp--; + if (m_core->status_stkp < 0) { fatalerror("SHARC: Status stack underflow!\n"); } - if (m_status_stkp == 0) + if (m_core->status_stkp == 0) { - m_stky |= 0x1000000; + m_core->stky |= 0x1000000; } else { - m_stky &= ~0x1000000; + m_core->stky &= ~0x1000000; } } @@ -1213,36 +1175,36 @@ int adsp21062_device::IF_CONDITION_CODE(int cond) { switch(cond) { - case 0x00: return m_astat & AZ; /* EQ */ - case 0x01: return !(m_astat & AZ) && (m_astat & AN); /* LT */ - case 0x02: return (m_astat & AZ) || (m_astat & AN); /* LE */ - case 0x03: return (m_astat & AC); /* AC */ - case 0x04: return (m_astat & AV); /* AV */ - case 0x05: return (m_astat & MV); /* MV */ - case 0x06: return (m_astat & MN); /* MS */ - case 0x07: return (m_astat & SV); /* SV */ - case 0x08: return (m_astat & SZ); /* SZ */ - case 0x09: return (m_flag[0] != 0); /* FLAG0 */ - case 0x0a: return (m_flag[1] != 0); /* FLAG1 */ - case 0x0b: return (m_flag[2] != 0); /* FLAG2 */ - case 0x0c: return (m_flag[3] != 0); /* FLAG3 */ - case 0x0d: return (m_astat & BTF); /* TF */ + case 0x00: return m_core->astat & AZ; /* EQ */ + case 0x01: return !(m_core->astat & AZ) && (m_core->astat & AN); /* LT */ + case 0x02: return (m_core->astat & AZ) || (m_core->astat & AN); /* LE */ + case 0x03: return (m_core->astat & AC); /* AC */ + case 0x04: return (m_core->astat & AV); /* AV */ + case 0x05: return (m_core->astat & MV); /* MV */ + case 0x06: return (m_core->astat & MN); /* MS */ + case 0x07: return (m_core->astat & SV); /* SV */ + case 0x08: return (m_core->astat & SZ); /* SZ */ + case 0x09: return (m_core->flag[0] != 0); /* FLAG0 */ + case 0x0a: return (m_core->flag[1] != 0); /* FLAG1 */ + case 0x0b: return (m_core->flag[2] != 0); /* FLAG2 */ + case 0x0c: return (m_core->flag[3] != 0); /* FLAG3 */ + case 0x0d: return (m_core->astat & BTF); /* TF */ case 0x0e: return 0; /* BM */ - case 0x0f: return (m_curlcntr!=1); /* NOT LCE */ - case 0x10: return !(m_astat & AZ); /* NOT EQUAL */ - case 0x11: return (m_astat & AZ) || !(m_astat & AN); /* GE */ - case 0x12: return !(m_astat & AZ) && !(m_astat & AN); /* GT */ - case 0x13: return !(m_astat & AC); /* NOT AC */ - case 0x14: return !(m_astat & AV); /* NOT AV */ - case 0x15: return !(m_astat & MV); /* NOT MV */ - case 0x16: return !(m_astat & MN); /* NOT MS */ - case 0x17: return !(m_astat & SV); /* NOT SV */ - case 0x18: return !(m_astat & SZ); /* NOT SZ */ - case 0x19: return (m_flag[0] == 0); /* NOT FLAG0 */ - case 0x1a: return (m_flag[1] == 0); /* NOT FLAG1 */ - case 0x1b: return (m_flag[2] == 0); /* NOT FLAG2 */ - case 0x1c: return (m_flag[3] == 0); /* NOT FLAG3 */ - case 0x1d: return !(m_astat & BTF); /* NOT TF */ + case 0x0f: return (m_core->curlcntr!=1); /* NOT LCE */ + case 0x10: return !(m_core->astat & AZ); /* NOT EQUAL */ + case 0x11: return (m_core->astat & AZ) || !(m_core->astat & AN); /* GE */ + case 0x12: return !(m_core->astat & AZ) && !(m_core->astat & AN); /* GT */ + case 0x13: return !(m_core->astat & AC); /* NOT AC */ + case 0x14: return !(m_core->astat & AV); /* NOT AV */ + case 0x15: return !(m_core->astat & MV); /* NOT MV */ + case 0x16: return !(m_core->astat & MN); /* NOT MS */ + case 0x17: return !(m_core->astat & SV); /* NOT SV */ + case 0x18: return !(m_core->astat & SZ); /* NOT SZ */ + case 0x19: return (m_core->flag[0] == 0); /* NOT FLAG0 */ + case 0x1a: return (m_core->flag[1] == 0); /* NOT FLAG1 */ + case 0x1b: return (m_core->flag[2] == 0); /* NOT FLAG2 */ + case 0x1c: return (m_core->flag[3] == 0); /* NOT FLAG3 */ + case 0x1d: return !(m_core->astat & BTF); /* NOT TF */ case 0x1e: return 1; /* NOT BM */ case 0x1f: return 1; /* TRUE */ } @@ -1253,36 +1215,36 @@ int adsp21062_device::DO_CONDITION_CODE(int cond) { switch(cond) { - case 0x00: return m_astat & AZ; /* EQ */ - case 0x01: return !(m_astat & AZ) && (m_astat & AN); /* LT */ - case 0x02: return (m_astat & AZ) || (m_astat & AN); /* LE */ - case 0x03: return (m_astat & AC); /* AC */ - case 0x04: return (m_astat & AV); /* AV */ - case 0x05: return (m_astat & MV); /* MV */ - case 0x06: return (m_astat & MN); /* MS */ - case 0x07: return (m_astat & SV); /* SV */ - case 0x08: return (m_astat & SZ); /* SZ */ - case 0x09: return (m_flag[0] != 0); /* FLAG0 */ - case 0x0a: return (m_flag[1] != 0); /* FLAG1 */ - case 0x0b: return (m_flag[2] != 0); /* FLAG2 */ - case 0x0c: return (m_flag[3] != 0); /* FLAG3 */ - case 0x0d: return (m_astat & BTF); /* TF */ + case 0x00: return m_core->astat & AZ; /* EQ */ + case 0x01: return !(m_core->astat & AZ) && (m_core->astat & AN); /* LT */ + case 0x02: return (m_core->astat & AZ) || (m_core->astat & AN); /* LE */ + case 0x03: return (m_core->astat & AC); /* AC */ + case 0x04: return (m_core->astat & AV); /* AV */ + case 0x05: return (m_core->astat & MV); /* MV */ + case 0x06: return (m_core->astat & MN); /* MS */ + case 0x07: return (m_core->astat & SV); /* SV */ + case 0x08: return (m_core->astat & SZ); /* SZ */ + case 0x09: return (m_core->flag[0] != 0); /* FLAG0 */ + case 0x0a: return (m_core->flag[1] != 0); /* FLAG1 */ + case 0x0b: return (m_core->flag[2] != 0); /* FLAG2 */ + case 0x0c: return (m_core->flag[3] != 0); /* FLAG3 */ + case 0x0d: return (m_core->astat & BTF); /* TF */ case 0x0e: return 0; /* BM */ - case 0x0f: return (m_curlcntr==1); /* LCE */ - case 0x10: return !(m_astat & AZ); /* NOT EQUAL */ - case 0x11: return (m_astat & AZ) || !(m_astat & AN); /* GE */ - case 0x12: return !(m_astat & AZ) && !(m_astat & AN); /* GT */ - case 0x13: return !(m_astat & AC); /* NOT AC */ - case 0x14: return !(m_astat & AV); /* NOT AV */ - case 0x15: return !(m_astat & MV); /* NOT MV */ - case 0x16: return !(m_astat & MN); /* NOT MS */ - case 0x17: return !(m_astat & SV); /* NOT SV */ - case 0x18: return !(m_astat & SZ); /* NOT SZ */ - case 0x19: return (m_flag[0] == 0); /* NOT FLAG0 */ - case 0x1a: return (m_flag[1] == 0); /* NOT FLAG1 */ - case 0x1b: return (m_flag[2] == 0); /* NOT FLAG2 */ - case 0x1c: return (m_flag[3] == 0); /* NOT FLAG3 */ - case 0x1d: return !(m_astat & BTF); /* NOT TF */ + case 0x0f: return (m_core->curlcntr==1); /* LCE */ + case 0x10: return !(m_core->astat & AZ); /* NOT EQUAL */ + case 0x11: return (m_core->astat & AZ) || !(m_core->astat & AN); /* GE */ + case 0x12: return !(m_core->astat & AZ) && !(m_core->astat & AN); /* GT */ + case 0x13: return !(m_core->astat & AC); /* NOT AC */ + case 0x14: return !(m_core->astat & AV); /* NOT AV */ + case 0x15: return !(m_core->astat & MV); /* NOT MV */ + case 0x16: return !(m_core->astat & MN); /* NOT MS */ + case 0x17: return !(m_core->astat & SV); /* NOT SV */ + case 0x18: return !(m_core->astat & SZ); /* NOT SZ */ + case 0x19: return (m_core->flag[0] == 0); /* NOT FLAG0 */ + case 0x1a: return (m_core->flag[1] == 0); /* NOT FLAG1 */ + case 0x1b: return (m_core->flag[2] == 0); /* NOT FLAG2 */ + case 0x1c: return (m_core->flag[3] == 0); /* NOT FLAG3 */ + case 0x1d: return !(m_core->astat & BTF); /* NOT TF */ case 0x1e: return 1; /* NOT BM */ case 0x1f: return 0; /* FALSE (FOREVER) */ } @@ -1295,15 +1257,15 @@ int adsp21062_device::DO_CONDITION_CODE(int cond) /* compute / dreg <-> DM / dreg <-> PM */ void adsp21062_device::sharcop_compute_dreg_dm_dreg_pm() { - int pm_dreg = (m_opcode >> 23) & 0xf; - int pmm = (m_opcode >> 27) & 0x7; - int pmi = (m_opcode >> 30) & 0x7; - int dm_dreg = (m_opcode >> 33) & 0xf; - int dmm = (m_opcode >> 38) & 0x7; - int dmi = (m_opcode >> 41) & 0x7; - int pmd = (m_opcode >> 37) & 0x1; - int dmd = (m_opcode >> 44) & 0x1; - int compute = m_opcode & 0x7fffff; + int pm_dreg = (m_core->opcode >> 23) & 0xf; + int pmm = (m_core->opcode >> 27) & 0x7; + int pmi = (m_core->opcode >> 30) & 0x7; + int dm_dreg = (m_core->opcode >> 33) & 0xf; + int dmm = (m_core->opcode >> 38) & 0x7; + int dmi = (m_core->opcode >> 41) & 0x7; + int pmd = (m_core->opcode >> 37) & 0x1; + int dmd = (m_core->opcode >> 44) & 0x1; + int compute = m_core->opcode & 0x7fffff; /* due to parallelity issues, source DREGs must be saved */ /* because the compute operation may change them */ @@ -1348,8 +1310,8 @@ void adsp21062_device::sharcop_compute_dreg_dm_dreg_pm() /* compute */ void adsp21062_device::sharcop_compute() { - int cond = (m_opcode >> 33) & 0x1f; - int compute = m_opcode & 0x7fffff; + int cond = (m_core->opcode >> 33) & 0x1f; + int compute = m_core->opcode & 0x7fffff; if (IF_CONDITION_CODE(cond) && compute != 0) { @@ -1363,13 +1325,13 @@ void adsp21062_device::sharcop_compute() /* compute / ureg <-> DM|PM, pre-modify */ void adsp21062_device::sharcop_compute_ureg_dmpm_premod() { - int i = (m_opcode >> 41) & 0x7; - int m = (m_opcode >> 38) & 0x7; - int cond = (m_opcode >> 33) & 0x1f; - int g = (m_opcode >> 32) & 0x1; - int d = (m_opcode >> 31) & 0x1; - int ureg = (m_opcode >> 23) & 0xff; - int compute = m_opcode & 0x7fffff; + int i = (m_core->opcode >> 41) & 0x7; + int m = (m_core->opcode >> 38) & 0x7; + int cond = (m_core->opcode >> 33) & 0x1f; + int g = (m_core->opcode >> 32) & 0x1; + int d = (m_core->opcode >> 31) & 0x1; + int ureg = (m_core->opcode >> 23) & 0xff; + int compute = m_core->opcode & 0x7fffff; if (IF_CONDITION_CODE(cond)) { @@ -1388,7 +1350,7 @@ void adsp21062_device::sharcop_compute_ureg_dmpm_premod() { if (ureg == 0xdb) /* PX register access is always 48-bit */ { - pm_write48(PM_REG_I(i)+PM_REG_M(m), m_px); + pm_write48(PM_REG_I(i)+PM_REG_M(m), m_core->px); } else { @@ -1399,7 +1361,7 @@ void adsp21062_device::sharcop_compute_ureg_dmpm_premod() { if (ureg == 0xdb) /* PX register access is always 48-bit */ { - m_px = pm_read48(PM_REG_I(i)+PM_REG_M(m)); + m_core->px = pm_read48(PM_REG_I(i)+PM_REG_M(m)); } else { @@ -1424,13 +1386,13 @@ void adsp21062_device::sharcop_compute_ureg_dmpm_premod() /* compute / ureg <-> DM|PM, post-modify */ void adsp21062_device::sharcop_compute_ureg_dmpm_postmod() { - int i = (m_opcode >> 41) & 0x7; - int m = (m_opcode >> 38) & 0x7; - int cond = (m_opcode >> 33) & 0x1f; - int g = (m_opcode >> 32) & 0x1; - int d = (m_opcode >> 31) & 0x1; - int ureg = (m_opcode >> 23) & 0xff; - int compute = m_opcode & 0x7fffff; + int i = (m_core->opcode >> 41) & 0x7; + int m = (m_core->opcode >> 38) & 0x7; + int cond = (m_core->opcode >> 33) & 0x1f; + int g = (m_core->opcode >> 32) & 0x1; + int d = (m_core->opcode >> 31) & 0x1; + int ureg = (m_core->opcode >> 23) & 0xff; + int compute = m_core->opcode & 0x7fffff; if(IF_CONDITION_CODE(cond)) { @@ -1449,7 +1411,7 @@ void adsp21062_device::sharcop_compute_ureg_dmpm_postmod() { if (ureg == 0xdb) /* PX register access is always 48-bit */ { - pm_write48(PM_REG_I(i), m_px); + pm_write48(PM_REG_I(i), m_core->px); } else { @@ -1462,7 +1424,7 @@ void adsp21062_device::sharcop_compute_ureg_dmpm_postmod() { if (ureg == 0xdb) /* PX register access is always 48-bit */ { - m_px = pm_read48(PM_REG_I(i)); + m_core->px = pm_read48(PM_REG_I(i)); } else { @@ -1496,12 +1458,12 @@ void adsp21062_device::sharcop_compute_ureg_dmpm_postmod() /* compute / dreg <- DM, immediate modify */ void adsp21062_device::sharcop_compute_dm_to_dreg_immmod() { - int cond = (m_opcode >> 33) & 0x1f; - int u = (m_opcode >> 38) & 0x1; - int dreg = (m_opcode >> 23) & 0xf; - int i = (m_opcode >> 41) & 0x7; - int mod = SIGN_EXTEND6((m_opcode >> 27) & 0x3f); - int compute = m_opcode & 0x7fffff; + int cond = (m_core->opcode >> 33) & 0x1f; + int u = (m_core->opcode >> 38) & 0x1; + int dreg = (m_core->opcode >> 23) & 0xf; + int i = (m_core->opcode >> 41) & 0x7; + int mod = SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f); + int compute = m_core->opcode & 0x7fffff; if (IF_CONDITION_CODE(cond)) { @@ -1526,12 +1488,12 @@ void adsp21062_device::sharcop_compute_dm_to_dreg_immmod() /* compute / dreg -> DM, immediate modify */ void adsp21062_device::sharcop_compute_dreg_to_dm_immmod() { - int cond = (m_opcode >> 33) & 0x1f; - int u = (m_opcode >> 38) & 0x1; - int dreg = (m_opcode >> 23) & 0xf; - int i = (m_opcode >> 41) & 0x7; - int mod = SIGN_EXTEND6((m_opcode >> 27) & 0x3f); - int compute = m_opcode & 0x7fffff; + int cond = (m_core->opcode >> 33) & 0x1f; + int u = (m_core->opcode >> 38) & 0x1; + int dreg = (m_core->opcode >> 23) & 0xf; + int i = (m_core->opcode >> 41) & 0x7; + int mod = SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f); + int compute = m_core->opcode & 0x7fffff; /* due to parallelity issues, source REG must be saved */ /* because the shift operation may change it */ @@ -1560,12 +1522,12 @@ void adsp21062_device::sharcop_compute_dreg_to_dm_immmod() /* compute / dreg <- PM, immediate modify */ void adsp21062_device::sharcop_compute_pm_to_dreg_immmod() { - int cond = (m_opcode >> 33) & 0x1f; - int u = (m_opcode >> 38) & 0x1; - int dreg = (m_opcode >> 23) & 0xf; - int i = (m_opcode >> 41) & 0x7; - int mod = SIGN_EXTEND6((m_opcode >> 27) & 0x3f); - int compute = m_opcode & 0x7fffff; + int cond = (m_core->opcode >> 33) & 0x1f; + int u = (m_core->opcode >> 38) & 0x1; + int dreg = (m_core->opcode >> 23) & 0xf; + int i = (m_core->opcode >> 41) & 0x7; + int mod = SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f); + int compute = m_core->opcode & 0x7fffff; if (IF_CONDITION_CODE(cond)) { @@ -1590,12 +1552,12 @@ void adsp21062_device::sharcop_compute_pm_to_dreg_immmod() /* compute / dreg -> PM, immediate modify */ void adsp21062_device::sharcop_compute_dreg_to_pm_immmod() { - int cond = (m_opcode >> 33) & 0x1f; - int u = (m_opcode >> 38) & 0x1; - int dreg = (m_opcode >> 23) & 0xf; - int i = (m_opcode >> 41) & 0x7; - int mod = SIGN_EXTEND6((m_opcode >> 27) & 0x3f); - int compute = m_opcode & 0x7fffff; + int cond = (m_core->opcode >> 33) & 0x1f; + int u = (m_core->opcode >> 38) & 0x1; + int dreg = (m_core->opcode >> 23) & 0xf; + int i = (m_core->opcode >> 41) & 0x7; + int mod = SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f); + int compute = m_core->opcode & 0x7fffff; /* due to parallelity issues, source REG must be saved */ /* because the compute operation may change it */ @@ -1627,10 +1589,10 @@ void adsp21062_device::sharcop_compute_dreg_to_pm_immmod() /* compute / ureg <-> ureg */ void adsp21062_device::sharcop_compute_ureg_to_ureg() { - int src_ureg = (m_opcode >> 36) & 0xff; - int dst_ureg = (m_opcode >> 23) & 0xff; - int cond = (m_opcode >> 31) & 0x1f; - int compute = m_opcode & 0x7fffff; + int src_ureg = (m_core->opcode >> 36) & 0xff; + int dst_ureg = (m_core->opcode >> 23) & 0xff; + int cond = (m_core->opcode >> 31) & 0x1f; + int compute = m_core->opcode & 0x7fffff; if (IF_CONDITION_CODE(cond)) { @@ -1653,16 +1615,16 @@ void adsp21062_device::sharcop_compute_ureg_to_ureg() /* immediate shift / dreg <-> DM|PM */ void adsp21062_device::sharcop_imm_shift_dreg_dmpm() { - int i = (m_opcode >> 41) & 0x7; - int m = (m_opcode >> 38) & 0x7; - int g = (m_opcode >> 32) & 0x1; - int d = (m_opcode >> 31) & 0x1; - int dreg = (m_opcode >> 23) & 0xf; - int cond = (m_opcode >> 33) & 0x1f; - int data = ((m_opcode >> 8) & 0xff) | ((m_opcode >> 19) & 0xf00); - int shiftop = (m_opcode >> 16) & 0x3f; - int rn = (m_opcode >> 4) & 0xf; - int rx = (m_opcode & 0xf); + int i = (m_core->opcode >> 41) & 0x7; + int m = (m_core->opcode >> 38) & 0x7; + int g = (m_core->opcode >> 32) & 0x1; + int d = (m_core->opcode >> 31) & 0x1; + int dreg = (m_core->opcode >> 23) & 0xf; + int cond = (m_core->opcode >> 33) & 0x1f; + int data = ((m_core->opcode >> 8) & 0xff) | ((m_core->opcode >> 19) & 0xf00); + int shiftop = (m_core->opcode >> 16) & 0x3f; + int rn = (m_core->opcode >> 4) & 0xf; + int rx = (m_core->opcode & 0xf); if (IF_CONDITION_CODE(cond)) { @@ -1711,11 +1673,11 @@ void adsp21062_device::sharcop_imm_shift_dreg_dmpm() /* immediate shift */ void adsp21062_device::sharcop_imm_shift() { - int cond = (m_opcode >> 33) & 0x1f; - int data = ((m_opcode >> 8) & 0xff) | ((m_opcode >> 19) & 0xf00); - int shiftop = (m_opcode >> 16) & 0x3f; - int rn = (m_opcode >> 4) & 0xf; - int rx = (m_opcode & 0xf); + int cond = (m_core->opcode >> 33) & 0x1f; + int data = ((m_core->opcode >> 8) & 0xff) | ((m_core->opcode >> 19) & 0xf00); + int shiftop = (m_core->opcode >> 16) & 0x3f; + int rn = (m_core->opcode >> 4) & 0xf; + int rx = (m_core->opcode & 0xf); if (IF_CONDITION_CODE(cond)) { @@ -1729,11 +1691,11 @@ void adsp21062_device::sharcop_imm_shift() /* compute / modify */ void adsp21062_device::sharcop_compute_modify() { - int cond = (m_opcode >> 33) & 0x1f; - int compute = m_opcode & 0x7fffff; - int g = (m_opcode >> 38) & 0x1; - int m = (m_opcode >> 27) & 0x7; - int i = (m_opcode >> 30) & 0x7; + int cond = (m_core->opcode >> 33) & 0x1f; + int compute = m_core->opcode & 0x7fffff; + int g = (m_core->opcode >> 38) & 0x1; + int m = (m_core->opcode >> 27) & 0x7; + int i = (m_core->opcode >> 30) & 0x7; if (IF_CONDITION_CODE(cond)) { @@ -1761,22 +1723,22 @@ void adsp21062_device::sharcop_compute_modify() /* direct call to absolute address */ void adsp21062_device::sharcop_direct_call() { - int j = (m_opcode >> 26) & 0x1; - int cond = (m_opcode >> 33) & 0x1f; - UINT32 address = m_opcode & 0xffffff; + int j = (m_core->opcode >> 26) & 0x1; + int cond = (m_core->opcode >> 33) & 0x1f; + UINT32 address = m_core->opcode & 0xffffff; if (IF_CONDITION_CODE(cond)) { if (j) { - //PUSH_PC(m_pc+3); /* 1 instruction + 2 delayed instructions */ - PUSH_PC(m_nfaddr); /* 1 instruction + 2 delayed instructions */ + //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */ + PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */ CHANGE_PC_DELAYED(address); } else { - //PUSH_PC(m_pc+1); - PUSH_PC(m_daddr); + //PUSH_PC(m_core->pc+1); + PUSH_PC(m_core->daddr); CHANGE_PC(address); } } @@ -1785,11 +1747,11 @@ void adsp21062_device::sharcop_direct_call() /* direct jump to absolute address */ void adsp21062_device::sharcop_direct_jump() { - int la = (m_opcode >> 38) & 0x1; - int ci = (m_opcode >> 24) & 0x1; - int j = (m_opcode >> 26) & 0x1; - int cond = (m_opcode >> 33) & 0x1f; - UINT32 address = m_opcode & 0xffffff; + int la = (m_core->opcode >> 38) & 0x1; + int ci = (m_core->opcode >> 24) & 0x1; + int j = (m_core->opcode >> 26) & 0x1; + int cond = (m_core->opcode >> 33) & 0x1f; + UINT32 address = m_core->opcode & 0xffffff; if(IF_CONDITION_CODE(cond)) { @@ -1797,13 +1759,13 @@ void adsp21062_device::sharcop_direct_jump() if (ci) { // TODO: anything else? - if (m_status_stkp > 0) + if (m_core->status_stkp > 0) { POP_STATUS_STACK(); } - m_interrupt_active = 0; - m_irptl &= ~(1 << m_active_irq_num); + m_core->interrupt_active = 0; + m_core->irptl &= ~(1 << m_core->active_irq_num); } if (la) @@ -1829,21 +1791,21 @@ void adsp21062_device::sharcop_direct_jump() /* direct call to relative address */ void adsp21062_device::sharcop_relative_call() { - int j = (m_opcode >> 26) & 0x1; - int cond = (m_opcode >> 33) & 0x1f; - UINT32 address = m_opcode & 0xffffff; + int j = (m_core->opcode >> 26) & 0x1; + int cond = (m_core->opcode >> 33) & 0x1f; + UINT32 address = m_core->opcode & 0xffffff; if (IF_CONDITION_CODE(cond)) { if (j) { - PUSH_PC(m_pc+3); /* 1 instruction + 2 delayed instructions */ - CHANGE_PC_DELAYED(m_pc + SIGN_EXTEND24(address)); + PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */ + CHANGE_PC_DELAYED(m_core->pc + SIGN_EXTEND24(address)); } else { - PUSH_PC(m_pc+1); - CHANGE_PC(m_pc + SIGN_EXTEND24(address)); + PUSH_PC(m_core->pc+1); + CHANGE_PC(m_core->pc + SIGN_EXTEND24(address)); } } } @@ -1851,11 +1813,11 @@ void adsp21062_device::sharcop_relative_call() /* direct jump to relative address */ void adsp21062_device::sharcop_relative_jump() { - int la = (m_opcode >> 38) & 0x1; - int ci = (m_opcode >> 24) & 0x1; - int j = (m_opcode >> 26) & 0x1; - int cond = (m_opcode >> 33) & 0x1f; - UINT32 address = m_opcode & 0xffffff; + int la = (m_core->opcode >> 38) & 0x1; + int ci = (m_core->opcode >> 24) & 0x1; + int j = (m_core->opcode >> 26) & 0x1; + int cond = (m_core->opcode >> 33) & 0x1f; + UINT32 address = m_core->opcode & 0xffffff; if (IF_CONDITION_CODE(cond)) { @@ -1863,13 +1825,13 @@ void adsp21062_device::sharcop_relative_jump() if (ci) { // TODO: anything else? - if (m_status_stkp > 0) + if (m_core->status_stkp > 0) { POP_STATUS_STACK(); } - m_interrupt_active = 0; - m_irptl &= ~(1 << m_active_irq_num); + m_core->interrupt_active = 0; + m_core->irptl &= ~(1 << m_core->active_irq_num); } if (la) @@ -1880,11 +1842,11 @@ void adsp21062_device::sharcop_relative_jump() if (j) { - CHANGE_PC_DELAYED(m_pc + SIGN_EXTEND24(address)); + CHANGE_PC_DELAYED(m_core->pc + SIGN_EXTEND24(address)); } else { - CHANGE_PC(m_pc + SIGN_EXTEND24(address)); + CHANGE_PC(m_core->pc + SIGN_EXTEND24(address)); } } } @@ -1895,26 +1857,26 @@ void adsp21062_device::sharcop_relative_jump() /* indirect jump */ void adsp21062_device::sharcop_indirect_jump() { - int la = (m_opcode >> 38) & 0x1; - int ci = (m_opcode >> 24) & 0x1; - int j = (m_opcode >> 26) & 0x1; - int e = (m_opcode >> 25) & 0x1; - int pmi = (m_opcode >> 30) & 0x7; - int pmm = (m_opcode >> 27) & 0x7; - int cond = (m_opcode >> 33) & 0x1f; - int compute = m_opcode & 0x7fffff; + int la = (m_core->opcode >> 38) & 0x1; + int ci = (m_core->opcode >> 24) & 0x1; + int j = (m_core->opcode >> 26) & 0x1; + int e = (m_core->opcode >> 25) & 0x1; + int pmi = (m_core->opcode >> 30) & 0x7; + int pmm = (m_core->opcode >> 27) & 0x7; + int cond = (m_core->opcode >> 33) & 0x1f; + int compute = m_core->opcode & 0x7fffff; // Clear Interrupt if (ci) { // TODO: anything else? - if (m_status_stkp > 0) + if (m_core->status_stkp > 0) { POP_STATUS_STACK(); } - m_interrupt_active = 0; - m_irptl &= ~(1 << m_active_irq_num); + m_core->interrupt_active = 0; + m_core->irptl &= ~(1 << m_core->active_irq_num); } if (e) /* IF...ELSE */ @@ -1974,12 +1936,12 @@ void adsp21062_device::sharcop_indirect_jump() /* indirect call */ void adsp21062_device::sharcop_indirect_call() { - int j = (m_opcode >> 26) & 0x1; - int e = (m_opcode >> 25) & 0x1; - int pmi = (m_opcode >> 30) & 0x7; - int pmm = (m_opcode >> 27) & 0x7; - int cond = (m_opcode >> 33) & 0x1f; - int compute = m_opcode & 0x7fffff; + int j = (m_core->opcode >> 26) & 0x1; + int e = (m_core->opcode >> 25) & 0x1; + int pmi = (m_core->opcode >> 30) & 0x7; + int pmm = (m_core->opcode >> 27) & 0x7; + int cond = (m_core->opcode >> 33) & 0x1f; + int compute = m_core->opcode & 0x7fffff; if (e) /* IF...ELSE */ { @@ -1987,14 +1949,14 @@ void adsp21062_device::sharcop_indirect_call() { if (j) { - //PUSH_PC(m_pc+3); /* 1 instruction + 2 delayed instructions */ - PUSH_PC(m_nfaddr); /* 1 instruction + 2 delayed instructions */ + //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */ + PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */ CHANGE_PC_DELAYED(PM_REG_I(pmi) + PM_REG_M(pmm)); } else { - //PUSH_PC(m_pc+1); - PUSH_PC(m_daddr); + //PUSH_PC(m_core->pc+1); + PUSH_PC(m_core->daddr); CHANGE_PC(PM_REG_I(pmi) + PM_REG_M(pmm)); } } @@ -2017,14 +1979,14 @@ void adsp21062_device::sharcop_indirect_call() if (j) { - //PUSH_PC(m_pc+3); /* 1 instruction + 2 delayed instructions */ - PUSH_PC(m_nfaddr); /* 1 instruction + 2 delayed instructions */ + //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */ + PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */ CHANGE_PC_DELAYED(PM_REG_I(pmi) + PM_REG_M(pmm)); } else { - //PUSH_PC(m_pc+1); - PUSH_PC(m_daddr); + //PUSH_PC(m_core->pc+1); + PUSH_PC(m_core->daddr); CHANGE_PC(PM_REG_I(pmi) + PM_REG_M(pmm)); } } @@ -2037,24 +1999,24 @@ void adsp21062_device::sharcop_indirect_call() /* indirect jump to relative address */ void adsp21062_device::sharcop_relative_jump_compute() { - int la = (m_opcode >> 38) & 0x1; - int ci = (m_opcode >> 24) & 0x1; - int j = (m_opcode >> 26) & 0x1; - int e = (m_opcode >> 25) & 0x1; - int cond = (m_opcode >> 33) & 0x1f; - int compute = m_opcode & 0x7fffff; + int la = (m_core->opcode >> 38) & 0x1; + int ci = (m_core->opcode >> 24) & 0x1; + int j = (m_core->opcode >> 26) & 0x1; + int e = (m_core->opcode >> 25) & 0x1; + int cond = (m_core->opcode >> 33) & 0x1f; + int compute = m_core->opcode & 0x7fffff; // Clear Interrupt if (ci) { // TODO: anything else? - if (m_status_stkp > 0) + if (m_core->status_stkp > 0) { POP_STATUS_STACK(); } - m_interrupt_active = 0; - m_irptl &= ~(1 << m_active_irq_num); + m_core->interrupt_active = 0; + m_core->irptl &= ~(1 << m_core->active_irq_num); } if (e) /* IF...ELSE */ @@ -2069,11 +2031,11 @@ void adsp21062_device::sharcop_relative_jump_compute() if (j) { - CHANGE_PC_DELAYED(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + CHANGE_PC_DELAYED(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } else { - CHANGE_PC(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + CHANGE_PC(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } } else @@ -2101,11 +2063,11 @@ void adsp21062_device::sharcop_relative_jump_compute() if (j) { - CHANGE_PC_DELAYED(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + CHANGE_PC_DELAYED(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } else { - CHANGE_PC(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + CHANGE_PC(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } } } @@ -2114,10 +2076,10 @@ void adsp21062_device::sharcop_relative_jump_compute() /* indirect call to relative address */ void adsp21062_device::sharcop_relative_call_compute() { - int j = (m_opcode >> 26) & 0x1; - int e = (m_opcode >> 25) & 0x1; - int cond = (m_opcode >> 33) & 0x1f; - int compute = m_opcode & 0x7fffff; + int j = (m_core->opcode >> 26) & 0x1; + int e = (m_core->opcode >> 25) & 0x1; + int cond = (m_core->opcode >> 33) & 0x1f; + int compute = m_core->opcode & 0x7fffff; if (e) /* IF...ELSE */ { @@ -2125,15 +2087,15 @@ void adsp21062_device::sharcop_relative_call_compute() { if (j) { - //PUSH_PC(m_pc+3); /* 1 instruction + 2 delayed instructions */ - PUSH_PC(m_nfaddr); /* 1 instruction + 2 delayed instructions */ - CHANGE_PC_DELAYED(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */ + PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */ + CHANGE_PC_DELAYED(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } else { - //PUSH_PC(m_pc+1); - PUSH_PC(m_daddr); - CHANGE_PC(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + //PUSH_PC(m_core->pc+1); + PUSH_PC(m_core->daddr); + CHANGE_PC(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } } else @@ -2155,15 +2117,15 @@ void adsp21062_device::sharcop_relative_call_compute() if (j) { - //PUSH_PC(m_pc+3); /* 1 instruction + 2 delayed instructions */ - PUSH_PC(m_nfaddr); /* 1 instruction + 2 delayed instructions */ - CHANGE_PC_DELAYED(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + //PUSH_PC(m_core->pc+3); /* 1 instruction + 2 delayed instructions */ + PUSH_PC(m_core->nfaddr); /* 1 instruction + 2 delayed instructions */ + CHANGE_PC_DELAYED(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } else { - //PUSH_PC(m_pc+1); - PUSH_PC(m_daddr); - CHANGE_PC(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + //PUSH_PC(m_core->pc+1); + PUSH_PC(m_core->daddr); + CHANGE_PC(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } } } @@ -2175,13 +2137,13 @@ void adsp21062_device::sharcop_relative_call_compute() /* indirect jump / compute / dreg <-> DM */ void adsp21062_device::sharcop_indirect_jump_compute_dreg_dm() { - int d = (m_opcode >> 44) & 0x1; - int dmi = (m_opcode >> 41) & 0x7; - int dmm = (m_opcode >> 38) & 0x7; - int pmi = (m_opcode >> 30) & 0x7; - int pmm = (m_opcode >> 27) & 0x7; - int cond = (m_opcode >> 33) & 0x1f; - int dreg = (m_opcode >> 23) & 0xf; + int d = (m_core->opcode >> 44) & 0x1; + int dmi = (m_core->opcode >> 41) & 0x7; + int dmm = (m_core->opcode >> 38) & 0x7; + int pmi = (m_core->opcode >> 30) & 0x7; + int pmm = (m_core->opcode >> 27) & 0x7; + int cond = (m_core->opcode >> 33) & 0x1f; + int dreg = (m_core->opcode >> 23) & 0xf; if (IF_CONDITION_CODE(cond)) { @@ -2189,7 +2151,7 @@ void adsp21062_device::sharcop_indirect_jump_compute_dreg_dm() } else { - UINT32 compute = m_opcode & 0x7fffff; + UINT32 compute = m_core->opcode & 0x7fffff; /* due to parallelity issues, source REG must be saved */ /* because the compute operation may change it */ UINT32 parallel_dreg = REG(dreg); @@ -2220,19 +2182,19 @@ void adsp21062_device::sharcop_indirect_jump_compute_dreg_dm() /* relative jump / compute / dreg <-> DM */ void adsp21062_device::sharcop_relative_jump_compute_dreg_dm() { - int d = (m_opcode >> 44) & 0x1; - int dmi = (m_opcode >> 41) & 0x7; - int dmm = (m_opcode >> 38) & 0x7; - int cond = (m_opcode >> 33) & 0x1f; - int dreg = (m_opcode >> 23) & 0xf; + int d = (m_core->opcode >> 44) & 0x1; + int dmi = (m_core->opcode >> 41) & 0x7; + int dmm = (m_core->opcode >> 38) & 0x7; + int cond = (m_core->opcode >> 33) & 0x1f; + int dreg = (m_core->opcode >> 23) & 0xf; if (IF_CONDITION_CODE(cond)) { - CHANGE_PC(m_pc + SIGN_EXTEND6((m_opcode >> 27) & 0x3f)); + CHANGE_PC(m_core->pc + SIGN_EXTEND6((m_core->opcode >> 27) & 0x3f)); } else { - UINT32 compute = m_opcode & 0x7fffff; + UINT32 compute = m_core->opcode & 0x7fffff; /* due to parallelity issues, source REG must be saved */ /* because the compute operation may change it */ UINT32 parallel_dreg = REG(dreg); @@ -2263,11 +2225,11 @@ void adsp21062_device::sharcop_relative_jump_compute_dreg_dm() /* return from subroutine / compute */ void adsp21062_device::sharcop_rts() { - int cond = (m_opcode >> 33) & 0x1f; - int j = (m_opcode >> 26) & 0x1; - int e = (m_opcode >> 25) & 0x1; - //int lr = (m_opcode >> 24) & 0x1; - int compute = m_opcode & 0x7fffff; + int cond = (m_core->opcode >> 33) & 0x1f; + int j = (m_core->opcode >> 26) & 0x1; + int e = (m_core->opcode >> 25) & 0x1; + //int lr = (m_core->opcode >> 24) & 0x1; + int compute = m_core->opcode & 0x7fffff; //if(lr) // fatalerror("SHARC: rts: loop reentry not implemented!\n"); @@ -2320,12 +2282,12 @@ void adsp21062_device::sharcop_rts() /* return from interrupt / compute */ void adsp21062_device::sharcop_rti() { - int cond = (m_opcode >> 33) & 0x1f; - int j = (m_opcode >> 26) & 0x1; - int e = (m_opcode >> 25) & 0x1; - int compute = m_opcode & 0x7fffff; + int cond = (m_core->opcode >> 33) & 0x1f; + int j = (m_core->opcode >> 26) & 0x1; + int e = (m_core->opcode >> 25) & 0x1; + int compute = m_core->opcode & 0x7fffff; - m_irptl &= ~(1 << m_active_irq_num); + m_core->irptl &= ~(1 << m_core->active_irq_num); if(e) /* IF...ELSE */ { @@ -2368,12 +2330,12 @@ void adsp21062_device::sharcop_rti() } } - if (m_status_stkp > 0) + if (m_core->status_stkp > 0) { POP_STATUS_STACK(); } - m_interrupt_active = 0; + m_core->interrupt_active = 0; check_interrupts(); } @@ -2383,9 +2345,9 @@ void adsp21062_device::sharcop_rti() /* do until counter expired, LCNTR immediate */ void adsp21062_device::sharcop_do_until_counter_imm() { - UINT16 data = (UINT16)(m_opcode >> 24); - int offset = SIGN_EXTEND24(m_opcode & 0xffffff); - UINT32 address = m_pc + offset; + UINT16 data = (UINT16)(m_core->opcode >> 24); + int offset = SIGN_EXTEND24(m_core->opcode & 0xffffff); + UINT32 address = m_core->pc + offset; int type; int cond = 0xf; /* until LCE (loop counter expired */ int distance = abs(offset); @@ -2403,11 +2365,11 @@ void adsp21062_device::sharcop_do_until_counter_imm() type = 3; } - m_lcntr = data; - if (m_lcntr > 0) + m_core->lcntr = data; + if (m_core->lcntr > 0) { - PUSH_PC(m_pc+1); - PUSH_LOOP(address, cond, type, m_lcntr); + PUSH_PC(m_core->pc+1); + PUSH_LOOP(address, cond, type, m_core->lcntr); } } @@ -2417,9 +2379,9 @@ void adsp21062_device::sharcop_do_until_counter_imm() /* do until counter expired, LCNTR from UREG */ void adsp21062_device::sharcop_do_until_counter_ureg() { - int ureg = (m_opcode >> 32) & 0xff; - int offset = SIGN_EXTEND24(m_opcode & 0xffffff); - UINT32 address = m_pc + offset; + int ureg = (m_core->opcode >> 32) & 0xff; + int offset = SIGN_EXTEND24(m_core->opcode & 0xffffff); + UINT32 address = m_core->pc + offset; int type; int cond = 0xf; /* until LCE (loop counter expired */ int distance = abs(offset); @@ -2437,11 +2399,11 @@ void adsp21062_device::sharcop_do_until_counter_ureg() type = 3; } - m_lcntr = GET_UREG(ureg); - if (m_lcntr > 0) + m_core->lcntr = GET_UREG(ureg); + if (m_core->lcntr > 0) { - PUSH_PC(m_pc+1); - PUSH_LOOP(address, cond, type, m_lcntr); + PUSH_PC(m_core->pc+1); + PUSH_LOOP(address, cond, type, m_core->lcntr); } } @@ -2451,11 +2413,11 @@ void adsp21062_device::sharcop_do_until_counter_ureg() /* do until */ void adsp21062_device::sharcop_do_until() { - int cond = (m_opcode >> 33) & 0x1f; - int offset = SIGN_EXTEND24(m_opcode & 0xffffff); - UINT32 address = (m_pc + offset); + int cond = (m_core->opcode >> 33) & 0x1f; + int offset = SIGN_EXTEND24(m_core->opcode & 0xffffff); + UINT32 address = (m_core->pc + offset); - PUSH_PC(m_pc+1); + PUSH_PC(m_core->pc+1); PUSH_LOOP(address, cond, 0, 0); } @@ -2465,8 +2427,8 @@ void adsp21062_device::sharcop_do_until() /* ureg <- DM (direct addressing) */ void adsp21062_device::sharcop_dm_to_ureg_direct() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 address = (UINT32)(m_opcode); + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 address = (UINT32)(m_core->opcode); SET_UREG(ureg, dm_read32(address)); } @@ -2474,8 +2436,8 @@ void adsp21062_device::sharcop_dm_to_ureg_direct() /* ureg -> DM (direct addressing) */ void adsp21062_device::sharcop_ureg_to_dm_direct() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 address = (UINT32)(m_opcode); + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 address = (UINT32)(m_core->opcode); dm_write32(address, GET_UREG(ureg)); } @@ -2483,12 +2445,12 @@ void adsp21062_device::sharcop_ureg_to_dm_direct() /* ureg <- PM (direct addressing) */ void adsp21062_device::sharcop_pm_to_ureg_direct() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 address = (UINT32)(m_opcode); + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 address = (UINT32)(m_core->opcode); if (ureg == 0xdb) // PX is 48-bit { - m_px = pm_read48(address); + m_core->px = pm_read48(address); } else { @@ -2499,12 +2461,12 @@ void adsp21062_device::sharcop_pm_to_ureg_direct() /* ureg -> PM (direct addressing) */ void adsp21062_device::sharcop_ureg_to_pm_direct() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 address = (UINT32)(m_opcode); + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 address = (UINT32)(m_core->opcode); if (ureg == 0xdb) // PX is 48-bit { - pm_write48(address, m_px); + pm_write48(address, m_core->px); } else { @@ -2518,9 +2480,9 @@ void adsp21062_device::sharcop_ureg_to_pm_direct() /* ureg <- DM (indirect addressing) */ void adsp21062_device::sharcop_dm_to_ureg_indirect() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 offset = (UINT32)m_opcode; - int i = (m_opcode >> 41) & 0x7; + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 offset = (UINT32)m_core->opcode; + int i = (m_core->opcode >> 41) & 0x7; SET_UREG(ureg, dm_read32(DM_REG_I(i) + offset)); } @@ -2528,9 +2490,9 @@ void adsp21062_device::sharcop_dm_to_ureg_indirect() /* ureg -> DM (indirect addressing) */ void adsp21062_device::sharcop_ureg_to_dm_indirect() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 offset = (UINT32)m_opcode; - int i = (m_opcode >> 41) & 0x7; + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 offset = (UINT32)m_core->opcode; + int i = (m_core->opcode >> 41) & 0x7; dm_write32(DM_REG_I(i) + offset, GET_UREG(ureg)); } @@ -2538,13 +2500,13 @@ void adsp21062_device::sharcop_ureg_to_dm_indirect() /* ureg <- PM (indirect addressing) */ void adsp21062_device::sharcop_pm_to_ureg_indirect() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 offset = m_opcode & 0xffffff; - int i = (m_opcode >> 41) & 0x7; + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 offset = m_core->opcode & 0xffffff; + int i = (m_core->opcode >> 41) & 0x7; if (ureg == 0xdb) /* PX is 48-bit */ { - m_px = pm_read48(PM_REG_I(i) + offset); + m_core->px = pm_read48(PM_REG_I(i) + offset); } else { @@ -2555,13 +2517,13 @@ void adsp21062_device::sharcop_pm_to_ureg_indirect() /* ureg -> PM (indirect addressing) */ void adsp21062_device::sharcop_ureg_to_pm_indirect() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 offset = (UINT32)m_opcode; - int i = (m_opcode >> 41) & 0x7; + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 offset = (UINT32)m_core->opcode; + int i = (m_core->opcode >> 41) & 0x7; if (ureg == 0xdb) /* PX is 48-bit */ { - pm_write48(PM_REG_I(i) + offset, m_px); + pm_write48(PM_REG_I(i) + offset, m_core->px); } else { @@ -2575,10 +2537,10 @@ void adsp21062_device::sharcop_ureg_to_pm_indirect() /* immediate data -> DM|PM */ void adsp21062_device::sharcop_imm_to_dmpm() { - int i = (m_opcode >> 41) & 0x7; - int m = (m_opcode >> 38) & 0x7; - int g = (m_opcode >> 37) & 0x1; - UINT32 data = (UINT32)m_opcode; + int i = (m_core->opcode >> 41) & 0x7; + int m = (m_core->opcode >> 38) & 0x7; + int g = (m_core->opcode >> 37) & 0x1; + UINT32 data = (UINT32)m_core->opcode; if (g) { @@ -2602,8 +2564,8 @@ void adsp21062_device::sharcop_imm_to_dmpm() /* immediate data -> ureg */ void adsp21062_device::sharcop_imm_to_ureg() { - int ureg = (m_opcode >> 32) & 0xff; - UINT32 data = (UINT32)m_opcode; + int ureg = (m_core->opcode >> 32) & 0xff; + UINT32 data = (UINT32)m_core->opcode; SET_UREG(ureg, data); } @@ -2614,9 +2576,9 @@ void adsp21062_device::sharcop_imm_to_ureg() /* system register bit manipulation */ void adsp21062_device::sharcop_sysreg_bitop() { - int bop = (m_opcode >> 37) & 0x7; - int sreg = (m_opcode >> 32) & 0xf; - UINT32 data = (UINT32)m_opcode; + int bop = (m_core->opcode >> 37) & 0x7; + int sreg = (m_core->opcode >> 32) & 0xf; + UINT32 data = (UINT32)m_core->opcode; UINT32 src = GET_UREG(0x70 | sreg); @@ -2641,11 +2603,11 @@ void adsp21062_device::sharcop_sysreg_bitop() { if ((src & data) == data) { - m_astat |= BTF; + m_core->astat |= BTF; } else { - m_astat &= ~BTF; + m_core->astat &= ~BTF; } break; } @@ -2653,11 +2615,11 @@ void adsp21062_device::sharcop_sysreg_bitop() { if (src == data) { - m_astat |= BTF; + m_core->astat |= BTF; } else { - m_astat &= ~BTF; + m_core->astat &= ~BTF; } break; } @@ -2675,9 +2637,9 @@ void adsp21062_device::sharcop_sysreg_bitop() /* I register modify */ void adsp21062_device::sharcop_modify() { - int g = (m_opcode >> 38) & 0x1; - int i = (m_opcode >> 32) & 0x7; - INT32 data = (m_opcode); + int g = (m_core->opcode >> 38) & 0x1; + int i = (m_core->opcode >> 32) & 0x7; + INT32 data = (m_core->opcode); if (g) // PM { @@ -2706,29 +2668,29 @@ void adsp21062_device::sharcop_bit_reverse() /* push/pop stacks / flush cache */ void adsp21062_device::sharcop_push_pop_stacks() { - if (m_opcode & U64(0x008000000000)) + if (m_core->opcode & U64(0x008000000000)) { fatalerror("sharcop_push_pop_stacks: push loop not implemented\n"); } - if (m_opcode & U64(0x004000000000)) + if (m_core->opcode & U64(0x004000000000)) { fatalerror("sharcop_push_pop_stacks: pop loop not implemented\n"); } - if (m_opcode & U64(0x002000000000)) + if (m_core->opcode & U64(0x002000000000)) { //fatalerror("sharcop_push_pop_stacks: push sts not implemented\n"); PUSH_STATUS_STACK(); } - if (m_opcode & U64(0x001000000000)) + if (m_core->opcode & U64(0x001000000000)) { //fatalerror("sharcop_push_pop_stacks: pop sts not implemented\n"); POP_STATUS_STACK(); } - if (m_opcode & U64(0x000800000000)) + if (m_core->opcode & U64(0x000800000000)) { - PUSH_PC(m_pcstk); + PUSH_PC(m_core->pcstk); } - if (m_opcode & U64(0x000400000000)) + if (m_core->opcode & U64(0x000400000000)) { POP_PC(); } @@ -2746,13 +2708,13 @@ void adsp21062_device::sharcop_nop() void adsp21062_device::sharcop_idle() { - //CHANGE_PC(m_pc); + //CHANGE_PC(m_core->pc); - m_daddr = m_pc; - m_faddr = m_pc+1; - m_nfaddr = m_pc+2; + m_core->daddr = m_core->pc; + m_core->faddr = m_core->pc+1; + m_core->nfaddr = m_core->pc+2; - m_idle = 1; + m_core->idle = 1; } /*****************************************************************************/ @@ -2761,7 +2723,7 @@ void adsp21062_device::sharcop_unimplemented() { extern CPU_DISASSEMBLE(sharc); char dasm[1000]; - CPU_DISASSEMBLE_NAME(sharc)(nullptr, dasm, m_pc, nullptr, nullptr, 0); - osd_printf_debug("SHARC: %08X: %s\n", m_pc, dasm); - fatalerror("SHARC: Unimplemented opcode %04X%08X at %08X\n", (UINT16)(m_opcode >> 32), (UINT32)(m_opcode), m_pc); + CPU_DISASSEMBLE_NAME(sharc)(nullptr, dasm, m_core->pc, nullptr, nullptr, 0); + osd_printf_debug("SHARC: %08X: %s\n", m_core->pc, dasm); + fatalerror("SHARC: Unimplemented opcode %04X%08X at %08X\n", (UINT16)(m_core->opcode >> 32), (UINT32)(m_core->opcode), m_core->pc); }