arcompact - start to add the hardware loop support (nw)

This commit is contained in:
mamehaze 2014-12-26 23:42:10 +00:00
parent 6216b82a84
commit 3b35928395
6 changed files with 80 additions and 77 deletions

View File

@ -63,6 +63,8 @@ void arcompact_device::device_start()
state_add( 0, "PC", m_debugger_temp).callimport().callexport().formatstr("%08X"); state_add( 0, "PC", m_debugger_temp).callimport().callexport().formatstr("%08X");
state_add( 0x10, "STATUS32", m_debugger_temp).callimport().callexport().formatstr("%08X"); state_add( 0x10, "STATUS32", m_debugger_temp).callimport().callexport().formatstr("%08X");
state_add( 0x11, "LP_START", m_debugger_temp).callimport().callexport().formatstr("%08X");
state_add( 0x12, "LP_END", m_debugger_temp).callimport().callexport().formatstr("%08X");
state_add(STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow(); state_add(STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow();
@ -88,6 +90,12 @@ void arcompact_device::state_export(const device_state_entry &entry)
case 0x10: case 0x10:
m_debugger_temp = m_status32; m_debugger_temp = m_status32;
break; break;
case 0x11:
m_debugger_temp = m_LP_START;
break;
case 0x12:
m_debugger_temp = m_LP_END;
break;
case STATE_GENPC: case STATE_GENPC:
m_debugger_temp = m_pc; m_debugger_temp = m_pc;
@ -116,6 +124,12 @@ void arcompact_device::state_import(const device_state_entry &entry)
case 0x10: case 0x10:
m_status32 = m_debugger_temp; m_status32 = m_debugger_temp;
break; break;
case 0x11:
m_LP_START = m_debugger_temp;
break;
case 0x12:
m_LP_END = m_debugger_temp;
break;
default: default:
if ((index >= 0x100) && (index < 0x140)) if ((index >= 0x100) && (index < 0x140))
@ -137,6 +151,9 @@ void arcompact_device::device_reset()
m_regs[i] = 0; m_regs[i] = 0;
m_status32 = 0; m_status32 = 0;
m_LP_START = 0;
m_LP_END = 0;
} }
/*****************************************************************************/ /*****************************************************************************/

View File

@ -186,7 +186,7 @@ protected:
ARCOMPACT_RETTYPE arcompact_handle04_2b(OPS_32); ARCOMPACT_RETTYPE arcompact_handle04_2b(OPS_32);
ARCOMPACT_RETTYPE arcompact_handle04_2f_00(OPS_32); ARCOMPACT_RETTYPE arcompact_handle04_2f_00(OPS_32);
ARCOMPACT_RETTYPE arcompact_handle04_2f_01(OPS_32); ARCOMPACT_RETTYPE arcompact_handle04_2f_01(OPS_32);
ARCOMPACT_RETTYPE arcompact_handle04_2f_02(OPS_32); // ARCOMPACT_RETTYPE arcompact_handle04_2f_02(OPS_32);
ARCOMPACT_RETTYPE arcompact_handle04_2f_03(OPS_32); ARCOMPACT_RETTYPE arcompact_handle04_2f_03(OPS_32);
ARCOMPACT_RETTYPE arcompact_handle04_2f_04(OPS_32); ARCOMPACT_RETTYPE arcompact_handle04_2f_04(OPS_32);
ARCOMPACT_RETTYPE arcompact_handle04_2f_05(OPS_32); ARCOMPACT_RETTYPE arcompact_handle04_2f_05(OPS_32);
@ -778,6 +778,7 @@ protected:
ARCOMPACT_HANDLER04_TYPE_PM(04_16); ARCOMPACT_HANDLER04_TYPE_PM(04_16);
ARCOMPACT_HANDLER04_TYPE_PM(04_20); ARCOMPACT_HANDLER04_TYPE_PM(04_20);
ARCOMPACT_HANDLER04_TYPE_PM(04_2f_02);
ARCOMPACT_HANDLER04_TYPE_PM(04_2f_07); ARCOMPACT_HANDLER04_TYPE_PM(04_2f_07);
ARCOMPACT_HANDLER04_TYPE_PM(04_2f_08); ARCOMPACT_HANDLER04_TYPE_PM(04_2f_08);
@ -815,6 +816,10 @@ private:
// f e d c| b a 9 8| 7 6 5 4| 3 2 1 0 // f e d c| b a 9 8| 7 6 5 4| 3 2 1 0
// - - - L| Z N C V| U DE AE A2|A1 E2 E1 H // - - - L| Z N C V| U DE AE A2|A1 E2 E1 H
UINT32 m_status32; UINT32 m_status32;
UINT32 m_LP_START;
UINT32 m_LP_END;
}; };
#define V_OVERFLOW_FLAG (0x00000100) #define V_OVERFLOW_FLAG (0x00000100)
@ -845,6 +850,7 @@ private:
// Condition 0x0c (LE) // Condition 0x0c (LE)
#define CONDITION_LE ((STATUS32_CHECK_Z) || (STATUS32_CHECK_N && !STATUS32_CHECK_V) || (!STATUS32_CHECK_N && STATUS32_CHECK_V)) // Z or (N and /V) or (/N and V) #define CONDITION_LE ((STATUS32_CHECK_Z) || (STATUS32_CHECK_N && !STATUS32_CHECK_V) || (!STATUS32_CHECK_N && STATUS32_CHECK_V)) // Z or (N and /V) or (/N and V)
#define CONDITION_EQ (STATUS32_CHECK_Z) #define CONDITION_EQ (STATUS32_CHECK_Z)
#define CONDITION_CS (STATUS32_CHECK_C)
extern const device_type ARCA5; extern const device_type ARCA5;

View File

@ -19,3 +19,4 @@ extern const char *opcodes_04[0x40];
#define REG_SP (0x1c) // r28 #define REG_SP (0x1c) // r28
#define REG_ILINK1 (0x1d) // r29 #define REG_ILINK1 (0x1d) // r29
#define REG_ILINK2 (0x1e) // r30 #define REG_ILINK2 (0x1e) // r30
#define REG_LP_COUNT (0x3c) // r60

View File

@ -36,6 +36,17 @@ void arcompact_device::execute_run()
m_pc = get_insruction(op); m_pc = get_insruction(op);
} }
// hardware loops
if (m_pc == m_LP_END)
{
if (m_regs[REG_LP_COUNT] != 1)
{
m_pc = m_LP_START;
}
m_regs[REG_LP_COUNT]--;
}
m_icount--; m_icount--;
} }
@ -138,7 +149,7 @@ int arcompact_device::check_condition(UINT8 condition)
case 0x02: return !CONDITION_EQ; // NE case 0x02: return !CONDITION_EQ; // NE
case 0x03: fatalerror("unhandled condition check %s", conditions[condition]); return -1; case 0x03: fatalerror("unhandled condition check %s", conditions[condition]); return -1;
case 0x04: fatalerror("unhandled condition check %s", conditions[condition]); return -1; case 0x04: fatalerror("unhandled condition check %s", conditions[condition]); return -1;
case 0x05: fatalerror("unhandled condition check %s", conditions[condition]); return -1; case 0x05: return CONDITION_CS; // CS (Carry Set / Lower than)
case 0x06: fatalerror("unhandled condition check %s", conditions[condition]); return -1; case 0x06: fatalerror("unhandled condition check %s", conditions[condition]); return -1;
case 0x07: fatalerror("unhandled condition check %s", conditions[condition]); return -1; case 0x07: fatalerror("unhandled condition check %s", conditions[condition]); return -1;
case 0x08: fatalerror("unhandled condition check %s", conditions[condition]); return -1; case 0x08: fatalerror("unhandled condition check %s", conditions[condition]); return -1;
@ -2054,23 +2065,46 @@ ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_23(OPS_32)
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_28(OPS_32) // LPcc (loop setup) ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_28(OPS_32) // LPcc (loop setup)
{ {
int size = 4; int size = 4;
// COMMON32_GET_breg; // breg is reserved
COMMON32_GET_p; COMMON32_GET_p;
if (p == 0x00) if (p == 0x00)
{ {
arcompact_fatal("<illegal LPcc, p = 0x00)");
} }
else if (p == 0x01) else if (p == 0x01)
{ {
arcompact_fatal("<illegal LPcc, p = 0x01)");
} }
else if (p == 0x02) // Loop unconditional else if (p == 0x02) // Loop unconditional
{ { // 0010 0RRR 1010 1000 0RRR ssss ssSS SSSS
COMMON32_GET_s12
if (S & 0x800) S = -0x800 + (S&0x7ff);
arcompact_fatal("Lp unconditional not supported %d", S);
} }
else if (p == 0x03) // Loop conditional else if (p == 0x03) // Loop conditional
{ // 0010 0RRR 1110 1000 0RRR uuuu uu1Q QQQQ
COMMON32_GET_u6
COMMON32_GET_CONDITION
//arcompact_fatal("Lp conditional %s not supported %d", conditions[condition], u);
// if the loop condition fails then just jump to after the end of the loop, don't set any registers
if (!check_condition(condition))
{ {
UINT32 realoffset = PC_ALIGNED32 + (u * 2);
return realoffset;
}
else
{
// otherwise set up the loop positions
m_LP_START = m_pc + (size >> 0);
m_LP_END = PC_ALIGNED32 + (u * 2);
return m_pc + (size>>0);
}
} }
arcompact_log("unimplemented LPcc %08x", op);
return m_pc + (size>>0); return m_pc + (size>>0);
} }
@ -2211,83 +2245,16 @@ ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_helper(OPS_32, const c
} }
#define SETUP_HANDLE04_2f_0x_P00 \
int size = 4; \
UINT32 limm = 0; \
\
COMMON32_GET_breg; \
COMMON32_GET_F; \
COMMON32_GET_creg; \
\
UINT32 c; \
\
if (creg == LIMM_REG) \
{ \
GET_LIMM_32; \
size = 8; \
c = limm; \
} \
else \
{ \
c = m_regs[creg]; \
} \
/* todo: is the limm, limm syntax valid? (it's pointless.) */ \
/* todo: if breg = LIMM then there is no result (but since that register can never be read, I guess it doesn't matter if we store it there anyway?) */ \
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_00(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ASL"); } // ASL ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_00(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ASL"); } // ASL
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_01(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ASR"); } // ASR ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_01(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ASR"); } // ASR
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_02(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "LSR"); } // LSR
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_03(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ROR"); } // ROR ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_03(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ROR"); } // ROR
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_04(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "RCC"); } // RCC ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_04(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "RCC"); } // RCC
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_05(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "SEXB"); } // SEXB ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_05(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "SEXB"); } // SEXB
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_06(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "SEXW"); } // SEXW ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_06(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "SEXW"); } // SEXW
// EXTW b <- c or EXTW b <- limm or EXTW limm <- c (no result) or EXTW limm, limm (invalid?)
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p00(OPS_32) // note 'b' destination for 04_2f_08_xx group
{
SETUP_HANDLE04_2f_0x_P00;
m_regs[breg] = c & 0x0000ffff;
if (F)
{
arcompact_fatal("arcompact_handle04_2f_08_p00 (EXTW) (F set)\n"); // not yet supported
}
return m_pc + (size >> 0);
}
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p01(OPS_32)
{
int size = 4;
arcompact_fatal("arcompact_handle04_2f_08_p01 (EXTW)\n");
return m_pc + (size >> 0);
}
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p10(OPS_32)
{
int size = 4;
arcompact_fatal("illegal 04_2f_08_p10 (EXTW)\n"); // illegal mode because 'S' bits have already been used for opcode select
return m_pc + (size >> 0);
}
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p11_m0(OPS_32)
{
int size = 4;
arcompact_fatal("arcompact_handle04_2f_08_p11_m0 (EXTW)\n"); // illegal mode because 'Q' bits have already been used for opcode select
return m_pc + (size >> 0);
}
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_08_p11_m1(OPS_32)
{
int size = 4;
arcompact_fatal("arcompact_handle04_2f_08_p11_m1 (EXTW)\n"); // illegal mode because 'Q' bits have already been used for opcode select
return m_pc + (size >> 0);
}
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_09(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ABS"); } // ABS ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_09(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "ABS"); } // ABS
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_0a(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "NOT"); } // NOT ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_0a(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "NOT"); } // NOT
ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_0b(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "RCL"); } // RLC ARCOMPACT_RETTYPE arcompact_device::arcompact_handle04_2f_0b(OPS_32) { return arcompact_handle04_2f_helper(PARAMS, "RCL"); } // RLC

View File

@ -9,6 +9,16 @@ def EmitGroup04_Handle_NZ_Flags(f, funcname, opname):
print >>f, " if (result == 0x00000000) { STATUS32_SET_Z; }" print >>f, " if (result == 0x00000000) { STATUS32_SET_Z; }"
print >>f, " else { STATUS32_CLEAR_Z; }" print >>f, " else { STATUS32_CLEAR_Z; }"
def EmitGroup04_Handle_NZC_LSR1_Flags(f, funcname, opname):
print >>f, " if (result & 0x80000000) { STATUS32_SET_N; }"
print >>f, " else { STATUS32_CLEAR_N; }"
print >>f, " if (result == 0x00000000) { STATUS32_SET_Z; }"
print >>f, " else { STATUS32_CLEAR_Z; }"
print >>f, " if (c == 0x00000001) { STATUS32_SET_C; }"
print >>f, " else { STATUS32_CLEAR_C; }"
def EmitGroup04_no_Flags(f, funcname, opname): def EmitGroup04_no_Flags(f, funcname, opname):
print >>f, " // no flag changes" print >>f, " // no flag changes"
@ -289,7 +299,9 @@ EmitGroup04(f, "05_00", "ASL", "UINT32 result = b << (c&0x1f);", "m_regs[areg] =
EmitGroup04(f, "05_01", "LSR", "UINT32 result = b >> (c&0x1f);", "m_regs[areg] = result;", "m_regs[breg] = result;", 0,0, -1, EmitGroup04_unsupported_Flags ) EmitGroup04(f, "05_01", "LSR", "UINT32 result = b >> (c&0x1f);", "m_regs[areg] = result;", "m_regs[breg] = result;", 0,0, -1, EmitGroup04_unsupported_Flags )
# the 04_2f subgroup uses the same encoding, but the areg is already used as sub-opcode select, so any modes relying on areg bits for other reasons (sign, condition) (modes 10, 11m0, 11m1) are illegal. the destination is also breg not areg # the 04_2f subgroup uses the same encoding, but the areg is already used as sub-opcode select, so any modes relying on areg bits for other reasons (sign, condition) (modes 10, 11m0, 11m1) are illegal. the destination is also breg not areg
EmitGroup04(f, "04_2f_07", "EXTB", "UINT32 result = c & 0x000000ff;", "m_regs[breg] = result;","", 2,1, -1, EmitGroup04_unsupported_Flags ) # no alt handler (invalid path) EmitGroup04(f, "04_2f_02", "LSR1", "UINT32 result = c >> 1;", "m_regs[breg] = result;","", 2,1, -1, EmitGroup04_Handle_NZC_LSR1_Flags ) # no alt handler (invalid path)
EmitGroup04(f, "04_2f_07", "EXTB", "UINT32 result = c & 0x000000ff;", "m_regs[breg] = result;","", 2,1, -1, EmitGroup04_unsupported_Flags ) # ^
EmitGroup04(f, "04_2f_08", "EXTW", "UINT32 result = c & 0x0000ffff;", "m_regs[breg] = result;","", 2,1, -1, EmitGroup04_unsupported_Flags ) # ^
# xxx_S b, b, u5 format opcodes # xxx_S b, b, u5 format opcodes

View File

@ -887,7 +887,7 @@ int arcompact_handle04_28_dasm(DASM_OPS_32) // LPcc (loop setup)
{ // 0010 0RRR 1110 1000 0RRR uuuu uu1Q QQQQ { // 0010 0RRR 1110 1000 0RRR uuuu uu1Q QQQQ
COMMON32_GET_u6 COMMON32_GET_u6
COMMON32_GET_CONDITION COMMON32_GET_CONDITION
output += sprintf(output, "LP<%s> (start %08x, end %08x)", conditions[condition], pc + 4, pc + u*2); output += sprintf(output, "LP<%s> (start %08x, end %08x)", conditions[condition], pc + 4, PC_ALIGNED32 + u*2);
int unused = (op & 0x00000020)>>5; int unused = (op & 0x00000020)>>5;
if (unused==0) output += sprintf(output, "(unused bit not set)"); if (unused==0) output += sprintf(output, "(unused bit not set)");