summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/powerpc/ppcdrc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/powerpc/ppcdrc.cpp')
-rw-r--r--src/devices/cpu/powerpc/ppcdrc.cpp271
1 files changed, 221 insertions, 50 deletions
diff --git a/src/devices/cpu/powerpc/ppcdrc.cpp b/src/devices/cpu/powerpc/ppcdrc.cpp
index 120328a50a0..b9c7484f1f9 100644
--- a/src/devices/cpu/powerpc/ppcdrc.cpp
+++ b/src/devices/cpu/powerpc/ppcdrc.cpp
@@ -2,7 +2,7 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- ppcdrc.c
+ ppcdrc.cpp
Universal machine language-based PowerPC emulator.
@@ -18,12 +18,10 @@
#include "ppc.h"
#include "ppccom.h"
#include "ppcfe.h"
-#include "ppc_dasm.h"
#include "cpu/drcfe.h"
#include "cpu/drcuml.h"
#include "cpu/drcumlsh.h"
-#include "debugger.h"
@@ -118,7 +116,7 @@ inline void ppc_device::load_fast_iregs(drcuml_block &block)
{
int regnum;
- for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (regnum = 0; regnum < std::size(m_regmap); regnum++)
{
if (m_regmap[regnum].is_int_register())
{
@@ -137,7 +135,7 @@ void ppc_device::save_fast_iregs(drcuml_block &block)
{
int regnum;
- for (regnum = 0; regnum < ARRAY_LENGTH(m_regmap); regnum++)
+ for (regnum = 0; regnum < std::size(m_regmap); regnum++)
{
if (m_regmap[regnum].is_int_register())
{
@@ -149,7 +147,7 @@ void ppc_device::save_fast_iregs(drcuml_block &block)
inline void ppc_device::load_fast_fregs(drcuml_block &block)
{
- for (int regnum = 0; regnum < ARRAY_LENGTH(m_fdregmap); regnum++)
+ for (int regnum = 0; regnum < std::size(m_fdregmap); regnum++)
{
if (m_fdregmap[regnum].is_float_register())
{
@@ -160,7 +158,7 @@ inline void ppc_device::load_fast_fregs(drcuml_block &block)
void ppc_device::save_fast_fregs(drcuml_block &block)
{
- for (int regnum = 0; regnum < ARRAY_LENGTH(m_fdregmap); regnum++)
+ for (int regnum = 0; regnum < std::size(m_fdregmap); regnum++)
{
if (m_fdregmap[regnum].is_float_register())
{
@@ -268,7 +266,7 @@ void ppc_device::ppcdrc_set_options(uint32_t options)
void ppc_device::ppcdrc_add_fastram(offs_t start, offs_t end, uint8_t readonly, void *base)
{
- if (m_fastram_select < ARRAY_LENGTH(m_fastram))
+ if (m_fastram_select < std::size(m_fastram))
{
m_fastram[m_fastram_select].start = start;
m_fastram[m_fastram_select].end = end;
@@ -285,7 +283,7 @@ void ppc_device::ppcdrc_add_fastram(offs_t start, offs_t end, uint8_t readonly,
void ppc_device::ppcdrc_add_hotspot(offs_t pc, uint32_t opcode, uint32_t cycles)
{
- if (m_hotspot_select < ARRAY_LENGTH(m_hotspot))
+ if (m_hotspot_select < std::size(m_hotspot))
{
m_hotspot[m_hotspot_select].pc = pc;
m_hotspot[m_hotspot_select].opcode = opcode;
@@ -383,7 +381,7 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc)
const opcode_desc *desclist;
bool override = false;
- g_profiler.start(PROFILER_DRC_COMPILE);
+ auto profile = g_profiler.start(PROFILER_DRC_COMPILE);
/* get a description of this sequence */
desclist = m_drcfe->describe_code(pc);
@@ -467,7 +465,6 @@ void ppc_device::code_compile_block(uint8_t mode, offs_t pc)
/* end the sequence */
block.end();
- g_profiler.stop();
succeeded = true;
}
catch (drcuml_block::abort_compilation &)
@@ -778,11 +775,11 @@ void ppc_device::static_generate_tlb_mismatch()
UML_SHR(block, I1, I0, 12); // shr i1,i0,12
UML_LOAD(block, I2, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i2,[vtlb],i1,dword
UML_MOV(block, mem(&m_core->param0), I0); // mov [param0],i0
- UML_MOV(block, mem(&m_core->param1), TRANSLATE_FETCH); // mov [param1],TRANSLATE_FETCH
+ UML_MOV(block, mem(&m_core->param1), TR_FETCH); // mov [param1],TR_FETCH
UML_CALLC(block, (c_function)cfunc_ppccom_mismatch, this);
UML_CALLC(block, (c_function)cfunc_ppccom_tlb_fill, this); // callc tlbfill,ppc
UML_LOAD(block, I1, (void *)vtlb_table(), I1, SIZE_DWORD, SCALE_x4); // load i1,[vtlb],i1,dword
- UML_TEST(block, I1, VTLB_FETCH_ALLOWED); // test i1,VTLB_FETCH_ALLOWED
+ UML_TEST(block, I1, FETCH_ALLOWED); // test i1,FETCH_ALLOWED
UML_JMPc(block, COND_Z, isi = label++); // jmp isi,z
UML_CMP(block, I2, 0); // cmp i2,0
UML_JMPc(block, COND_NZ, exit = label++); // jmp exit,nz
@@ -1010,9 +1007,9 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
int ramnum;
if (mode & MODE_USER)
- translate_type = iswrite ? TRANSLATE_WRITE_USER : TRANSLATE_READ_USER;
+ translate_type = iswrite ? TR_UWRITE : TR_UREAD;
else
- translate_type = iswrite ? TRANSLATE_WRITE : TRANSLATE_READ;
+ translate_type = iswrite ? TR_WRITE : TR_READ;
/* begin generating */
drcuml_block &block(m_drcuml->begin_block(1024));
@@ -1024,32 +1021,30 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
/* check for unaligned accesses and break into two */
if (!ismasked && size != 1)
{
- /* in little-endian mode, anything misaligned generates an exception */
if ((mode & MODE_LITTLE_ENDIAN) || masked == nullptr || !(m_cap & PPCCAP_MISALIGNED))
{
+ /* in little-endian mode, anything misaligned generates an exception */
UML_TEST(block, I0, size - 1); // test i0,size-1
- UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
}
-
- /* in big-endian mode, it's more complicated */
else
{
- /* 8-byte accesses must be word-aligned */
+ /* in big-endian mode, it's more complicated */
if (size == 8)
{
+ /* 8-byte accesses must be word-aligned */
UML_TEST(block, I0, 3); // test i0,3
- UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
+ UML_JMPc(block, COND_NZ, alignex = label++); // jmp alignex,nz
/* word aligned accesses need to be broken up */
UML_TEST(block, I0, 4); // test i0,4
UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned, nz
}
-
- /* unaligned 2 and 4 byte accesses need to be broken up */
else
{
+ /* unaligned 2 and 4 byte accesses need to be broken up */
UML_TEST(block, I0, size - 1); // test i0,size-1
- UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned,nz
+ UML_JMPc(block, COND_NZ, unaligned = label++); // jmp unaligned,nz
}
}
}
@@ -1057,18 +1052,18 @@ void ppc_device::static_generate_memory_accessor(int mode, int size, int iswrite
/* general case: assume paging and perform a translation */
if (((m_cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION)) || (iswrite && (m_cap & PPCCAP_4XX) && (mode & MODE_PROTECTION)))
{
- UML_SHR(block, I3, I0, 12); // shr i3,i0,12
- UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4);// load i3,[vtlb],i3,dword
- UML_TEST(block, I3, (uint64_t)1 << translate_type); // test i3,1 << translate_type
- UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
- UML_LABEL(block, tlbreturn = label++); // tlbreturn:
- UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
+ UML_SHR(block, I3, I0, 12); // shr i3,i0,12
+ UML_LOAD(block, I3, (void *)vtlb_table(), I3, SIZE_DWORD, SCALE_x4); // load i3,[vtlb],i3,dword
+ UML_TEST(block, I3, (uint64_t)1 << translate_type); // test i3,1 << translate_type
+ UML_JMPc(block, COND_Z, tlbmiss = label++); // jmp tlbmiss,z
+ UML_LABEL(block, tlbreturn = label++); // tlbreturn:
+ UML_ROLINS(block, I0, I3, 0, 0xfffff000); // rolins i0,i3,0,0xfffff000
}
else if (m_cap & PPCCAP_4XX)
UML_AND(block, I0, I0, 0x7fffffff); // and i0,i0,0x7fffffff
UML_XOR(block, I0, I0, (mode & MODE_LITTLE_ENDIAN) ? (8 - size) : 0); // xor i0,i0,8-size
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0)
+ if (!debugger_enabled())
for (ramnum = 0; ramnum < PPC_MAX_FASTRAM; ramnum++)
if (m_fastram[ramnum].base != nullptr && (!iswrite || !m_fastram[ramnum].readonly))
{
@@ -1468,7 +1463,7 @@ void ppc_device::static_generate_lsw_entries(int mode)
char temp[20];
/* allocate a handle */
- sprintf(temp, "lsw%d", regnum);
+ snprintf(temp, 20, "lsw%d", regnum);
alloc_handle(m_drcuml.get(), &m_lsw[mode][regnum], temp);
UML_HANDLE(block, *m_lsw[mode][regnum]); // handle lsw<regnum>
UML_LABEL(block, regnum); // regnum:
@@ -1520,7 +1515,7 @@ void ppc_device::static_generate_stsw_entries(int mode)
char temp[20];
/* allocate a handle */
- sprintf(temp, "stsw%d", regnum);
+ snprintf(temp, 20, "stsw%d", regnum);
alloc_handle(m_drcuml.get(), &m_stsw[mode][regnum], temp);
UML_HANDLE(block, *m_stsw[mode][regnum]); // handle stsw<regnum>
UML_LABEL(block, regnum); // regnum:
@@ -1716,7 +1711,7 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta
}
/* if we are debugging, call the debugger */
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
+ if (debugger_enabled())
{
UML_MOV(block, mem(&m_core->pc), desc->pc); // mov [pc],desc->pc
save_fast_iregs(block); // <save fastregs>
@@ -1739,25 +1734,31 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta
if (PRINTF_MMU)
{
const char *text = "Compiler page fault @ %08X\n";
- UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ if (sizeof(uintptr_t) == 8)
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ else
+ UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
UML_MOV(block, mem(&m_core->arg0), desc->pc); // mov [arg0],desc->pc
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
UML_EXH(block, *m_tlb_mismatch, 0); // exh tlb_mismatch,0
}
- /* validate our TLB entry at this PC; if we fail, we need to handle it */
- if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION))
+ // validate our TLB entry at this PC; if we fail, we need to handle it
+ // TODO: this code is highly sus based on the PPC architecture manual, but I'll only disable for 601 for now
+ if ((desc->flags & OPFLAG_VALIDATE_TLB) && (m_core->mode & MODE_DATA_TRANSLATION) && !(m_cap & PPCCAP_601BAT))
{
const vtlb_entry *tlbtable = vtlb_table();
- /* if we currently have a valid TLB read entry, we just verify */
if (tlbtable[desc->pc >> 12] != 0)
{
if (PRINTF_MMU)
{
const char *text = "Checking TLB at @ %08X\n";
- UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ if (sizeof(uintptr_t) == 8)
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ else
+ UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
UML_MOV(block, mem(&m_core->arg0), desc->pc); // mov [arg0],desc->pc
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
@@ -1772,7 +1773,10 @@ void ppc_device::generate_sequence_instruction(drcuml_block &block, compiler_sta
if (PRINTF_MMU)
{
const char *text = "No valid TLB @ %08X\n";
- UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ if (sizeof(uintptr_t) == 8)
+ UML_DMOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
+ else
+ UML_MOV(block, mem(&m_core->format), (uintptr_t)text); // mov [format],text
UML_MOV(block, mem(&m_core->arg0), desc->pc); // mov [arg0],desc->pc
UML_CALLC(block, cfunc_printf_debug, this); // callc printf_debug
}
@@ -2018,6 +2022,23 @@ bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler,
// muls rd,rd,ra,simm
return true;
+ case 0x9: /* DOZI (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_AND(block, I0, op, 0xffff);
+ UML_CMP(block, R32(G_RA(op)), I0); // cmp ra, I0
+ UML_JMPc(block, COND_B, compiler->labelnum); // bae 0:
+
+ UML_XOR(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RD(op))); // xor rd, rd, rd (rd = 0)
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), I0);
+ UML_ADD(block, R32(G_RD(op)), R32(G_RD(op)), 0x1);
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ return true;
+
case 0x0e: /* ADDI */
UML_ADD(block, R32(G_RD(op)), R32Z(G_RA(op)), (int16_t)G_SIMM(op)); // add rd,ra,simm
return true;
@@ -2250,12 +2271,15 @@ bool ppc_device::generate_opcode(drcuml_block &block, compiler_state *compiler,
case 0x2e: /* LMW */
UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
UML_MOV(block, mem(&m_core->tempaddr), R32Z(G_RA(op))); // mov [tempaddr],ra
+
for (int regnum = G_RD(op); regnum < 32; regnum++)
{
UML_ADD(block, I0, mem(&m_core->tempaddr), (int16_t)G_SIMM(op) + 4 * (regnum - G_RD(op)));
// add i0,[tempaddr],simm + 4*(regnum-rd)
UML_CALLH(block, *m_read32align[m_core->mode]); // callh read32align
- UML_MOV(block, R32(regnum), I0); // mov regnum,i0
+
+ if (regnum != G_RA(op) || ((m_cap & PPCCAP_4XX) && regnum == 31))
+ UML_MOV(block, R32(regnum), I0); // mov regnum,i0
}
generate_update_cycles(block, compiler, desc->pc + 4, true); // <update cycles>
return true;
@@ -2672,10 +2696,19 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
case 0x0eb: /* MULLWx */
case 0x2eb: /* MULLWOx */
- UML_MULS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // muls rd,rd,ra,rb
+ // The flags are calculated based on the resulting 32-bit value from the 32x32=32 multiplication
+ // reference: example 4 https://www.ibm.com/docs/en/aix/7.2?topic=set-mullw-muls-multiply-low-word-instruction
+ UML_MULSLW(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // mulslw rd,ra,rb
generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), false);// <update flags>
return true;
+ case 0x6b: /* MUL (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_MULU(block, SPR32(SPR601_MQ), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // mulu mq, rd, ra, rb
+ generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV | XER_SO : 0), false); // <update flags>
+ return true;
+
case 0x1cb: /* DIVWUx */
case 0x3cb: /* DIVWUOx */
UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
@@ -2703,6 +2736,68 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
UML_LABEL(block, compiler->labelnum++); // 1:
return true;
+ case 0x14b: /* DIV (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_MOV(block, I0, R32(G_RA(op)));
+ UML_MOV(block, I1, SPR32(SPR601_MQ));
+ UML_DSHL(block, I0, I0, 32); // I0 = RA << 32
+ UML_DOR(block, I0, I0, I1); // I0 |= MQ
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // bne 0:
+
+ UML_MOV(block, R32(G_RD(op)), 0x0); // mov rd, #0
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1
+ UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1
+ }
+ if (op & M_RC)
+ {
+ UML_MOV(block, CR32(0), 0x2); // CR = EQ
+ UML_AND(block, CR32(0), CR32(0), ~0x1);
+ UML_OR(block, CR32(0), CR32(0), XERSO32);
+ }
+
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++);
+ UML_MOV(block, I1, R32(G_RB(op)));
+ UML_DSEXT(block, I1, I1, SIZE_DWORD);
+ UML_DDIVS(block, I0, I1, I0, I1);
+ UML_MOV(block, R32(G_RD(op)), I0);
+ UML_MOV(block, SPR32(SPR601_MQ), I1);
+ generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV | XER_SO : 0), false); // <update flags>
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ return true;
+
+ case 0x16b: /* DIVS (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
+ UML_JMPc(block, COND_NZ, compiler->labelnum); // bne 0:
+
+ UML_MOV(block, R32(G_RD(op)), 0x0); // mov rd, #0
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1
+ UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1
+ }
+ if (op & M_RC)
+ {
+ UML_MOV(block, CR32(0), 0x2); // CR = EQ
+ UML_AND(block, CR32(0), CR32(0), ~0x1);
+ UML_OR(block, CR32(0), CR32(0), XERSO32);
+ }
+
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_DIVS(block, R32(G_RD(op)), SPR32(SPR601_MQ), R32(G_RA(op)), R32(G_RB(op))); // divs rd,mq,ra,rb
+ generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), false); // <update flags>
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ return true;
+
case 0x1eb: /* DIVWx */
case 0x3eb: /* DIVWOx */
UML_CMP(block, R32(G_RB(op)), 0x0); // cmp rb, #0
@@ -2756,6 +2851,78 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
UML_LABEL(block, compiler->labelnum++); // 3:
return true;
+ case 0x108: /* DOZ (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra, rb
+ UML_JMPc(block, COND_B, compiler->labelnum); // bae 0:
+
+ UML_XOR(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RD(op))); // xor rd, rd, rd (rd = 0)
+ UML_JMP(block, compiler->labelnum+1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_ADD(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)));
+ UML_ADD(block, R32(G_RD(op)), R32(G_RD(op)), 0x1);
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ if (op & M_OE)
+ {
+ UML_OR(block, XERSO32, XERSO32, 0x1); // SO |= 1
+ UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), XER_OV); // OV |= 1
+ }
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RD(op)), ~0); // test rd,~0
+ generate_compute_flags(block, desc, op & M_RC, 0, false); // <update flags>
+ }
+ return true;
+
+ case 0x168: /* ABS (POWER) */
+ case 0x1e8: /* NABS (POWER) */
+ assert(m_cap & PPCCAP_LEGACY_POWER);
+
+ // is rA already the correct sign (positive for ABS, negative for NABS)?
+ UML_CMP(block, R32(G_RA(op)), 0);
+ if (op & 0x080)
+ {
+ UML_JMPc(block, COND_L, compiler->labelnum); // bl 0:
+ }
+ else
+ {
+ UML_JMPc(block, COND_GE, compiler->labelnum); // bge 0:
+ }
+
+ UML_SUB(block, I0, 0, R32(G_RA(op))); // sub 0, ra (make positive)
+ UML_JMP(block, compiler->labelnum + 1); // jmp 1:
+
+ UML_LABEL(block, compiler->labelnum++); // 0:
+ UML_MOV(block, I0, R32(G_RA(op)));
+
+ UML_LABEL(block, compiler->labelnum++); // 1:
+ UML_MOV(block, R32(G_RD(op)), I0); // mov rd, I0
+ if (op & M_RC)
+ {
+ UML_GETFLGS(block, I0, FLAG_Z | FLAG_V | FLAG_C | FLAG_S); // getflgs i0,zvcs
+ UML_LOAD(block, I0, m_cmp_cr_table, I0, SIZE_DWORD, SCALE_x4); // load i0,cmp_cr_table,i0,dword
+ }
+ if (op & M_OE)
+ {
+ UML_OR(block, CR32(G_CRFD(op)), I0, XERSO32); // or [crn],i0,[xerso]
+ }
+ return true;
+
+ case 0x21d: /* MASKIR (POWER) */
+ UML_AND(block, I0, R32(G_RS(op)), R32(G_RB(op))); // and i0, rs, rb
+ UML_XOR(block, I1, R32(G_RB(op)), 0xffffffff); // xor i1, rb, 0xffffffff
+ UML_AND(block, I1, I1, R32(G_RA(op))); // and i1, i1, ra
+ UML_OR(block, R32(G_RA(op)), I0, I1); // or ra, i0, i1
+ if (op & M_RC)
+ {
+ UML_GETFLGS(block, R32(G_RA(op)), FLAG_Z | FLAG_V | FLAG_C | FLAG_S); // getflgs i0,zvcs
+ UML_LOAD(block, I0, m_cmp_cr_table, I0, SIZE_DWORD, SCALE_x4); // load i0,cmp_cr_table,i0,dword
+ }
+ return true;
+
case 0x01c: /* ANDx */
UML_AND(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // and ra,rs,rb
generate_compute_flags(block, desc, op & M_RC, 0, false); // <update flags>
@@ -3066,9 +3233,11 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
case 0x215: /* LSWX */
UML_ADD(block, mem(&m_core->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
- UML_AND(block, mem(&m_core->swcount), SPR32(SPR_XER), 0x7f); // and [swcount],[xer],0x7f
- UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), mem(&m_core->swcount));// sub icount,icount,[swcount]
- UML_CALLHc(block, COND_NZ, *m_lsw[m_core->mode][G_RD(op)]); // call lsw[rd],nz
+ UML_AND(block, I0, SPR32(SPR_XER), 0x7f); // and i0,[xer],0x7f
+ UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I0);// sub icount,icount,i0
+ UML_MOV(block, mem(&m_core->swcount), I0); // mov [swcount],i0
+ UML_TEST(block, I0, I0); // test i0,i0
+ UML_CALLHc(block, COND_NZ, *m_lsw[m_core->mode][G_RD(op)]); // call lsw[rd]
generate_update_cycles(block, compiler, desc->pc + 4, true); // <update cycles>
return true;
@@ -3218,8 +3387,10 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
case 0x295: /* STSWX */
UML_ADD(block, mem(&m_core->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
- UML_AND(block, mem(&m_core->swcount), SPR32(SPR_XER), 0x7f); // and [swcount],[xer],0x7f
- UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), mem(&m_core->swcount));// sub icount,icount,[swcount]
+ UML_AND(block, I0, SPR32(SPR_XER), 0x7f); // and i0,[xer],0x7f
+ UML_SUB(block, mem(&m_core->icount), mem(&m_core->icount), I0);// sub icount,icount,i0
+ UML_MOV(block, mem(&m_core->swcount), I0); // mov [swcount],i0
+ UML_TEST(block, I0, I0); // test i0,i0
UML_CALLHc(block, COND_NZ, *m_stsw[m_core->mode][G_RD(op)]); // call stsw[rd]
generate_update_cycles(block, compiler, desc->pc + 4, true); // <update cycles>
return true;
@@ -3405,7 +3576,7 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
return true;
case 0x200: /* MCRXR */
- UML_ROLAND(block, I0, SPR32(SPR_XER), 28, 0x0f); // roland i0,[xer],28,0x0f
+ UML_ROLAND(block, I0, SPR32(SPR_XER), 4, 0x0f); // roland i0,[xer],4,0x0f
UML_SHL(block, I1, XERSO32, 3); // shl i1,[xerso],3
UML_OR(block, CR32(G_CRFD(op)), I0, I1); // or [crd],i0,i1
UML_AND(block, SPR32(SPR_XER), SPR32(SPR_XER), ~0xf0000000); // and [xer],[xer],~0xf0000000
@@ -3793,7 +3964,7 @@ void ppc_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32
if (m_drcuml->logging())
{
std::ostringstream stream;
- powerpc_disassembler::dasm_one(stream, pc, op);
+ m_dasm.dasm_one(stream, pc, op);
block.append_comment("%08X: %s", pc, stream.str()); // comment
}
}
@@ -3982,7 +4153,7 @@ void ppc_device::log_opcode_desc(const opcode_desc *desclist, int indent)
if (desclist->flags & OPFLAG_VIRTUAL_NOOP)
buffer << "<virtual nop>";
else
- powerpc_disassembler::dasm_one(buffer, desclist->pc, desclist->opptr.l[0]);
+ m_dasm.dasm_one(buffer, desclist->pc, desclist->opptr.l[0]);
}
else
buffer << "???";