* minor flags optimizations:
    - broke CR into several individual bits of state
    - extracted the SO bit from XER into its own state
This commit is contained in:
Aaron Giles 2008-06-09 16:18:19 +00:00
parent 7ebd242d8b
commit 748e83917a
3 changed files with 311 additions and 245 deletions

View File

@ -105,6 +105,61 @@ INLINE int tlb_entry_allocate(powerpc_state *ppc, int entrynum, offs_t address,
}
/*-------------------------------------------------
get_cr - return the current CR value
-------------------------------------------------*/
INLINE UINT32 get_cr(powerpc_state *ppc)
{
return ((ppc->cr[0] & 0x0f) << 28) |
((ppc->cr[1] & 0x0f) << 24) |
((ppc->cr[2] & 0x0f) << 20) |
((ppc->cr[3] & 0x0f) << 16) |
((ppc->cr[4] & 0x0f) << 12) |
((ppc->cr[5] & 0x0f) << 8) |
((ppc->cr[6] & 0x0f) << 4) |
((ppc->cr[7] & 0x0f) << 0);
}
/*-------------------------------------------------
set_cr - set the current CR value
-------------------------------------------------*/
INLINE void set_cr(powerpc_state *ppc, UINT32 value)
{
ppc->cr[0] = value >> 28;
ppc->cr[1] = value >> 24;
ppc->cr[2] = value >> 20;
ppc->cr[3] = value >> 16;
ppc->cr[4] = value >> 12;
ppc->cr[5] = value >> 8;
ppc->cr[6] = value >> 4;
ppc->cr[7] = value >> 0;
}
/*-------------------------------------------------
get_xer - return the current XER value
-------------------------------------------------*/
INLINE UINT32 get_xer(powerpc_state *ppc)
{
return ppc->spr[SPR_XER] | (ppc->xerso << 31);
}
/*-------------------------------------------------
set_xer - set the current XER value
-------------------------------------------------*/
INLINE void set_xer(powerpc_state *ppc, UINT32 value)
{
ppc->spr[SPR_XER] = value & ~XER_SO;
ppc->xerso = value >> 31;
}
/*-------------------------------------------------
get_timebase - return the current timebase
value
@ -984,10 +1039,10 @@ void ppccom_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + PPC_PC: ppc->pc = info->i; break;
case CPUINFO_INT_REGISTER + PPC_MSR: ppc->msr = info->i; break;
case CPUINFO_INT_REGISTER + PPC_CR: ppc->cr = info->i; break;
case CPUINFO_INT_REGISTER + PPC_CR: set_cr(ppc, info->i); break;
case CPUINFO_INT_REGISTER + PPC_LR: ppc->spr[SPR_LR] = info->i; break;
case CPUINFO_INT_REGISTER + PPC_CTR: ppc->spr[SPR_CTR] = info->i; break;
case CPUINFO_INT_REGISTER + PPC_XER: ppc->spr[SPR_XER] = info->i; break;
case CPUINFO_INT_REGISTER + PPC_XER: set_xer(ppc, info->i); break;
case CPUINFO_INT_REGISTER + PPC_SRR0: ppc->spr[SPROEA_SRR0] = info->i; break;
case CPUINFO_INT_REGISTER + PPC_SRR1: ppc->spr[SPROEA_SRR1] = info->i; break;
case CPUINFO_INT_REGISTER + PPC_SPRG0: ppc->spr[SPROEA_SPRG0] = info->i; break;
@ -1074,10 +1129,10 @@ void ppccom_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + PPC_PC: info->i = ppc->pc; break;
case CPUINFO_INT_REGISTER + PPC_MSR: info->i = ppc->msr; break;
case CPUINFO_INT_REGISTER + PPC_CR: info->i = ppc->cr; break;
case CPUINFO_INT_REGISTER + PPC_CR: info->i = get_cr(ppc); break;
case CPUINFO_INT_REGISTER + PPC_LR: info->i = ppc->spr[SPR_LR]; break;
case CPUINFO_INT_REGISTER + PPC_CTR: info->i = ppc->spr[SPR_CTR]; break;
case CPUINFO_INT_REGISTER + PPC_XER: info->i = ppc->spr[SPR_XER]; break;
case CPUINFO_INT_REGISTER + PPC_XER: info->i = get_xer(ppc); break;
case CPUINFO_INT_REGISTER + PPC_SRR0: info->i = ppc->spr[SPROEA_SRR0]; break;
case CPUINFO_INT_REGISTER + PPC_SRR1: info->i = ppc->spr[SPROEA_SRR1]; break;
case CPUINFO_INT_REGISTER + PPC_SPRG0: info->i = ppc->spr[SPROEA_SPRG0]; break;
@ -1150,10 +1205,10 @@ void ppccom_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
case CPUINFO_STR_REGISTER + PPC_PC: sprintf(info->s, "PC: %08X", ppc->pc); break;
case CPUINFO_STR_REGISTER + PPC_MSR: sprintf(info->s, "MSR:%08X", ppc->msr); break;
case CPUINFO_STR_REGISTER + PPC_CR: sprintf(info->s, "CR: %08X", ppc->cr); break;
case CPUINFO_STR_REGISTER + PPC_CR: sprintf(info->s, "CR: %08X", get_cr(ppc)); break;
case CPUINFO_STR_REGISTER + PPC_LR: sprintf(info->s, "LR: %08X", ppc->spr[SPR_LR]); break;
case CPUINFO_STR_REGISTER + PPC_CTR: sprintf(info->s, "CTR:%08X", ppc->spr[SPR_CTR]); break;
case CPUINFO_STR_REGISTER + PPC_XER: sprintf(info->s, "XER:%08X", ppc->spr[SPR_XER]); break;
case CPUINFO_STR_REGISTER + PPC_XER: sprintf(info->s, "XER:%08X", get_xer(ppc)); break;
case CPUINFO_STR_REGISTER + PPC_SRR0: sprintf(info->s, "SRR0: %08X", ppc->spr[SPROEA_SRR0]); break;
case CPUINFO_STR_REGISTER + PPC_SRR1: sprintf(info->s, "SRR1: %08X", ppc->spr[SPROEA_SRR1]); break;
case CPUINFO_STR_REGISTER + PPC_SPRG0: sprintf(info->s, "SPRG0: %08X", ppc->spr[SPROEA_SPRG0]); break;

View File

@ -13,14 +13,6 @@
#include "ppc.h"
/***************************************************************************
WIDE-SCALE CONTROLS
***************************************************************************/
#define SIMULATE_603_TLB (0)
/***************************************************************************
CONSTANTS
***************************************************************************/
@ -524,7 +516,8 @@ struct _powerpc_state
int icount;
UINT32 r[32];
double f[32];
UINT32 cr;
UINT32 cr[8];
UINT32 xerso;
UINT32 fpscr;
UINT32 msr;
UINT32 sr[16];

View File

@ -90,9 +90,10 @@ extern offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op);
#define R32(reg) ppc->impstate->regmap[reg].type, ppc->impstate->regmap[reg].value
#define R32Z(reg) (((reg) == 0) ? DRCUML_PTYPE_IMMEDIATE : ppc->impstate->regmap[reg].type), (((reg) == 0) ? 0 : ppc->impstate->regmap[reg].value)
#define F64(reg) ppc->impstate->fdregmap[reg].type, ppc->impstate->fdregmap[reg].value
#define CR32 MEM(&ppc->cr)
#define CR32(reg) MEM(&ppc->cr[reg])
#define FPSCR32 MEM(&ppc->fpscr)
#define MSR32 MEM(&ppc->msr)
#define XERSO32 MEM(&ppc->xerso)
#define SR32(reg) MEM(&ppc->sr[reg])
#define SPR32(reg) MEM(&ppc->spr[reg])
@ -184,10 +185,10 @@ struct _ppcimp_state
/* tables */
UINT8 fpmode[4]; /* FPU mode table */
UINT32 sz_cr_table[32]; /* SZ CR table */
UINT32 cmp_cr_table[32]; /* CMP CR table */
UINT32 cmpl_cr_table[32]; /* CMPL CR table */
UINT32 fcmp_cr_table[32]; /* FCMP CR table */
UINT8 sz_cr_table[32]; /* SZ CR table */
UINT8 cmp_cr_table[32]; /* CMP CR table */
UINT8 cmpl_cr_table[32]; /* CMPL CR table */
UINT8 fcmp_cr_table[32]; /* FCMP CR table */
/* internal stuff */
UINT8 cache_dirty; /* true if we need to flush the cache */
@ -289,151 +290,151 @@ static const UINT8 fpmode_source[4] =
};
/* flag lookup table for SZ */
static const UINT32 sz_cr_table_source[32] =
static const UINT8 sz_cr_table_source[32] =
{
/* ..... */ 0x40000000,
/* ....C */ 0x42000000,
/* ...V. */ 0x4c000000,
/* ...VC */ 0x4e000000,
/* ..Z.. */ 0x20000000,
/* ..Z.C */ 0x22000000,
/* ..ZV. */ 0x2c000000,
/* ..ZVC */ 0x2e000000,
/* .S... */ 0x80000000,
/* .S..C */ 0x82000000,
/* .S.V. */ 0x8c000000,
/* .S.VC */ 0x8e000000,
/* .SZ.. */ 0x20000000,
/* .SZ.C */ 0x22000000,
/* .SZV. */ 0x2c000000,
/* .SZVC */ 0x2e000000,
/* U.... */ 0x40000000,
/* U...C */ 0x42000000,
/* U..V. */ 0x4c000000,
/* U..VC */ 0x4e000000,
/* U.Z.. */ 0x20000000,
/* U.Z.C */ 0x22000000,
/* U.ZV. */ 0x2c000000,
/* U.ZVC */ 0x2e000000,
/* US... */ 0x80000000,
/* US..C */ 0x82000000,
/* US.V. */ 0x8c000000,
/* US.VC */ 0x8e000000,
/* USZ.. */ 0x20000000,
/* USZ.C */ 0x22000000,
/* USZV. */ 0x2c000000,
/* USZVC */ 0x2e000000
/* ..... */ 0x4,
/* ....C */ 0x4,
/* ...V. */ 0x4,
/* ...VC */ 0x4,
/* ..Z.. */ 0x2,
/* ..Z.C */ 0x2,
/* ..ZV. */ 0x2,
/* ..ZVC */ 0x2,
/* .S... */ 0x8,
/* .S..C */ 0x8,
/* .S.V. */ 0x8,
/* .S.VC */ 0x8,
/* .SZ.. */ 0x2,
/* .SZ.C */ 0x2,
/* .SZV. */ 0x2,
/* .SZVC */ 0x2,
/* U.... */ 0x4,
/* U...C */ 0x4,
/* U..V. */ 0x4,
/* U..VC */ 0x4,
/* U.Z.. */ 0x2,
/* U.Z.C */ 0x2,
/* U.ZV. */ 0x2,
/* U.ZVC */ 0x2,
/* US... */ 0x8,
/* US..C */ 0x8,
/* US.V. */ 0x8,
/* US.VC */ 0x8,
/* USZ.. */ 0x2,
/* USZ.C */ 0x2,
/* USZV. */ 0x2,
/* USZVC */ 0x2
};
/* flag lookup table for CMP */
static const UINT32 cmp_cr_table_source[32] =
static const UINT8 cmp_cr_table_source[32] =
{
/* ..... */ 0x44444444,
/* ....C */ 0x44444444,
/* ...V. */ 0x88888888,
/* ...VC */ 0x88888888,
/* ..Z.. */ 0x22222222,
/* ..Z.C */ 0x22222222,
/* ..ZV. */ 0x22222222,
/* ..ZVC */ 0x22222222,
/* .S... */ 0x88888888,
/* .S..C */ 0x88888888,
/* .S.V. */ 0x44444444,
/* .S.VC */ 0x44444444,
/* .SZ.. */ 0x22222222,
/* .SZ.C */ 0x22222222,
/* .SZV. */ 0x22222222,
/* .SZVC */ 0x22222222,
/* U.... */ 0x44444444,
/* U...C */ 0x44444444,
/* U..V. */ 0x88888888,
/* U..VC */ 0x88888888,
/* U.Z.. */ 0x22222222,
/* U.Z.C */ 0x22222222,
/* U.ZV. */ 0x22222222,
/* U.ZVC */ 0x22222222,
/* US... */ 0x88888888,
/* US..C */ 0x88888888,
/* US.V. */ 0x44444444,
/* US.VC */ 0x44444444,
/* USZ.. */ 0x22222222,
/* USZ.C */ 0x22222222,
/* USZV. */ 0x22222222,
/* USZVC */ 0x22222222
/* ..... */ 0x4,
/* ....C */ 0x4,
/* ...V. */ 0x8,
/* ...VC */ 0x8,
/* ..Z.. */ 0x2,
/* ..Z.C */ 0x2,
/* ..ZV. */ 0x2,
/* ..ZVC */ 0x2,
/* .S... */ 0x8,
/* .S..C */ 0x8,
/* .S.V. */ 0x4,
/* .S.VC */ 0x4,
/* .SZ.. */ 0x2,
/* .SZ.C */ 0x2,
/* .SZV. */ 0x2,
/* .SZVC */ 0x2,
/* U.... */ 0x4,
/* U...C */ 0x4,
/* U..V. */ 0x8,
/* U..VC */ 0x8,
/* U.Z.. */ 0x2,
/* U.Z.C */ 0x2,
/* U.ZV. */ 0x2,
/* U.ZVC */ 0x2,
/* US... */ 0x8,
/* US..C */ 0x8,
/* US.V. */ 0x4,
/* US.VC */ 0x4,
/* USZ.. */ 0x2,
/* USZ.C */ 0x2,
/* USZV. */ 0x2,
/* USZVC */ 0x2
};
/* flag lookup table for CMPL */
static const UINT32 cmpl_cr_table_source[32] =
static const UINT8 cmpl_cr_table_source[32] =
{
/* ..... */ 0x44444444,
/* ....C */ 0x88888888,
/* ...V. */ 0x44444444,
/* ...VC */ 0x88888888,
/* ..Z.. */ 0x22222222,
/* ..Z.C */ 0x22222222,
/* ..ZV. */ 0x22222222,
/* ..ZVC */ 0x22222222,
/* .S... */ 0x44444444,
/* .S..C */ 0x88888888,
/* .S.V. */ 0x44444444,
/* .S.VC */ 0x88888888,
/* .SZ.. */ 0x22222222,
/* .SZ.C */ 0x22222222,
/* .SZV. */ 0x22222222,
/* .SZVC */ 0x22222222,
/* U.... */ 0x44444444,
/* U...C */ 0x88888888,
/* U..V. */ 0x44444444,
/* U..VC */ 0x88888888,
/* U.Z.. */ 0x22222222,
/* U.Z.C */ 0x22222222,
/* U.ZV. */ 0x22222222,
/* U.ZVC */ 0x22222222,
/* US... */ 0x44444444,
/* US..C */ 0x88888888,
/* US.V. */ 0x44444444,
/* US.VC */ 0x88888888,
/* USZ.. */ 0x22222222,
/* USZ.C */ 0x22222222,
/* USZV. */ 0x22222222,
/* USZVC */ 0x22222222
/* ..... */ 0x4,
/* ....C */ 0x8,
/* ...V. */ 0x4,
/* ...VC */ 0x8,
/* ..Z.. */ 0x2,
/* ..Z.C */ 0x2,
/* ..ZV. */ 0x2,
/* ..ZVC */ 0x2,
/* .S... */ 0x4,
/* .S..C */ 0x8,
/* .S.V. */ 0x4,
/* .S.VC */ 0x8,
/* .SZ.. */ 0x2,
/* .SZ.C */ 0x2,
/* .SZV. */ 0x2,
/* .SZVC */ 0x2,
/* U.... */ 0x4,
/* U...C */ 0x8,
/* U..V. */ 0x4,
/* U..VC */ 0x8,
/* U.Z.. */ 0x2,
/* U.Z.C */ 0x2,
/* U.ZV. */ 0x2,
/* U.ZVC */ 0x2,
/* US... */ 0x4,
/* US..C */ 0x8,
/* US.V. */ 0x4,
/* US.VC */ 0x8,
/* USZ.. */ 0x2,
/* USZ.C */ 0x2,
/* USZV. */ 0x2,
/* USZVC */ 0x2
};
/* flag lookup table for FCMP */
static const UINT32 fcmp_cr_table_source[32] =
static const UINT8 fcmp_cr_table_source[32] =
{
/* ..... */ 0x44444444,
/* ....C */ 0x88888888,
/* ...V. */ 0x44444444,
/* ...VC */ 0x88888888,
/* ..Z.. */ 0x22222222,
/* ..Z.C */ 0xaaaaaaaa,
/* ..ZV. */ 0x22222222,
/* ..ZVC */ 0xaaaaaaaa,
/* .S... */ 0x44444444,
/* .S..C */ 0x88888888,
/* .S.V. */ 0x44444444,
/* .S.VC */ 0x88888888,
/* .SZ.. */ 0x22222222,
/* .SZ.C */ 0xaaaaaaaa,
/* .SZV. */ 0x22222222,
/* .SZVC */ 0xaaaaaaaa,
/* U.... */ 0x55555555,
/* U...C */ 0x99999999,
/* U..V. */ 0x55555555,
/* U..VC */ 0x99999999,
/* U.Z.. */ 0x33333333,
/* U.Z.C */ 0xbbbbbbbb,
/* U.ZV. */ 0x33333333,
/* U.ZVC */ 0xbbbbbbbb,
/* US... */ 0x55555555,
/* US..C */ 0x99999999,
/* US.V. */ 0x55555555,
/* US.VC */ 0x99999999,
/* USZ.. */ 0x33333333,
/* USZ.C */ 0xbbbbbbbb,
/* USZV. */ 0x33333333,
/* USZVC */ 0xbbbbbbbb
/* ..... */ 0x4,
/* ....C */ 0x8,
/* ...V. */ 0x4,
/* ...VC */ 0x8,
/* ..Z.. */ 0x2,
/* ..Z.C */ 0xa,
/* ..ZV. */ 0x2,
/* ..ZVC */ 0xa,
/* .S... */ 0x4,
/* .S..C */ 0x8,
/* .S.V. */ 0x4,
/* .S.VC */ 0x8,
/* .SZ.. */ 0x2,
/* .SZ.C */ 0xa,
/* .SZV. */ 0x2,
/* .SZVC */ 0xa,
/* U.... */ 0x5,
/* U...C */ 0x9,
/* U..V. */ 0x5,
/* U..VC */ 0x9,
/* U.Z.. */ 0x3,
/* U.Z.C */ 0xb,
/* U.ZV. */ 0x3,
/* U.ZVC */ 0xb,
/* US... */ 0x5,
/* US..C */ 0x9,
/* US.V. */ 0x5,
/* US.VC */ 0x9,
/* USZ.. */ 0x3,
/* USZ.C */ 0xb,
/* USZV. */ 0x3,
/* USZVC */ 0xb
};
@ -598,7 +599,12 @@ static void ppcdrc_init(powerpc_flavor flavor, UINT8 cap, int tb_divisor, int cl
sprintf(buf, "fpr%d", regnum);
drcuml_symbol_add(ppc->impstate->drcuml, &ppc->f[regnum], sizeof(ppc->r[regnum]), buf);
}
drcuml_symbol_add(ppc->impstate->drcuml, &ppc->cr, sizeof(ppc->cr), "cr");
for (regnum = 0; regnum < 8; regnum++)
{
char buf[10];
sprintf(buf, "cr%d", regnum);
drcuml_symbol_add(ppc->impstate->drcuml, &ppc->cr[regnum], sizeof(ppc->cr[regnum]), buf);
}
drcuml_symbol_add(ppc->impstate->drcuml, &ppc->fpscr, sizeof(ppc->fpscr), "fpscr");
drcuml_symbol_add(ppc->impstate->drcuml, &ppc->msr, sizeof(ppc->msr), "msr");
drcuml_symbol_add(ppc->impstate->drcuml, &ppc->sr, sizeof(ppc->sr), "sr");
@ -1316,7 +1322,7 @@ static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int
else if (exception == EXCEPTION_DTLBMISSL)
UML_OR(block, SPR32(SPROEA_SRR1), SPR32(SPROEA_SRR1), IMM(0x00010000)); // or [srr1],0x00010000
if (exception == EXCEPTION_ITLBMISS || exception == EXCEPTION_DTLBMISSL || exception == EXCEPTION_DTLBMISSS)
UML_ROLINS(block, SPR32(SPROEA_SRR1), CR32, IMM(0), IMM(CRMASK(0))); // rolins [srr1],[cr],0,crmask(0)
UML_ROLINS(block, SPR32(SPROEA_SRR1), CR32(0), IMM(28), IMM(CRMASK(0))); // rolins [srr1],[cr0],28,crmask(0)
}
/* update MSR */
@ -1484,7 +1490,7 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
if (((ppc->cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION)) || (iswrite && (ppc->cap & PPCCAP_4XX) && (mode & MODE_PROTECTION)))
{
UML_SHR(block, IREG(3), IREG(0), IMM(12)); // shr i3,i0,12
UML_LOAD(block, IREG(3), ppc->tlb_table, IREG(3), DWORD); // load i3,[tlb_table],i3,dword
UML_LOAD(block, IREG(3), ppc->tlb_table, IREG(3), BYTE); // load i3,[tlb_table],i3,byte
UML_TEST(block, IREG(3), IMM(iswrite ? TLB_WRITE : TLB_READ)); // test i3,iswrite ? TLB_WRITE : TLB_READ
UML_JMPc(block, IF_Z, tlbmiss = label++); // jmp tlbmiss,z
UML_LABEL(block, tlbreturn = label++); // tlbreturn:
@ -1779,7 +1785,7 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
UML_CMP(block, MEM(&ppc->param0), IMM(1)); // cmp [param0],1
UML_JMPc(block, IF_A, dsi = label++); // jmp dsi,A
UML_SHR(block, IREG(3), IREG(0), IMM(12)); // shr i3,i0,12
UML_LOAD(block, IREG(3), ppc->tlb_table, IREG(3), DWORD); // load i3,[tlb_table],i3,dword
UML_LOAD(block, IREG(3), ppc->tlb_table, IREG(3), BYTE); // load i3,[tlb_table],i3,byte
UML_JMP(block, tlbreturn); // jmp tlbreturn
UML_LABEL(block, dsi); // dsi:
@ -2196,7 +2202,6 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c
static void generate_compute_flags(drcuml_block *block, int updatecr, UINT32 xermask, int invertcarry)
{
int xerflags = ((xermask & XER_OV) ? DRCUML_FLAG_V : 0) | ((xermask & XER_CA) ? DRCUML_FLAG_C : 0);
UINT32 xermask_so = xermask | ((xermask & XER_OV) ? XER_SO : 0);
/* easy case: nothing to do */
if (!updatecr && xermask == 0)
@ -2205,13 +2210,9 @@ static void generate_compute_flags(drcuml_block *block, int updatecr, UINT32 xer
/* semi-easy case: crfield only */
if (xermask == 0)
{
UML_MOV(block, IREG(0), CR32); // mov i0,cr32
UML_GETFLGS(block, IREG(1), DRCUML_FLAG_S | DRCUML_FLAG_Z); // getflgs i1,sz
UML_LOAD(block, IREG(1), ppc->impstate->sz_cr_table, IREG(1), DWORD); // load i1,sz_cr_table,i1,dword
UML_ROLINS(block, IREG(0), IREG(1), IMM(0), IMM(CRMASK(0))); // rolins i0,i1,0,crmask(field)
UML_AND(block, IREG(1), SPR32(SPR_XER), IMM(XER_SO)); // and i1,[xer],XER_SO
UML_SHR(block, IREG(1), IREG(1), IMM(3)); // shr i1,i1,3
UML_OR(block, CR32, IREG(0), IREG(1)); // or [cr],i0,i1
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_S | DRCUML_FLAG_Z); // getflgs i0,sz
UML_LOAD(block, IREG(0), ppc->impstate->sz_cr_table, IREG(0), BYTE); // load i0,sz_cr_table,i0,byte
UML_OR(block, CR32(0), IREG(0), XERSO32); // or [cr0],i0,[xerso]
return;
}
@ -2220,14 +2221,12 @@ static void generate_compute_flags(drcuml_block *block, int updatecr, UINT32 xer
{
if (xermask & XER_OV)
{
UML_MOV(block, IREG(0), SPR32(SPR_XER)); // mov i0,[xer]
UML_GETFLGS(block, IREG(1), xerflags); // getflgs i1,xerflags
UML_GETFLGS(block, IREG(0), xerflags); // getflgs i0,xerflags
if (invertcarry && (xermask & XER_CA))
UML_XOR(block, IREG(1), IREG(1), IMM(DRCUML_FLAG_C)); // xor i1,i1,FLAG_C
UML_ROLINS(block, IREG(0), IREG(1), IMM(29), IMM(xermask)); // rolins i0,i1,29,crmask(xermask)
UML_AND(block, IREG(1), SPR32(SPR_XER), IMM(XER_OV)); // and i1,[xer],XER_OV
UML_SHL(block, IREG(1), IREG(1), IMM(1)); // shl i1,i1,1
UML_OR(block, SPR32(SPR_XER), IREG(0), IREG(1)); // or [xer],i0,i1
UML_XOR(block, IREG(0), IREG(0), IMM(DRCUML_FLAG_C)); // xor i0,i0,FLAG_C
UML_ROLINS(block, SPR32(SPR_XER), IREG(0), IMM(29), IMM(xermask)); // rolins [xer],i0,29,xermask
UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
UML_OR(block, XERSO32, XERSO32, IREG(0)); // or [xerso],i0
}
else
{
@ -2238,19 +2237,14 @@ static void generate_compute_flags(drcuml_block *block, int updatecr, UINT32 xer
}
/* tricky case: both */
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_S | DRCUML_FLAG_Z | xerflags); // getflgs i0,sz|xerflags
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_S | DRCUML_FLAG_Z | xerflags); // getflgs i0,SZ | xerflags
UML_LOAD(block, IREG(1), ppc->impstate->sz_cr_table, IREG(0), BYTE); // load i1,sz_cr_table,i0,byte
if (invertcarry && (xermask & XER_CA))
UML_XOR(block, IREG(0), IREG(0), IMM(DRCUML_FLAG_C)); // xor i0,i0,FLAG_C
UML_LOAD(block, IREG(0), ppc->impstate->sz_cr_table, IREG(0), DWORD); // load i0,sz_cr_table,i0,dword
UML_AND(block, IREG(1), SPR32(SPR_XER), IMM(~xermask)); // and i1,[xer],~xermask
UML_SHL(block, IREG(2), IREG(0), IMM(4)); // shl i2,i0,4
if (xermask_so != (XER_CA | XER_OV | XER_SO))
UML_AND(block, IREG(2), IREG(2), IMM(xermask_so)); // and i2,i2,xermask
UML_OR(block, IREG(1), IREG(1), IREG(2)); // or i1,i1,i2
UML_MOV(block, SPR32(SPR_XER), IREG(1)); // mov [xer],i1
UML_SHR(block, IREG(1), IREG(1), IMM(3)); // shr i1,i1,3
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
UML_ROLINS(block, CR32, IREG(0), IMM(0), IMM(CRMASK(0))); // rolins [cr],i0,0,crmask(0)
UML_ROLINS(block, SPR32(SPR_XER), IREG(0), IMM(29), IMM(xermask)); // rolins [xer],i0,29,xermask
UML_ROLAND(block, IREG(0), IREG(0), IMM(31), IMM(1)); // roland i0,i0,31,0x0001
UML_OR(block, XERSO32, XERSO32, IREG(0)); // or [xerso],i0
UML_OR(block, CR32(0), IREG(1), IREG(0)); // or [cr0],i1,i0
}
@ -2315,7 +2309,7 @@ static void generate_branch_bo(drcuml_block *block, compiler_state *compiler, co
}
if (!(bo & 0x10))
{
UML_TEST(block, CR32, IMM(0x80000000 >> bi)); // test cr32,0x80000000 >> bi
UML_TEST(block, CR32(bi / 4), IMM(8 >> (bi % 4))); // test cr32(bi/4),8 >> (bi % 4)
UML_JMPc(block, (bo & 0x08) ? IF_Z : IF_NZ, skip); // jmp skip,z/nz
}
generate_branch(block, compiler, desc, source, link); // <branch>
@ -2372,19 +2366,15 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
case 0x0a: /* CMPLI */
UML_CMP(block, R32(G_RA(op)), IMM(G_UIMM(op))); // cmp ra,uimm
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_Z | DRCUML_FLAG_C); // getflgs i0,zc
UML_LOAD(block, IREG(0), ppc->impstate->cmpl_cr_table, IREG(0), DWORD); // load i0,cmpl_cr_table,i0,dword
UML_ROLINS(block, IREG(0), SPR32(SPR_XER), IMM(32 - (3 + 4 * G_CRFD(op))), IMM(CRMASK(G_CRFD(op)) & 0x11111111));
// rolins i0,[xer],32-(3+4*crfd),0x11111111 & crmask[cr]
UML_ROLINS(block, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
UML_LOAD(block, IREG(0), ppc->impstate->cmpl_cr_table, IREG(0), BYTE); // load i0,cmpl_cr_table,i0,byte
UML_OR(block, CR32(G_CRFD(op)), IREG(0), XERSO32); // or [crn],i0,[xerso]
return TRUE;
case 0x0b: /* CMPI */
UML_CMP(block, R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // cmp ra,uimm
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_Z | DRCUML_FLAG_C | DRCUML_FLAG_S); // getflgs i0,zcs
UML_LOAD(block, IREG(0), ppc->impstate->cmp_cr_table, IREG(0), DWORD); // load i0,cmp_cr_table,i0,dword
UML_ROLINS(block, IREG(0), SPR32(SPR_XER), IMM(32 - (3 + 4 * G_CRFD(op))), IMM(CRMASK(G_CRFD(op)) & 0x11111111));
// rolins i0,[xer],32-(3+4*crfd),0x11111111 & crmask[cr]
UML_ROLINS(block, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
UML_LOAD(block, IREG(0), ppc->impstate->cmp_cr_table, IREG(0), BYTE); // load i0,cmp_cr_table,i0,byte
UML_OR(block, CR32(G_CRFD(op)), IREG(0), XERSO32); // or [crn],i0,[xerso]
return TRUE;
case 0x08: /* SUBFIC */
@ -2731,77 +2721,76 @@ static int generate_instruction_13(drcuml_block *block, compiler_state *compiler
return TRUE;
case 0x000: /* MCRF */
UML_ROLINS(block, CR32, CR32, IMM(((G_CRFS(op) - G_CRFD(op)) & 7) * 4), IMM(CRMASK(G_CRFD(op))));
// rolins cr,cr,4*(crfs-crfd),crmask[crfd]
UML_MOV(block, CR32(G_CRFD(op)), CR32(G_CRFS(op))); // mov [crd],[crs]
return TRUE;
case 0x101: /* CRAND */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_AND(block, IREG(0), IREG(0), IREG(1)); // and i0,i1
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x081: /* CRANDC */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_XOR(block, IREG(1), IREG(1), IMM(~0)); // xor i1,~0
UML_AND(block, IREG(0), IREG(0), IREG(1)); // and i0,i1
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x0e1: /* CRNAND */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_AND(block, IREG(0), IREG(0), IREG(1)); // and i0,i1
UML_XOR(block, IREG(0), IREG(0), IMM(~0)); // xor i0,~0
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x1c1: /* CROR */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i1
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x1a1: /* CRORC */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_XOR(block, IREG(1), IREG(1), IMM(~0)); // xor i1,~0
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i1
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x021: /* CRNOR */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i1
UML_XOR(block, IREG(0), IREG(0), IMM(~0)); // xor i0,~0
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x0c1: /* CRXOR */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_XOR(block, IREG(0), IREG(0), IREG(1)); // xor i0,i1
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x121: /* CREQV */
UML_SHL(block, IREG(0), CR32, IMM(G_CRBA(op))); // shl i0,cr,crba(op)
UML_SHL(block, IREG(1), CR32, IMM(G_CRBB(op))); // shl i1,cr,crbb(op)
UML_SHL(block, IREG(0), CR32(G_CRBA(op) / 4), IMM(G_CRBA(op) % 4)); // shl i0,cr(a / 4),a % 4
UML_SHL(block, IREG(1), CR32(G_CRBB(op) / 4), IMM(G_CRBB(op) % 4)); // shl i1,cr(b / 4),b % 4
UML_XOR(block, IREG(0), IREG(0), IREG(1)); // xor i0,i1
UML_XOR(block, IREG(0), IREG(0), IMM(~0)); // xor i0,~0
UML_ROLINS(block, CR32, IREG(0), IMM(32 - G_CRBD(op)), IMM(0x80000000 >> G_CRBD(op)));
// rolins cr,i0,32-crbd,1<<crbd
UML_ROLINS(block, CR32(G_CRBD(op) / 4), IREG(0), IMM(32 - G_CRBD(op) % 4), IMM(8 >> (G_CRBD(op) % 4)));
// rolins cr(d / 4),i0,32-(d % 4),8 >> (d % 4)
return TRUE;
case 0x032: /* RFI */
@ -2980,19 +2969,15 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler
case 0x000: /* CMP */
UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra,rb
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_Z | DRCUML_FLAG_C | DRCUML_FLAG_S); // getflgs i0,zcs
UML_LOAD(block, IREG(0), ppc->impstate->cmp_cr_table, IREG(0), DWORD); // load i0,cmp_cr_table,i0,dword
UML_ROLINS(block, IREG(0), SPR32(SPR_XER), IMM(32 - (3 + 4 * G_CRFD(op))), IMM(CRMASK(G_CRFD(op)) & 0x11111111));
// rolins i0,[xer],32-(3+4*crfd),0x11111111 & crmask[cr]
UML_ROLINS(block, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
UML_LOAD(block, IREG(0), ppc->impstate->cmp_cr_table, IREG(0), BYTE); // load i0,cmp_cr_table,i0,byte
UML_OR(block, CR32(G_CRFD(op)), IREG(0), XERSO32); // or [crn],i0,[xerso]
return TRUE;
case 0x020: /* CMPL */
UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra,rb
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_Z | DRCUML_FLAG_C); // getflgs i0,zc
UML_LOAD(block, IREG(0), ppc->impstate->cmpl_cr_table, IREG(0), DWORD); // load i0,cmpl_cr_table,i0,dword
UML_ROLINS(block, IREG(0), SPR32(SPR_XER), IMM(32 - (3 + 4 * G_CRFD(op))), IMM(CRMASK(G_CRFD(op)) & 0x11111111));
// rolins i0,[xer],32-(3+4*crfd),0x11111111 & crmask[cr]
UML_ROLINS(block, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
UML_LOAD(block, IREG(0), ppc->impstate->cmpl_cr_table, IREG(0), BYTE); // load i0,cmpl_cr_table,i0,byte
UML_OR(block, CR32(G_CRFD(op)), IREG(0), XERSO32); // or [crn],i0,[xerso]
return TRUE;
case 0x00b: /* MULHWUx */
@ -3412,8 +3397,6 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler
UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs
UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
UML_CALLH(block, ppc->impstate->write32align[ppc->impstate->mode & 3]); // callh write32align
UML_AND(block, IREG(0), CR32, IMM(~CRMASK(0))); // and i0,cr,~crmask(0)
UML_ROLINS(block, IREG(0), SPR32(SPR_XER), IMM(29), IMM(0x10000000)); // rolins i0,[xer],29,0x10000000
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
UML_CMP(block, IREG(0), IREG(0)); // cmp i0,i0
generate_compute_flags(block, TRUE, 0, FALSE); // <update flags>
@ -3485,7 +3468,21 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler
return TRUE;
case 0x013: /* MFCR */
UML_MOV(block, R32(G_RD(op)), CR32); // mov rd,cr
UML_SHL(block, IREG(0), CR32(0), IMM(28)); // shl i0,cr(0),28
UML_ROLAND(block, IREG(1), CR32(1), IMM(24), IMM(0x0f000000)); // roland i1,cr(1),24,0x0f000000
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
UML_ROLAND(block, IREG(1), CR32(2), IMM(20), IMM(0x00f00000)); // roland i1,cr(2),20,0x00f00000
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
UML_ROLAND(block, IREG(1), CR32(3), IMM(16), IMM(0x000f0000)); // roland i1,cr(3),16,0x000f0000
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
UML_ROLAND(block, IREG(1), CR32(4), IMM(12), IMM(0x0000f000)); // roland i1,cr(4),12,0x0000f000
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
UML_ROLAND(block, IREG(1), CR32(5), IMM(8), IMM(0x00000f00)); // roland i1,cr(5),8,0x00000f00
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
UML_ROLAND(block, IREG(1), CR32(6), IMM(4), IMM(0x000000f0)); // roland i1,cr(6),4,0x000000f0
UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
UML_ROLAND(block, IREG(1), CR32(7), IMM(0), IMM(0x0000000f)); // roland i1,cr(7),0,0x0000000f
UML_OR(block, R32(G_RD(op)), IREG(0), IREG(1)); // or rd,i0,i1
return TRUE;
case 0x053: /* MFMSR */
@ -3495,8 +3492,14 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler
case 0x153: /* MFSPR */
{
UINT32 spr = compute_spr(G_SPR(op));
if (spr == SPR_LR || spr == SPR_CTR || spr == SPR_XER || (spr >= SPROEA_SPRG0 && spr <= SPROEA_SPRG3))
if (spr == SPR_LR || spr == SPR_CTR || (spr >= SPROEA_SPRG0 && spr <= SPROEA_SPRG3))
UML_MOV(block, R32(G_RD(op)), SPR32(spr)); // mov rd,spr
else if (spr == SPR_XER)
{
UML_MOV(block, IREG(0), SPR32(spr)); // mov i0,spr
UML_SHL(block, IREG(1), XERSO32, IMM(31)); // shl i1,[xerso],31
UML_OR(block, R32(G_RD(op)), IREG(0), IREG(1)); // or [rd],i0,i1
}
else if (spr == SPROEA_PVR)
UML_MOV(block, R32(G_RD(op)), IMM(ppc->flavor)); // mov rd,flavor
else
@ -3531,7 +3534,15 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler
}
case 0x090: /* MTCRF */
UML_ROLINS(block, CR32, R32(G_RS(op)), IMM(0), IMM(compute_crf_mask(G_CRM(op))));// rolins cr,rs,0,G_CRM
UML_MOV(block, IREG(0), R32(G_RS(op))); // mov i0,rs
if (G_CRM(op) & 0x80) UML_ROLAND(block, CR32(0), IREG(0), IMM(4), IMM(0xf)); // roland cr(0),i0,4,0x0f
if (G_CRM(op) & 0x40) UML_ROLAND(block, CR32(1), IREG(0), IMM(8), IMM(0xf)); // roland cr(1),i0,8,0x0f
if (G_CRM(op) & 0x20) UML_ROLAND(block, CR32(2), IREG(0), IMM(12), IMM(0xf)); // roland cr(2),i0,12,0x0f
if (G_CRM(op) & 0x10) UML_ROLAND(block, CR32(3), IREG(0), IMM(16), IMM(0xf)); // roland cr(3),i0,16,0x0f
if (G_CRM(op) & 0x08) UML_ROLAND(block, CR32(4), IREG(0), IMM(20), IMM(0xf)); // roland cr(4),i0,20,0x0f
if (G_CRM(op) & 0x04) UML_ROLAND(block, CR32(5), IREG(0), IMM(24), IMM(0xf)); // roland cr(5),i0,24,0x0f
if (G_CRM(op) & 0x02) UML_ROLAND(block, CR32(6), IREG(0), IMM(28), IMM(0xf)); // roland cr(6),i0,28,0x0f
if (G_CRM(op) & 0x01) UML_ROLAND(block, CR32(7), IREG(0), IMM(0), IMM(0xf)); // roland cr(7),i0,0,0x0f
return TRUE;
case 0x092: /* MTMSR */
@ -3549,8 +3560,13 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler
case 0x1d3: /* MTSPR */
{
UINT32 spr = compute_spr(G_SPR(op));
if (spr == SPR_LR || spr == SPR_CTR || spr == SPR_XER || (spr >= SPROEA_SPRG0 && spr <= SPROEA_SPRG3))
if (spr == SPR_LR || spr == SPR_CTR || (spr >= SPROEA_SPRG0 && spr <= SPROEA_SPRG3))
UML_MOV(block, SPR32(spr), R32(G_RS(op))); // mov spr,rs
else if (spr == SPR_XER)
{
UML_AND(block, SPR32(spr), R32(G_RS(op)), IMM(~XER_SO)); // and spr,rs,~XER_SO
UML_SHR(block, XERSO32, R32(G_RS(op)), IMM(31)); // shr [xerso],rs,31
}
else if (spr == SPROEA_PVR)
; // read only
else
@ -3577,9 +3593,11 @@ static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler
return TRUE;
case 0x200: /* MCRXR */
UML_ROLINS(block, CR32, SPR32(SPR_XER), IMM(32 - 4 * G_CRFD(op)), IMM(CRMASK(G_CRFD(op))));
// rolins cr,[xer],32-4*crfd,crmask(crfd)
UML_ROLAND(block, IREG(0), SPR32(SPR_XER), IMM(28), IMM(0x0f)); // roland i0,[xer],28,0x0f
UML_SHL(block, IREG(1), XERSO32, IMM(3)); // shl i1,[xerso],3
UML_OR(block, CR32(G_CRFD(op)), IREG(0), IREG(1)); // or [crd],i0,i1
UML_AND(block, SPR32(SPR_XER), SPR32(SPR_XER), IMM(~0xf0000000)); // and [xer],[xer],~0xf0000000
UML_MOV(block, XERSO32, IMM(0)); // mov [xerso],0
return TRUE;
case 0x106: /* ICBT */
@ -3797,8 +3815,8 @@ static int generate_instruction_3f(drcuml_block *block, compiler_state *compiler
case 0x020: /* FCMPO */
UML_FDCMP(block, F64(G_RA(op)), F64(G_RB(op))); // fdcmp ra,rb
UML_GETFLGS(block, IREG(0), DRCUML_FLAG_C | DRCUML_FLAG_Z | DRCUML_FLAG_U); // getflgs i0,czu
UML_LOAD(block, IREG(0), ppc->impstate->fcmp_cr_table, IREG(0), DWORD); // load i0,fcmp_cr_table,i0,dword
UML_ROLINS(block, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
UML_LOAD(block, IREG(0), ppc->impstate->fcmp_cr_table, IREG(0), BYTE); // load i0,fcmp_cr_table,i0,byte
UML_OR(block, CR32(G_CRFD(op)), IREG(0), XERSO32); // or [crn],i0,[xerso]
return TRUE;
case 0x00c: /* FRSPx */
@ -3843,8 +3861,8 @@ static int generate_instruction_3f(drcuml_block *block, compiler_state *compiler
return TRUE;
case 0x040: /* MCRFS */
UML_ROLINS(block, CR32, FPSCR32, IMM(((G_CRFS(op) - G_CRFD(op)) & 7) * 4), IMM(CRMASK(G_CRFD(op))));
// rolins cr,fpscr,shift,crmask[crfd]
UML_ROLAND(block, CR32(G_CRFD(op)), FPSCR32, IMM(((G_CRFS(op) - 7) & 7) * 4), IMM(0x0f));
// roland [crd],[fpscr],shift,0x0f
UML_AND(block, FPSCR32, FPSCR32, IMM(~CRMASK(G_CRFS(op)))); // and fpscr,fpscr,~crmask[crfs]
return TRUE;