sharcdrc: Model 2 compatibility (nw)

This commit is contained in:
Ville Linde 2016-06-07 21:01:31 +03:00
parent 33db067893
commit 7fe3b170be
5 changed files with 363 additions and 16 deletions

View File

@ -173,6 +173,7 @@ opcode_desc *drc_frontend::describe_one(offs_t curpc, const opcode_desc *prevdes
// set the delay slot flag
desc->flags = in_delay_slot ? OPFLAG_IN_DELAY_SLOT : 0;
desc->userflags = 0;
desc->userdata0 = 0;
desc->cycles = 0;
memset(desc->regin, 0x00, sizeof(desc->regin));
memset(desc->regout, 0x00, sizeof(desc->regout));

View File

@ -114,6 +114,7 @@ struct opcode_desc
UINT8 skipslots; // number of skip slots (for branches)
UINT32 flags; // OPFLAG_* opcode flags
UINT32 userflags; // core specific flags
UINT32 userdata0; // core specific data
UINT32 cycles; // number of cycles needed to execute
// register usage information

View File

@ -129,6 +129,7 @@ struct SHARC_DMA_OP
#define OP_USERFLAG_ASTAT_DELAY_COPY_SZ 0x00080000
#define OP_USERFLAG_ASTAT_DELAY_COPY_BTF 0x00100000
#define OP_USERFLAG_ASTAT_DELAY_COPY 0x001ff000
#define OP_USERFLAG_CALL 0x10000000
#define MCFG_SHARC_BOOT_MODE(boot_mode) \
@ -403,7 +404,9 @@ private:
ASTAT_DRC astat_drc_copy;
ASTAT_DRC astat_delay_copy;
UINT32 dreg_temp;
UINT32 dreg_temp2;
UINT32 jmpdest;
UINT32 temp_return;
float fp0;
float fp1;
@ -630,6 +633,7 @@ private:
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_loop_jump(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
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);

View File

@ -1366,6 +1366,57 @@ void adsp21062_device::generate_sequence_instruction(drcuml_block *block, compil
UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE
}
// handle a special case where call is used as the last operation in a loop
if (desc->userflags & OP_USERFLAG_CALL && desc->userflags & (OP_USERFLAG_COND_LOOP | OP_USERFLAG_COUNTER_LOOP))
{
if (desc->userflags & OP_USERFLAG_COUNTER_LOOP)
{
code_label end = compiler->labelnum++;
UML_LOAD(block, I0, m_core->lastack, LSTKP, SIZE_DWORD, SCALE_x4);
UML_CMP(block, I0, desc->pc);
UML_JMPc(block, COND_NE, end);
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
UML_MOV(block, mem(&m_core->temp_return), desc->userdata0);
UML_JMP(block, end);
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
UML_MOV(block, mem(&m_core->temp_return), desc->pc + 1);
UML_LABEL(block, end);
}
if (desc->userflags & OP_USERFLAG_COND_LOOP)
{
code_label end = compiler->labelnum++;
UML_LOAD(block, I0, m_core->lastack, LSTKP, SIZE_DWORD, SCALE_x4);
UML_CMP(block, I0, desc->pc);
UML_JMPc(block, COND_NE, end);
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);
UML_MOV(block, mem(&m_core->temp_return), desc->userdata0);
UML_JMP(block, end);
UML_LABEL(block, label_expire);
UML_CALLH(block, *m_pop_pc);
UML_CALLH(block, *m_pop_loop);
UML_MOV(block, mem(&m_core->temp_return), desc->pc + 1);
UML_LABEL(block, end);
}
}
/* 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
@ -1432,7 +1483,7 @@ void adsp21062_device::generate_sequence_instruction(drcuml_block *block, compil
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);
generate_loop_jump(block, compiler, desc);
UML_LABEL(block, label_expire); // label_expire:
UML_CALLH(block, *m_pop_pc); // callh m_pop_pc
@ -1452,7 +1503,7 @@ void adsp21062_device::generate_sequence_instruction(drcuml_block *block, compil
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);
generate_loop_jump(block, compiler, desc);
UML_LABEL(block, label_expire);
UML_CALLH(block, *m_pop_pc);
@ -1786,10 +1837,18 @@ void adsp21062_device::generate_call(drcuml_block *block, compiler_state *compil
generate_sequence_instruction(block, &compiler_temp, desc->delay.last(), true);
}
if (delayslot)
UML_MOV(block, I0, desc->pc + 3);
// if this is the last instruction of a loop, we need to use the return PC from the resolved loop
if (desc->userflags & OP_USERFLAG_CALL && desc->userflags & (OP_USERFLAG_COND_LOOP | OP_USERFLAG_COUNTER_LOOP))
{
UML_MOV(block, I0, mem(&m_core->temp_return));
}
else
UML_MOV(block, I0, desc->pc + 1);
{
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
@ -1878,6 +1937,23 @@ void adsp21062_device::generate_jump(drcuml_block *block, compiler_state *compil
UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
}
void adsp21062_device::generate_loop_jump(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
{
// update cycles and hash jump
generate_update_cycles(block, compiler, desc->userdata0, 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
*/
UML_HASHJMP(block, 0, desc->userdata0, *m_nocode);
/* 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
-------------------------------------------------*/
@ -2734,8 +2810,51 @@ int adsp21062_device::generate_opcode(drcuml_block *block, compiler_state *compi
compiler->mode1_delay.data = data;
compiler->mode1_delay.mode = MODE1_SET;
break;
case 0xc: // ASTAT
return FALSE;
case 0xc: // ASTAT
// TODO: does this need delay?
if (data & ASTAT_FLAGS::AZ)
UML_MOV(block, ASTAT_AZ, 1);
if (data & ASTAT_FLAGS::AV)
UML_MOV(block, ASTAT_AV, 1);
if (data & ASTAT_FLAGS::AN)
UML_MOV(block, ASTAT_AN, 1);
if (data & ASTAT_FLAGS::AC)
UML_MOV(block, ASTAT_AC, 1);
if (data & ASTAT_FLAGS::AS)
UML_MOV(block, ASTAT_AS, 1);
if (data & ASTAT_FLAGS::AI)
UML_MOV(block, ASTAT_AI, 1);
if (data & ASTAT_FLAGS::MN)
UML_MOV(block, ASTAT_MN, 1);
if (data & ASTAT_FLAGS::MV)
UML_MOV(block, ASTAT_MV, 1);
if (data & ASTAT_FLAGS::MU)
UML_MOV(block, ASTAT_MU, 1);
if (data & ASTAT_FLAGS::MI)
UML_MOV(block, ASTAT_MI, 1);
if (data & ASTAT_FLAGS::AF)
UML_MOV(block, ASTAT_AF, 1);
if (data & ASTAT_FLAGS::SV)
UML_MOV(block, ASTAT_SV, 1);
if (data & ASTAT_FLAGS::SZ)
UML_MOV(block, ASTAT_SZ, 1);
if (data & ASTAT_FLAGS::SS)
UML_MOV(block, ASTAT_SS, 1);
if (data & ASTAT_FLAGS::BTF)
UML_MOV(block, ASTAT_BTF, 1);
if (data & ASTAT_FLAGS::FLG0)
UML_MOV(block, FLAG0, 1);
if (data & ASTAT_FLAGS::FLG1)
UML_MOV(block, FLAG1, 1);
if (data & ASTAT_FLAGS::FLG2)
UML_MOV(block, FLAG2, 1);
if (data & ASTAT_FLAGS::FLG3)
UML_MOV(block, FLAG3, 1);
if (data & 0xff000000)
{
UML_OR(block, mem(&m_core->astat_drc.cacc), mem(&m_core->astat_drc.cacc), (data >> 24));
}
break;
case 0xd: // IMASK
UML_OR(block, IMASK, IMASK, data);
break;
@ -2773,7 +2892,50 @@ int adsp21062_device::generate_opcode(drcuml_block *block, compiler_state *compi
compiler->mode1_delay.mode = MODE1_CLEAR;
break;
case 0xc: // ASTAT
return FALSE;
// TODO: does this need delay?
if (data & ASTAT_FLAGS::AZ)
UML_MOV(block, ASTAT_AZ, 0);
if (data & ASTAT_FLAGS::AV)
UML_MOV(block, ASTAT_AV, 0);
if (data & ASTAT_FLAGS::AN)
UML_MOV(block, ASTAT_AN, 0);
if (data & ASTAT_FLAGS::AC)
UML_MOV(block, ASTAT_AC, 0);
if (data & ASTAT_FLAGS::AS)
UML_MOV(block, ASTAT_AS, 0);
if (data & ASTAT_FLAGS::AI)
UML_MOV(block, ASTAT_AI, 0);
if (data & ASTAT_FLAGS::MN)
UML_MOV(block, ASTAT_MN, 0);
if (data & ASTAT_FLAGS::MV)
UML_MOV(block, ASTAT_MV, 0);
if (data & ASTAT_FLAGS::MU)
UML_MOV(block, ASTAT_MU, 0);
if (data & ASTAT_FLAGS::MI)
UML_MOV(block, ASTAT_MI, 0);
if (data & ASTAT_FLAGS::AF)
UML_MOV(block, ASTAT_AF, 0);
if (data & ASTAT_FLAGS::SV)
UML_MOV(block, ASTAT_SV, 0);
if (data & ASTAT_FLAGS::SZ)
UML_MOV(block, ASTAT_SZ, 0);
if (data & ASTAT_FLAGS::SS)
UML_MOV(block, ASTAT_SS, 0);
if (data & ASTAT_FLAGS::BTF)
UML_MOV(block, ASTAT_BTF, 0);
if (data & ASTAT_FLAGS::FLG0)
UML_MOV(block, FLAG0, 0);
if (data & ASTAT_FLAGS::FLG1)
UML_MOV(block, FLAG1, 0);
if (data & ASTAT_FLAGS::FLG2)
UML_MOV(block, FLAG2, 0);
if (data & ASTAT_FLAGS::FLG3)
UML_MOV(block, FLAG3, 0);
if (data & 0xff000000)
{
UML_AND(block, mem(&m_core->astat_drc.cacc), mem(&m_core->astat_drc.cacc), ~(data >> 24));
}
break;
case 0xd: // IMASK
UML_AND(block, IMASK, IMASK, ~data);
break;
@ -2961,7 +3123,77 @@ int adsp21062_device::generate_opcode(drcuml_block *block, compiler_state *compi
case 1: // compute / dreg <-> DM / dreg <-> PM |001|
{
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;
int compute = opcode & 0x7fffff;
bool temp_pm_dreg = false;
if (compute != 0 && pmd && desc->regout[0] & (1 << pm_dreg))
{
UML_MOV(block, mem(&m_core->dreg_temp), REG(pm_dreg));
temp_pm_dreg = true;
}
bool temp_dm_dreg = false;
if (compute != 0 && dmd && desc->regout[0] & (1 << dm_dreg))
{
UML_MOV(block, mem(&m_core->dreg_temp2), REG(dm_dreg));
temp_dm_dreg = true;
}
generate_compute(block, compiler, desc);
// PM transfer
if (pmd)
{
// dreg -> PM
if (temp_pm_dreg)
UML_MOV(block, I0, mem(&m_core->dreg_temp));
else
UML_MOV(block, I0, REG(pm_dreg));
UML_MOV(block, I1, PM_I(pmi));
UML_CALLH(block, *m_pm_write32);
UML_ADD(block, PM_I(pmi), PM_I(pmi), PM_M(pmm));
generate_update_circular_buffer(block, compiler, desc, 1, pmi);
}
else
{
// PM -> dreg
UML_MOV(block, I1, PM_I(pmi));
UML_CALLH(block, *m_pm_read32);
UML_MOV(block, REG(pm_dreg), I0);
UML_ADD(block, PM_I(pmi), PM_I(pmi), PM_M(pmm));
generate_update_circular_buffer(block, compiler, desc, 1, pmi);
}
// DM transfer
if (dmd)
{
// dreg -> DM
if (temp_dm_dreg)
UML_MOV(block, I0, mem(&m_core->dreg_temp2));
else
UML_MOV(block, I0, REG(dm_dreg));
UML_MOV(block, I1, DM_I(dmi));
UML_CALLH(block, *m_dm_write32);
UML_ADD(block, DM_I(dmi), DM_I(dmi), DM_M(dmm));
generate_update_circular_buffer(block, compiler, desc, 0, dmi);
}
else
{
// DM -> dreg
UML_MOV(block, I1, DM_I(dmi));
UML_CALLH(block, *m_dm_read32);
UML_MOV(block, REG(dm_dreg), I0);
UML_ADD(block, DM_I(dmi), DM_I(dmi), DM_M(dmm));
generate_update_circular_buffer(block, compiler, desc, 0, dmi);
}
return TRUE;
}
case 2: // compute / ureg <-> DM|PM, register modify |010|
@ -3184,7 +3416,31 @@ int adsp21062_device::generate_opcode(drcuml_block *block, compiler_state *compi
{
if (opcode & U64(0x100000000000)) // immediate data -> DM|PM |100|1|
{
return FALSE;
int i = (opcode >> 41) & 0x7;
int m = (opcode >> 38) & 0x7;
int g = (opcode >> 37) & 0x1;
UINT32 data = (UINT32)opcode;
if (g)
{
// PM
UML_MOV(block, I0, data);
UML_MOV(block, I1, PM_I(i));
UML_CALLH(block, *m_pm_write32);
UML_ADD(block, PM_I(i), PM_I(i), PM_M(m));
}
else
{
// DM
UML_MOV(block, I0, data);
UML_MOV(block, I1, DM_I(i));
UML_CALLH(block, *m_dm_write32);
UML_ADD(block, DM_I(i), DM_I(i), DM_M(m));
}
generate_update_circular_buffer(block, compiler, desc, g, i);
return TRUE;
}
else // immediate shift / dreg <-> DM|PM |100|0|
{
@ -3865,7 +4121,6 @@ void adsp21062_device::generate_compute(drcuml_block *block, compiler_state *com
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
@ -3873,7 +4128,6 @@ void adsp21062_device::generate_compute(drcuml_block *block, compiler_state *com
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 0xcd: // Rn = TRUNC Fx
@ -4147,6 +4401,19 @@ void adsp21062_device::generate_compute(drcuml_block *block, compiler_state *com
if (AI_CALC_REQUIRED) UML_MOV(block, ASTAT_AI, 0); // TODO
return;
case 0xb0: // Fn = ABS(Fx)
UML_FSCOPYI(block, F0, REG(rx));
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);
if (AC_CALC_REQUIRED) UML_MOV(block, ASTAT_AC, 0);
if (AS_CALC_REQUIRED) UML_MOV(block, ASTAT_AS, 0); // TODO
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));
@ -4377,6 +4644,36 @@ void adsp21062_device::generate_compute(drcuml_block *block, compiler_state *com
UML_ICOPYFS(block, REG(rn), F4);
return;
case 0xe3: // Fn = CLIP Fx BY Fy
{
code_label label_1 = compiler->labelnum++;
code_label label_2 = compiler->labelnum++;
UML_FSCOPYI(block, F0, REG(rx));
UML_FSCOPYI(block, F1, REG(ry));
UML_FSABS(block, F1, F1);
UML_FSCMP(block, F0, F1);
UML_JMPc(block, COND_C, label_1);
UML_FSCMP(block, F0, mem(&m_core->fp0));
UML_JMPc(block, COND_C, label_2);
UML_FSMOV(block, F0, F1);
UML_JMP(block, label_1);
UML_LABEL(block, label_2);
UML_FSNEG(block, F0, F1);
UML_LABEL(block, label_1);
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
UML_ICOPYFS(block, REG(rn), F0);
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:
{
@ -5162,8 +5459,7 @@ void adsp21062_device::generate_shift_imm(drcuml_block *block, compiler_state *c
int len = (data >> 6) & 0x3f;
switch (shiftop)
{
case 0x01: // ASHIFT Rx BY <data8>
{
case 0x11: // FDEP Rx BY <bit6>:<len6>
case 0x13: // FDEP Rx BY <bit6>:<len6> (SE)
case 0x1b: // Rn = Rn OR FDEP Rx BY <bit6>:<len6> (SE)
@ -5193,6 +5489,29 @@ void adsp21062_device::generate_shift_imm(drcuml_block *block, compiler_state *c
}
return;
case 0x01: // ASHIFT Rx BY <data8>
if (abs(shift) >= 32)
{
UML_MOV(block, REG(rn), 0);
UML_TEST(block, REG(rn), 0x80000000);
UML_MOVc(block, COND_NZ, REG(rn), 0xffffffff);
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_SAR(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 <data8>
if (shift < 0)
UML_ROR(block, REG(rn), REG(rx), (-shift) & 0x1f);

View File

@ -206,7 +206,7 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
int index = desc.pc & 0x1ffff;
desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
desc.targetpc = map[index].start_pc;
desc.userdata0 = map[index].start_pc;
if (map[index].looptype == LOOP_TYPE_COUNTER)
{
desc.userflags |= OP_USERFLAG_COUNTER_LOOP;
@ -294,6 +294,7 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
case 0x06: // direct jump|call |000|00110|
{
int j = (opcode >> 26) & 0x1;
int b = (opcode >> 39) & 0x1;
int cond = (opcode >> 33) & 0x1f;
UINT32 address = opcode & 0xffffff;
@ -306,12 +307,15 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
desc.targetpc = address;
desc.delayslots = (j) ? 2 : 0;
desc.userflags |= (b) ? OP_USERFLAG_CALL : 0;
break;
}
case 0x07: // direct jump|call |000|00111|
{
int j = (opcode >> 26) & 0x1;
int b = (opcode >> 39) & 0x1;
int cond = (opcode >> 33) & 0x1f;
UINT32 address = opcode & 0xffffff;
@ -324,12 +328,15 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
desc.targetpc = desc.pc + SIGN_EXTEND24(address);
desc.delayslots = (j) ? 2 : 0;
desc.userflags |= (b) ? OP_USERFLAG_CALL : 0;
break;
}
case 0x08: // indirect jump|call / compute |000|01000|
{
int j = (opcode >> 26) & 0x1;
int b = (opcode >> 39) & 0x1;
int pmi = (opcode >> 30) & 0x7;
int pmm = (opcode >> 27) & 0x7;
int cond = (opcode >> 33) & 0x1f;
@ -349,12 +356,15 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
desc.targetpc = BRANCH_TARGET_DYNAMIC;
desc.delayslots = (j) ? 2 : 0;
desc.userflags |= (b) ? OP_USERFLAG_CALL : 0;
break;
}
case 0x09: // indirect jump|call / compute |000|01001|
{
int j = (opcode >> 26) & 0x1;;
int j = (opcode >> 26) & 0x1;
int b = (opcode >> 39) & 0x1;
int cond = (opcode >> 33) & 0x1f;
if (!describe_compute(desc, opcode))
@ -370,6 +380,7 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
desc.targetpc = desc.pc + SIGN_EXTEND6((opcode >> 27) & 0x3f);
desc.delayslots = (j) ? 2 : 0;
desc.userflags |= (b) ? OP_USERFLAG_CALL : 0;
break;
}
@ -458,9 +469,20 @@ bool sharc_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
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);
*/
int jump_diff = loop.end_pc - loop.start_pc;
if (jump_diff >= 2)
loop.astat_check_pc = loop.end_pc - 2;
else if (jump_diff == 1)
loop.astat_check_pc = loop.end_pc - 1;
else
loop.astat_check_pc = loop.end_pc;
insert_loop(loop);
break;