summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2008-06-05 08:34:13 +0000
committer Aaron Giles <aaron@aarongiles.com>2008-06-05 08:34:13 +0000
commited6ad8b4f933fa4c18b683a2f2362c2c8cbe8c82 (patch)
treed077746962ad9a3bbb4bda243d417de7e98a6f4d
parent8ea2d9e334e001ec58ba6bbd057bebe7009bb1ff (diff)
PowerPC dynamic recompiler: [Aaron Giles]
- rewrote PowerPC implementation as a dynamic recompiler on top of the universal recompiler engine - wrote a front-end to analyze PowerPC code paths and register usage - wrote a common shared module with C implementations of tricky CPU behaviors - added separate CPU types for the variants supported, instead of relying on a hidden model enum - rewrote the serial port emulation for the 4xx series to be more accurate and not rely on separate DMA handlers - rewrote the MMU handling to implement a software TLB that faults in pages and handles changed bits appropriately - implemented emulation of the PowerPC 603's software TLB, which allows the model 3 games to run without a hack to disable the MMU Updated the PowerPC disassembler to share constants with the rest of the core, and to more aggressively use simplified mnemonics, especially for branches. [Aaron Giles] Universal recompiler: - fixed frontend to handle opcode widths different from bus width - added several new opcodes: * (D)GETFLGS - copies the UML flags to a destination operand * FDRNDS - rounds a double precision value to single precision - renamed several opcodes: * SETC -> CARRY * XTRACT -> ROLAND * INSERT -> ROLINS - consolidated the following opcodes: * LOAD?U -> LOAD * LOAD?S -> LOADS * STORE? -> STORE * READ?U -> READ * READ?M -> READM * WRITE? -> WRITE * WRITM? -> WRITEM * SEXT? -> SEXT * FTOI?? -> FTOINT * FFRI? -> FFRINT * FFRF? -> FFRFLT - removed some opcodes: * FLAGS - can be done with GETFLGS/LOAD4/ROLINS * ZEXT - can be achieved with AND * READ?S - can be achieved with READ/SEXT - updated C, x86, and x64 back-ends to support these opcode changes - updated disassembler to support these opcode changes MIPS3 dynamic recompiler: - updated to use new/changed opcode forms - changed context switch so that it only swaps a single pointer Konami Hornet changes: [Aaron Giles] - updated to new PowerPC configurations - updated some memory handlers to be native 8-bit handlers - cleaned up JVS implementation to work with new serial code - added fast RAM for the work RAM to give a small speed boost Konami GTI Club changes: [Aaron Giles] - updated to new PowerPC configurations - updated some memory handlers to be native 8-bit handlers Konami Viper/ZR107 changes: [Aaron Giles] - updated to new PowerPC configurations Sega Model 3 changes: [Aaron Giles] - updated to new PowerPC configurations - reimplemented/centralized interrupt handling - these games are broken for the moment Fixed crasher due to some Konami games using 8 layers in the K056832 implementation, even though it was only written for 4. [Aaron Giles] Added fisttp opcode to i386 disassembler. [Aaron Giles]
-rw-r--r--.gitattributes10
-rw-r--r--makefile8
-rw-r--r--src/emu/cpu/cpu.mak49
-rw-r--r--src/emu/cpu/drcbec.c393
-rw-r--r--src/emu/cpu/drcbex64.c2363
-rw-r--r--src/emu/cpu/drcbex86.c2439
-rw-r--r--src/emu/cpu/drcfe.c11
-rw-r--r--src/emu/cpu/drcuml.c82
-rw-r--r--src/emu/cpu/drcuml.h108
-rw-r--r--src/emu/cpu/drcumld.c125
-rw-r--r--src/emu/cpu/drcumlsh.h148
-rw-r--r--src/emu/cpu/i386/i386dasm.c6
-rw-r--r--src/emu/cpu/mips/mips3drc.c657
-rw-r--r--src/emu/cpu/powerpc/ppc.c73
-rw-r--r--src/emu/cpu/powerpc/ppc.h411
-rw-r--r--src/emu/cpu/powerpc/ppc403.c22
-rw-r--r--src/emu/cpu/powerpc/ppc_dasm.c326
-rw-r--r--src/emu/cpu/powerpc/ppc_mem.c2
-rw-r--r--src/emu/cpu/powerpc/ppccom.c1792
-rw-r--r--src/emu/cpu/powerpc/ppccom.h611
-rw-r--r--src/emu/cpu/powerpc/ppcdrc.c4337
-rw-r--r--src/emu/cpu/powerpc/ppcdrco.c2485
-rw-r--r--src/emu/cpu/powerpc/ppcfe.c942
-rw-r--r--src/emu/cpu/powerpc/ppcfe.h40
-rw-r--r--src/emu/cpu/x64drc.c633
-rw-r--r--src/emu/cpu/x64drc.h223
-rw-r--r--src/emu/cpu/x86drc.c767
-rw-r--r--src/emu/cpu/x86drc.h194
-rw-r--r--src/emu/cpuexec.h5
-rw-r--r--src/emu/cpuintrf.c18
-rw-r--r--src/emu/memory.c2
-rw-r--r--src/mame/drivers/firebeat.c17
-rw-r--r--src/mame/drivers/gticlub.c84
-rw-r--r--src/mame/drivers/hornet.c173
-rw-r--r--src/mame/drivers/konamim2.c6
-rw-r--r--src/mame/drivers/model3.c103
-rw-r--r--src/mame/drivers/nwk-tr.c36
-rw-r--r--src/mame/drivers/ultrsprt.c8
-rw-r--r--src/mame/drivers/viper.c6
-rw-r--r--src/mame/drivers/zr107.c19
-rw-r--r--src/mame/mame.mak5
-rw-r--r--src/mame/video/konamiic.c18
-rw-r--r--src/mame/video/model3.c5
43 files changed, 10338 insertions, 9424 deletions
diff --git a/.gitattributes b/.gitattributes
index c9441f52f98..43c25630a71 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -320,7 +320,11 @@ src/emu/cpu/powerpc/ppc_dasm.c svneol=native#text/plain
src/emu/cpu/powerpc/ppc_mem.c svneol=native#text/plain
src/emu/cpu/powerpc/ppc_ops.c svneol=native#text/plain
src/emu/cpu/powerpc/ppc_ops.h svneol=native#text/plain
-src/emu/cpu/powerpc/ppcdrco.c svneol=native#text/plain
+src/emu/cpu/powerpc/ppccom.c svneol=native#text/plain
+src/emu/cpu/powerpc/ppccom.h svneol=native#text/plain
+src/emu/cpu/powerpc/ppcdrc.c svneol=native#text/plain
+src/emu/cpu/powerpc/ppcfe.c svneol=native#text/plain
+src/emu/cpu/powerpc/ppcfe.h svneol=native#text/plain
src/emu/cpu/rsp/rsp.c svneol=native#text/plain
src/emu/cpu/rsp/rsp.h svneol=native#text/plain
src/emu/cpu/rsp/rsp_dasm.c svneol=native#text/plain
@@ -448,10 +452,6 @@ src/emu/cpu/v60/v60mem.c svneol=native#text/plain
src/emu/cpu/v810/v810.c svneol=native#text/plain
src/emu/cpu/v810/v810.h svneol=native#text/plain
src/emu/cpu/v810/v810dasm.c svneol=native#text/plain
-src/emu/cpu/x64drc.c svneol=native#text/plain
-src/emu/cpu/x64drc.h svneol=native#text/plain
-src/emu/cpu/x86drc.c svneol=native#text/plain
-src/emu/cpu/x86drc.h svneol=native#text/plain
src/emu/cpu/x86emit.h svneol=native#text/plain
src/emu/cpu/x86log.c svneol=native#text/plain
src/emu/cpu/x86log.h svneol=native#text/plain
diff --git a/makefile b/makefile
index 5b162f5a2da..b587e5b73c6 100644
--- a/makefile
+++ b/makefile
@@ -111,9 +111,6 @@ endif
# a native backend
# FORCE_DRC_C_BACKEND = 1
-# uncomment next line to use DRC PowerPC engine
-X86_PPC_DRC = 1
-
#-------------------------------------------------
@@ -159,11 +156,6 @@ BUILD_ZLIB = 1
# sanity check the configuration
#-------------------------------------------------
-# disable DRC cores for 64-bit builds
-ifdef PTR64
-X86_PPC_DRC =
-endif
-
# specify a default optimization level if none explicitly stated
ifndef OPTIMIZE
ifndef SYMBOLS
diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak
index 31e249b6c05..945a836cfbe 100644
--- a/src/emu/cpu/cpu.mak
+++ b/src/emu/cpu/cpu.mak
@@ -41,13 +41,10 @@ ifdef PTR64
DRCOBJ += \
$(CPUOBJ)/drcbex64.o \
- $(CPUOBJ)/x64drc.o \
- $(CPUOBJ)/x86log.o \
+ $(CPUOBJ)/x86log.o
DRCDEPS += \
- $(CPUSRC)/x86emit.h \
- $(CPUSRC)/x64drc.c \
- $(CPUSRC)/x64drc.h \
+ $(CPUSRC)/x86emit.h
DEFS += -DNATIVE_DRC=drcbe_x64_be_interface
@@ -55,13 +52,10 @@ else
DRCOBJ += \
$(CPUOBJ)/drcbex86.o \
- $(CPUOBJ)/x86drc.o \
- $(CPUOBJ)/x86log.o \
+ $(CPUOBJ)/x86log.o
DRCDEPS += \
- $(CPUSRC)/x86emit.h \
- $(CPUSRC)/x86drc.c \
- $(CPUSRC)/x86drc.h \
+ $(CPUSRC)/x86emit.h
DEFS += -DNATIVE_DRC=drcbe_x86_be_interface
@@ -839,7 +833,7 @@ CPUDEFS += -DHAS_RM7000=$(if $(filter RM7000,$(CPUS)),1,0)
ifneq ($(filter R4600 R4650 R4700 R5000 QED5271 RM7000,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/mips
-CPUOBJS += $(CPUOBJ)/mips/mips3com.o $(CPUOBJ)/mips/mips3drc.o $(CPUOBJ)/mips/mips3fe.o $(DRCOBJ)
+CPUOBJS += $(CPUOBJ)/mips/mips3com.o $(CPUOBJ)/mips/mips3fe.o $(CPUOBJ)/mips/mips3drc.o $(DRCOBJ)
DBGOBJS += $(CPUOBJ)/mips/mips3dsm.o
endif
@@ -1125,41 +1119,26 @@ $(CPUOBJ)/pdp1/pdp1.o: $(CPUSRC)/pdp1/pdp1.c \
# Motorola PowerPC series
#-------------------------------------------------
-CPUDEFS += -DHAS_PPC403=$(if $(filter PPC403,$(CPUS)),1,0)
+CPUDEFS += -DHAS_PPC403GA=$(if $(filter PPC403GA,$(CPUS)),1,0)
+CPUDEFS += -DHAS_PPC403GCX=$(if $(filter PPC403GCX,$(CPUS)),1,0)
CPUDEFS += -DHAS_PPC601=$(if $(filter PPC601,$(CPUS)),1,0)
CPUDEFS += -DHAS_PPC602=$(if $(filter PPC602,$(CPUS)),1,0)
CPUDEFS += -DHAS_PPC603=$(if $(filter PPC603,$(CPUS)),1,0)
+CPUDEFS += -DHAS_PPC603E=$(if $(filter PPC603E,$(CPUS)),1,0)
+CPUDEFS += -DHAS_PPC603R=$(if $(filter PPC603R,$(CPUS)),1,0)
CPUDEFS += -DHAS_PPC604=$(if $(filter PPC604,$(CPUS)),1,0)
CPUDEFS += -DHAS_MPC8240=$(if $(filter MPC8240,$(CPUS)),1,0)
-ifneq ($(filter PPC403 PPC601 PPC602 PPC603 PPC604 MPC8240,$(CPUS)),)
+ifneq ($(filter PPC403GA PPC403GCX PPC601 PPC602 PPC603 PPC603E PPC603R PPC604 MPC8240,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/powerpc
+CPUOBJS += $(CPUOBJ)/powerpc/ppccom.o $(CPUOBJ)/powerpc/ppcfe.o $(CPUOBJ)/powerpc/ppcdrc.o $(DRCOBJ)
DBGOBJS += $(CPUOBJ)/powerpc/ppc_dasm.o
-
-ifdef X86_PPC_DRC
-CPUOBJS += $(CPUOBJ)/powerpc/ppcdrco.o $(DRCOBJ)
-else
-CPUOBJS += $(CPUOBJ)/powerpc/ppc.o
-endif
endif
-$(CPUOBJ)/powerpc/ppc.o: $(CPUSRC)/powerpc/ppc.c \
- $(CPUSRC)/powerpc/ppc.h \
- $(CPUSRC)/powerpc/ppc_ops.c \
- $(CPUSRC)/powerpc/ppc_mem.c \
- $(CPUSRC)/powerpc/ppc403.c \
- $(CPUSRC)/powerpc/ppc602.c \
- $(CPUSRC)/powerpc/ppc603.c
-
-$(CPUOBJ)/powerpc/ppcdrco.o:$(CPUSRC)/powerpc/ppcdrco.c \
+$(CPUOBJ)/powerpc/ppcdrc.o: $(CPUSRC)/powerpc/ppcdrc.c \
$(CPUSRC)/powerpc/ppc.h \
- $(CPUSRC)/powerpc/drc_ops.c \
- $(CPUSRC)/powerpc/drc_ops.h \
- $(CPUSRC)/powerpc/ppc_ops.c \
- $(CPUSRC)/powerpc/ppc_mem.c \
- $(CPUSRC)/powerpc/ppc403.c \
- $(CPUSRC)/powerpc/ppc602.c \
- $(CPUSRC)/powerpc/ppc603.c \
+ $(CPUSRC)/powerpc/ppccom.h \
+ $(CPUSRC)/powerpc/ppcfe.h \
$(DRCDEPS)
diff --git a/src/emu/cpu/drcbec.c b/src/emu/cpu/drcbec.c
index a0edfd84c06..4506d4f2651 100644
--- a/src/emu/cpu/drcbec.c
+++ b/src/emu/cpu/drcbec.c
@@ -47,6 +47,58 @@
#define LEBIT (0x1000 << (DRCUML_COND_LE & 15))
+/* internal opcodes */
+enum
+{
+ DRCUML_OP_LOAD1 = DRCUML_OP_MAX,
+ DRCUML_OP_LOAD2,
+ DRCUML_OP_LOAD4,
+ DRCUML_OP_LOAD8,
+ DRCUML_OP_LOADS1,
+ DRCUML_OP_LOADS2,
+ DRCUML_OP_LOADS4,
+ DRCUML_OP_LOADS8,
+ DRCUML_OP_STORE1,
+ DRCUML_OP_STORE2,
+ DRCUML_OP_STORE4,
+ DRCUML_OP_STORE8,
+ DRCUML_OP_READ1,
+ DRCUML_OP_READ2,
+ DRCUML_OP_READ4,
+ DRCUML_OP_READ8,
+ DRCUML_OP_READM1,
+ DRCUML_OP_READM2,
+ DRCUML_OP_READM4,
+ DRCUML_OP_READM8,
+ DRCUML_OP_WRITE1,
+ DRCUML_OP_WRITE2,
+ DRCUML_OP_WRITE4,
+ DRCUML_OP_WRITE8,
+ DRCUML_OP_WRITEM1,
+ DRCUML_OP_WRITEM2,
+ DRCUML_OP_WRITEM4,
+ DRCUML_OP_WRITEM8,
+ DRCUML_OP_SEXT1,
+ DRCUML_OP_SEXT2,
+ DRCUML_OP_SEXT4,
+ DRCUML_OP_SEXT8,
+ DRCUML_OP_FTOI4T,
+ DRCUML_OP_FTOI4R,
+ DRCUML_OP_FTOI4C,
+ DRCUML_OP_FTOI4F,
+ DRCUML_OP_FTOI4,
+ DRCUML_OP_FTOI8T,
+ DRCUML_OP_FTOI8R,
+ DRCUML_OP_FTOI8C,
+ DRCUML_OP_FTOI8F,
+ DRCUML_OP_FTOI8,
+ DRCUML_OP_FFRI4,
+ DRCUML_OP_FFRI8,
+ DRCUML_OP_FFRFS,
+ DRCUML_OP_FFRFD,
+};
+
+
/***************************************************************************
MACROS
@@ -337,10 +389,11 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
UINT8 psize[ARRAY_LENGTH(instlist->param)];
drcuml_instruction modified_inst;
int immedbytes, immedwords, pnum;
+ drcuml_opcode opcode = inst->opcode;
void *immed;
/* handle most instructions generally, but a few special cases */
- switch (inst->opcode)
+ switch (opcode)
{
/* when we hit a HANDLE opcode, register the current pointer for the handle */
case DRCUML_OP_HANDLE:
@@ -378,7 +431,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
case DRCUML_OP_JMP:
assert(inst->numparams == 1);
assert(inst->param[0].type == DRCUML_PTYPE_IMMEDIATE);
- (dst++)->i = MAKE_OPCODE_FULL(inst->opcode, inst->size, inst->condflags, 1);
+ (dst++)->i = MAKE_OPCODE_FULL(opcode, inst->size, inst->condflags, 1);
dst->inst = (drcbec_instruction *)drclabel_get_codeptr(drcbe->labels, inst->param[0].value, fixup_label, dst);
dst++;
break;
@@ -387,7 +440,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
default:
/* for RECOVER opcodes, we need to fixup the second parameter into an immediate */
- if (inst->opcode == DRCUML_OP_RECOVER)
+ if (opcode == DRCUML_OP_RECOVER)
{
assert(inst->param[1].type == DRCUML_PTYPE_MAPVAR);
modified_inst = *inst;
@@ -398,22 +451,44 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
/* determine the operand size for each operand; mostly this is just the instruction size */
for (pnum = 0; pnum < inst->numparams; pnum++)
psize[pnum] = inst->size;
- if ((inst->opcode >= DRCUML_OP_LOAD1U && inst->opcode <= DRCUML_OP_LOAD8U) || inst->opcode == DRCUML_OP_FLOAD)
+ if (opcode == DRCUML_OP_LOAD || opcode == DRCUML_OP_FLOAD)
psize[2] = 4;
- if ((inst->opcode >= DRCUML_OP_STORE1 && inst->opcode <= DRCUML_OP_STORE8) || inst->opcode == DRCUML_OP_FSTORE)
+ if (opcode == DRCUML_OP_STORE || opcode == DRCUML_OP_FSTORE)
psize[1] = 4;
- if ((inst->opcode >= DRCUML_OP_READ1U && inst->opcode <= DRCUML_OP_READ8M) || inst->opcode == DRCUML_OP_FREAD)
- psize[1] = psize[2] = 4;
- if ((inst->opcode >= DRCUML_OP_WRITE1 && inst->opcode <= DRCUML_OP_WRIT8M) || inst->opcode == DRCUML_OP_FWRITE)
+ if (opcode == DRCUML_OP_READ || opcode == DRCUML_OP_READM || opcode == DRCUML_OP_FREAD)
+ psize[0] = psize[1] = 4;
+ if (opcode == DRCUML_OP_WRITE || opcode == DRCUML_OP_WRITEM || opcode == DRCUML_OP_FWRITE)
psize[0] = psize[1] = 4;
- if (inst->opcode >= DRCUML_OP_FTOI4 && inst->opcode <= DRCUML_OP_FTOI4C)
- psize[0] = 4;
- if (inst->opcode >= DRCUML_OP_FTOI8 && inst->opcode <= DRCUML_OP_FTOI8C)
- psize[0] = 8;
- if ((inst->opcode >= DRCUML_OP_ZEXT1 && inst->opcode <= DRCUML_OP_SEXT4) || inst->opcode == DRCUML_OP_FFRFS || inst->opcode == DRCUML_OP_FFRI4)
+ if (opcode == DRCUML_OP_SEXT && inst->param[2].value != DRCUML_SIZE_QWORD)
psize[1] = 4;
- if (inst->opcode == DRCUML_OP_FFRFD || inst->opcode == DRCUML_OP_FFRI8)
- psize[1] = 8;
+ if (opcode == DRCUML_OP_FTOINT)
+ psize[0] = 1 << inst->param[2].value;
+ if (opcode == DRCUML_OP_FFRINT || opcode == DRCUML_OP_FFRFLT)
+ psize[1] = 1 << inst->param[2].value;
+
+ /* pre-expand opcodes that encode size in them */
+ if (opcode == DRCUML_OP_LOAD)
+ opcode = DRCUML_OP_LOAD1 + (inst->param[3].value & 3);
+ if (opcode == DRCUML_OP_LOADS)
+ opcode = DRCUML_OP_LOADS1 + (inst->param[3].value & 3);
+ if (opcode == DRCUML_OP_STORE)
+ opcode = DRCUML_OP_STORE1 + (inst->param[3].value & 3);
+ if (opcode == DRCUML_OP_READ)
+ opcode = DRCUML_OP_READ1 + (inst->param[2].value & 3);
+ if (opcode == DRCUML_OP_READM)
+ opcode = DRCUML_OP_READM1 + (inst->param[3].value & 3);
+ if (opcode == DRCUML_OP_WRITE)
+ opcode = DRCUML_OP_WRITE1 + (inst->param[2].value & 3);
+ if (opcode == DRCUML_OP_WRITEM)
+ opcode = DRCUML_OP_WRITEM1 + (inst->param[3].value & 3);
+ if (opcode == DRCUML_OP_SEXT)
+ opcode = DRCUML_OP_SEXT1 + (inst->param[2].value & 3);
+ if (opcode == DRCUML_OP_FTOINT)
+ opcode = DRCUML_OP_FTOI4T + 5 * ((inst->param[2].value & 3) - 2) + inst->param[3].value;
+ if (opcode == DRCUML_OP_FFRINT)
+ opcode = DRCUML_OP_FFRI4 + ((inst->param[2].value & 3) - 2);
+ if (opcode == DRCUML_OP_FFRFLT)
+ opcode = DRCUML_OP_FFRFS + ((inst->param[2].value & 3) - 2);
/* count how many bytes of immediates we need */
immedbytes = 0;
@@ -426,7 +501,7 @@ static void drcbec_generate(drcbe_state *drcbe, drcuml_block *block, const drcum
immedwords = (immedbytes + sizeof(drcbec_instruction) - 1) / sizeof(drcbec_instruction);
/* first item is the opcode, size, condition flags and length */
- (dst++)->i = MAKE_OPCODE_FULL(inst->opcode, inst->size, inst->condflags, inst->numparams + immedwords);
+ (dst++)->i = MAKE_OPCODE_FULL(opcode, inst->size, inst->condflags, inst->numparams + immedwords);
/* immediates start after parameters */
immed = dst + inst->numparams;
@@ -504,6 +579,7 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
while (TRUE)
{
UINT32 opcode = (inst++)->i;
+
switch (OPCODE_GET_SHORT(opcode))
{
/* ----------------------- Control Flow Operations ----------------------- */
@@ -623,6 +699,11 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
PARAM0 = drcbe->state.exp;
break;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_GETFLGS, 4, 0): /* GETFLGS dst[,f] */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_GETFLGS, 4, 1): /* GETFLGS dst[,f] */
+ PARAM0 = flags;
+ break;
+
case MAKE_OPCODE_SHORT(DRCUML_OP_SAVE, 4, 0): /* SAVE dst */
*inst[0].state = drcbe->state;
inst[0].state->flags = flags;
@@ -636,91 +717,83 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
/* ----------------------- 32-Bit Integer Operations ----------------------- */
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD1U, 4, 0): /* LOAD1U dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD1, 4, 0): /* LOAD dst,base,index,BYTE */
PARAM0 = inst[1].puint8[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD1S, 4, 0): /* LOAD1S dst,base,index */
- PARAM0 = inst[1].pint8[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2, 4, 0): /* LOAD dst,base,index,WORD */
+ PARAM0 = inst[1].puint16[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2U, 4, 0): /* LOAD2U dst,base,index */
- PARAM0 = inst[1].puint16[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD4, 4, 0): /* LOAD dst,base,index,DWORD */
+ PARAM0 = inst[1].puint32[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2S, 4, 0): /* LOAD2S dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOADS1, 4, 0): /* LOADS dst,base,index,BYTE */
+ PARAM0 = inst[1].pint8[PARAM2];
+ break;
+
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOADS2, 4, 0): /* LOADS dst,base,index,WORD */
PARAM0 = inst[1].pint16[PARAM2];
break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD4U, 4, 0): /* LOAD4U dst,base,index */
- PARAM0 = inst[1].puint32[PARAM2];
+
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOADS4, 4, 0): /* LOADS dst,base,index,DWORD */
+ PARAM0 = inst[1].pint32[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_STORE1, 4, 0): /* STORE1 dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_STORE1, 4, 0): /* STORE dst,base,index,BYTE */
inst[0].puint8[PARAM1] = PARAM2;
break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_STORE2, 4, 0): /* STORE2 dst,base,index */
+
+ case MAKE_OPCODE_SHORT(DRCUML_OP_STORE2, 4, 0): /* STORE dst,base,index,WORD */
inst[0].puint16[PARAM1] = PARAM2;
break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_STORE4, 4, 0): /* STORE4 dst,base,index */
+
+ case MAKE_OPCODE_SHORT(DRCUML_OP_STORE4, 4, 0): /* STORE dst,base,index,DWORD */
inst[0].puint32[PARAM1] = PARAM2;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ1U, 4, 0): /* READ1U dst,space,src1 */
- PARAM0 = (UINT8)(*active_address_space[PARAM1].accessors->read_byte)(PARAM2);
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ1S, 4, 0): /* READ1S dst,space,src1 */
- PARAM0 = (INT8)(*active_address_space[PARAM1].accessors->read_byte)(PARAM2);
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ2U, 4, 0): /* READ2U dst,space,src1 */
- PARAM0 = (UINT16)(*active_address_space[PARAM1].accessors->read_word)(PARAM2);
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ2S, 4, 0): /* READ2S dst,space,src1 */
- PARAM0 = (INT16)(*active_address_space[PARAM1].accessors->read_word)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READ1, 4, 0): /* READ dst,src1,space_BYTE */
+ PARAM0 = (UINT8)(*active_address_space[PARAM2 / 16].accessors->read_byte)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ2M, 4, 0): /* READ2M dst,space,src1,mask */
- PARAM0 = (UINT16)(*active_address_space[PARAM1].accessors->read_word_masked)(PARAM2, PARAM3);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READ2, 4, 0): /* READ dst,src1,space_WORD */
+ PARAM0 = (UINT16)(*active_address_space[PARAM2 / 16].accessors->read_word)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ4U, 4, 0): /* READ4U dst,space,src1 */
- PARAM0 = (UINT32)(*active_address_space[PARAM1].accessors->read_dword)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READ4, 4, 0): /* READ dst,src1,space_DWORD */
+ PARAM0 = (UINT32)(*active_address_space[PARAM2 / 16].accessors->read_dword)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ4M, 4, 0): /* READ4M dst,space,src1,mask */
- PARAM0 = (UINT32)(*active_address_space[PARAM1].accessors->read_dword_masked)(PARAM2, PARAM3);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READM2, 4, 0): /* READM dst,src1,mask,space_WORD */
+ PARAM0 = (UINT16)(*active_address_space[PARAM3 / 16].accessors->read_word_masked)(PARAM1, PARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE1, 4, 0): /* WRITE1 space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_byte)(PARAM1, PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READM4, 4, 0): /* READM dst,src1,mask,space_DWORD */
+ PARAM0 = (UINT32)(*active_address_space[PARAM3 / 16].accessors->read_dword_masked)(PARAM1, PARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE2, 4, 0): /* WRITE2 space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_word)(PARAM1, PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE1, 4, 0): /* WRITE dst,src1,space_BYTE */
+ (*active_address_space[PARAM2 / 16].accessors->write_byte)(PARAM0, PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRIT2M, 4, 0): /* WRIT2M space,dst,mask,src1 */
- (*active_address_space[PARAM0].accessors->write_word_masked)(PARAM1, PARAM2, PARAM3);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE2, 4, 0): /* WRITE dst,src1,space_WORD */
+ (*active_address_space[PARAM2 / 16].accessors->write_word)(PARAM0, PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE4, 4, 0): /* WRITE4 space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_dword)(PARAM1, PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE4, 4, 0): /* WRITE dst,src1,space_DWORD */
+ (*active_address_space[PARAM2 / 16].accessors->write_dword)(PARAM0, PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRIT4M, 4, 0): /* WRIT4M space,dst,mask,src1 */
- (*active_address_space[PARAM0].accessors->write_dword_masked)(PARAM1, PARAM2, PARAM3);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM2, 4, 0): /* WRITEM dst,src1,mask,space_WORD */
+ (*active_address_space[PARAM3 / 16].accessors->write_word_masked)(PARAM0, PARAM1, PARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FLAGS, 4, 0): /* FLAGS dst,mask,table */
- PARAM0 = (PARAM0 & ~PARAM1) | (inst[2].puint32[flags & 0x1f] & PARAM1);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM4, 4, 0): /* WRITEM dst,src1,mask,space_DWORD */
+ (*active_address_space[PARAM3 / 16].accessors->write_dword_masked)(PARAM0, PARAM1, PARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_SETC, 4, 0): /* SETC src,bitnum */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_CARRY, 4, 0): /* CARRY src,bitnum */
flags = (flags & ~DRCUML_FLAG_C) | ((PARAM0 >> (PARAM1 & 31)) & DRCUML_FLAG_C);
break;
@@ -733,12 +806,8 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
PARAM0 = PARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_ZEXT1, 4, 0): /* ZEXT1 dst,src */
- PARAM0 = (UINT8)PARAM1;
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_ZEXT2, 4, 0): /* ZEXT2 dst,src */
- PARAM0 = (UINT16)PARAM1;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_SET, 4, 1): /* SET dst,c */
+ PARAM0 = OPCODE_FAIL_CONDITION(opcode, flags) ? 0 : 1;
break;
case MAKE_OPCODE_SHORT(DRCUML_OP_SEXT1, 4, 0): /* SEXT1 dst,src */
@@ -749,12 +818,12 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
PARAM0 = (INT16)PARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_XTRACT, 4, 0): /* XTRACT dst,src,count,mask[,f] */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_ROLAND, 4, 0): /* ROLAND dst,src,count,mask[,f] */
shift = PARAM2 & 31;
PARAM0 = ((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_INSERT, 4, 0): /* INSERT dst,src,count,mask[,f] */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_ROLINS, 4, 0): /* ROLINS dst,src,count,mask[,f] */
shift = PARAM2 & 31;
PARAM0 = (PARAM0 & ~PARAM3) | (((PARAM1 << shift) | (PARAM1 >> (32 - shift))) & PARAM3);
break;
@@ -1025,123 +1094,107 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
/* ----------------------- 64-Bit Integer Operations ----------------------- */
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD1U, 8, 0): /* DLOAD1U dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD1, 8, 0): /* DLOAD dst,base,index,BYTE */
DPARAM0 = inst[1].puint8[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD1S, 8, 0): /* DLOAD1S dst,base,index */
- DPARAM0 = inst[1].pint8[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2, 8, 0): /* DLOAD dst,base,index,WORD */
+ DPARAM0 = inst[1].puint16[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2U, 8, 0): /* DLOAD2U dst,base,index */
- DPARAM0 = inst[1].puint16[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD4, 8, 0): /* DLOAD dst,base,index,DWORD */
+ DPARAM0 = inst[1].puint32[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2S, 8, 0): /* DLOAD2S dst,base,index */
- DPARAM0 = inst[1].pint16[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD8, 8, 0): /* DLOAD dst,base,index,QWORD */
+ DPARAM0 = inst[1].puint64[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD4U, 8, 0): /* DLOAD4U dst,base,index */
- DPARAM0 = inst[1].puint32[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOADS1, 8, 0): /* DLOADS dst,base,index,BYTE */
+ DPARAM0 = inst[1].pint8[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD4S, 8, 0): /* DLOAD4S dst,base,index */
- DPARAM0 = inst[1].pint32[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOADS2, 8, 0): /* DLOADS dst,base,index,WORD */
+ DPARAM0 = inst[1].pint16[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD8U, 8, 0): /* DLOAD8U dst,base,index */
- DPARAM0 = inst[1].puint64[PARAM2];
+ case MAKE_OPCODE_SHORT(DRCUML_OP_LOADS4, 8, 0): /* DLOADS dst,base,index,DWORD */
+ DPARAM0 = inst[1].pint32[PARAM2];
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_STORE1, 8, 0): /* DSTORE1 dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_STORE1, 8, 0): /* DSTORE dst,base,index,BYTE */
inst[0].puint8[PARAM1] = DPARAM2;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_STORE2, 8, 0): /* DSTORE2 dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_STORE2, 8, 0): /* DSTORE dst,base,index,WORD */
inst[0].puint16[PARAM1] = DPARAM2;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_STORE4, 8, 0): /* DSTORE4 dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_STORE4, 8, 0): /* DSTORE dst,base,index,DWORD */
inst[0].puint32[PARAM1] = DPARAM2;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_STORE8, 8, 0): /* DSTORE8 dst,base,index */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_STORE8, 8, 0): /* DSTORE dst,base,index,QWORD */
inst[0].puint64[PARAM1] = DPARAM2;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ1U, 8, 0): /* DREAD1U dst,space,src1 */
- DPARAM0 = (UINT8)(*active_address_space[PARAM1].accessors->read_byte)(PARAM2);
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ1S, 8, 0): /* DREAD1S dst,space,src1 */
- DPARAM0 = (INT8)(*active_address_space[PARAM1].accessors->read_byte)(PARAM2);
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ2U, 8, 0): /* DREAD2U dst,space,src1 */
- DPARAM0 = (UINT16)(*active_address_space[PARAM1].accessors->read_word)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READ1, 8, 0): /* DREAD dst,src1,space_BYTE */
+ DPARAM0 = (UINT8)(*active_address_space[PARAM2 / 16].accessors->read_byte)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ2S, 8, 0): /* DREAD2S dst,space,src1 */
- DPARAM0 = (INT16)(*active_address_space[PARAM1].accessors->read_word)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READ2, 8, 0): /* DREAD dst,src1,space_WORD */
+ DPARAM0 = (UINT16)(*active_address_space[PARAM2 / 16].accessors->read_word)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ2M, 8, 0): /* DREAD2M dst,space,src1,mask */
- DPARAM0 = (UINT16)(*active_address_space[PARAM1].accessors->read_word_masked)(PARAM2, DPARAM3);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READ4, 8, 0): /* DREAD dst,src1,space_DWORD */
+ DPARAM0 = (UINT32)(*active_address_space[PARAM2 / 16].accessors->read_dword)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ4U, 8, 0): /* DREAD4U dst,space,src1 */
- DPARAM0 = (UINT32)(*active_address_space[PARAM1].accessors->read_dword)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READ8, 8, 0): /* DREAD dst,src1,space_QOWRD */
+ DPARAM0 = (UINT64)(*active_address_space[PARAM2 / 16].accessors->read_qword)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ4S, 8, 0): /* DREAD4S dst,space,src1 */
- DPARAM0 = (INT32)(*active_address_space[PARAM1].accessors->read_dword)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READM2, 8, 0): /* DREADM dst,src1,mask,space_WORD */
+ DPARAM0 = (UINT16)(*active_address_space[PARAM3 / 16].accessors->read_word_masked)(PARAM1, PARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ4M, 8, 0): /* DREAD4M dst,space,src1,mask */
- DPARAM0 = (UINT32)(*active_address_space[PARAM1].accessors->read_dword_masked)(PARAM2, DPARAM3);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READM4, 8, 0): /* DREADM dst,src1,mask,space_DWORD */
+ DPARAM0 = (UINT32)(*active_address_space[PARAM3 / 16].accessors->read_dword_masked)(PARAM1, PARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ8U, 8, 0): /* DREAD8U dst,space,src1 */
- DPARAM0 = (UINT64)(*active_address_space[PARAM1].accessors->read_qword)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_READM8, 8, 0): /* DREADM dst,src1,mask,space_QWORD */
+ DPARAM0 = (UINT64)(*active_address_space[PARAM3 / 16].accessors->read_qword_masked)(PARAM1, PARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_READ8M, 8, 0): /* DREAD8M dst,space,src1,mask */
- DPARAM0 = (UINT64)(*active_address_space[PARAM1].accessors->read_qword_masked)(PARAM2, DPARAM3);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE1, 8, 0): /* DWRITE dst,src1,space_BYTE */
+ (*active_address_space[PARAM2 / 16].accessors->write_byte)(PARAM0, PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE1, 8, 0): /* DWRITE1 space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_byte)(PARAM1, DPARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE2, 8, 0): /* DWRITE dst,src1,space_WORD */
+ (*active_address_space[PARAM2 / 16].accessors->write_word)(PARAM0, PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE2, 8, 0): /* DWRITE2 space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_word)(PARAM1, DPARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE4, 8, 0): /* DWRITE dst,src1,space_DWORD */
+ (*active_address_space[PARAM2 / 16].accessors->write_dword)(PARAM0, PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRIT2M, 8, 0): /* DWRIT2M space,dst,mask,src1 */
- (*active_address_space[PARAM0].accessors->write_word_masked)(PARAM1, DPARAM3, DPARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE8, 8, 0): /* DWRITE dst,src1,space_QWORD */
+ (*active_address_space[PARAM2 / 16].accessors->write_qword)(PARAM0, PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE4, 8, 0): /* DWRITE4 space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_dword)(PARAM1, DPARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM2, 8, 0): /* DWRITEM dst,src1,mask,space_WORD */
+ (*active_address_space[PARAM3 / 16].accessors->write_word_masked)(PARAM0, DPARAM1, DPARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRIT4M, 8, 0): /* DWRIT4M space,dst,mask,src1 */
- (*active_address_space[PARAM0].accessors->write_dword_masked)(PARAM1, DPARAM3, DPARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM4, 8, 0): /* DWRITEM dst,src1,mask,space_DWORD */
+ (*active_address_space[PARAM3 / 16].accessors->write_dword_masked)(PARAM0, DPARAM1, DPARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE8, 8, 0): /* DWRITE8 space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_qword)(PARAM1, DPARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_WRITEM8, 8, 0): /* DWRITEM dst,src1,mask,space_QWORD */
+ (*active_address_space[PARAM3 / 16].accessors->write_qword_masked)(PARAM0, DPARAM1, DPARAM2);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_WRIT8M, 8, 0): /* DWRIT8M space,dst,mask,src1 */
- (*active_address_space[PARAM0].accessors->write_qword_masked)(PARAM1, DPARAM3, DPARAM2);
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_FLAGS, 8, 0): /* DFLAGS dst,mask,table */
- DPARAM0 = (DPARAM0 & ~DPARAM1) | (inst[2].puint64[flags & 0x0f] & DPARAM1);
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_SETC, 8, 0): /* DSETC src,bitnum */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_CARRY, 8, 0): /* DCARRY src,bitnum */
flags = (flags & ~DRCUML_FLAG_C) | ((DPARAM0 >> (DPARAM1 & 63)) & DRCUML_FLAG_C);
break;
@@ -1154,36 +1207,28 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
DPARAM0 = DPARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_ZEXT1, 8, 0): /* DZEXT1 dst,src */
- DPARAM0 = (UINT8)PARAM1;
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_ZEXT2, 8, 0): /* DZEXT2 dst,src */
- DPARAM0 = (UINT16)PARAM1;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_SET, 8, 1): /* DSET dst,c */
+ DPARAM0 = OPCODE_FAIL_CONDITION(opcode, flags) ? 0 : 1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_ZEXT4, 8, 0): /* DZEXT4 dst,src */
- DPARAM0 = (UINT32)PARAM1;
- break;
-
- case MAKE_OPCODE_SHORT(DRCUML_OP_SEXT1, 8, 0): /* DSEXT1 dst,src */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_SEXT1, 8, 0): /* DSEXT dst,src,BYTE */
DPARAM0 = (INT8)PARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_SEXT2, 8, 0): /* DSEXT2 dst,src */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_SEXT2, 8, 0): /* DSEXT dst,src,WORD */
DPARAM0 = (INT16)PARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_SEXT4, 8, 0): /* DSEXT4 dst,src */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_SEXT4, 8, 0): /* DSEXT dst,src,DWORD */
DPARAM0 = (INT32)PARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_XTRACT, 8, 0): /* DXTRACT dst,src,count,mask[,f] */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_ROLAND, 8, 0): /* DROLAND dst,src,count,mask[,f] */
shift = DPARAM2 & 63;
DPARAM0 = ((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_INSERT, 8, 0): /* DINSERT dst,src,count,mask[,f] */
+ case MAKE_OPCODE_SHORT(DRCUML_OP_ROLINS, 8, 0): /* DROLINS dst,src,count,mask[,f] */
shift = DPARAM2 & 63;
DPARAM0 = (DPARAM0 & ~DPARAM3) | (((DPARAM1 << shift) | (DPARAM1 >> (64 - shift))) & DPARAM3);
break;
@@ -1455,12 +1500,12 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
inst[0].pfloat[PARAM1] = FSPARAM2;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FREAD, 4, 0): /* FSREAD dst,space,src1 */
- PARAM0 = (UINT32)(*active_address_space[PARAM1].accessors->read_dword)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FREAD, 4, 0): /* FSREAD dst,src1,space */
+ PARAM0 = (UINT32)(*active_address_space[PARAM2].accessors->read_dword)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FWRITE, 4, 0): /* FSWRITE space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_dword)(PARAM1, PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FWRITE, 4, 0): /* FSWRITE dst,src1,space */
+ (*active_address_space[PARAM2].accessors->write_dword)(PARAM0, PARAM1);
break;
case MAKE_OPCODE_SHORT(DRCUML_OP_FMOV, 4, 1): /* FSMOV dst,src[,c] */
@@ -1472,10 +1517,6 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
FSPARAM0 = FSPARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI4, 4, 0): /* FSTOI4 dst,src1 */
- *inst[0].pint32 = FSPARAM1;
- break;
-
case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI4T, 4, 0): /* FSTOI4T dst,src1 */
if (FSPARAM1 >= 0)
*inst[0].pint32 = floor(FSPARAM1);
@@ -1498,8 +1539,8 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
*inst[0].pint32 = ceil(FSPARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI8, 4, 0): /* FSTOI8 dst,src1 */
- *inst[0].pint64 = FSPARAM1;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI4, 4, 0): /* FSTOI4 dst,src1 */
+ *inst[0].pint32 = FSPARAM1;
break;
case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI8T, 4, 0): /* FSTOI8T dst,src1 */
@@ -1524,8 +1565,8 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
*inst[0].pint64 = ceil(FSPARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FFRFD, 4, 0): /* FSFRFD dst,src1 */
- FSPARAM0 = FDPARAM1;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI8, 4, 0): /* FSTOI8 dst,src1 */
+ *inst[0].pint64 = FSPARAM1;
break;
case MAKE_OPCODE_SHORT(DRCUML_OP_FFRI4, 4, 0): /* FSFRI4 dst,src1 */
@@ -1536,6 +1577,10 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
FSPARAM0 = *inst[1].pint64;
break;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FFRFD, 4, 0): /* FSFRFD dst,src1 */
+ FSPARAM0 = FDPARAM1;
+ break;
+
case MAKE_OPCODE_SHORT(DRCUML_OP_FADD, 4, 0): /* FSADD dst,src1,src2 */
FSPARAM0 = FSPARAM1 + FSPARAM2;
break;
@@ -1590,12 +1635,12 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
inst[0].pdouble[PARAM1] = FDPARAM2;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FREAD, 8, 0): /* FDREAD dst,space,src1 */
- DPARAM0 = (UINT64)(*active_address_space[PARAM1].accessors->read_qword)(PARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FREAD, 8, 0): /* FDREAD dst,src1,space */
+ DPARAM0 = (UINT64)(*active_address_space[PARAM2].accessors->read_qword)(PARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FWRITE, 8, 0): /* FDWRITE space,dst,src1 */
- (*active_address_space[PARAM0].accessors->write_qword)(PARAM1, DPARAM2);
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FWRITE, 8, 0): /* FDWRITE dst,src1,space */
+ (*active_address_space[PARAM2].accessors->write_qword)(PARAM0, DPARAM1);
break;
case MAKE_OPCODE_SHORT(DRCUML_OP_FMOV, 8, 1): /* FDMOV dst,src[,c] */
@@ -1607,10 +1652,6 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
FDPARAM0 = FDPARAM1;
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI4, 8, 0): /* FDTOI4 dst,src1 */
- *inst[0].pint32 = FDPARAM1;
- break;
-
case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI4T, 8, 0): /* FDTOI4T dst,src1 */
if (FDPARAM1 >= 0)
*inst[0].pint32 = floor(FDPARAM1);
@@ -1633,8 +1674,8 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
*inst[0].pint32 = ceil(FDPARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI8, 8, 0): /* FDTOI8 dst,src1 */
- *inst[0].pint64 = FDPARAM1;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI4, 8, 0): /* FDTOI4 dst,src1 */
+ *inst[0].pint32 = FDPARAM1;
break;
case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI8T, 8, 0): /* FDTOI8T dst,src1 */
@@ -1659,8 +1700,8 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
*inst[0].pint64 = ceil(FDPARAM1);
break;
- case MAKE_OPCODE_SHORT(DRCUML_OP_FFRFS, 8, 0): /* FDFRFS dst,src1 */
- FDPARAM0 = FSPARAM1;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FTOI8, 8, 0): /* FDTOI8 dst,src1 */
+ *inst[0].pint64 = FDPARAM1;
break;
case MAKE_OPCODE_SHORT(DRCUML_OP_FFRI4, 8, 0): /* FDFRI4 dst,src1 */
@@ -1671,6 +1712,14 @@ static int drcbec_execute(drcbe_state *drcbe, drcuml_codehandle *entry)
FDPARAM0 = *inst[1].pint64;
break;
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FFRFS, 8, 0): /* FDFRFS dst,src1 */
+ FDPARAM0 = FSPARAM1;
+ break;
+
+ case MAKE_OPCODE_SHORT(DRCUML_OP_FRNDS, 8, 0): /* FDRNDS dst,src1 */
+ FDPARAM0 = (float)FDPARAM1;
+ break;
+
case MAKE_OPCODE_SHORT(DRCUML_OP_FADD, 8, 0): /* FDADD dst,src1,src2 */
FDPARAM0 = FDPARAM1 + FDPARAM2;
break;
diff --git a/src/emu/cpu/drcbex64.c b/src/emu/cpu/drcbex64.c
index 29dc2377f2d..1e4dd02e44b 100644
--- a/src/emu/cpu/drcbex64.c
+++ b/src/emu/cpu/drcbex64.c
@@ -18,6 +18,8 @@
* Identify common pairs and optimize output
+ * Convert AND 0xff/0xffff to movzx
+
****************************************************************************
-------------------------
@@ -396,48 +398,23 @@ static x86code *op_recover(drcbe_state *drcbe, x86code *dst, const drcuml_instru
static x86code *op_setfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_getfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_getexp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_getflgs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_save(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_restore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_writ2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_writ4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_writ8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_flags(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_setc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_loads(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_store(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_read(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_readm(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_write(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_writem(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_carry(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_set(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_mov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_zext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_zext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_zext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_sext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_sext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_sext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_xtract(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_insert(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_sext(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_roland(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_rolins(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_add(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_addc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_sub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
@@ -466,20 +443,10 @@ static x86code *op_fstore(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
static x86code *op_fread(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fwrite(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffrfs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffrfd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffri4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffri8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_ftoint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_ffrint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_ffrflt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_frnds(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fadd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fsub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fcmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
@@ -514,50 +481,25 @@ static const opcode_table_entry opcode_table_source[] =
/* Internal Register Operations */
{ DRCUML_OP_SETFMOD, op_setfmod }, /* SETFMOD src */
{ DRCUML_OP_GETFMOD, op_getfmod }, /* GETFMOD dst */
- { DRCUML_OP_GETEXP, op_getexp }, /* GETEXP dst,index */
- { DRCUML_OP_SAVE, op_save }, /* SAVE dst,index */
- { DRCUML_OP_RESTORE, op_restore }, /* RESTORE dst,index */
+ { DRCUML_OP_GETEXP, op_getexp }, /* GETEXP dst */
+ { DRCUML_OP_GETFLGS, op_getflgs }, /* GETFLGS dst[,f] */
+ { DRCUML_OP_SAVE, op_save }, /* SAVE dst */
+ { DRCUML_OP_RESTORE, op_restore }, /* RESTORE dst */
/* Integer Operations */
- { DRCUML_OP_LOAD1U, op_load1u }, /* LOAD1U dst,base,index */
- { DRCUML_OP_LOAD1S, op_load1s }, /* LOAD1S dst,base,index */
- { DRCUML_OP_LOAD2U, op_load2u }, /* LOAD2U dst,base,index */
- { DRCUML_OP_LOAD2S, op_load2s }, /* LOAD2S dst,base,index */
- { DRCUML_OP_LOAD4U, op_load4u }, /* LOAD4U dst,base,index */
- { DRCUML_OP_LOAD4S, op_load4s }, /* LOAD4S dst,base,index */
- { DRCUML_OP_LOAD8U, op_load8u }, /* LOAD8U dst,base,index */
- { DRCUML_OP_STORE1, op_store1 }, /* STORE1 base,index,src */
- { DRCUML_OP_STORE2, op_store2 }, /* STORE2 base,index,src */
- { DRCUML_OP_STORE4, op_store4 }, /* STORE4 base,index,src */
- { DRCUML_OP_STORE8, op_store8 }, /* STORE8 base,index,src */
- { DRCUML_OP_READ1U, op_read1u }, /* READ1U dst,space,src1 */
- { DRCUML_OP_READ1S, op_read1s }, /* READ1S dst,space,src1 */
- { DRCUML_OP_READ2U, op_read2u }, /* READ2U dst,space,src1 */
- { DRCUML_OP_READ2S, op_read2s }, /* READ2S dst,space,src1 */
- { DRCUML_OP_READ2M, op_read2m }, /* READ2M dst,space,src1,mask */
- { DRCUML_OP_READ4U, op_read4u }, /* READ4U dst,space,src1 */
- { DRCUML_OP_READ4S, op_read4s }, /* READ4S dst,space,src1 */
- { DRCUML_OP_READ4M, op_read4m }, /* READ4M dst,space,src1,mask */
- { DRCUML_OP_READ8U, op_read8u }, /* READ8U dst,space,src1 */
- { DRCUML_OP_READ8M, op_read8m }, /* READ8M dst,space,src1,mask */
- { DRCUML_OP_WRITE1, op_write1 }, /* WRITE1 space,dst,src1 */
- { DRCUML_OP_WRITE2, op_write2 }, /* WRITE2 space,dst,src1 */
- { DRCUML_OP_WRIT2M, op_writ2m }, /* WRIT2M space,dst,src1 */
- { DRCUML_OP_WRITE4, op_write4 }, /* WRITE4 space,dst,src1 */
- { DRCUML_OP_WRIT4M, op_writ4m }, /* WRIT4M space,dst,mask,src1 */
- { DRCUML_OP_WRITE8, op_write8 }, /* WRITE8 space,dst,src1 */
- { DRCUML_OP_WRIT8M, op_writ8m }, /* WRIT8M space,dst,mask,src1 */
- { DRCUML_OP_FLAGS, op_flags }, /* FLAGS dst,mask,table */
- { DRCUML_OP_SETC, op_setc }, /* FLAGS src,bitnum */
+ { DRCUML_OP_LOAD, op_load }, /* LOAD dst,base,index,size */
+ { DRCUML_OP_LOADS, op_loads }, /* LOADS dst,base,index,size */
+ { DRCUML_OP_STORE, op_store }, /* STORE base,index,src,size */
+ { DRCUML_OP_READ, op_read }, /* READ dst,src1,spacesize */
+ { DRCUML_OP_READM, op_readm }, /* READM dst,src1,mask,spacesize */
+ { DRCUML_OP_WRITE, op_write }, /* WRITE dst,src1,spacesize */
+ { DRCUML_OP_WRITEM, op_writem }, /* WRITEM dst,src1,spacesize */
+ { DRCUML_OP_CARRY, op_carry }, /* CARRY src,bitnum */
+ { DRCUML_OP_SET, op_set }, /* SET dst,c */
{ DRCUML_OP_MOV, op_mov }, /* MOV dst,src[,c] */
- { DRCUML_OP_ZEXT1, op_zext1 }, /* ZEXT1 dst,src */
- { DRCUML_OP_ZEXT2, op_zext2 }, /* ZEXT2 dst,src */
- { DRCUML_OP_ZEXT4, op_zext4 }, /* ZEXT4 dst,src */
- { DRCUML_OP_SEXT1, op_sext1 }, /* SEXT1 dst,src */
- { DRCUML_OP_SEXT2, op_sext2 }, /* SEXT2 dst,src */
- { DRCUML_OP_SEXT4, op_sext4 }, /* SEXT4 dst,src */
- { DRCUML_OP_XTRACT, op_xtract }, /* XTRACT dst,src1,src2,src3 */
- { DRCUML_OP_INSERT, op_insert }, /* INSERT dst,src1,src2,src3 */
+ { DRCUML_OP_SEXT, op_sext }, /* SEXT dst,src */
+ { DRCUML_OP_ROLAND, op_roland }, /* ROLAND dst,src1,src2,src3 */
+ { DRCUML_OP_ROLINS, op_rolins }, /* ROLINS dst,src1,src2,src3 */
{ DRCUML_OP_ADD, op_add }, /* ADD dst,src1,src2[,f] */
{ DRCUML_OP_ADDC, op_addc }, /* ADDC dst,src1,src2[,f] */
{ DRCUML_OP_SUB, op_sub }, /* SUB dst,src1,src2[,f] */
@@ -587,20 +529,10 @@ static const opcode_table_entry opcode_table_source[] =
{ DRCUML_OP_FREAD, op_fread }, /* FREAD dst,space,src1 */
{ DRCUML_OP_FWRITE, op_fwrite }, /* FWRITE space,dst,src1 */
{ DRCUML_OP_FMOV, op_fmov }, /* FMOV dst,src1[,c] */
- { DRCUML_OP_FTOI4, op_ftoi4 }, /* FTOI4 dst,src1 */
- { DRCUML_OP_FTOI4T, op_ftoi4t }, /* FTOI4T dst,src1 */
- { DRCUML_OP_FTOI4R, op_ftoi4r }, /* FTOI4R dst,src1 */
- { DRCUML_OP_FTOI4F, op_ftoi4f }, /* FTOI4F dst,src1 */
- { DRCUML_OP_FTOI4C, op_ftoi4c }, /* FTOI4C dst,src1 */
- { DRCUML_OP_FTOI8, op_ftoi8 }, /* FTOI8 dst,src1 */
- { DRCUML_OP_FTOI8T, op_ftoi8t }, /* FTOI8T dst,src1 */
- { DRCUML_OP_FTOI8R, op_ftoi8r }, /* FTOI8R dst,src1 */
- { DRCUML_OP_FTOI8F, op_ftoi8f }, /* FTOI8F dst,src1 */
- { DRCUML_OP_FTOI8C, op_ftoi8c }, /* FTOI8C dst,src1 */
- { DRCUML_OP_FFRFS, op_ffrfs }, /* FFRFS dst,src1 */
- { DRCUML_OP_FFRFD, op_ffrfd }, /* FFRFD dst,src1 */
- { DRCUML_OP_FFRI4, op_ffri4 }, /* FFRI4 dst,src1 */
- { DRCUML_OP_FFRI8, op_ffri8 }, /* FFRI8 dst,src1 */
+ { DRCUML_OP_FTOINT, op_ftoint }, /* FTOINT dst,src1,size,round */
+ { DRCUML_OP_FFRINT, op_ffrint }, /* FFRINT dst,src1,size */
+ { DRCUML_OP_FFRFLT, op_ffrflt }, /* FFRFLT dst,src1,size */
+ { DRCUML_OP_FRNDS, op_frnds }, /* FRNDS dst,src1 */
{ DRCUML_OP_FADD, op_fadd }, /* FADD dst,src1,src2 */
{ DRCUML_OP_FSUB, op_fsub }, /* FSUB dst,src1,src2 */
{ DRCUML_OP_FCMP, op_fcmp }, /* FCMP src1,src2 */
@@ -3553,6 +3485,133 @@ static x86code *op_getexp(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
+ op_getflgs - process a GETFLGS opcode
+-------------------------------------------------*/
+
+static x86code *op_getflgs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+{
+ drcuml_parameter dstp;
+ int dstreg;
+
+ /* validate instruction */
+ assert(inst->size == 4);
+ assert(inst->condflags != DRCUML_COND_ALWAYS);
+
+ /* normalize parameters */
+ param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
+
+ /* pick a target register for the general case */
+ dstreg = param_select_register(REG_EAX, &dstp, NULL);
+
+ switch (inst->condflags)
+ {
+ /* single flags only */
+ case DRCUML_FLAG_C:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ break;
+
+ case DRCUML_FLAG_V:
+ emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case DRCUML_FLAG_Z:
+ emit_setcc_r8(&dst, COND_Z, REG_AL); // setz al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ case DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_S, REG_AL); // sets al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 3); // shl dstreg,3
+ break;
+
+ case DRCUML_FLAG_U:
+ emit_setcc_r8(&dst, COND_P, REG_AL); // setp al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 4); // shl dstreg,4
+ break;
+
+ /* carry plus another flag */
+ case DRCUML_FLAG_C | DRCUML_FLAG_V:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_setcc_r8(&dst, COND_O, REG_CL); // seto cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ break;
+
+ case DRCUML_FLAG_C | DRCUML_FLAG_Z:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_setcc_r8(&dst, COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ break;
+
+ case DRCUML_FLAG_C | DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 8, 0)); // lea dstreg,[eax+ecx*8]
+ break;
+
+ /* overflow plus another flag */
+ case DRCUML_FLAG_V | DRCUML_FLAG_Z:
+ emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
+ emit_setcc_r8(&dst, COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case DRCUML_FLAG_V | DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
+ emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ /* zero plus another flag */
+ case DRCUML_FLAG_Z | DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_Z, REG_AL); // setz al
+ emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(&dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ /* default cases */
+ default:
+ emit_pushf(&dst); // pushf
+ emit_pop_r64(&dst, REG_EAX); // pop eax
+ emit_and_r32_imm(&dst, REG_EAX, 0x8c5); // and eax,0x8c5
+ emit_movzx_r32_m8(&dst, dstreg, MBISD(REG_RBP, REG_RAX, 1, offset_from_rbp(drcbe, (FPTR)&drcbe->flagsmap[0])));
+ // movzx dstreg,[flags_map]
+ break;
+ }
+
+ /* 32-bit form */
+ if (inst->size == 4)
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+
+ /* 64-bit form */
+ else if (inst->size == 8)
+ emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+
+ return dst;
+}
+
+
+/*-------------------------------------------------
op_save - process a SAVE opcode
-------------------------------------------------*/
@@ -3680,12 +3739,12 @@ static x86code *op_restore(drcbe_state *drcbe, x86code *dst, const drcuml_instru
***************************************************************************/
/*-------------------------------------------------
- op_load1u - process a LOAD1U opcode
+ op_load - process a LOAD opcode
-------------------------------------------------*/
-static x86code *op_load1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, basep, indp;
+ drcuml_parameter dstp, basep, indp, sizep;
int basereg, dstreg;
INT32 baseoffs;
@@ -3694,30 +3753,46 @@ static x86code *op_load1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI, &sizep, PTYPE_I);
/* determine the pointer base */
basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
+ /* pick a target register for the general case */
+ dstreg = param_select_register(REG_EAX, &dstp, NULL);
+
/* immediate index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movzx_r32_m8(&dst, dstreg, MBD(basereg, baseoffs + 1*indp.value)); // movzx dstreg,[basep + 1*indp]
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movzx_r32_m8(&dst, dstreg, MBD(basereg, baseoffs + 1*indp.value)); // movzx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movzx_r32_m16(&dst, dstreg, MBD(basereg, baseoffs + 2*indp.value)); // movzx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MBD(basereg, baseoffs + 4*indp.value)); // mov dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_r64_m64(&dst, dstreg, MBD(basereg, baseoffs + 8*indp.value)); // mov dstreg,[basep + 8*indp]
+ }
/* other index */
else
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movzx_r32_m8(&dst, dstreg, MBISD(basereg, indreg, 1, baseoffs)); // movzx dstreg,[basep + 1*indp]
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movzx_r32_m8(&dst, dstreg, MBISD(basereg, indreg, 1, baseoffs)); // movzx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movzx_r32_m16(&dst, dstreg, MBISD(basereg, indreg, 2, baseoffs)); // movzx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MBISD(basereg, indreg, 4, baseoffs)); // mov dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_r64_m64(&dst, dstreg, MBISD(basereg, indreg, 8, baseoffs)); // mov dstreg,[basep + 8*indp]
}
- /* store to appropriate target size */
+ /* store result */
if (inst->size == 4)
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- else if (inst->size == 8)
+ else
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
return dst;
@@ -3725,12 +3800,12 @@ static x86code *op_load1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
- op_load1s - process a LOAD1S opcode
+ op_loads - process a LOADS opcode
-------------------------------------------------*/
-static x86code *op_load1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_loads(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, basep, indp;
+ drcuml_parameter dstp, basep, indp, sizep;
int basereg, dstreg;
INT32 baseoffs;
@@ -3739,325 +3814,139 @@ static x86code *op_load1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI, &sizep, PTYPE_I);
/* determine the pointer base */
basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
- /* 32-bit form */
- if (inst->size == 4)
- {
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movsx_r32_m8(&dst, dstreg, MBD(basereg, baseoffs + 1*indp.value)); // movsx eax,[basep + 1*indp]
-
- /* other index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movsx_r32_m8(&dst, dstreg, MBISD(basereg, indreg, 1, baseoffs)); // movsx eax,[basep + 1*indp]
- }
-
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* 64-bit form */
- else
- {
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movsx_r64_m8(&dst, dstreg, MBD(basereg, baseoffs + 1*indp.value)); // movsx rax,[basep + 1*indp]
-
- /* other index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movsx_r64_m8(&dst, dstreg, MBISD(basereg, indreg, 1, baseoffs)); // movsx rax,[basep + 1*indp]
- }
-
- /* general case */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load2u - process a LOAD2U opcode
--------------------------------------------------*/
-
-static x86code *op_load2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
- int basereg, dstreg;
- INT32 baseoffs;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
/* pick a target register for the general case */
dstreg = param_select_register(REG_EAX, &dstp, NULL);
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
-
/* immediate index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movzx_r32_m16(&dst, dstreg, MBD(basereg, baseoffs + 2*indp.value)); // movzx dstreg,[basep + 2*indp]
-
- /* other index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movzx_r32_m16(&dst, dstreg, MBISD(basereg, indreg, 2, baseoffs)); // movzx dstreg,[basep + 2*indp]
- }
-
- /* store to appropriate target size */
- if (inst->size == 4)
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- else if (inst->size == 8)
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load2s - process a LOAD2S opcode
--------------------------------------------------*/
-
-static x86code *op_load2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
- int basereg, dstreg;
- INT32 baseoffs;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
-
- /* 32-bit form */
- if (inst->size == 4)
{
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movsx_r32_m16(&dst, dstreg, MBD(basereg, baseoffs + 2*indp.value)); // movsx eax,[basep + 2*indp]
-
- /* other index */
- else
+ if (inst->size == 4)
{
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movsx_r32_m16(&dst, dstreg, MBISD(basereg, indreg, 2, baseoffs)); // movsx eax,[basep + 2*indp]
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r32_m8(&dst, dstreg, MBD(basereg, baseoffs + 1*indp.value)); // movsx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_m16(&dst, dstreg, MBD(basereg, baseoffs + 2*indp.value));// movsx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MBD(basereg, baseoffs + 4*indp.value)); // mov dstreg,[basep + 4*indp]
}
-
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* 64-bit form */
- else
- {
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movsx_r64_m16(&dst, dstreg, MBD(basereg, baseoffs + 2*indp.value)); // movsx rax,[basep + 2*indp]
-
- /* other index */
- else
+ else if (inst->size == 8)
{
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movsx_r64_m16(&dst, dstreg, MBISD(basereg, indreg, 2, baseoffs)); // movsx rax,[basep + 2*indp]
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r64_m8(&dst, dstreg, MBD(basereg, baseoffs + 1*indp.value)); // movzx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r64_m16(&dst, dstreg, MBD(basereg, baseoffs + 2*indp.value));// movzx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_movsxd_r64_m32(&dst, dstreg, MBD(basereg, baseoffs + 4*indp.value));// movsxd dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_r64_m64(&dst, dstreg, MBD(basereg, baseoffs + 8*indp.value)); // mov dstreg,[basep + 8*indp]
}
-
- /* general case */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load4u - process a LOAD4U opcode
--------------------------------------------------*/
-
-static x86code *op_load4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
- int basereg, dstreg;
- INT32 baseoffs;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
-
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_r32_m32(&dst, dstreg, MBD(basereg, baseoffs + 4*indp.value)); // mov dstreg,[basep + 4*indp]
/* other index */
else
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_mov_r32_m32(&dst, dstreg, MBISD(basereg, indreg, 4, baseoffs)); // mov dstreg,[basep + 4*indp]
+ if (inst->size == 4)
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r32_m8(&dst, dstreg, MBISD(basereg, indreg, 1, baseoffs)); // movsx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_m16(&dst, dstreg, MBISD(basereg, indreg, 2, baseoffs)); // movsx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MBISD(basereg, indreg, 4, baseoffs)); // mov dstreg,[basep + 4*indp]
+ }
+ else if (inst->size == 8)
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r64_m8(&dst, dstreg, MBISD(basereg, indreg, 1, baseoffs)); // movsx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r64_m16(&dst, dstreg, MBISD(basereg, indreg, 2, baseoffs)); // movsx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_movsxd_r64_m32(&dst, dstreg, MBISD(basereg, indreg, 4, baseoffs)); // movsxd dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_r64_m64(&dst, dstreg, MBISD(basereg, indreg, 8, baseoffs)); // mov dstreg,[basep + 8*indp]
+ }
}
- /* store to appropriate target size */
+ /* store result */
if (inst->size == 4)
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- else if (inst->size == 8)
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load4s - process a LOAD4S opcode
--------------------------------------------------*/
-
-static x86code *op_load4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
- int basereg, dstreg;
- INT32 baseoffs;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
-
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movsxd_r64_m32(&dst, dstreg, MBD(basereg, baseoffs + 4*indp.value)); // mov dstreg,[basep + 4*indp]
-
- /* other index */
else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movsxd_r64_m32(&dst, dstreg, MISD(indreg, 4, basep.value)); // movsx dstreg,[basep + 4*indp]
- }
-
- /* general case */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
return dst;
}
/*-------------------------------------------------
- op_load8u - process a LOAD8U opcode
+ op_store - process a STORE opcode
-------------------------------------------------*/
-static x86code *op_load8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_store(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, basep, indp;
- int basereg, dstreg;
+ drcuml_parameter srcp, basep, indp, sizep;
+ int srcreg, basereg;
INT32 baseoffs;
/* validate instruction */
- assert(inst->size == 8);
+ assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
+ param_normalize_4(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
/* determine the pointer base */
basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_r64_m64(&dst, dstreg, MBD(basereg, baseoffs + 8*indp.value)); // mov dstreg,[basep + 8*indp]
-
- /* other index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_mov_r64_m64(&dst, dstreg, MBISD(basereg, indreg, 8, baseoffs)); // mov dstreg,[basep + 8*indp]
- }
-
- /* general case */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,edx:dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_store1 - process a STORE1 opcode
--------------------------------------------------*/
-
-static x86code *op_store1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter srcp, basep, indp;
- int basereg, srcreg;
- INT32 baseoffs;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
/* pick a source register for the general case */
srcreg = param_select_register(REG_EAX, &srcp, NULL);
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
-
/* degenerate case: constant index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
{
+ /* immediate source */
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m8_imm(&dst, MBD(basereg, baseoffs + 1*indp.value), srcp.value); // mov [basep + 1*indp],srcp
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_imm(&dst, MBD(basereg, baseoffs + 1*indp.value), srcp.value); // mov [basep + 1*indp],srcp
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_imm(&dst, MBD(basereg, baseoffs + 2*indp.value), srcp.value); // mov [basep + 2*indp],srcp
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_imm(&dst, MBD(basereg, baseoffs + 4*indp.value), srcp.value); // mov [basep + 4*indp],srcp
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ if (short_immediate(srcp.value))
+ emit_mov_m64_imm(&dst, MBD(basereg, baseoffs + 8*indp.value), srcp.value);// mov [basep + 8*indp],srcp
+ else
+ {
+ emit_mov_m32_imm(&dst, MBD(basereg, baseoffs + 8*indp.value), srcp.value);// mov [basep + 8*indp],srcp
+ emit_mov_m32_imm(&dst, MBD(basereg, baseoffs + 8*indp.value + 4), srcp.value >> 32);
+ // mov [basep + 8*indp + 4],srcp >> 32
+ }
+ }
+ }
+
+ /* variable source */
else
{
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m8_r8(&dst, MBD(basereg, baseoffs + 1*indp.value), srcreg); // mov [basep + 1*indp],srcreg
+ if (sizep.value != DRCUML_SIZE_QWORD)
+ emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_r8(&dst, MBD(basereg, baseoffs + 1*indp.value), srcreg); // mov [basep + 1*indp],srcreg
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_r16(&dst, MBD(basereg, baseoffs + 2*indp.value), srcreg); // mov [basep + 2*indp],srcreg
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_r32(&dst, MBD(basereg, baseoffs + 4*indp.value), srcreg); // mov [basep + 4*indp],srcreg
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_m64_r64(&dst, MBD(basereg, baseoffs + 8*indp.value), srcreg); // mov [basep + 8*indp],srcreg
}
}
@@ -4066,64 +3955,44 @@ static x86code *op_store1(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m8_imm(&dst, MBISD(basereg, indreg, 1, baseoffs), srcp.value); // mov [basep + 1*ecx],srcp
- else
- {
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m8_r8(&dst, MBISD(basereg, indreg, 1, baseoffs), srcreg); // mov [basep + 1*ecx],srcreg
- }
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_store2 - process a STORE2 opcode
--------------------------------------------------*/
-
-static x86code *op_store2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter srcp, basep, indp;
- int basereg, srcreg;
- INT32 baseoffs;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
- /* pick a source register for the general case */
- srcreg = param_select_register(REG_EAX, &srcp, NULL);
-
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
-
- /* degenerate case: constant index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- {
+ /* immediate source */
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m16_imm(&dst, MBD(basereg, baseoffs + 2*indp.value), srcp.value); // mov [basep + 2*indp],srcp
- else
{
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m16_r16(&dst, MBD(basereg, baseoffs + 2*indp.value), srcreg); // mov [basep + 2*indp],srcreg
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_imm(&dst, MBISD(basereg, indreg, 1, baseoffs), srcp.value); // mov [basep + 1*ecx],srcp
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_imm(&dst, MBISD(basereg, indreg, 2, baseoffs), srcp.value);// mov [basep + 2*ecx],srcp
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_imm(&dst, MBISD(basereg, indreg, 4, baseoffs), srcp.value);// mov [basep + 4*ecx],srcp
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ if (short_immediate(srcp.value))
+ emit_mov_m64_imm(&dst, MBISD(basereg, indreg, 8, baseoffs), srcp.value);// mov [basep + 8*indp],srcp
+ else
+ {
+ emit_mov_m32_imm(&dst, MBISD(basereg, indreg, 8, baseoffs), srcp.value);// mov [basep + 8*ecx],srcp
+ emit_mov_m32_imm(&dst, MBISD(basereg, indreg, 8, baseoffs + 4), srcp.value >> 32);
+ // mov [basep + 8*ecx + 4],srcp >> 32
+ }
+ }
}
- }
- /* normal case: variable index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m16_imm(&dst, MBISD(basereg, indreg, 2, baseoffs), srcp.value); // mov [basep + 2*ecx],srcp
+ /* variable source */
else
{
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m16_r16(&dst, MBISD(basereg, indreg, 2, baseoffs), srcreg); // mov [basep + 2*ecx],srcreg
+ if (sizep.value != DRCUML_SIZE_QWORD)
+ emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov edx:srcreg,srcp
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_r8(&dst, MBISD(basereg, indreg, 1, baseoffs), srcreg); // mov [basep + 1*ecx],srcreg
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_r16(&dst, MBISD(basereg, indreg, 2, baseoffs), srcreg); // mov [basep + 2*ecx],srcreg
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_r32(&dst, MBISD(basereg, indreg, 4, baseoffs), srcreg); // mov [basep + 4*ecx],srcreg
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_m64_r64(&dst, MBISD(basereg, indreg, 8, baseoffs), srcreg); // mov [basep + 8*ecx],srcreg
}
}
return dst;
@@ -4131,137 +4000,57 @@ static x86code *op_store2(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
- op_store4 - process a STORE4 opcode
+ op_read - process a READ opcode
-------------------------------------------------*/
-static x86code *op_store4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_read(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter srcp, basep, indp;
- int basereg, srcreg;
- INT32 baseoffs;
+ drcuml_parameter dstp, addrp, spacesizep;
+ int dstreg;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &spacesizep, PTYPE_I);
- /* pick a source register for the general case */
- srcreg = param_select_register(REG_EAX, &srcp, NULL);
-
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
+ /* pick a target register for the general case */
+ dstreg = param_select_register(REG_EAX, &dstp, NULL);
- /* degenerate case: constant index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
+ /* set up a call to the read byte handler */
+ emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
+ if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE)
{
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m32_imm(&dst, MBD(basereg, baseoffs + 4*indp.value), srcp.value); // mov [basep + 4*indp],srcp
- else
- {
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m32_r32(&dst, MBD(basereg, baseoffs + 4*indp.value), srcreg); // mov [basep + 4*indp],srcreg
- }
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].read_byte);
+ // call read_byte
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
}
-
- /* normal case: variable index */
- else
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
{
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m32_imm(&dst, MBISD(basereg, indreg, 4, baseoffs), srcp.value); // mov [basep + 4*ecx],srcp
- else
- {
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m32_r32(&dst, MBISD(basereg, indreg, 4, baseoffs), srcreg); // mov [basep + 4*ecx],srcreg
- }
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].read_word);
+ // call read_word
+ emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_store8 - process a STORE8 opcode
--------------------------------------------------*/
-
-static x86code *op_store8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter srcp, basep, indp;
- int basereg, srcreg;
- INT32 baseoffs;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* pick a source register for the general case */
- srcreg = param_select_register(REG_EAX, &srcp, NULL);
-
- /* determine the pointer base */
- basereg = get_base_register_and_offset(drcbe, &dst, basep.value, REG_RDX, &baseoffs);
-
- /* degenerate case: constant index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
{
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE && short_immediate(srcp.value))
- emit_mov_m64_imm(&dst, MBD(basereg, baseoffs + 8*indp.value), srcp.value); // mov [basep + 8*indp],srcp
- else
- {
- emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m64_r64(&dst, MBD(basereg, baseoffs + 8*indp.value), srcreg); // mov [basep + 8*indp],srcreg
- }
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].read_dword);
+ // call read_dword
+ if (dstreg != REG_EAX || inst->size == 8)
+ emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
}
-
- /* normal case: variable index */
- else
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
{
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE && short_immediate(srcp.value))
- emit_mov_m64_imm(&dst, MBISD(basereg, indreg, 8, baseoffs), srcp.value); // mov [basep + 8*ecx],srcp
- else
- {
- emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m64_r64(&dst, MBISD(basereg, indreg, 8, baseoffs), srcreg); // mov [basep + 8*ecx],srcreg
- }
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].read_qword);
+ // call read_qword
+ if (dstreg != REG_RAX)
+ emit_mov_r64_r64(&dst, dstreg, REG_RAX); // mov dstreg,rax
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read1u - process a READ1U opcode
--------------------------------------------------*/
-
-static x86code *op_read1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read byte handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_byte);// call read_byte
- emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
- /* store to appropriate target size */
+ /* store result */
if (inst->size == 4)
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- else if (inst->size == 8)
+ else
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
return dst;
@@ -4269,12 +4058,12 @@ static x86code *op_read1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
- op_read1s - process a READ1S opcode
+ op_readm - process a READM opcode
-------------------------------------------------*/
-static x86code *op_read1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_readm(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, spacep, addrp;
+ drcuml_parameter dstp, addrp, maskp, spacesizep;
int dstreg;
/* validate instruction */
@@ -4282,139 +4071,42 @@ static x86code *op_read1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &spacesizep, PTYPE_I);
/* pick a target register for the general case */
dstreg = param_select_register(REG_EAX, &dstp, NULL);
/* set up a call to the read byte handler */
emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_byte);// call read_byte
-
- /* 32-bit form */
- if (inst->size == 4)
- {
- /* general case */
- emit_movsx_r32_r8(&dst, dstreg, REG_AL); // movsx dstreg,al
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* 64-bit form */
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
+ emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &maskp); // mov param2,maskp
else
+ emit_mov_r64_p64(drcbe, &dst, REG_PARAM2, &maskp); // mov param2,maskp
+ if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
{
- /* general case */
- emit_movsx_r64_r8(&dst, dstreg, REG_AL); // movsx dstreg,al
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].read_word_masked);
+ // call read_word_masked
+ emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read2u - process a READ2U opcode
--------------------------------------------------*/
-
-static x86code *op_read2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read word handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_word);// call read_word
- emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
-
- /* store to appropriate target size */
- if (inst->size == 4)
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- else if (inst->size == 8)
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read2s - process a READ2S opcode
--------------------------------------------------*/
-
-static x86code *op_read2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read word handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_word);// call read_word
-
- /* 32-bit form */
- if (inst->size == 4)
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
{
- /* general case */
- emit_movsx_r32_r16(&dst, dstreg, REG_AX); // movsx dstreg,ax
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].read_dword_masked);
+ // call read_dword_masked
+ if (dstreg != REG_EAX || inst->size == 8)
+ emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
}
-
- /* 64-bit form */
- else
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
{
- /* general case */
- emit_movsx_r64_r16(&dst, dstreg, REG_AX); // movsx dstreg,ax
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].read_qword_masked);
+ // call read_qword_masked
+ if (dstreg != REG_RAX)
+ emit_mov_r64_r64(&dst, dstreg, REG_RAX); // mov dstreg,rax
}
- return dst;
-}
-
-/*-------------------------------------------------
- op_read2m - process a READ2M opcode
--------------------------------------------------*/
-
-static x86code *op_read2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp, maskp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read dword masked handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &maskp); // mov param1,maskp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_word_masked);// call read_word_masked
- emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
-
- /* store to appropriate target size */
+ /* store result */
if (inst->size == 4)
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- else if (inst->size == 8)
+ else
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
return dst;
@@ -4422,410 +4114,87 @@ static x86code *op_read2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
- op_read4u - process a READ4U opcode
--------------------------------------------------*/
-
-static x86code *op_read4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* set up a call to the read dword handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_dword);// call read_dword
-
- /* store to appropriate target size */
- if (inst->size == 4)
- emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
- else if (inst->size == 8)
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_RAX); // mov dstp,rax
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read4s - process a READ4S opcode
--------------------------------------------------*/
-
-static x86code *op_read4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read dword handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_dword);// call read_dword
-
- /* 64-bit form */
- emit_movsxd_r64_r32(&dst, dstreg, REG_EAX); // movsxd dstreg,eax
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read4m - process a READ4M opcode
+ op_write - process a WRITE opcode
-------------------------------------------------*/
-static x86code *op_read4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_write(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, spacep, addrp, maskp;
+ drcuml_parameter addrp, srcp, spacesizep;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI);
-
- /* set up a call to the read dword masked handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &maskp); // mov param2,maskp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_dword_masked);// call read_dword_masked
-
- /* store to appropriate target size */
- if (inst->size == 4)
- emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
- else if (inst->size == 8)
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_RAX); // mov dstp,rax
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read8u - process a READ8U opcode
--------------------------------------------------*/
-
-static x86code *op_read8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* set up a call to the read qword handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_qword);// call read_qword
-
- /* 64-bit form */
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_RAX); // mov dstp,rax
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read8m - process a READ8M opcode
--------------------------------------------------*/
-
-static x86code *op_read8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp, maskp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI);
-
- /* set up a call to the read qword masked handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r64_p64(drcbe, &dst, REG_PARAM2, &maskp); // mov param2,maskp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].read_qword_masked);// call read_qword_masked
-
- /* 64-bit form */
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_RAX); // mov dstp,rax
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write1 - process a WRITE1 opcode
--------------------------------------------------*/
-
-static x86code *op_write1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI, &spacesizep, PTYPE_I);
/* set up a call to the write byte handler */
emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].write_byte);// call write_byte
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write2 - process a WRITE2 opcode
--------------------------------------------------*/
-
-static x86code *op_write2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write word handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].write_word);// call write_word
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_writ2m - process a WRIT2M opcode
--------------------------------------------------*/
-
-static x86code *op_writ2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, maskp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write word handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM3, &maskp); // mov param3,maskp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].write_word_masked);// call write_word_masked
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write4 - process a WRITE4 opcode
--------------------------------------------------*/
-
-static x86code *op_write4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write dword handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].write_dword);// call write_dword
-
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
+ emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &srcp); // mov param1,srcp
+ else
+ emit_mov_r64_p64(drcbe, &dst, REG_PARAM2, &srcp); // mov param1,srcp
+ if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE)
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].write_byte);
+ // call write_byte
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].write_word);
+ // call write_word
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].write_dword);
+ // call write_dword
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
+ emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacesizep.value / 16].write_qword);
+ // call write_qword
return dst;
}
/*-------------------------------------------------
- op_writ4m - process a WRIT4M opcode
+ op_writem - process a WRITEM opcode
-------------------------------------------------*/
-static x86code *op_writ4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_writem(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter spacep, addrp, maskp, srcp;
+ drcuml_parameter addrp, srcp, maskp, spacesizep;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_4(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write word handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM3, &maskp); // mov param3,maskp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].write_dword_masked);// call write_dword_masked
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write8 - process a WRITE8 opcode
--------------------------------------------------*/
-
-static x86code *op_write8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write qword handler */
- emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r64_p64(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].write_qword);// call write_qword
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_writ8m - process a WRIT8M opcode
--------------------------------------------------*/
-
-static x86code *op_writ8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, maskp, srcp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &srcp, PTYPE_MRI);
+ param_normalize_4(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI, &maskp, PTYPE_MRI, &spacesizep, PTYPE_I);
- /* set up a call to the write word handler */
+ /* set up a call to the write byte handler */
emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
- emit_mov_r64_p64(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
- emit_mov_r64_p64(drcbe, &dst, REG_PARAM3, &maskp); // mov param3,maskp
- emit_smart_call_m64(drcbe, &dst, (x86code **)&drcbe->accessors[spacep.value].write_qword_masked);// call write_qword_masked
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_flags - process a FLAGS opcode
--------------------------------------------------*/
-
-static x86code *op_flags(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, maskp, tablep;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &maskp, PTYPE_I, &tablep, PTYPE_M);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_ECX, &dstp, NULL);
-
- /* translate live flags into UML flags */
- emit_pushf(&dst); // pushf
- emit_pop_r64(&dst, REG_RAX); // pop rax
- emit_and_r32_imm(&dst, REG_EAX, 0x8c5); // and eax,0x8c5
- emit_movzx_r32_m8(&dst, REG_EAX, MBISD(REG_RBP, REG_RAX, 1, offset_from_rbp(drcbe, (FPTR)&drcbe->flagsmap[0])));
- // movzx eax,[flags_map]
-
- /* 32-bit form */
- if (inst->size == 4)
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
{
- /* no masking */
- if (maskp.value == 0xffffffff)
- {
- emit_mov_r32_m32(&dst, dstreg, MBISD(REG_RBP, REG_EAX, 4, offset_from_rbp(drcbe, tablep.value)));
- // mov dstreg,[eax*4+table]
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* general case */
- else
- {
- emit_mov_r32_p32(drcbe, &dst, dstreg, &dstp); // mov dstreg,dstp
- emit_mov_r32_m32(&dst, REG_EDX, MBISD(REG_RBP, REG_EAX, 4, offset_from_rbp(drcbe, tablep.value)));
- // mov edx,[eax*4+table]
- emit_and_r32_imm(&dst, dstreg, ~maskp.value); // and dstreg,~mask
- emit_and_r32_imm(&dst, REG_EDX, maskp.value); // and edx,mask
- emit_or_r32_r32(&dst, dstreg, REG_EDX); // or dstreg,edx
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
+ emit_mov_r32_p32(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
+ emit_mov_r32_p32(drcbe, &dst, REG_PARAM3, &maskp); // mov param3,maskp
}
-
- /* 64-bit form */
else
{
- /* no masking */
- if (maskp.value == U64(0xffffffffffffffff))
- {
- emit_mov_r64_m64(&dst, dstreg, MBISD(REG_RBP, REG_EAX, 8, offset_from_rbp(drcbe, tablep.value)));
- // mov dstreg,[eax*8+table]
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* general case */
- else
- {
- emit_mov_r64_p64(drcbe, &dst, dstreg, &dstp); // mov dstreg,dstp
- emit_mov_r64_m64(&dst, REG_EDX, MBISD(REG_RBP, REG_EAX, 8, offset_from_rbp(drcbe, tablep.value)));
- // mov edx,[eax*84+table]
- if (short_immediate(~maskp.value))
- emit_and_r64_imm(&dst, dstreg, ~maskp.value); // and dstreg,~mask
- else
- {
- emit_mov_r64_imm(&dst, REG_R11, ~maskp.value); // mov r11,~mask
- emit_and_r64_r64(&dst, dstreg, REG_R11); // and dstreg,r11
- }
- if (short_immediate(maskp.value))
- emit_and_r64_imm(&dst, REG_EDX, maskp.value); // and edx,mask
- else
- {
- emit_mov_r64_imm(&dst, REG_R11, maskp.value); // mov r11,mask
- emit_and_r64_r64(&dst, REG_EDX, REG_R11); // and edx,r11
- }
- emit_or_r64_r64(&dst, dstreg, REG_EDX); // or dstreg,edx
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
- }
+ emit_mov_r64_p64(drcbe, &dst, REG_PARAM2, &srcp); // mov param2,srcp
+ emit_mov_r64_p64(drcbe, &dst, REG_PARAM3, &maskp); // mov param3,maskp
+ }
+ if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
+ emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_word_masked);
+ // call write_word_masked
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
+ emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_dword_masked);
+ // call write_dword_masked
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
+ emit_call(&dst, (x86code *)drcbe->accessors[spacesizep.value / 16].write_qword_masked);
+ // call write_qword_masked
return dst;
}
/*-------------------------------------------------
- op_setc - process a SETC opcode
+ op_carry - process a CARRY opcode
-------------------------------------------------*/
-static x86code *op_setc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_carry(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter srcp, bitp;
@@ -4895,6 +4264,41 @@ static x86code *op_setc(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
/*-------------------------------------------------
+ op_set - process a SET opcode
+-------------------------------------------------*/
+
+static x86code *op_set(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+{
+ drcuml_parameter dstp;
+ int dstreg;
+
+ /* validate instruction */
+ assert(inst->size == 4 || inst->size == 8);
+ assert(inst->condflags >= DRCUML_COND_Z && inst->condflags < DRCUML_COND_MAX);
+
+ /* normalize parameters */
+ param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
+
+ /* pick a target register for the general case */
+ dstreg = param_select_register(REG_EAX, &dstp, NULL);
+
+ /* set to AL */
+ emit_setcc_r8(&dst, X86_CONDITION(inst->condflags), REG_AL); // setcc al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+
+ /* 32-bit form */
+ if (inst->size == 4)
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+
+ /* 64-bit form */
+ else if (inst->size == 8)
+ emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+
+ return dst;
+}
+
+
+/*-------------------------------------------------
op_mov - process a MOV opcode
-------------------------------------------------*/
@@ -5012,12 +4416,12 @@ static x86code *op_mov(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
/*-------------------------------------------------
- op_zext1 - process a ZEXT1 opcode
+ op_sext - process a SEXT opcode
-------------------------------------------------*/
-static x86code *op_zext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_sext(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep;
int dstreg;
/* validate instruction */
@@ -5025,183 +4429,19 @@ static x86code *op_zext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
/* degenerate cases -- convert to a move */
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (UINT8)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movzx_r32_m8(&dst, dstreg, MABS(drcbe, srcp.value)); // movzx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movzx_r32_r8(&dst, dstreg, srcp.value); // movzx dstreg,srcp
-
- /* 32-bit form */
- if (inst->size == 4)
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- /* 64-bit form */
- else if (inst->size == 8)
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_zext2 - process a ZEXT2 opcode
--------------------------------------------------*/
-
-static x86code *op_zext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (UINT16)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movzx_r32_m16(&dst, dstreg, MABS(drcbe, srcp.value)); // movzx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movzx_r32_r16(&dst, dstreg, srcp.value); // movzx dstreg,srcp
-
- /* 32-bit form */
- if (inst->size == 4)
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- /* 64-bit form */
- else if (inst->size == 8)
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_zext4 - process a ZEXT4 opcode
--------------------------------------------------*/
-
-static x86code *op_zext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (UINT32)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_r32_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // mov dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_r32_r32(&dst, dstreg, srcp.value); // mov dstreg,srcp
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_sext1 - process a SEXT1 opcode
--------------------------------------------------*/
-
-static x86code *op_sext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT8)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* convert 8-bit source registers */
- if (srcp.type == DRCUML_PTYPE_INT_REGISTER && (srcp.value & 4))
- {
- emit_mov_r32_r32(&dst, REG_EAX, srcp.value); // mov eax,srcp
- srcp.value = REG_EAX;
- }
-
- /* 32-bit form */
- if (inst->size == 4)
{
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsx_r32_m8(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r32_r8(&dst, dstreg, srcp.value); // movsx dstreg,srcp
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT8)srcp.value);
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT16)srcp.value);
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT32)srcp.value);
}
- /* 64-bit form */
- else if (inst->size == 8)
- {
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsx_r64_m8(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r64_r8(&dst, dstreg, srcp.value); // movsx dstreg,srcp
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_sext2 - process a SEXT2 opcode
--------------------------------------------------*/
-
-static x86code *op_sext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT16)srcp.value);
-
/* pick a target register for the general case */
dstreg = param_select_register(REG_EAX, &dstp, NULL);
@@ -5210,9 +4450,23 @@ static x86code *op_sext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
{
/* general case */
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsx_r32_m16(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r32_m8(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_m16(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // mov dstreg,[srcp]
+ }
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r32_r16(&dst, dstreg, srcp.value); // movsx dstreg,srcp
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r32_r8(&dst, dstreg, srcp.value); // movsx dstreg,srcp
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_r16(&dst, dstreg, srcp.value); // movsx dstreg,srcp
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_r32(&dst, dstreg, srcp.value); // mov dstreg,srcp
+ }
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
}
@@ -5221,46 +4475,27 @@ static x86code *op_sext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
{
/* general case */
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsx_r64_m16(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r64_r16(&dst, dstreg, srcp.value); // movsx dstreg,srcp
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_sext4 - process a SEXT4 opcode
--------------------------------------------------*/
-
-static x86code *op_sext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT32)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* 64-bit form */
- if (inst->size == 8)
- {
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsxd_r64_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // movsxd dstreg,[srcp]
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r64_m8(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r64_m16(&dst, dstreg, MABS(drcbe, srcp.value)); // movsx dstreg,[srcp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_movsxd_r64_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // movsxd dstreg,[srcp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_r64_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // mov dstreg,[srcp]
+ }
else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsxd_r64_r32(&dst, dstreg, srcp.value); // movsxd dstreg,srcp
+ {
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r64_r8(&dst, dstreg, srcp.value); // movsx dstreg,srcp
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r64_r16(&dst, dstreg, srcp.value); // movsx dstreg,srcp
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_movsxd_r64_r32(&dst, dstreg, srcp.value); // movsxd dstreg,srcp
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_mov_r64_r64(&dst, dstreg, srcp.value); // mov dstreg,srcp
+ }
emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
}
return dst;
@@ -5268,10 +4503,10 @@ static x86code *op_sext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/*-------------------------------------------------
- op_xtract - process an XTRACT opcode
+ op_roland - process an ROLAND opcode
-------------------------------------------------*/
-static x86code *op_xtract(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_roland(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter dstp, srcp, shiftp, maskp;
int dstreg;
@@ -5333,10 +4568,10 @@ static x86code *op_xtract(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
- op_insert - process an INSERT opcode
+ op_rolins - process an ROLINS opcode
-------------------------------------------------*/
-static x86code *op_insert(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_rolins(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter dstp, srcp, shiftp, maskp;
int dstreg;
@@ -5753,6 +4988,27 @@ static x86code *op_mulu(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
if (compute_hi)
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
+
+ /* compute flags */
+ if (inst->condflags != 0)
+ {
+ if (compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
+ }
}
/* 64-bit form */
@@ -5772,6 +5028,27 @@ static x86code *op_mulu(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_RAX); // mov dstp,rax
if (compute_hi)
emit_mov_p64_r64(drcbe, &dst, &edstp, REG_RDX); // mov edstp,rdx
+
+ /* compute flags */
+ if (inst->condflags != 0)
+ {
+ if (compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r64_r64(&dst, REG_RDX, REG_RAX); // or rdx,rax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r64_r64(&dst, REG_RDX, REG_RDX); // test rdx,rdx
+ else
+ {
+ emit_mov_r32_r32(&dst, REG_ECX, REG_EAX); // mov ecx,eax
+ emit_shr_r64_imm(&dst, REG_RAX, 32); // shr rax,32
+ emit_or_r64_r64(&dst, REG_RDX, REG_RCX); // or rdx,rcx
+ emit_or_r64_r64(&dst, REG_RDX, REG_RAX); // or rdx,rax
+ }
+ }
+ else
+ emit_test_r64_r64(&dst, REG_RAX, REG_RAX); // test rax,rax
+ }
}
return dst;
}
@@ -5850,6 +5127,27 @@ static x86code *op_muls(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
}
+
+ /* compute flags */
+ if (inst->condflags != 0)
+ {
+ if (compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
+ }
}
/* 64-bit form */
@@ -5892,6 +5190,27 @@ static x86code *op_muls(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_RAX); // mov dstp,rax
emit_mov_p64_r64(drcbe, &dst, &edstp, REG_RDX); // mov edstp,rdx
}
+
+ /* compute flags */
+ if (inst->condflags != 0)
+ {
+ if (compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r64_r64(&dst, REG_RDX, REG_RAX); // or rdx,rax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r64_r64(&dst, REG_RDX, REG_RDX); // test rdx,rdx
+ else
+ {
+ emit_mov_r32_r32(&dst, REG_ECX, REG_EAX); // mov ecx,eax
+ emit_shr_r64_imm(&dst, REG_RAX, 32); // shr rax,32
+ emit_or_r64_r64(&dst, REG_RDX, REG_RCX); // or rdx,rcx
+ emit_or_r64_r64(&dst, REG_RDX, REG_RAX); // or rdx,rax
+ }
+ }
+ else
+ emit_test_r64_r64(&dst, REG_RAX, REG_RAX); // test rax,rax
+ }
}
return dst;
}
@@ -6945,7 +6264,7 @@ static x86code *op_fread(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &addrp, PTYPE_MRI, &spacep, PTYPE_I);
/* set up a call to the read dword/qword handler */
emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
@@ -6986,7 +6305,7 @@ static x86code *op_fwrite(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MF);
+ param_normalize_3(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MF, &spacep, PTYPE_I);
/* general case */
emit_mov_r32_p32(drcbe, &dst, REG_PARAM1, &addrp); // mov param1,addrp
@@ -7061,12 +6380,12 @@ static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
/*-------------------------------------------------
- op_ftoi4 - process a FTOI4 opcode
+ op_ftoint - process a FTOINT opcode
-------------------------------------------------*/
-static x86code *op_ftoi4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_ftoint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep, roundp;
int dstreg;
/* validate instruction */
@@ -7074,213 +6393,123 @@ static x86code *op_ftoi4(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF, &sizep, PTYPE_I, &roundp, PTYPE_I);
/* pick a target register for the general case */
dstreg = param_select_register(REG_EAX, &dstp, NULL);
- /* 32-bit form */
- if (inst->size == 4)
+ /* set rounding mode if necessary */
+ if (roundp.value != DRCUML_FMOD_DEFAULT && roundp.value != DRCUML_FMOD_TRUNC)
{
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtss2si_r32_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtss2si_r32_r128(&dst, dstreg, srcp.value); // cvtss2si dstreg,srcp
- }
-
- /* 64-bit form */
- else if (inst->size == 8)
- {
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsd2si_r32_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtsd2si_r32_r128(&dst, dstreg, srcp.value); // cvtsd2si dstreg,srcp
+ emit_stmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssemodesave)); // stmxcsr [ssemodesave]
+ emit_ldmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssecontrol[roundp.value])); // ldmxcsr fpcontrol[mode]
}
-
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi4t - process a FTOI4T opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi4t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
+
/* 32-bit form */
if (inst->size == 4)
{
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvttss2si_r32_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttss2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvttss2si_r32_r128(&dst, dstreg, srcp.value); // cvttss2si dstreg,srcp
+ /* 32-bit integer source */
+ if (sizep.value == DRCUML_SIZE_DWORD)
+ {
+ if (srcp.type == DRCUML_PTYPE_MEMORY)
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtss2si_r32_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2si dstreg,[srcp]
+ else
+ emit_cvttss2si_r32_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttss2si dstreg,[srcp]
+ }
+ else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtss2si_r32_r128(&dst, dstreg, srcp.value); // cvtss2si dstreg,srcp
+ else
+ emit_cvttss2si_r32_r128(&dst, dstreg, srcp.value); // cvttss2si dstreg,srcp
+ }
+ }
+
+ /* 64-bit integer source */
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ if (srcp.type == DRCUML_PTYPE_MEMORY)
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtss2si_r64_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2si dstreg,[srcp]
+ else
+ emit_cvttss2si_r64_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttss2si dstreg,[srcp]
+ }
+ else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtss2si_r64_r128(&dst, dstreg, srcp.value); // cvtss2si dstreg,srcp
+ else
+ emit_cvttss2si_r64_r128(&dst, dstreg, srcp.value); // cvttss2si dstreg,srcp
+ }
+ }
}
/* 64-bit form */
else if (inst->size == 8)
{
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvttsd2si_r32_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttsd2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvttsd2si_r32_r128(&dst, dstreg, srcp.value); // cvttsd2si dstreg,srcp
- }
-
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi4x - process a FTOI4R/F/C opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi4x(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst, int mode)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* non-SSE4.1 case */
- if (!drcbe->sse41 || inst->size == 8)
- {
- /* save and set the control word */
- emit_stmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssemodesave)); // stmxcsr [ssemodesave]
- emit_ldmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssecontrol[mode])); // ldmxcsr fpcontrol[mode]
-
- /* 32-bit form */
- if (inst->size == 4)
+ /* 32-bit integer source */
+ if (sizep.value == DRCUML_SIZE_DWORD)
{
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtss2si_r32_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2si dstreg,[srcp]
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtsd2si_r32_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2si dstreg,[srcp]
+ else
+ emit_cvttsd2si_r32_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttsd2si dstreg,[srcp]
+ }
else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtss2si_r32_r128(&dst, dstreg, srcp.value); // cvtss2si dstreg,srcp
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtsd2si_r32_r128(&dst, dstreg, srcp.value); // cvtsd2si dstreg,srcp
+ else
+ emit_cvttsd2si_r32_r128(&dst, dstreg, srcp.value); // cvttsd2si dstreg,srcp
+ }
}
-
- /* 64-bit form */
- else if (inst->size == 8)
+
+ /* 64-bit integer source */
+ else if (sizep.value == DRCUML_SIZE_QWORD)
{
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsd2si_r32_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2si dstreg,[srcp]
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtsd2si_r64_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2si dstreg,[srcp]
+ else
+ emit_cvttsd2si_r64_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttsd2si dstreg,[srcp]
+ }
else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtsd2si_r32_r128(&dst, dstreg, srcp.value); // cvtsd2si dstreg,srcp
+ {
+ if (roundp.value != DRCUML_FMOD_TRUNC)
+ emit_cvtsd2si_r64_r128(&dst, dstreg, srcp.value); // cvtsd2si dstreg,srcp
+ else
+ emit_cvttsd2si_r64_r128(&dst, dstreg, srcp.value); // cvttsd2si dstreg,srcp
+ }
}
-
- /* restore control word and proceed */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- emit_ldmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssemodesave)); // ldmxcsr [ssemodesave]
}
- /* SSE4.1 case */
+ /* general case */
+ if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
else
- {
- /* 32-bit form */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_roundss_r128_m32_imm(&dst, REG_XMM0, MABS(drcbe, srcp.value), fprnd_map[mode]);
- // roundss xmm0,[srcp],mode
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_roundss_r128_r128_imm(&dst, REG_XMM0, srcp.value, fprnd_map[mode]); // roundss xmm0,srcp,mode
-
- /* store to the destination */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_movd_m32_r128(&dst, MABS(drcbe, dstp.value), REG_XMM0); // movd [dstp],xmm0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movd_r32_r128(&dst, dstp.value, REG_XMM0); // movd dstp,xmm0
- }
- return dst;
-
-}
-
-static x86code *op_ftoi4r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- return op_ftoi4x(drcbe, dst, inst, DRCUML_FMOD_ROUND);
-}
-
-static x86code *op_ftoi4f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- return op_ftoi4x(drcbe, dst, inst, DRCUML_FMOD_FLOOR);
-}
-
-static x86code *op_ftoi4c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- return op_ftoi4x(drcbe, dst, inst, DRCUML_FMOD_CEIL);
-}
-
-
-/*-------------------------------------------------
- op_ftoi8 - process a FTOI8 opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* 32-bit form */
- if (inst->size == 4)
- {
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtss2si_r64_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtss2si_r64_r128(&dst, dstreg, srcp.value); // cvtss2si dstreg,srcp
- }
+ emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- /* 64-bit form */
- else if (inst->size == 8)
- {
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsd2si_r64_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtsd2si_r64_r128(&dst, dstreg, srcp.value); // cvtsd2si dstreg,srcp
- }
+ /* restore rounding mode */
+ if (roundp.value != DRCUML_FMOD_DEFAULT && roundp.value != DRCUML_FMOD_TRUNC)
+ emit_ldmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssemodesave)); // ldmxcsr [ssemodesave]
- /* general case */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
return dst;
}
/*-------------------------------------------------
- op_ftoi8t - process a FTOI8T opcode
+ op_ffrint - process a FFRINT opcode
-------------------------------------------------*/
-static x86code *op_ftoi8t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_ffrint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep;
int dstreg;
/* validate instruction */
@@ -7288,187 +6517,83 @@ static x86code *op_ftoi8t(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
/* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
+ dstreg = param_select_register(REG_XMM0, &dstp, NULL);
/* 32-bit form */
if (inst->size == 4)
{
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvttss2si_r64_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttss2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvttss2si_r64_r128(&dst, dstreg, srcp.value); // cvttss2si dstreg,srcp
+ /* 32-bit integer source */
+ if (sizep.value == DRCUML_SIZE_DWORD)
+ {
+ if (srcp.type == DRCUML_PTYPE_MEMORY)
+ emit_cvtsi2ss_r128_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2ss dstreg,[srcp]
+ else
+ {
+ int srcreg = param_select_register(REG_EAX, &srcp, NULL);
+ emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ emit_cvtsi2ss_r128_r32(&dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg
+ }
+ }
+
+ /* 64-bit integer source */
+ else
+ {
+ if (srcp.type == DRCUML_PTYPE_MEMORY)
+ emit_cvtsi2ss_r128_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2ss dstreg,[srcp]
+ else
+ {
+ int srcreg = param_select_register(REG_RAX, &srcp, NULL);
+ emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ emit_cvtsi2ss_r128_r64(&dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg
+ }
+ }
+ emit_movss_p32_r128(drcbe, &dst, &dstp, dstreg); // movss dstp,dstreg
}
/* 64-bit form */
else if (inst->size == 8)
{
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvttsd2si_r64_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvttsd2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvttsd2si_r64_r128(&dst, dstreg, srcp.value); // cvttsd2si dstreg,srcp
- }
-
- /* general case */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi8x - process a FTOI8R/F/C opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi8x(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst, int mode)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* non-SSE4.1 case */
- if (!drcbe->sse41 || inst->size == 4)
- {
- /* save and set the control word */
- emit_stmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssemodesave)); // stmxcsr [ssemodesave]
- emit_ldmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssecontrol[mode])); // ldmxcsr fpcontrol[mode]
-
- /* 32-bit form */
- if (inst->size == 4)
+ /* 32-bit integer source */
+ if (sizep.value == DRCUML_SIZE_DWORD)
{
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtss2si_r64_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtss2si_r64_r128(&dst, dstreg, srcp.value); // cvtss2si dstreg,srcp
+ emit_cvtsi2sd_r128_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2sd dstreg,[srcp]
+ else
+ {
+ int srcreg = param_select_register(REG_EAX, &srcp, NULL);
+ emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ emit_cvtsi2sd_r128_r32(&dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg
+ }
}
-
- /* 64-bit form */
- else if (inst->size == 8)
+
+ /* 64-bit integer source */
+ else
{
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsd2si_r64_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2si dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtsd2si_r64_r128(&dst, dstreg, srcp.value); // cvtsd2si dstreg,srcp
+ emit_cvtsi2sd_r128_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2sd dstreg,[srcp]
+ else
+ {
+ int srcreg = param_select_register(REG_EAX, &srcp, NULL);
+ emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ emit_cvtsi2sd_r128_r64(&dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg
+ }
}
-
- /* restore control word and proceed */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- emit_ldmxcsr_m32(&dst, MABS(drcbe, &drcbe->ssemodesave)); // ldmxcsr [ssemodesave]
- }
-
- /* SSE4.1 case */
- else
- {
- /* 64-bit form */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_roundsd_r128_m64_imm(&dst, REG_XMM0, MABS(drcbe, srcp.value), fprnd_map[mode]);
- // roundsd xmm0,[srcp],mode
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_roundsd_r128_r128_imm(&dst, REG_XMM0, srcp.value, fprnd_map[mode]); // roundsd xmm0,srcp,mode
-
- /* store to the destination */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_movq_m64_r128(&dst, MABS(drcbe, dstp.value), REG_XMM0); // movq [dstp],xmm0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movq_r64_r128(&dst, dstp.value, REG_XMM0); // movq dstp,xmm0
+ emit_movsd_p64_r128(drcbe, &dst, &dstp, dstreg); // movsd dstp,dstreg
}
return dst;
-
-}
-
-static x86code *op_ftoi8r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- return op_ftoi8x(drcbe, dst, inst, DRCUML_FMOD_ROUND);
-}
-
-static x86code *op_ftoi8f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- return op_ftoi8x(drcbe, dst, inst, DRCUML_FMOD_FLOOR);
-}
-
-static x86code *op_ftoi8c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- return op_ftoi8x(drcbe, dst, inst, DRCUML_FMOD_CEIL);
}
/*-------------------------------------------------
- op_ffrfs - process a FFRFS opcode
+ op_ffrflt - process a FFRFLT opcode
-------------------------------------------------*/
-static x86code *op_ffrfs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_ffrflt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_XMM0, &dstp, NULL);
-
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtss2sd_r128_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2sd dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtss2sd_r128_r128(&dst, dstreg, srcp.value); // cvtss2sd dstreg,srcp
- emit_movsd_p64_r128(drcbe, &dst, &dstp, dstreg); // movsd dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ffrfd - process a FFRFD opcode
--------------------------------------------------*/
-
-static x86code *op_ffrfd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_XMM0, &dstp, NULL);
-
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsd2ss_r128_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2ss dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
- emit_cvtsd2ss_r128_r128(&dst, dstreg, srcp.value); // cvtsd2ss dstreg,srcp
- emit_movss_p32_r128(drcbe, &dst, &dstp, dstreg); // movss dstp,dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ffri4 - process a FFRI4 opcode
--------------------------------------------------*/
-
-static x86code *op_ffri4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep;
int dstreg;
/* validate instruction */
@@ -7476,53 +6601,45 @@ static x86code *op_ffri4(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF, &sizep, PTYPE_I);
/* pick a target register for the general case */
dstreg = param_select_register(REG_XMM0, &dstp, NULL);
- /* 32-bit form */
- if (inst->size == 4)
+ /* single-to-double */
+ if (inst->size == 8 && sizep.value == DRCUML_SIZE_DWORD)
{
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsi2ss_r128_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2ss dstreg,[srcp]
- else
- {
- int srcreg = param_select_register(REG_EAX, &srcp, NULL);
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_cvtsi2ss_r128_r32(&dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg
- }
- emit_movss_p32_r128(drcbe, &dst, &dstp, dstreg); // movss dstp,dstreg
+ emit_cvtss2sd_r128_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtss2sd dstreg,[srcp]
+ else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
+ emit_cvtss2sd_r128_r128(&dst, dstreg, srcp.value); // cvtss2sd dstreg,srcp
+ emit_movsd_p64_r128(drcbe, &dst, &dstp, dstreg); // movsd dstp,dstreg
}
-
- /* 64-bit form */
- else if (inst->size == 8)
+
+ /* double-to-single */
+ else if (inst->size == 4 && sizep.value == DRCUML_SIZE_QWORD)
{
if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsi2sd_r128_m32(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2sd dstreg,[srcp]
- else
- {
- int srcreg = param_select_register(REG_EAX, &srcp, NULL);
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_cvtsi2sd_r128_r32(&dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg
- }
- emit_movsd_p64_r128(drcbe, &dst, &dstp, dstreg); // movsd dstp,dstreg
+ emit_cvtsd2ss_r128_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2ss dstreg,[srcp]
+ else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
+ emit_cvtsd2ss_r128_r128(&dst, dstreg, srcp.value); // cvtsd2ss dstreg,srcp
+ emit_movss_p32_r128(drcbe, &dst, &dstp, dstreg); // movss dstp,dstreg
}
return dst;
}
/*-------------------------------------------------
- op_ffri8 - process a FFRI8 opcode
+ op_frnds - process a FRNDS opcode
-------------------------------------------------*/
-static x86code *op_ffri8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_frnds(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter dstp, srcp;
int dstreg;
/* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
+ assert(inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
@@ -7531,33 +6648,13 @@ static x86code *op_ffri8(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/* pick a target register for the general case */
dstreg = param_select_register(REG_XMM0, &dstp, NULL);
- /* 32-bit form */
- if (inst->size == 4)
- {
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsi2ss_r128_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2ss dstreg,[srcp]
- else
- {
- int srcreg = param_select_register(REG_EAX, &srcp, NULL);
- emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_cvtsi2ss_r128_r64(&dst, dstreg, srcreg); // cvtsi2ss dstreg,srcreg
- }
- emit_movss_p32_r128(drcbe, &dst, &dstp, dstreg); // movss dstp,dstreg
- }
-
/* 64-bit form */
- else if (inst->size == 8)
- {
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_cvtsi2sd_r128_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsi2sd dstreg,[srcp]
- else
- {
- int srcreg = param_select_register(REG_EAX, &srcp, NULL);
- emit_mov_r64_p64(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_cvtsi2sd_r128_r64(&dst, dstreg, srcreg); // cvtsi2sd dstreg,srcreg
- }
- emit_movsd_p64_r128(drcbe, &dst, &dstp, dstreg); // movsd dstp,dstreg
- }
+ if (srcp.type == DRCUML_PTYPE_MEMORY)
+ emit_cvtsd2ss_r128_m64(&dst, dstreg, MABS(drcbe, srcp.value)); // cvtsd2ss dstreg,[srcp]
+ else if (srcp.type == DRCUML_PTYPE_FLOAT_REGISTER)
+ emit_cvtsd2ss_r128_r128(&dst, dstreg, srcp.value); // cvtsd2ss dstreg,srcp
+ emit_cvtss2sd_r128_r128(&dst, dstreg, dstreg); // cvtss2sd dstreg,dstreg
+ emit_movsd_p64_r128(drcbe, &dst, &dstp, dstreg); // movsd dstp,dstreg
return dst;
}
diff --git a/src/emu/cpu/drcbex86.c b/src/emu/cpu/drcbex86.c
index ea4e7cc4085..f0bffc6829f 100644
--- a/src/emu/cpu/drcbex86.c
+++ b/src/emu/cpu/drcbex86.c
@@ -17,6 +17,8 @@
- also FCMP/FLAGS has unnecessary PUSHF/POP EAX
* Identify common pairs and optimize output
+
+ * Convert AND 0xff/0xffff to movzx
****************************************************************************
@@ -282,48 +284,23 @@ static x86code *op_recover(drcbe_state *drcbe, x86code *dst, const drcuml_instru
static x86code *op_setfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_getfmod(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_getexp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_getflgs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_save(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_restore(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_load8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_store8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_read8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_writ2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_writ4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_write8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_writ8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_flags(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_setc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_loads(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_store(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_read(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_readm(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_write(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_writem(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_carry(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_set(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_mov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_zext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_zext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_zext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_sext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_sext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_sext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_xtract(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_insert(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_sext(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_roland(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_rolins(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_add(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_addc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_sub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
@@ -352,20 +329,10 @@ static x86code *op_fstore(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
static x86code *op_fread(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fwrite(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi4c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ftoi8c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffrfs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffrfd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffri4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
-static x86code *op_ffri8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_ftoint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_ffrint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_ffrflt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
+static x86code *op_frnds(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fadd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fsub(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
static x86code *op_fcmp(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst);
@@ -400,50 +367,25 @@ static const opcode_table_entry opcode_table_source[] =
/* Internal Register Operations */
{ DRCUML_OP_SETFMOD, op_setfmod }, /* SETFMOD src */
{ DRCUML_OP_GETFMOD, op_getfmod }, /* GETFMOD dst */
- { DRCUML_OP_GETEXP, op_getexp }, /* GETEXP dst,index */
- { DRCUML_OP_SAVE, op_save }, /* SAVE dst,index */
- { DRCUML_OP_RESTORE, op_restore }, /* RESTORE dst,index */
+ { DRCUML_OP_GETEXP, op_getexp }, /* GETEXP dst */
+ { DRCUML_OP_GETFLGS, op_getflgs }, /* GETFLGS dst[,f] */
+ { DRCUML_OP_SAVE, op_save }, /* SAVE dst */
+ { DRCUML_OP_RESTORE, op_restore }, /* RESTORE dst */
/* Integer Operations */
- { DRCUML_OP_LOAD1U, op_load1u }, /* LOAD1U dst,base,index */
- { DRCUML_OP_LOAD1S, op_load1s }, /* LOAD1S dst,base,index */
- { DRCUML_OP_LOAD2U, op_load2u }, /* LOAD2U dst,base,index */
- { DRCUML_OP_LOAD2S, op_load2s }, /* LOAD2S dst,base,index */
- { DRCUML_OP_LOAD4U, op_load4u }, /* LOAD4U dst,base,index */
- { DRCUML_OP_LOAD4S, op_load4s }, /* LOAD4S dst,base,index */
- { DRCUML_OP_LOAD8U, op_load8u }, /* LOAD8U dst,base,index */
- { DRCUML_OP_STORE1, op_store1 }, /* STORE1 base,index,src */
- { DRCUML_OP_STORE2, op_store2 }, /* STORE2 base,index,src */
- { DRCUML_OP_STORE4, op_store4 }, /* STORE4 base,index,src */
- { DRCUML_OP_STORE8, op_store8 }, /* STORE8 base,index,src */
- { DRCUML_OP_READ1U, op_read1u }, /* READ1U dst,space,src1 */
- { DRCUML_OP_READ1S, op_read1s }, /* READ1S dst,space,src1 */
- { DRCUML_OP_READ2U, op_read2u }, /* READ2U dst,space,src1 */
- { DRCUML_OP_READ2S, op_read2s }, /* READ2S dst,space,src1 */
- { DRCUML_OP_READ2M, op_read2m }, /* READ2M dst,space,src1,mask */
- { DRCUML_OP_READ4U, op_read4u }, /* READ4U dst,space,src1 */
- { DRCUML_OP_READ4S, op_read4s }, /* READ4S dst,space,src1 */
- { DRCUML_OP_READ4M, op_read4m }, /* READ4M dst,space,src1,mask */
- { DRCUML_OP_READ8U, op_read8u }, /* READ8U dst,space,src1 */
- { DRCUML_OP_READ8M, op_read8m }, /* READ8M dst,space,src1,mask */
- { DRCUML_OP_WRITE1, op_write1 }, /* WRITE1 space,dst,src1 */
- { DRCUML_OP_WRITE2, op_write2 }, /* WRITE2 space,dst,src1 */
- { DRCUML_OP_WRIT2M, op_writ2m }, /* WRIT2M space,dst,src1 */
- { DRCUML_OP_WRITE4, op_write4 }, /* WRITE4 space,dst,src1 */
- { DRCUML_OP_WRIT4M, op_writ4m }, /* WRIT4M space,dst,mask,src1 */
- { DRCUML_OP_WRITE8, op_write8 }, /* WRITE8 space,dst,src1 */
- { DRCUML_OP_WRIT8M, op_writ8m }, /* WRIT8M space,dst,mask,src1 */
- { DRCUML_OP_FLAGS, op_flags }, /* FLAGS dst,mask,table */
- { DRCUML_OP_SETC, op_setc }, /* FLAGS src,bitnum */
+ { DRCUML_OP_LOAD, op_load }, /* LOAD dst,base,index,size */
+ { DRCUML_OP_LOADS, op_loads }, /* LOADS dst,base,index,size */
+ { DRCUML_OP_STORE, op_store }, /* STORE base,index,src,size */
+ { DRCUML_OP_READ, op_read }, /* READ dst,src1,spacesize */
+ { DRCUML_OP_READM, op_readm }, /* READM dst,src1,mask,spacesize */
+ { DRCUML_OP_WRITE, op_write }, /* WRITE dst,src1,spacesize */
+ { DRCUML_OP_WRITEM, op_writem }, /* WRITEM dst,src1,spacesize */
+ { DRCUML_OP_CARRY, op_carry }, /* CARRY src,bitnum */
+ { DRCUML_OP_SET, op_set }, /* SET dst,c */
{ DRCUML_OP_MOV, op_mov }, /* MOV dst,src[,c] */
- { DRCUML_OP_ZEXT1, op_zext1 }, /* ZEXT1 dst,src */
- { DRCUML_OP_ZEXT2, op_zext2 }, /* ZEXT2 dst,src */
- { DRCUML_OP_ZEXT4, op_zext4 }, /* ZEXT4 dst,src */
- { DRCUML_OP_SEXT1, op_sext1 }, /* SEXT1 dst,src */
- { DRCUML_OP_SEXT2, op_sext2 }, /* SEXT2 dst,src */
- { DRCUML_OP_SEXT4, op_sext4 }, /* SEXT4 dst,src */
- { DRCUML_OP_XTRACT, op_xtract }, /* XTRACT dst,src1,src2,src3 */
- { DRCUML_OP_INSERT, op_insert }, /* INSERT dst,src1,src2,src3 */
+ { DRCUML_OP_SEXT, op_sext }, /* SEXT dst,src */
+ { DRCUML_OP_ROLAND, op_roland }, /* ROLAND dst,src1,src2,src3 */
+ { DRCUML_OP_ROLINS, op_rolins }, /* ROLINS dst,src1,src2,src3 */
{ DRCUML_OP_ADD, op_add }, /* ADD dst,src1,src2[,f] */
{ DRCUML_OP_ADDC, op_addc }, /* ADDC dst,src1,src2[,f] */
{ DRCUML_OP_SUB, op_sub }, /* SUB dst,src1,src2[,f] */
@@ -470,23 +412,13 @@ static const opcode_table_entry opcode_table_source[] =
/* Floating Point Operations */
{ DRCUML_OP_FLOAD, op_fload }, /* FLOAD dst,base,index */
{ DRCUML_OP_FSTORE, op_fstore }, /* FSTORE base,index,src */
- { DRCUML_OP_FREAD, op_fread }, /* FREAD dst,space,src1 */
- { DRCUML_OP_FWRITE, op_fwrite }, /* FWRITE space,dst,src1 */
+ { DRCUML_OP_FREAD, op_fread }, /* FREAD dst,src1,space */
+ { DRCUML_OP_FWRITE, op_fwrite }, /* FWRITE dst,src1,space */
{ DRCUML_OP_FMOV, op_fmov }, /* FMOV dst,src1[,c] */
- { DRCUML_OP_FTOI4, op_ftoi4 }, /* FTOI4 dst,src1 */
- { DRCUML_OP_FTOI4T, op_ftoi4t }, /* FTOI4T dst,src1 */
- { DRCUML_OP_FTOI4R, op_ftoi4r }, /* FTOI4R dst,src1 */
- { DRCUML_OP_FTOI4F, op_ftoi4f }, /* FTOI4F dst,src1 */
- { DRCUML_OP_FTOI4C, op_ftoi4c }, /* FTOI4C dst,src1 */
- { DRCUML_OP_FTOI8, op_ftoi8 }, /* FTOI8 dst,src1 */
- { DRCUML_OP_FTOI8T, op_ftoi8t }, /* FTOI8T dst,src1 */
- { DRCUML_OP_FTOI8R, op_ftoi8r }, /* FTOI8R dst,src1 */
- { DRCUML_OP_FTOI8F, op_ftoi8f }, /* FTOI8F dst,src1 */
- { DRCUML_OP_FTOI8C, op_ftoi8c }, /* FTOI8C dst,src1 */
- { DRCUML_OP_FFRFS, op_ffrfs }, /* FFRFS dst,src1 */
- { DRCUML_OP_FFRFD, op_ffrfd }, /* FFRFD dst,src1 */
- { DRCUML_OP_FFRI4, op_ffri4 }, /* FFRI4 dst,src1 */
- { DRCUML_OP_FFRI8, op_ffri8 }, /* FFRI8 dst,src1 */
+ { DRCUML_OP_FTOINT, op_ftoint }, /* FTOINT dst,src1,size,round */
+ { DRCUML_OP_FFRINT, op_ffrint }, /* FFRINT dst,src1,size */
+ { DRCUML_OP_FFRFLT, op_ffrflt }, /* FFRFLT dst,src1,size */
+ { DRCUML_OP_FRNDS, op_frnds }, /* FRNDS dst,src1 */
{ DRCUML_OP_FADD, op_fadd }, /* FADD dst,src1,src2 */
{ DRCUML_OP_FSUB, op_fsub }, /* FSUB dst,src1,src2 */
{ DRCUML_OP_FCMP, op_fcmp }, /* FCMP src1,src2 */
@@ -3603,6 +3535,136 @@ static x86code *op_getexp(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
+ op_getflgs - process a GETFLGS opcode
+-------------------------------------------------*/
+
+static x86code *op_getflgs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+{
+ drcuml_parameter dstp;
+ int dstreg;
+
+ /* validate instruction */
+ assert(inst->size == 4);
+ assert(inst->condflags != DRCUML_COND_ALWAYS);
+
+ /* normalize parameters */
+ param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
+
+ /* pick a target register for the general case */
+ dstreg = param_select_register(REG_EAX, &dstp, NULL);
+
+ switch (inst->condflags)
+ {
+ /* single flags only */
+ case DRCUML_FLAG_C:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ break;
+
+ case DRCUML_FLAG_V:
+ emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case DRCUML_FLAG_Z:
+ emit_setcc_r8(&dst, COND_Z, REG_AL); // setz al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ case DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_S, REG_AL); // sets al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 3); // shl dstreg,3
+ break;
+
+ case DRCUML_FLAG_U:
+ emit_setcc_r8(&dst, COND_P, REG_AL); // setp al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+ emit_shl_r32_imm(&dst, dstreg, 4); // shl dstreg,4
+ break;
+
+ /* carry plus another flag */
+ case DRCUML_FLAG_C | DRCUML_FLAG_V:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_setcc_r8(&dst, COND_O, REG_CL); // seto cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ break;
+
+ case DRCUML_FLAG_C | DRCUML_FLAG_Z:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_setcc_r8(&dst, COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ break;
+
+ case DRCUML_FLAG_C | DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_C, REG_AL); // setc al
+ emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 8, 0)); // lea dstreg,[eax+ecx*8]
+ break;
+
+ /* overflow plus another flag */
+ case DRCUML_FLAG_V | DRCUML_FLAG_Z:
+ emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
+ emit_setcc_r8(&dst, COND_Z, REG_CL); // setz cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ case DRCUML_FLAG_V | DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_O, REG_AL); // seto al
+ emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 4, 0)); // lea dstreg,[eax+ecx*4]
+ emit_shl_r32_imm(&dst, dstreg, 1); // shl dstreg,1
+ break;
+
+ /* zero plus another flag */
+ case DRCUML_FLAG_Z | DRCUML_FLAG_S:
+ emit_setcc_r8(&dst, COND_Z, REG_AL); // setz al
+ emit_setcc_r8(&dst, COND_S, REG_CL); // sets cl
+ emit_movzx_r32_r8(&dst, REG_EAX, REG_AL); // movzx eax,al
+ emit_movzx_r32_r8(&dst, REG_ECX, REG_CL); // movzx ecx,al
+ emit_lea_r32_m32(&dst, dstreg, MBISD(REG_EAX, REG_ECX, 2, 0)); // lea dstreg,[eax+ecx*2]
+ emit_shl_r32_imm(&dst, dstreg, 2); // shl dstreg,2
+ break;
+
+ /* default cases */
+ default:
+ emit_pushf(&dst); // pushf
+ emit_pop_r32(&dst, REG_EAX); // pop eax
+ emit_and_r32_imm(&dst, REG_EAX, 0x8c5); // and eax,0x8c5
+ emit_movzx_r32_m8(&dst, dstreg, MBD(REG_EAX, flags_map)); // movzx dstreg,[flags_map]
+ break;
+ }
+
+ /* store low 32 bits */
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+
+ /* 64-bit form stores upper 32 bits */
+ if (inst->size == 8)
+ {
+ /* general case */
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ }
+ return dst;
+}
+
+
+/*-------------------------------------------------
op_save - process a SAVE opcode
-------------------------------------------------*/
@@ -3726,12 +3788,12 @@ static x86code *op_restore(drcbe_state *drcbe, x86code *dst, const drcuml_instru
***************************************************************************/
/*-------------------------------------------------
- op_load1u - process a LOAD1U opcode
+ op_load - process a LOAD opcode
-------------------------------------------------*/
-static x86code *op_load1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_load(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, basep, indp;
+ drcuml_parameter dstp, basep, indp, sizep;
int dstreg;
/* validate instruction */
@@ -3739,117 +3801,43 @@ static x86code *op_load1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI, &sizep, PTYPE_I);
/* pick a target register for the general case */
dstreg = param_select_register(REG_EAX, &dstp, NULL);
/* immediate index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movzx_r32_m8(&dst, dstreg, MABS(basep.value + 1*indp.value)); // movzx dstreg,[basep + 1*indp]
-
- /* other index */
- else
{
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movzx_r32_m8(&dst, dstreg, MISD(indreg, 1, basep.value)); // movzx dstreg,[basep + 1*indp]
- }
-
- /* store low 32 bits */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- /* 64-bit form stores upper 32 bits */
- if (inst->size == 8)
- {
- /* general case */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load1s - process a LOAD1S opcode
--------------------------------------------------*/
-
-static x86code *op_load1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = (inst->size == 8) ? REG_EAX : param_select_register(REG_EAX, &dstp, NULL);
-
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movsx_r32_m8(&dst, dstreg, MABS(basep.value + 1*indp.value)); // movsx eax,[basep + 1*indp]
-
- /* other index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movsx_r32_m8(&dst, dstreg, MISD(indreg, 1, basep.value)); // movsx eax,[basep + 1*indp]
- }
-
- /* 32-bit form */
- if (inst->size == 4)
- {
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* 64-bit form */
- else
- {
- /* general case */
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movzx_r32_m8(&dst, dstreg, MABS(basep.value + 1*indp.value)); // movzx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movzx_r32_m16(&dst, dstreg, MABS(basep.value + 2*indp.value)); // movzx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + 4*indp.value)); // mov dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_r32_m32(&dst, REG_EDX, MABS(basep.value + 8*indp.value + 4)); // mov edx,[basep + 8*indp + 4]
+ emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + 8*indp.value)); // mov dstreg,[basep + 8*indp]
+ }
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load2u - process a LOAD2U opcode
--------------------------------------------------*/
-
-static x86code *op_load2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movzx_r32_m16(&dst, dstreg, MABS(basep.value + 2*indp.value)); // movzx dstreg,[basep + 2*indp]
/* other index */
else
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movzx_r32_m16(&dst, dstreg, MISD(indreg, 2, basep.value)); // movzx dstreg,[basep + 2*indp]
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movzx_r32_m8(&dst, dstreg, MISD(indreg, 1, basep.value)); // movzx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movzx_r32_m16(&dst, dstreg, MISD(indreg, 2, basep.value)); // movzx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MISD(indreg, 4, basep.value)); // mov dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_r32_m32(&dst, REG_EDX, MISD(indreg, 8, basep.value + 4)); // mov edx,[basep + 8*indp + 4]
+ emit_mov_r32_m32(&dst, dstreg, MISD(indreg, 8, basep.value)); // mov dstreg,[basep + 8*indp]
+ }
}
/* store low 32 bits */
@@ -3858,23 +3846,35 @@ static x86code *op_load2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/* 64-bit form stores upper 32 bits */
if (inst->size == 8)
{
- /* general case */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ /* 1, 2, or 4-byte case */
+ if (sizep.value != DRCUML_SIZE_QWORD)
+ {
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ }
+
+ /* 8-byte case */
+ else
+ {
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
+ }
}
return dst;
}
/*-------------------------------------------------
- op_load2s - process a LOAD2S opcode
+ op_loads - process a LOADS opcode
-------------------------------------------------*/
-static x86code *op_load2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_loads(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, basep, indp;
+ drcuml_parameter dstp, basep, indp, sizep;
int dstreg;
/* validate instruction */
@@ -3882,70 +3882,43 @@ static x86code *op_load2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI, &sizep, PTYPE_I);
/* pick a target register for the general case */
- dstreg = (inst->size == 8) ? REG_EAX : param_select_register(REG_EAX, &dstp, NULL);
+ dstreg = param_select_register(REG_EAX, &dstp, NULL);
/* immediate index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_movsx_r32_m16(&dst, dstreg, MABS(basep.value + 2*indp.value)); // movsx eax,[basep + 2*indp]
-
- /* other index */
- else
{
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_movsx_r32_m16(&dst, dstreg, MISD(indreg, 2, basep.value)); // movsx eax,[basep + 2*indp]
- }
-
- /* 32-bit form */
- if (inst->size == 4)
- {
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* 64-bit form */
- else
- {
- /* general case */
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r32_m8(&dst, dstreg, MABS(basep.value + 1*indp.value)); // movsx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_m16(&dst, dstreg, MABS(basep.value + 2*indp.value)); // movsx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + 4*indp.value)); // mov dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_r32_m32(&dst, REG_EDX, MABS(basep.value + 8*indp.value + 4)); // mov edx,[basep + 8*indp + 4]
+ emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + 8*indp.value)); // mov dstreg,[basep + 8*indp]
+ }
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load4u - process a LOAD4U opcode
--------------------------------------------------*/
-
-static x86code *op_load4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + 4*indp.value)); // mov dstreg,[basep + 4*indp]
/* other index */
else
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_mov_r32_m32(&dst, dstreg, MISD(indreg, 4, basep.value)); // mov dstreg,[basep + 4*indp]
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r32_m8(&dst, dstreg, MISD(indreg, 1, basep.value)); // movsx dstreg,[basep + 1*indp]
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_m16(&dst, dstreg, MISD(indreg, 2, basep.value)); // movsx dstreg,[basep + 2*indp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MISD(indreg, 4, basep.value)); // mov dstreg,[basep + 4*indp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_r32_m32(&dst, REG_EDX, MISD(indreg, 8, basep.value + 4)); // mov edx,[basep + 8*indp + 4]
+ emit_mov_r32_m32(&dst, dstreg, MISD(indreg, 8, basep.value)); // mov dstreg,[basep + 8*indp]
+ }
}
/* store low 32 bits */
@@ -3954,100 +3927,23 @@ static x86code *op_load4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/* 64-bit form stores upper 32 bits */
if (inst->size == 8)
{
- /* general case */
+ emit_cdq(&dst); // cdq
if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
+ emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_load4s - process a LOAD4S opcode
--------------------------------------------------*/
-
-static x86code *op_load4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, basep, indp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_r32_m32(&dst, REG_EAX, MABS(basep.value + 4*indp.value)); // mov eax,[basep + 4*indp]
-
- /* other index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_mov_r32_m32(&dst, REG_EAX, MISD(indreg, 4, basep.value)); // movsx eax,[basep + 4*indp]
+ emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
}
-
- /* general case */
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
-
return dst;
}
/*-------------------------------------------------
- op_load8u - process a LOAD8U opcode
+ op_store - process a STORE opcode
-------------------------------------------------*/
-static x86code *op_load8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_store(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, basep, indp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &basep, PTYPE_M, &indp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* immediate index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- {
- emit_mov_r32_m32(&dst, REG_EDX, MABS(basep.value + 8*indp.value + 4)); // mov edx,[basep + 8*indp + 4]
- emit_mov_r32_m32(&dst, dstreg, MABS(basep.value + 8*indp.value)); // mov dstreg,[basep + 8*indp]
- }
-
- /* other index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- emit_mov_r32_m32(&dst, REG_EDX, MISD(indreg, 8, basep.value + 4)); // mov edx,[basep + 8*indp + 4]
- emit_mov_r32_m32(&dst, dstreg, MISD(indreg, 8, basep.value)); // mov dstreg,[basep + 8*indp]
- }
-
- /* general case */
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dstp,edx:dstreg
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_store1 - process a STORE1 opcode
--------------------------------------------------*/
-
-static x86code *op_store1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter srcp, basep, indp;
+ drcuml_parameter srcp, basep, indp, sizep;
int srcreg;
/* validate instruction */
@@ -4055,118 +3951,51 @@ static x86code *op_store1(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
+ param_normalize_4(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
/* pick a source register for the general case */
srcreg = param_select_register(REG_EAX, &srcp, NULL);
- if (srcreg & 4)
+ if (sizep.value == DRCUML_SIZE_BYTE && (srcreg & 4))
srcreg = REG_EAX;
/* degenerate case: constant index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
{
+ /* immediate source */
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m8_imm(&dst, MABS(basep.value + 1*indp.value), srcp.value); // mov [basep + 1*indp],srcp
- else
- {
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m8_r8(&dst, MABS(basep.value + 1*indp.value), srcreg); // mov [basep + 1*indp],srcreg
- }
- }
-
- /* normal case: variable index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m8_imm(&dst, MISD(indreg, 1, basep.value), srcp.value); // mov [basep + 1*ecx],srcp
- else
{
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m8_r8(&dst, MISD(indreg, 1, basep.value), srcreg); // mov [basep + 1*ecx],srcreg
- }
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_store2 - process a STORE2 opcode
--------------------------------------------------*/
-
-static x86code *op_store2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter srcp, basep, indp;
- int srcreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* pick a source register for the general case */
- srcreg = param_select_register(REG_EAX, &srcp, NULL);
-
- /* degenerate case: constant index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- {
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m16_imm(&dst, MABS(basep.value + 2*indp.value), srcp.value); // mov [basep + 2*indp],srcp
- else
- {
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m16_r16(&dst, MABS(basep.value + 2*indp.value), srcreg); // mov [basep + 2*indp],srcreg
- }
- }
-
- /* normal case: variable index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m16_imm(&dst, MISD(indreg, 2, basep.value), srcp.value); // mov [basep + 2*ecx],srcp
- else
- {
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m16_r16(&dst, MISD(indreg, 2, basep.value), srcreg); // mov [basep + 2*ecx],srcreg
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_imm(&dst, MABS(basep.value + 1*indp.value), srcp.value); // mov [basep + 1*indp],srcp
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_imm(&dst, MABS(basep.value + 2*indp.value), srcp.value); // mov [basep + 2*indp],srcp
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_imm(&dst, MABS(basep.value + 4*indp.value), srcp.value); // mov [basep + 4*indp],srcp
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_m32_imm(&dst, MABS(basep.value + 8*indp.value), srcp.value); // mov [basep + 8*indp],srcp
+ emit_mov_m32_imm(&dst, MABS(basep.value + 8*indp.value + 4), srcp.value >> 32);
+ // mov [basep + 8*indp + 4],srcp >> 32
+ }
}
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_store4 - process a STORE4 opcode
--------------------------------------------------*/
-
-static x86code *op_store4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter srcp, basep, indp;
- int srcreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* pick a source register for the general case */
- srcreg = param_select_register(REG_EAX, &srcp, NULL);
-
- /* degenerate case: constant index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- {
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m32_imm(&dst, MABS(basep.value + 4*indp.value), srcp.value); // mov [basep + 4*indp],srcp
+
+ /* variable source */
else
{
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m32_r32(&dst, MABS(basep.value + indp.value), srcreg); // mov [basep + 4*indp],srcreg
+ if (sizep.value != DRCUML_SIZE_QWORD)
+ emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(drcbe, &dst, srcreg, REG_EDX, &srcp); // mov edx:srcreg,srcp
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_r8(&dst, MABS(basep.value + 1*indp.value), srcreg); // mov [basep + 1*indp],srcreg
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_r16(&dst, MABS(basep.value + 2*indp.value), srcreg); // mov [basep + 2*indp],srcreg
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_r32(&dst, MABS(basep.value + 4*indp.value), srcreg); // mov [basep + 4*indp],srcreg
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_m32_r32(&dst, MABS(basep.value + 8*indp.value), srcreg); // mov [basep + 8*indp],srcreg
+ emit_mov_m32_r32(&dst, MABS(basep.value + 8*indp.value + 4), REG_EDX); // mov [basep + 8*indp + 4],edx
+ }
}
}
@@ -4175,69 +4004,42 @@ static x86code *op_store4(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- emit_mov_m32_imm(&dst, MISD(indreg, 4, basep.value), srcp.value); // mov [basep + 4*ecx],srcp
- else
- {
- emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
- emit_mov_m32_r32(&dst, MISD(indreg, 4, basep.value), srcreg); // mov [basep + 4*ecx],srcreg
- }
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_store8 - process a STORE8 opcode
--------------------------------------------------*/
-static x86code *op_store8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter srcp, basep, indp;
- int srcreg;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* pick a source register for the general case */
- srcreg = param_select_register(REG_EAX, &srcp, NULL);
-
- /* degenerate case: constant index */
- if (indp.type == DRCUML_PTYPE_IMMEDIATE)
- {
+ /* immediate source */
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
{
- emit_mov_m32_imm(&dst, MABS(basep.value + 8*indp.value), srcp.value); // mov [basep + 8*indp],srcp
- emit_mov_m32_imm(&dst, MABS(basep.value + 4 + 8*indp.value), srcp.value >> 32);
- // mov [basep + 4 + 8*indp],srcp >> 32
- }
- else
- {
- emit_mov_r64_p64(drcbe, &dst, srcreg, REG_EDX, &srcp); // mov edx:srcreg,srcp
- emit_mov_m32_r32(&dst, MABS(basep.value + 8*indp.value), srcreg); // mov [basep + 8*indp],srcreg
- emit_mov_m32_r32(&dst, MABS(basep.value + 4 + 8*indp.value), REG_EDX); // mov [basep + 8*indp + 4],edx
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_imm(&dst, MISD(indreg, 1, basep.value), srcp.value); // mov [basep + 1*ecx],srcp
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_imm(&dst, MISD(indreg, 2, basep.value), srcp.value); // mov [basep + 2*ecx],srcp
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_imm(&dst, MISD(indreg, 4, basep.value), srcp.value); // mov [basep + 4*ecx],srcp
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_m32_imm(&dst, MISD(indreg, 8, basep.value), srcp.value); // mov [basep + 8*ecx],srcp
+ emit_mov_m32_imm(&dst, MISD(indreg, 8, basep.value + 4), srcp.value >> 32);
+ // mov [basep + 8*ecx + 4],srcp >> 32
+ }
}
- }
- /* normal case: variable index */
- else
- {
- int indreg = param_select_register(REG_ECX, &indp, NULL);
- emit_mov_r32_p32(drcbe, &dst, indreg, &indp); // mov indreg,indp
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- {
- emit_mov_m32_imm(&dst, MISD(indreg, 8, basep.value), srcp.value); // mov [basep + 8*ecx],srcp
- emit_mov_m32_imm(&dst, MISD(indreg, 8, basep.value + 4), srcp.value >> 32); // mov [basep + 8*ecx + 4],srcp >> 32
- }
+ /* variable source */
else
{
- emit_mov_r64_p64(drcbe, &dst, srcreg, REG_EDX, &srcp); // mov edx:srcreg,srcp
- emit_mov_m32_r32(&dst, MISD(indreg, 8, basep.value), srcreg); // mov [basep + 8*ecx],srcreg
- emit_mov_m32_r32(&dst, MISD(indreg, 8, basep.value + 4), REG_EDX); // mov [basep + 4 + 8*ecx],edx
+ if (sizep.value != DRCUML_SIZE_QWORD)
+ emit_mov_r32_p32(drcbe, &dst, srcreg, &srcp); // mov srcreg,srcp
+ else
+ emit_mov_r64_p64(drcbe, &dst, srcreg, REG_EDX, &srcp); // mov edx:srcreg,srcp
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_mov_m8_r8(&dst, MISD(indreg, 1, basep.value), srcreg); // mov [basep + 1*ecx],srcreg
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_mov_m16_r16(&dst, MISD(indreg, 2, basep.value), srcreg); // mov [basep + 2*ecx],srcreg
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_m32_r32(&dst, MISD(indreg, 4, basep.value), srcreg); // mov [basep + 4*ecx],srcreg
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ {
+ emit_mov_m32_r32(&dst, MISD(indreg, 8, basep.value), srcreg); // mov [basep + 8*ecx],srcreg
+ emit_mov_m32_r32(&dst, MISD(indreg, 8, basep.value + 4), REG_EDX); // mov [basep + 8*ecx],edx
+ }
}
}
return dst;
@@ -4245,12 +4047,12 @@ static x86code *op_store8(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
- op_read1u - process a READ1U opcode
+ op_read - process a READ opcode
-------------------------------------------------*/
-static x86code *op_read1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_read(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, spacep, addrp;
+ drcuml_parameter dstp, addrp, spacesizep;
int dstreg;
/* validate instruction */
@@ -4258,124 +4060,74 @@ static x86code *op_read1u(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &spacesizep, PTYPE_I);
/* pick a target register for the general case */
dstreg = param_select_register(REG_EAX, &dstp, NULL);
/* set up a call to the read byte handler */
emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_byte);// call read_byte
- emit_add_r32_imm(&dst, REG_ESP, 4); // add esp,4
- emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
-
- /* store low 32 bits */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- /* 64-bit form stores upper 32 bits */
- if (inst->size == 8)
+ if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE)
{
- /* general case */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->read_byte);
+ // call read_byte
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read1s - process a READ1S opcode
--------------------------------------------------*/
-
-static x86code *op_read1s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read byte handler */
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_byte);// call read_byte
- emit_add_r32_imm(&dst, REG_ESP, 4); // add esp,4
- emit_movsx_r32_r8(&dst, dstreg, REG_AL); // movsx dstreg,al
-
- /* 32-bit form */
- if (inst->size == 4)
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
{
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->read_word);
+ // call read_word
+ emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
}
-
- /* 64-bit form */
- else
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
{
- /* general case */
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->read_dword);
+ // call read_dword
+ emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
+ }
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
+ {
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->read_qword);
+ // call read_qword
+ emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read2u - process a READ2U opcode
--------------------------------------------------*/
-
-static x86code *op_read2u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read word handler */
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_word);// call read_word
emit_add_r32_imm(&dst, REG_ESP, 4); // add esp,4
- emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
/* store low 32 bits */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
/* 64-bit form stores upper 32 bits */
if (inst->size == 8)
{
- /* general case */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ /* 1, 2, or 4-byte case */
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
+ {
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ }
+
+ /* 8-byte case */
+ else
+ {
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
+ }
}
return dst;
}
/*-------------------------------------------------
- op_read2s - process a READ2S opcode
+ op_readm - process a READM opcode
-------------------------------------------------*/
-static x86code *op_read2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_readm(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, spacep, addrp;
+ drcuml_parameter dstp, addrp, maskp, spacesizep;
int dstreg;
/* validate instruction */
@@ -4383,510 +4135,151 @@ static x86code *op_read2s(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &spacesizep, PTYPE_I);
/* pick a target register for the general case */
dstreg = param_select_register(REG_EAX, &dstp, NULL);
- /* set up a call to the read word handler */
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_word);// call read_word
- emit_add_r32_imm(&dst, REG_ESP, 4); // add esp,4
- emit_movsx_r32_r16(&dst, dstreg, REG_AX); // movsx dstreg,ax
-
- /* 32-bit form */
- if (inst->size == 4)
- {
- /* general case */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* 64-bit form */
+ /* set up a call to the read byte handler */
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
+ emit_push_p32(drcbe, &dst, &maskp); // push maskp
else
- {
- /* general case */
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read2m - process a READ2M opcode
--------------------------------------------------*/
-
-static x86code *op_read2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp, maskp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* set up a call to the read dword masked handler */
- emit_push_p32(drcbe, &dst, &maskp); // push maskp
+ emit_push_p64(drcbe, &dst, &maskp); // push maskp
emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_word_masked);
+ if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
+ {
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->read_word_masked);
// call read_word_masked
- emit_add_r32_imm(&dst, REG_ESP, 8); // add esp,8
- emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
-
- /* store low 32 bits */
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
-
- /* 64-bit form stores upper 32 bits */
- if (inst->size == 8)
+ emit_movzx_r32_r16(&dst, dstreg, REG_AX); // movzx dstreg,ax
+ }
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
{
- /* general case */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->read_dword_masked);
+ // call read_dword_masked
+ emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read4u - process a READ4U opcode
--------------------------------------------------*/
-
-static x86code *op_read4u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* set up a call to the read dword handler */
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_dword);// call read_dword
- emit_add_r32_imm(&dst, REG_ESP, 4); // add esp,4
-
- /* store low 32 bits */
- emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
-
- /* 64-bit form stores upper 32 bits */
- if (inst->size == 8)
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
{
- /* general case */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->read_qword_masked);
+ // call read_qword_masked
+ emit_mov_r32_r32(&dst, dstreg, REG_EAX); // mov dstreg,eax
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read4s - process a READ4S opcode
--------------------------------------------------*/
-
-static x86code *op_read4s(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* set up a call to the read dword handler */
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_dword);// call read_dword
- emit_add_r32_imm(&dst, REG_ESP, 4); // add esp,4
-
- /* 64-bit form */
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dst,edx:eax
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read4m - process a READ4M opcode
--------------------------------------------------*/
-
-static x86code *op_read4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp, maskp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI);
-
- /* set up a call to the read dword masked handler */
- emit_push_p32(drcbe, &dst, &maskp); // push maskp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_dword_masked);
- // call read_dword_masked
- emit_add_r32_imm(&dst, REG_ESP, 8); // add esp,8
-
+ emit_add_r32_imm(&dst, REG_ESP, ((spacesizep.value & 3) != DRCUML_SIZE_QWORD) ? 8 : 12);
+ // add esp,8/12
/* store low 32 bits */
- emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
/* 64-bit form stores upper 32 bits */
if (inst->size == 8)
{
- /* general case */
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ /* 1, 2, or 4-byte case */
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
+ {
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ }
+
+ /* 8-byte case */
+ else
+ {
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp+4],edx
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_EDX); // mov [reghi],edx
+ }
}
return dst;
}
/*-------------------------------------------------
- op_read8u - process a READ8U opcode
+ op_write - process a WRITE opcode
-------------------------------------------------*/
-static x86code *op_read8u(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_write(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, spacep, addrp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
-
- /* set up a call to the read qword handler */
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_qword);// call read_qword
- emit_add_r32_imm(&dst, REG_ESP, 4); // add esp,4
-
- /* 64-bit form */
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dst,edx:eax
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_read8m - process a READ8M opcode
--------------------------------------------------*/
-
-static x86code *op_read8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, spacep, addrp, maskp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI);
-
- /* set up a call to the read qword masked handler */
- emit_push_p64(drcbe, &dst, &maskp); // push maskp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->read_qword_masked);
- // call read_qword_masked
- emit_add_r32_imm(&dst, REG_ESP, 12); // add esp,12
-
- /* 64-bit form */
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dst,edx:eax
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write1 - process a WRITE1 opcode
--------------------------------------------------*/
-
-static x86code *op_write1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
+ drcuml_parameter addrp, srcp, spacesizep;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI, &spacesizep, PTYPE_I);
/* set up a call to the write byte handler */
- emit_push_p32(drcbe, &dst, &srcp); // push srcp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->write_byte);// call write_byte
- emit_add_r32_imm(&dst, REG_ESP, 8); // add esp,8
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write2 - process a WRITE2 opcode
--------------------------------------------------*/
-
-static x86code *op_write2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write word handler */
- emit_push_p32(drcbe, &dst, &srcp); // push srcp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->write_word);// call write_word
- emit_add_r32_imm(&dst, REG_ESP, 8); // add esp,8
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_writ2m - process a WRIT2M opcode
--------------------------------------------------*/
-
-static x86code *op_writ2m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, maskp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write word handler */
- emit_push_p32(drcbe, &dst, &maskp); // push maskp
- emit_push_p32(drcbe, &dst, &srcp); // push srcp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->write_word_masked);
- // call write_word_masked
- emit_add_r32_imm(&dst, REG_ESP, 12); // add esp,12
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write4 - process a WRITE4 opcode
--------------------------------------------------*/
-
-static x86code *op_write4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write dword handler */
- emit_push_p32(drcbe, &dst, &srcp); // push srcp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->write_dword);// call write_dword
- emit_add_r32_imm(&dst, REG_ESP, 8); // add esp,8
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_writ4m - process a WRIT4M opcode
--------------------------------------------------*/
-
-static x86code *op_writ4m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, maskp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write word handler */
- emit_push_p32(drcbe, &dst, &maskp); // push maskp
- emit_push_p32(drcbe, &dst, &srcp); // push srcp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->write_dword_masked);
- // call write_dword_masked
- emit_add_r32_imm(&dst, REG_ESP, 12); // add esp,12
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_write8 - process a WRITE8 opcode
--------------------------------------------------*/
-
-static x86code *op_write8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, srcp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write qword handler */
- emit_push_p64(drcbe, &dst, &srcp); // push srcp
- emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->write_qword);// call write_qword
-
- emit_add_r32_imm(&dst, REG_ESP, 12); // add esp,12
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_writ8m - process a WRIT8M opcode
--------------------------------------------------*/
-
-static x86code *op_writ8m(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter spacep, addrp, maskp, srcp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_4(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &maskp, PTYPE_MRI, &srcp, PTYPE_MRI);
-
- /* set up a call to the write word handler */
- emit_push_p64(drcbe, &dst, &maskp); // push maskp
- emit_push_p64(drcbe, &dst, &srcp); // push srcp
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
+ emit_push_p32(drcbe, &dst, &srcp); // push srcp
+ else
+ emit_push_p64(drcbe, &dst, &srcp); // push srcp
emit_push_p32(drcbe, &dst, &addrp); // push addrp
- emit_call(&dst, (x86code *)active_address_space[spacep.value].accessors->write_qword_masked);
- // call write_qword_masked
- emit_add_r32_imm(&dst, REG_ESP, 20); // add esp,20
+ if ((spacesizep.value & 3) == DRCUML_SIZE_BYTE)
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->write_byte);
+ // call write_byte
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->write_word);
+ // call write_word
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->write_dword);
+ // call write_dword
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->write_qword);
+ // call write_qword
+ emit_add_r32_imm(&dst, REG_ESP, ((spacesizep.value & 3) != DRCUML_SIZE_QWORD) ? 8 : 12);
+ // add esp,8/12
return dst;
}
/*-------------------------------------------------
- op_flags - process a FLAGS opcode
+ op_writem - process a WRITEM opcode
-------------------------------------------------*/
-static x86code *op_flags(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_writem(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, maskp, tablep;
- int dstreg;
+ drcuml_parameter addrp, srcp, maskp, spacesizep;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &maskp, PTYPE_I, &tablep, PTYPE_M);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_ECX, &dstp, NULL);
+ param_normalize_4(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MRI, &maskp, PTYPE_MRI, &spacesizep, PTYPE_I);
- /* translate live flags into UML flags */
- emit_pushf(&dst); // pushf
- emit_pop_r32(&dst, REG_EAX); // pop eax
- emit_and_r32_imm(&dst, REG_EAX, 0x8c5); // and eax,0x8c5
- emit_movzx_r32_m8(&dst, REG_EAX, MBD(REG_EAX, flags_map)); // movzx eax,[flags_map]
-
- /* 32-bit form */
- if (inst->size == 4)
+ /* set up a call to the write byte handler */
+ if ((spacesizep.value & 3) != DRCUML_SIZE_QWORD)
{
- /* no masking */
- if (maskp.value == 0xffffffff)
- {
- emit_mov_r32_m32(&dst, dstreg, MISD(REG_EAX, 4, tablep.value)); // mov dstreg,[eax*4+table]
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* general case */
- else
- {
- emit_mov_r32_p32(drcbe, &dst, dstreg, &dstp); // mov dstreg,dstp
- emit_mov_r32_m32(&dst, REG_EDX, MISD(REG_EAX, 4, tablep.value)); // mov edx,[eax*4+table]
- emit_and_r32_imm(&dst, dstreg, ~maskp.value); // and dstreg,~mask
- emit_and_r32_imm(&dst, REG_EDX, maskp.value); // and edx,mask
- emit_or_r32_r32(&dst, dstreg, REG_EDX); // or dstreg,edx
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
+ emit_push_p32(drcbe, &dst, &maskp); // push maskp
+ emit_push_p32(drcbe, &dst, &srcp); // push srcp
}
-
- /* 64-bit form */
else
{
- /* no masking */
- if (maskp.value == U64(0xffffffffffffffff))
- {
- emit_mov_r32_m32(&dst, dstreg, MISD(REG_EAX, 8, tablep.value)); // mov dstreg,[eax*4+table]
- emit_mov_r32_m32(&dst, REG_EDX, MISD(REG_EAX, 8, tablep.value + 4)); // mov edx,[eax*4+table+4]
- emit_mov_p64_r64(drcbe, &dst, &dstp, dstreg, REG_EDX); // mov dst,edx:dstreg
- }
-
- /* general case */
- else
- {
- if ((UINT32)maskp.value != 0)
- {
- emit_mov_r32_p32(drcbe, &dst, dstreg, &dstp); // mov dstreg,dstp
- emit_mov_r32_m32(&dst, REG_EDX, MISD(REG_EAX, 8, tablep.value)); // mov edx,[eax*8+table]
- emit_and_r32_imm(&dst, dstreg, ~maskp.value); // and dstreg,~mask
- emit_and_r32_imm(&dst, REG_EDX, maskp.value); // and edx,mask
- emit_or_r32_r32(&dst, dstreg, REG_EDX); // or dstreg,edx
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg.lo
- }
- if ((UINT32)(maskp.value >> 32) != 0)
- {
- if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_r32_m32(&dst, REG_ECX, MABS(drcbe->reghi[dstp.value])); // mov ecx,dstp.hi
- else
- emit_mov_r32_m32(&dst, REG_ECX, MABS(dstp.value + 4)); // mov ecx,dstp.hi
- emit_mov_r32_m32(&dst, REG_EDX, MISD(REG_EDX, 8, tablep.value+4)); // mov edx,[eax*8+table+4]
- emit_and_r32_imm(&dst, REG_ECX, ~maskp.value); // and ecx,~mask
- emit_and_r32_imm(&dst, REG_EDX, maskp.value); // and edx,mask
- emit_or_r32_r32(&dst, REG_ECX, REG_EDX); // or ecx,edx
- if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_r32(&dst, MABS(drcbe->reghi[dstp.value]), REG_ECX); // mov dstp.hi,ecx
- else
- emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_ECX); // mov dstp.hi,ecx
- }
- }
+ emit_push_p64(drcbe, &dst, &maskp); // push maskp
+ emit_push_p64(drcbe, &dst, &srcp); // push srcp
}
+ emit_push_p32(drcbe, &dst, &addrp); // push addrp
+ if ((spacesizep.value & 3) == DRCUML_SIZE_WORD)
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->write_word_masked);
+ // call write_word_masked
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_DWORD)
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->write_dword_masked);
+ // call write_dword_masked
+ else if ((spacesizep.value & 3) == DRCUML_SIZE_QWORD)
+ emit_call(&dst, (x86code *)active_address_space[spacesizep.value / 16].accessors->write_qword_masked);
+ // call write_qword_masked
+ emit_add_r32_imm(&dst, REG_ESP, ((spacesizep.value & 3) != DRCUML_SIZE_QWORD) ? 12 : 20);
+ // add esp,12/20
return dst;
}
/*-------------------------------------------------
- op_setc - process a SETC opcode
+ op_carry - process a CARRY opcode
-------------------------------------------------*/
-static x86code *op_setc(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_carry(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter srcp, bitp;
@@ -4961,6 +4354,45 @@ static x86code *op_setc(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
/*-------------------------------------------------
+ op_set - process a SET opcode
+-------------------------------------------------*/
+
+static x86code *op_set(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+{
+ drcuml_parameter dstp;
+ int dstreg;
+
+ /* validate instruction */
+ assert(inst->size == 4 || inst->size == 8);
+ assert(inst->condflags >= DRCUML_COND_Z && inst->condflags < DRCUML_COND_MAX);
+
+ /* normalize parameters */
+ param_normalize_1(drcbe, inst, &dstp, PTYPE_MR);
+
+ /* pick a target register for the general case */
+ dstreg = param_select_register(REG_EAX, &dstp, NULL);
+
+ /* set to AL */
+ emit_setcc_r8(&dst, X86_CONDITION(inst->condflags), REG_AL); // setcc al
+ emit_movzx_r32_r8(&dst, dstreg, REG_AL); // movzx dstreg,al
+
+ /* store low 32 bits */
+ emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+
+ /* 64-bit form stores upper 32 bits */
+ if (inst->size == 8)
+ {
+ /* general case */
+ if (dstp.type == DRCUML_PTYPE_MEMORY)
+ emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
+ else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov [reghi],0
+ }
+ return dst;
+}
+
+
+/*-------------------------------------------------
op_mov - process a MOV opcode
-------------------------------------------------*/
@@ -5067,71 +4499,12 @@ static x86code *op_mov(drcbe_state *drcbe, x86code *dst, const drcuml_instructio
/*-------------------------------------------------
- op_zext1 - process a ZEXT1 opcode
--------------------------------------------------*/
-
-static x86code *op_zext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (UINT8)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* convert 8-bit source registers */
- if (srcp.type == DRCUML_PTYPE_INT_REGISTER && (srcp.value & 4))
- {
- emit_mov_r32_r32(&dst, REG_EAX, srcp.value); // mov eax,srcp
- srcp.value = REG_EAX;
- }
-
- /* 32-bit form */
- if (inst->size == 4)
- {
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movzx_r32_m8(&dst, dstreg, MABS(srcp.value)); // movzx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movzx_r32_r8(&dst, dstreg, srcp.value); // movzx dstreg,srcp
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
-
- /* 64-bit form */
- else if (inst->size == 8)
- {
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movzx_r32_m8(&dst, dstreg, MABS(srcp.value)); // movzx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movzx_r32_r8(&dst, dstreg, srcp.value); // movzx dstreg,srcp
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov reghi[dstp],0
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_zext2 - process a ZEXT2 opcode
+ op_sext - process a SEXT opcode
-------------------------------------------------*/
-static x86code *op_zext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_sext(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep;
int dstreg;
/* validate instruction */
@@ -5139,180 +4512,56 @@ static x86code *op_zext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
/* degenerate cases -- convert to a move */
if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (UINT16)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* 32-bit form */
- if (inst->size == 4)
{
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movzx_r32_m16(&dst, dstreg, MABS(srcp.value)); // movzx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movzx_r32_r16(&dst, dstreg, srcp.value); // movzx dstreg,srcp
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT8)srcp.value);
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT16)srcp.value);
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT32)srcp.value);
}
- /* 64-bit form */
- else if (inst->size == 8)
- {
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movzx_r32_m16(&dst, dstreg, MABS(srcp.value)); // movzx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movzx_r32_r16(&dst, dstreg, srcp.value); // movzx dstreg,srcp
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov reghi[dstp],0
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_zext4 - process a ZEXT4 opcode
--------------------------------------------------*/
-
-static x86code *op_zext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (UINT32)srcp.value);
-
/* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* 64-bit form */
- if (inst->size == 8)
- {
- /* general case */
- emit_mov_r32_p32(drcbe, &dst, dstreg, &srcp); // mov dstreg,srcp
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_mov_m32_imm(&dst, MABS(dstp.value + 4), 0); // mov [dstp+4],0
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_mov_m32_imm(&dst, MABS(drcbe->reghi[dstp.value]), 0); // mov reghi[dstp],0
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_sext1 - process a SEXT1 opcode
--------------------------------------------------*/
-
-static x86code *op_sext1(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT8)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
+ dstreg = (inst->size == 8) ? REG_EAX : param_select_register(REG_EAX, &dstp, NULL);
- /* convert 8-bit source registers */
- if (srcp.type == DRCUML_PTYPE_INT_REGISTER && (srcp.value & 4))
+ /* convert 8-bit source registers to EAX */
+ if (sizep.value == DRCUML_SIZE_BYTE && srcp.type == DRCUML_PTYPE_INT_REGISTER && (srcp.value & 4))
{
emit_mov_r32_r32(&dst, REG_EAX, srcp.value); // mov eax,srcp
srcp.value = REG_EAX;
}
- /* 32-bit form */
- if (inst->size == 4)
+ /* general case */
+ if (srcp.type == DRCUML_PTYPE_MEMORY)
{
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
+ if (sizep.value == DRCUML_SIZE_BYTE)
emit_movsx_r32_m8(&dst, dstreg, MABS(srcp.value)); // movsx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r32_r8(&dst, dstreg, srcp.value); // movsx dstreg,srcp
- emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_m16(&dst, dstreg, MABS(srcp.value)); // movsx dstreg,[srcp]
+ else if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_mov_r32_m32(&dst, dstreg, MABS(srcp.value)); // mov dstreg,[srcp]
}
-
- /* 64-bit form */
- else if (inst->size == 8)
+ else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
{
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsx_r32_m8(&dst, REG_EAX, MABS(srcp.value)); // movsx eax,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r32_r8(&dst, REG_EAX, srcp.value); // movsx eax,srcp
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
+ if (sizep.value == DRCUML_SIZE_BYTE)
+ emit_movsx_r32_r8(&dst, dstreg, srcp.value); // movsx dstreg,srcp
+ else if (sizep.value == DRCUML_SIZE_WORD)
+ emit_movsx_r32_r16(&dst, dstreg, srcp.value); // movsx dstreg,srcp
+ else if (sizep.value == DRCUML_SIZE_DWORD && dstreg != srcp.value)
+ emit_mov_r32_r32(&dst, dstreg, srcp.value); // mov dstreg,srcp
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_sext2 - process a SEXT2 opcode
--------------------------------------------------*/
-
-static x86code *op_sext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
- int dstreg;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT16)srcp.value);
-
- /* pick a target register for the general case */
- dstreg = param_select_register(REG_EAX, &dstp, NULL);
-
- /* 32-bit form */
+
+ /* 32-bit form: store the low 32 bits */
if (inst->size == 4)
- {
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsx_r32_m16(&dst, dstreg, MABS(srcp.value)); // movsx dstreg,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r32_r16(&dst, dstreg, srcp.value); // movsx dstreg,srcp
emit_mov_p32_r32(drcbe, &dst, &dstp, dstreg); // mov dstp,dstreg
- }
- /* 64-bit form */
+ /* 64-bit form: sign extend to 64 bits and store edx:eax */
else if (inst->size == 8)
{
- /* general case */
- if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_movsx_r32_m16(&dst, REG_EAX, MABS(srcp.value)); // movsx eax,[srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- emit_movsx_r32_r16(&dst, REG_EAX, srcp.value); // movsx eax,srcp
emit_cdq(&dst); // cdq
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
}
@@ -5321,41 +4570,10 @@ static x86code *op_sext2(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/*-------------------------------------------------
- op_sext4 - process a SEXT4 opcode
+ op_roland - process an ROLAND opcode
-------------------------------------------------*/
-static x86code *op_sext4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MRI);
-
- /* degenerate cases -- convert to a move */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- return convert_to_mov_imm(drcbe, dst, inst, &dstp, (INT32)srcp.value);
-
- /* 64-bit form */
- if (inst->size == 8)
- {
- /* general case */
- emit_mov_r32_p32(drcbe, &dst, REG_EAX, &srcp); // mov eax,srcp
- emit_cdq(&dst); // cdq
- emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_xtract - process an XTRACT opcode
--------------------------------------------------*/
-
-static x86code *op_xtract(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_roland(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter dstp, srcp, shiftp, maskp;
int dstreg;
@@ -5417,10 +4635,10 @@ static x86code *op_xtract(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
/*-------------------------------------------------
- op_insert - process an INSERT opcode
+ op_rolins - process an ROLINS opcode
-------------------------------------------------*/
-static x86code *op_insert(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_rolins(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter dstp, srcp, shiftp, maskp;
int dstreg;
@@ -5889,6 +5107,27 @@ static x86code *op_mulu(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
if (compute_hi)
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
+
+ /* compute flags */
+ if (inst->condflags != 0)
+ {
+ if (compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
+ }
}
/* 64-bit form */
@@ -5907,13 +5146,45 @@ static x86code *op_mulu(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reslo + 0)); // mov eax,reslo.lo
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reslo + 1)); // mov edx,reslo.hi
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
- if (inst->condflags != 0)
- emit_or_r32_r32(&dst, REG_EAX, REG_EDX); // or eax,edx
+ if (inst->condflags != 0 && !compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
if (compute_hi)
{
+ if (inst->condflags & DRCUML_FLAG_Z)
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reshi + 0)); // mov eax,reshi.lo
- emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reshi + 1)); // mov edx,reshi.hi
- emit_mov_p64_r64(drcbe, &dst, &edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
+ emit_mov_r32_m32(&dst, REG_ECX, MABS((UINT32 *)&drcbe->reshi + 1)); // mov ecx,reshi.hi
+ emit_mov_p64_r64(drcbe, &dst, &edstp, REG_EAX, REG_ECX); // mov edstp,ecx:eax
+ if (inst->condflags != 0)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ {
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ }
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_ECX, REG_ECX); // test ecx,ecx
+ else
+ {
+ emit_or_r32_r32(&dst, REG_EAX, REG_EDX); // or eax,edx
+ emit_movzx_r32_r16(&dst, REG_EDX, REG_AX); // movzx edx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_ECX, REG_EDX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_ECX, REG_EAX); // or edx,eax
+ }
+ }
}
}
return dst;
@@ -6008,6 +5279,27 @@ static x86code *op_muls(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_p32_r32(drcbe, &dst, &dstp, REG_EAX); // mov dstp,eax
emit_mov_p32_r32(drcbe, &dst, &edstp, REG_EDX); // mov edstp,edx
}
+
+ /* compute flags */
+ if (inst->condflags != 0)
+ {
+ if (compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
+ else
+ emit_test_r32_r32(&dst, REG_EAX, REG_EAX); // test eax,eax
+ }
}
/* 64-bit form */
@@ -6026,13 +5318,43 @@ static x86code *op_muls(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reslo + 0)); // mov eax,reslo.lo
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reslo + 1)); // mov edx,reslo.hi
emit_mov_p64_r64(drcbe, &dst, &dstp, REG_EAX, REG_EDX); // mov dstp,edx:eax
- if (inst->condflags != 0)
- emit_or_r32_r32(&dst, REG_EAX, REG_EDX); // or eax,edx
+ if (inst->condflags != 0 && !compute_hi)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_EDX, REG_EDX); // test edx,edx
+ else
+ {
+ emit_movzx_r32_r16(&dst, REG_ECX, REG_AX); // movzx ecx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ }
+ }
if (compute_hi)
{
emit_mov_r32_m32(&dst, REG_EAX, MABS((UINT32 *)&drcbe->reshi + 0)); // mov eax,reshi.lo
emit_mov_r32_m32(&dst, REG_EDX, MABS((UINT32 *)&drcbe->reshi + 1)); // mov edx,reshi.hi
emit_mov_p64_r64(drcbe, &dst, &edstp, REG_EAX, REG_EDX); // mov edstp,edx:eax
+ if (inst->condflags != 0)
+ {
+ if (inst->condflags == DRCUML_FLAG_Z)
+ {
+ emit_or_r32_r32(&dst, REG_EDX, REG_EAX); // or edx,eax
+ emit_or_r32_r32(&dst, REG_EDX, REG_ECX); // or edx,ecx
+ }
+ else if (inst->condflags == DRCUML_FLAG_S)
+ emit_test_r32_r32(&dst, REG_ECX, REG_ECX); // test ecx,ecx
+ else
+ {
+ emit_or_r32_r32(&dst, REG_EAX, REG_EDX); // or eax,edx
+ emit_movzx_r32_r16(&dst, REG_EDX, REG_AX); // movzx edx,ax
+ emit_shr_r32_imm(&dst, REG_EAX, 16); // shr eax,16
+ emit_or_r32_r32(&dst, REG_ECX, REG_EDX); // or edx,ecx
+ emit_or_r32_r32(&dst, REG_ECX, REG_EAX); // or edx,eax
+ }
+ }
}
}
return dst;
@@ -6963,10 +6285,9 @@ static x86code *op_fload(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/* immediate index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
{
- if (inst->size == 4)
- emit_fld_m32(&dst, MABS(basep.value + 4*indp.value)); // fld [basep + 4*indp]
- else if (inst->size == 8)
- emit_fld_m64(&dst, MABS(basep.value + 8*indp.value)); // fld [basep + 8*indp]
+ emit_mov_r32_m32(&dst, REG_EAX, MABS(basep.value + 4*indp.value)); // mov eax,[basep + 4*indp]
+ if (inst->size == 8)
+ emit_mov_r32_m32(&dst, REG_EDX, MABS(basep.value + 4 + 4*indp.value)); // mov edx,[basep + 4*indp + 4]
}
/* other index */
@@ -6974,15 +6295,15 @@ static x86code *op_fload(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- if (inst->size == 4)
- emit_fld_m32(&dst, MISD(indreg, 4, basep.value)); // fld [basep + 4*indp]
- else if (inst->size == 8)
- emit_fld_m64(&dst, MISD(indreg, 8, basep.value)); // fld [basep + 8*indp]
+ emit_mov_r32_m32(&dst, REG_EAX, MISD(indreg, 4, basep.value)); // mov eax,[basep + 4*indp]
+ if (inst->size == 8)
+ emit_mov_r32_m32(&dst, REG_EDX, MISD(indreg, 4, basep.value + 4)); // mov edx,[basep + 4*indp + 4]
}
/* general case */
- emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
-
+ emit_mov_m32_r32(&dst, MABS(dstp.value), REG_EAX); // mov [dstp],eax
+ if (inst->size == 8)
+ emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp + 4],edx
return dst;
}
@@ -7003,15 +6324,16 @@ static x86code *op_fstore(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
param_normalize_3(drcbe, inst, &basep, PTYPE_M, &indp, PTYPE_MRI, &srcp, PTYPE_MF);
/* general case */
- emit_fld_p(&dst, inst->size, &srcp);
+ emit_mov_r32_m32(&dst, REG_EAX, MABS(srcp.value)); // mov eax,[srcp]
+ if (inst->size == 8)
+ emit_mov_r32_m32(&dst, REG_EDX, MABS(srcp.value + 4)); // mov edx,[srcp + 4]
/* immediate index */
if (indp.type == DRCUML_PTYPE_IMMEDIATE)
{
- if (inst->size == 4)
- emit_fstp_m32(&dst, MABS(basep.value + 4*indp.value)); // fstp [basep + 4*indp]
- else if (inst->size == 8)
- emit_fstp_m64(&dst, MABS(basep.value + 8*indp.value)); // fstp [basep + 8*indp]
+ emit_mov_m32_r32(&dst, MABS(basep.value + 4*indp.value), REG_EAX); // mov [basep + 4*indp],eax
+ if (inst->size == 8)
+ emit_mov_m32_r32(&dst, MABS(basep.value + 4 + 4*indp.value), REG_EDX); // mov [basep + 4*indp + 4],edx
}
/* other index */
@@ -7019,10 +6341,9 @@ static x86code *op_fstore(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
{
int indreg = param_select_register(REG_ECX, &indp, NULL);
emit_mov_r32_p32(drcbe, &dst, indreg, &indp);
- if (inst->size == 4)
- emit_fstp_m32(&dst, MISD(indreg, 4, basep.value)); // fstp [basep + 4*indp]
- else if (inst->size == 8)
- emit_fstp_m64(&dst, MISD(indreg, 8, basep.value)); // fstp [basep + 8*indp]
+ emit_mov_m32_r32(&dst, MISD(indreg, 4, basep.value), REG_EAX); // mov [basep + 4*indp],eax
+ if (inst->size == 8)
+ emit_mov_m32_r32(&dst, MISD(indreg, 4, basep.value + 4), REG_EDX); // mov [basep + 4*indp + 4],edx
}
return dst;
}
@@ -7041,7 +6362,7 @@ static x86code *op_fread(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &spacep, PTYPE_I, &addrp, PTYPE_MRI);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &addrp, PTYPE_MRI, &spacep, PTYPE_I);
/* set up a call to the read dword/qword handler */
emit_push_p32(drcbe, &dst, &addrp); // push addrp
@@ -7074,7 +6395,7 @@ static x86code *op_fwrite(drcbe_state *drcbe, x86code *dst, const drcuml_instruc
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_3(drcbe, inst, &spacep, PTYPE_I, &addrp, PTYPE_MRI, &srcp, PTYPE_MF);
+ param_normalize_3(drcbe, inst, &addrp, PTYPE_MRI, &srcp, PTYPE_MF, &spacep, PTYPE_I);
/* set up a call to the write dword/qword handler */
if (inst->size == 4)
@@ -7113,8 +6434,12 @@ static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
emit_jcc_short_link(&dst, X86_NOT_CONDITION(inst->condflags), &skip); // jcc skip
/* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
+ emit_mov_r32_m32(&dst, REG_EAX, MABS(srcp.value)); // mov eax,[srcp]
+ if (inst->size == 8)
+ emit_mov_r32_m32(&dst, REG_EDX, MABS(srcp.value + 4)); // mov edx,[srcp + 4]
+ emit_mov_m32_r32(&dst, MABS(dstp.value), REG_EAX); // mov [dstp],eax
+ if (inst->size == 8)
+ emit_mov_m32_r32(&dst, MABS(dstp.value + 4), REG_EDX); // mov [dstp + 4],edx
/* resolve the jump */
if (skip.target != NULL)
@@ -7124,394 +6449,154 @@ static x86code *op_fmov(drcbe_state *drcbe, x86code *dst, const drcuml_instructi
/*-------------------------------------------------
- op_ftoi4 - process a FTOI4 opcode
+ op_ftoint - process a FTOINT opcode
-------------------------------------------------*/
-static x86code *op_ftoi4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_ftoint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep, roundp;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
+ param_normalize_4(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF, &sizep, PTYPE_I, &roundp, PTYPE_I);
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m32(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ /* set rounding mode if necessary */
+ if (roundp.value != DRCUML_FMOD_DEFAULT && (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC))
{
- emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
+ emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
+ emit_fldcw_m16(&dst, MABS(&fp_control[roundp.value])); // fldcw fpcontrol[roundp]
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi4t - process a FTOI4T opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi4t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* non-SSE3 case */
- if (!drcbe->sse3)
+
+ /* general case */
+ emit_fld_p(&dst, inst->size, &srcp); // fld srcp
+
+ /* 4-byte integer case */
+ if (sizep.value == DRCUML_SIZE_DWORD)
{
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_TRUNC])); // fldcw fpcontrol[DRCUML_FMOD_TRUNC]
-
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m32(&dst, MABS(dstp.value)); // fistp [dstp]
+ {
+ if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
+ emit_fistp_m32(&dst, MABS(dstp.value)); // fistp [dstp]
+ else
+ emit_fisttp_m32(&dst, MABS(dstp.value)); // fisttp [dstp]
+ }
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
{
- emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
+ if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
+ emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
+ else
+ emit_fisttp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fisttp reglo[dstp]
emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
}
-
- /* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
}
-
- /* SSE3 case */
- else
+
+ /* 8-byte integer case */
+ else if (sizep.value == DRCUML_SIZE_QWORD)
{
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fisttp_m32(&dst, MABS(dstp.value)); // fisttp [dstp]
+ {
+ if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
+ emit_fistp_m64(&dst, MABS(dstp.value)); // fistp [dstp]
+ else
+ emit_fisttp_m64(&dst, MABS(dstp.value)); // fisttp [dstp]
+ }
else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
{
- emit_fisttp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fisttp reglo[dstp]
+ if (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC)
+ emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
+ else
+ emit_fisttp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fisttp reglo[dstp]
emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
}
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi4r - process a FTOI4R opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi4r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_ROUND])); // fldcw fpcontrol[DRCUML_FMOD_ROUND]
-
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m32(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- {
- emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
- }
/* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi4f - process a FTOI4F opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi4f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_FLOOR])); // fldcw fpcontrol[DRCUML_FMOD_FLOOR]
-
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m32(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- {
- emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
- }
-
- /* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi4c - process a FTOI4C opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi4c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_CEIL])); // fldcw fpcontrol[DRCUML_FMOD_CEIL]
-
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m32(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- {
- emit_fistp_m32(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
- }
+ if (roundp.value != DRCUML_FMOD_DEFAULT && (!drcbe->sse3 || roundp.value != DRCUML_FMOD_TRUNC))
+ emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
- /* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
return dst;
}
/*-------------------------------------------------
- op_ftoi8 - process a FTOI8 opcode
+ op_ffrint - process a FFRINT opcode
-------------------------------------------------*/
-static x86code *op_ftoi8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_ffrint(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MRI, &sizep, PTYPE_I);
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m64(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ /* 4-byte integer case */
+ if (sizep.value == DRCUML_SIZE_DWORD)
{
- emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
- }
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi8t - process a FTOI8T opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi8t(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* non-SSE3 case */
- if (!drcbe->sse3)
- {
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_TRUNC])); // fldcw fpcontrol[DRCUML_FMOD_TRUNC]
-
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m64(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
{
- emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
+ emit_mov_m32_imm(&dst, MABS(&drcbe->fptemp), srcp.value); // mov [fptemp],srcp
+ emit_fild_m32(&dst, MABS(&drcbe->fptemp)); // fild [fptemp]
}
-
- /* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
- }
-
- /* SSE3 case */
- else
- {
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fisttp_m64(&dst, MABS(dstp.value)); // fisttp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+ else if (srcp.type == DRCUML_PTYPE_MEMORY)
+ emit_fild_m32(&dst, MABS(srcp.value)); // fild [srcp]
+ else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
{
- emit_fisttp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fisttp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
+ emit_mov_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), srcp.value); // mov reglo[srcp],srcp
+ emit_fild_m32(&dst, MABS(drcbe->reglo[srcp.value])); // fild reglo[srcp]
}
}
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi8r - process a FTOI8R opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi8r(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_ROUND])); // fldcw fpcontrol[DRCUML_FMOD_ROUND]
-
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m64(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- {
- emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
- }
-
- /* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ftoi8f - process a FTOI8F opcode
--------------------------------------------------*/
-
-static x86code *op_ftoi8f(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_FLOOR])); // fldcw fpcontrol[DRCUML_FMOD_FLOOR]
-
- /* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m64(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
+
+ /* 8-bit integer case */
+ else if (sizep.value == DRCUML_SIZE_QWORD)
{
- emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
+ if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
+ {
+ emit_mov_m32_imm(&dst, MABS(&drcbe->fptemp), srcp.value); // mov [fptemp],srcp
+ emit_mov_m32_imm(&dst, MABS((UINT8 *)&drcbe->fptemp + 4), srcp.value); // mov [fptemp+4],srcp
+ emit_fild_m64(&dst, MABS(&drcbe->fptemp)); // fild [fptemp]
+ }
+ else if (srcp.type == DRCUML_PTYPE_MEMORY)
+ emit_fild_m64(&dst, MABS(srcp.value)); // fild [srcp]
+ else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
+ {
+ emit_mov_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), srcp.value); // mov reglo[srcp],srcp
+ emit_fild_m64(&dst, MABS(drcbe->reglo[srcp.value])); // fild reglo[srcp]
+ }
}
- /* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
+ /* store the result and be done */
+ emit_fstp_p(&dst, inst->size, &dstp); // fstp [dstp]
return dst;
}
/*-------------------------------------------------
- op_ftoi8c - process a FTOI8C opcode
+ op_ffrflt - process a FFRFLT opcode
-------------------------------------------------*/
-static x86code *op_ftoi8c(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_ffrflt(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
- drcuml_parameter dstp, srcp;
+ drcuml_parameter dstp, srcp, sizep;
/* validate instruction */
assert(inst->size == 4 || inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MR, &srcp, PTYPE_MF);
-
- /* save and set the control word */
- emit_fstcw_m16(&dst, MABS(&drcbe->fmodesave)); // fstcw [fmodesave]
- emit_fldcw_m16(&dst, MABS(&fp_control[DRCUML_FMOD_CEIL])); // fldcw fpcontrol[DRCUML_FMOD_CEIL]
+ param_normalize_3(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF, &sizep, PTYPE_I);
/* general case */
- emit_fld_p(&dst, inst->size, &srcp); // fld srcp
- if (dstp.type == DRCUML_PTYPE_MEMORY)
- emit_fistp_m64(&dst, MABS(dstp.value)); // fistp [dstp]
- else if (dstp.type == DRCUML_PTYPE_INT_REGISTER)
- {
- emit_fistp_m64(&dst, MABS(drcbe->reglo[dstp.value])); // fistp reglo[dstp]
- emit_mov_r32_m32(&dst, dstp.value, MABS(drcbe->reglo[dstp.value])); // mov dstp,reglo[dstp]
- }
-
- /* restore control word and proceed */
- emit_fldcw_m16(&dst, MABS(&drcbe->fmodesave)); // fldcw [fmodesave]
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ffrfs - process a FFRFS opcode
--------------------------------------------------*/
-
-static x86code *op_ffrfs(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
-
- /* general case */
- emit_fld_m32(&dst, MABS(srcp.value)); // fld [srcp]
+ if (sizep.value == DRCUML_SIZE_DWORD)
+ emit_fld_m32(&dst, MABS(srcp.value)); // fld [srcp]
+ else if (sizep.value == DRCUML_SIZE_QWORD)
+ emit_fld_m64(&dst, MABS(srcp.value)); // fld [srcp]
emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
return dst;
@@ -7519,90 +6604,24 @@ static x86code *op_ffrfs(drcbe_state *drcbe, x86code *dst, const drcuml_instruct
/*-------------------------------------------------
- op_ffrfd - process a FFRFD opcode
+ op_frnds - process a FRNDS opcode
-------------------------------------------------*/
-static x86code *op_ffrfd(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
+static x86code *op_frnds(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
{
drcuml_parameter dstp, srcp;
/* validate instruction */
- assert(inst->size == 4);
+ assert(inst->size == 8);
assert(inst->condflags == DRCUML_COND_ALWAYS);
/* normalize parameters */
param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MF);
/* general case */
- emit_fld_m64(&dst, MABS(srcp.value)); // fld [srcp]
- emit_fstp_p(&dst, inst->size, &dstp); // fstp dstp
-
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ffri4 - process a FFRI4 opcode
--------------------------------------------------*/
-
-static x86code *op_ffri4(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MRI);
-
- /* general case */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- {
- emit_mov_m32_imm(&dst, MABS(&drcbe->fptemp), srcp.value); // mov [fptemp],srcp
- emit_fild_m32(&dst, MABS(&drcbe->fptemp)); // fild [fptemp]
- }
- else if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_fild_m32(&dst, MABS(srcp.value)); // fild [srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- {
- emit_mov_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), srcp.value); // mov reglo[srcp],srcp
- emit_fild_m32(&dst, MABS(drcbe->reglo[srcp.value])); // fild reglo[srcp]
- }
- emit_fstp_p(&dst, inst->size, &dstp); // fstp [dstp]
- return dst;
-}
-
-
-/*-------------------------------------------------
- op_ffri8 - process a FFRI8 opcode
--------------------------------------------------*/
-
-static x86code *op_ffri8(drcbe_state *drcbe, x86code *dst, const drcuml_instruction *inst)
-{
- drcuml_parameter dstp, srcp;
-
- /* validate instruction */
- assert(inst->size == 4 || inst->size == 8);
- assert(inst->condflags == DRCUML_COND_ALWAYS);
-
- /* normalize parameters */
- param_normalize_2(drcbe, inst, &dstp, PTYPE_MF, &srcp, PTYPE_MRI);
-
- /* general case */
- if (srcp.type == DRCUML_PTYPE_IMMEDIATE)
- {
- emit_mov_m32_imm(&dst, MABS(&drcbe->fptemp), srcp.value); // mov [fptemp],srcp
- emit_mov_m32_imm(&dst, MABS((UINT8 *)&drcbe->fptemp + 4), srcp.value); // mov [fptemp+4],srcp
- emit_fild_m64(&dst, MABS(&drcbe->fptemp)); // fild [fptemp]
- }
- else if (srcp.type == DRCUML_PTYPE_MEMORY)
- emit_fild_m64(&dst, MABS(srcp.value)); // fild [srcp]
- else if (srcp.type == DRCUML_PTYPE_INT_REGISTER)
- {
- emit_mov_m32_r32(&dst, MABS(drcbe->reglo[srcp.value]), srcp.value); // mov reglo[srcp],srcp
- emit_fild_m64(&dst, MABS(drcbe->reglo[srcp.value])); // fild reglo[srcp]
- }
+ emit_fld_p(&dst, inst->size, &srcp); // fld srcp
+ emit_fstp_m32(&dst, MABS(&drcbe->fptemp)); // fstp [fptemp]
+ emit_fld_m32(&dst, MABS(&drcbe->fptemp)); // fld [fptemp]
emit_fstp_p(&dst, inst->size, &dstp); // fstp [dstp]
return dst;
}
diff --git a/src/emu/cpu/drcfe.c b/src/emu/cpu/drcfe.c
index f6282e60c04..d84452b506c 100644
--- a/src/emu/cpu/drcfe.c
+++ b/src/emu/cpu/drcfe.c
@@ -63,6 +63,7 @@ struct _drcfe_state
/* CPU parameters */
offs_t pageshift; /* shift to convert address to a page index */
cpu_translate_func translate; /* pointer to translation function */
+ offs_t codexor; /* XOR to reach code */
/* opcode descriptor arrays */
opcode_desc * desc_live_list; /* head of list of live descriptions */
@@ -149,6 +150,12 @@ drcfe_state *drcfe_init(const drcfe_config *config, void *param)
/* initialize the state */
drcfe->pageshift = activecpu_page_shift(ADDRESS_SPACE_PROGRAM);
drcfe->translate = (cpu_translate_func)activecpu_get_info_fct(CPUINFO_PTR_TRANSLATE);
+#ifdef LSB_FIRST
+ if (activecpu_endianness() == CPU_IS_BE)
+#else
+ if (activecpu_endianness() == CPU_IS_LE)
+#endif
+ drcfe->codexor = (activecpu_databus_width(ADDRESS_SPACE_PROGRAM) / 8 / activecpu_min_instruction_bytes() - 1) * activecpu_min_instruction_bytes();
return drcfe;
}
@@ -225,7 +232,7 @@ const opcode_desc *drcfe_describe_code(drcfe_state *drcfe, offs_t startpc)
}
/* loop until we exit the block */
- for (curpc = curstack->targetpc; curpc < maxpc && drcfe->desc_array[curpc - minpc] == NULL; curpc += drcfe->desc_array[curpc - minpc]->length)
+ for (curpc = curstack->targetpc; curpc >= minpc && curpc < maxpc && drcfe->desc_array[curpc - minpc] == NULL; curpc += drcfe->desc_array[curpc - minpc]->length)
{
/* allocate a new description and describe this instruction */
drcfe->desc_array[curpc - minpc] = curdesc = describe_one(drcfe, curpc);
@@ -297,7 +304,7 @@ static opcode_desc *describe_one(drcfe_state *drcfe, offs_t curpc)
/* get a pointer to the physical address */
memory_set_opbase(desc->physpc);
- desc->opptr.v = cpu_opptr(desc->physpc);
+ desc->opptr.v = cpu_opptr(desc->physpc ^ drcfe->codexor);
assert(desc->opptr.v != NULL);
if (desc->opptr.v == NULL)
{
diff --git a/src/emu/cpu/drcuml.c b/src/emu/cpu/drcuml.c
index 988425fb7cc..a6a3c0609af 100644
--- a/src/emu/cpu/drcuml.c
+++ b/src/emu/cpu/drcuml.c
@@ -12,6 +12,12 @@
Future improvements/changes:
+ * UML optimizer:
+ - detects constant operations, converts to MOV
+ - eliminates no-ops (add i0,i0,0)
+ - determines flags automatically
+ - constant folding
+
* Write a back-end validator:
- checks all combinations of memory/register/immediate on all params
- checks behavior of all opcodes
@@ -21,9 +27,6 @@
* Support for FPU exceptions
* New instructions?
- - FDRNDS dst,src
- round to single-precision
-
- FCOPYI, ICOPYF
copy raw between float and integer registers
@@ -201,49 +204,24 @@ static const drcuml_opcode_valid opcode_valid_list[] =
OPVALID_ENTRY_1(SETFMOD, 4, NONE, IANY)
OPVALID_ENTRY_1(GETFMOD, 4, NONE, IRM)
OPVALID_ENTRY_1(GETEXP, 4, NONE, IRM)
+ OPVALID_ENTRY_1(GETFLGS, 4, NONE, IRM)
OPVALID_ENTRY_1(SAVE, 4, NONE, ANYMEM)
OPVALID_ENTRY_1(RESTORE, 4, NONE, ANYMEM)
/* Integer Operations */
- OPVALID_ENTRY_3(LOAD1U, 4|8, NONE, IRM, ANYMEM,IANY4)
- OPVALID_ENTRY_3(LOAD1S, 4|8, NONE, IRM, ANYMEM,IANY4)
- OPVALID_ENTRY_3(LOAD2U, 4|8, NONE, IRM, ANYMEM,IANY4)
- OPVALID_ENTRY_3(LOAD2S, 4|8, NONE, IRM, ANYMEM,IANY4)
- OPVALID_ENTRY_3(LOAD4U, 4|8, NONE, IRM, ANYMEM,IANY4)
- OPVALID_ENTRY_3(LOAD4S, 8, NONE, IRM, ANYMEM,IANY4)
- OPVALID_ENTRY_3(LOAD8U, 8, NONE, IRM, ANYMEM,IANY4)
- OPVALID_ENTRY_3(STORE1, 4|8, NONE, ANYMEM,IANY4, IANY)
- OPVALID_ENTRY_3(STORE2, 4|8, NONE, ANYMEM,IANY4, IANY)
- OPVALID_ENTRY_3(STORE4, 4|8, NONE, ANYMEM,IANY4, IANY)
- OPVALID_ENTRY_3(STORE8, 8, NONE, ANYMEM,IANY4, IANY)
- OPVALID_ENTRY_3(READ1U, 4|8, NONE, IRM, IMV4, IANY4)
- OPVALID_ENTRY_3(READ1S, 4|8, NONE, IRM, IMV4, IANY4)
- OPVALID_ENTRY_3(READ2U, 4|8, NONE, IRM, IMV4, IANY4)
- OPVALID_ENTRY_3(READ2S, 4|8, NONE, IRM, IMV4, IANY4)
- OPVALID_ENTRY_4(READ2M, 4|8, NONE, IRM, IMV4, IANY4, IANY)
- OPVALID_ENTRY_3(READ4U, 4|8, NONE, IRM, IMV4, IANY4)
- OPVALID_ENTRY_3(READ4S, 8, NONE, IRM, IMV4, IANY4)
- OPVALID_ENTRY_4(READ4M, 4|8, NONE, IRM, IMV4, IANY4, IANY)
- OPVALID_ENTRY_3(READ8U, 8, NONE, IRM, IMV4, IANY4)
- OPVALID_ENTRY_4(READ8M, 8, NONE, IRM, IMV4, IANY4, IANY)
- OPVALID_ENTRY_3(WRITE1, 4|8, NONE, IMV4, IANY4, IANY)
- OPVALID_ENTRY_3(WRITE2, 4|8, NONE, IMV4, IANY4, IANY)
- OPVALID_ENTRY_4(WRIT2M, 4|8, NONE, IMV4, IANY4, IANY, IANY)
- OPVALID_ENTRY_3(WRITE4, 4|8, NONE, IMV4, IANY4, IANY)
- OPVALID_ENTRY_4(WRIT4M, 4|8, NONE, IMV4, IANY4, IANY, IANY)
- OPVALID_ENTRY_3(WRITE8, 8, NONE, IMV4, IANY4, IANY)
- OPVALID_ENTRY_4(WRIT8M, 8, NONE, IMV4, IANY4, IANY, IANY)
- OPVALID_ENTRY_3(FLAGS, 4|8, NONE, IRM, IMV, MEM)
- OPVALID_ENTRY_2(SETC, 4|8, NONE, IANY, IANY)
+ OPVALID_ENTRY_4(LOAD, 4|8, NONE, IRM, ANYMEM,IANY4, IMV)
+ OPVALID_ENTRY_4(LOADS, 4|8, NONE, IRM, ANYMEM,IANY4, IMV)
+ OPVALID_ENTRY_4(STORE, 4|8, NONE, ANYMEM,IANY4, IANY, IMV)
+ OPVALID_ENTRY_3(READ, 4|8, NONE, IRM, IANY4, IMV)
+ OPVALID_ENTRY_4(READM, 4|8, NONE, IRM, IANY4, IANY, IMV)
+ OPVALID_ENTRY_3(WRITE, 4|8, NONE, IANY4, IANY, IMV)
+ OPVALID_ENTRY_4(WRITEM, 4|8, NONE, IANY4, IANY, IANY, IMV)
+ OPVALID_ENTRY_2(CARRY, 4|8, NONE, IANY, IANY)
OPVALID_ENTRY_2(MOV, 4|8, COND, IRM, IANY)
- OPVALID_ENTRY_2(ZEXT1, 4|8, NONE, IRM, IANY4)
- OPVALID_ENTRY_2(ZEXT2, 4|8, NONE, IRM, IANY4)
- OPVALID_ENTRY_2(ZEXT4, 8, NONE, IRM, IANY4)
- OPVALID_ENTRY_2(SEXT1, 4|8, NONE, IRM, IANY4)
- OPVALID_ENTRY_2(SEXT2, 4|8, NONE, IRM, IANY4)
- OPVALID_ENTRY_2(SEXT4, 8, NONE, IRM, IANY4)
- OPVALID_ENTRY_4(XTRACT, 4|8, NONE, IRM, IANY, IANY, IANY)
- OPVALID_ENTRY_4(INSERT, 4|8, NONE, IRM, IANY, IANY, IANY)
+ OPVALID_ENTRY_1(SET, 4|8, COND, IRM)
+ OPVALID_ENTRY_3(SEXT, 4|8, NONE, IRM, IANY4, IMV)
+ OPVALID_ENTRY_4(ROLAND, 4|8, NONE, IRM, IANY, IANY, IANY)
+ OPVALID_ENTRY_4(ROLINS, 4|8, NONE, IRM, IANY, IANY, IANY)
OPVALID_ENTRY_3(ADD, 4|8, SZVC, IRM, IANY, IANY)
OPVALID_ENTRY_3(ADDC, 4|8, SZVC, IRM, IANY, IANY)
OPVALID_ENTRY_3(SUB, 4|8, SZVC, IRM, IANY, IANY)
@@ -270,23 +248,13 @@ static const drcuml_opcode_valid opcode_valid_list[] =
/* Floating Point Operations */
OPVALID_ENTRY_3(FLOAD, 4|8, NONE, FRM, ANYMEM,IANY4)
OPVALID_ENTRY_3(FSTORE, 4|8, NONE, ANYMEM,IANY4, FANY)
- OPVALID_ENTRY_3(FREAD, 4|8, NONE, FRM, IMV4, IANY4)
- OPVALID_ENTRY_3(FWRITE, 4|8, NONE, IMV4, IANY4, FANY)
+ OPVALID_ENTRY_3(FREAD, 4|8, NONE, FRM, IANY4, IMV4)
+ OPVALID_ENTRY_3(FWRITE, 4|8, NONE, IANY4, FANY, IMV4)
OPVALID_ENTRY_2(FMOV, 4|8, COND, FRM, FANY)
- OPVALID_ENTRY_2(FTOI4, 4|8, NONE, IRM4, FANY)
- OPVALID_ENTRY_2(FTOI4T, 4|8, NONE, IRM4, FANY)
- OPVALID_ENTRY_2(FTOI4R, 4|8, NONE, IRM4, FANY)
- OPVALID_ENTRY_2(FTOI4F, 4|8, NONE, IRM4, FANY)
- OPVALID_ENTRY_2(FTOI4C, 4|8, NONE, IRM4, FANY)
- OPVALID_ENTRY_2(FTOI8, 4|8, NONE, IRM8, FANY)
- OPVALID_ENTRY_2(FTOI8T, 4|8, NONE, IRM8, FANY)
- OPVALID_ENTRY_2(FTOI8R, 4|8, NONE, IRM8, FANY)
- OPVALID_ENTRY_2(FTOI8F, 4|8, NONE, IRM8, FANY)
- OPVALID_ENTRY_2(FTOI8C, 4|8, NONE, IRM8, FANY)
- OPVALID_ENTRY_2(FFRFS, 8, NONE, FRM, FANY4)
- OPVALID_ENTRY_2(FFRFD, 4 , NONE, FRM, FANY8)
- OPVALID_ENTRY_2(FFRI4, 4|8, NONE, FRM, IANY4)
- OPVALID_ENTRY_2(FFRI8, 4|8, NONE, FRM, IANY8)
+ OPVALID_ENTRY_4(FTOINT, 4|8, NONE, IRM, FANY, IMM, IMM)
+ OPVALID_ENTRY_3(FFRINT, 4|8, NONE, FRM, IANY, IMM)
+ OPVALID_ENTRY_3(FFRFLT, 4|8, NONE, FRM, FANY, IMM)
+ OPVALID_ENTRY_2(FRNDS, 8, NONE, FRM, FANY)
OPVALID_ENTRY_3(FADD, 4|8, NONE, FRM, FANY, FANY)
OPVALID_ENTRY_3(FSUB, 4|8, NONE, FRM, FANY, FANY)
OPVALID_ENTRY_2(FCMP, 4|8, UZC, FANY, FANY)
diff --git a/src/emu/cpu/drcuml.h b/src/emu/cpu/drcuml.h
index c3200150ff0..a902165b8ba 100644
--- a/src/emu/cpu/drcuml.h
+++ b/src/emu/cpu/drcuml.h
@@ -142,10 +142,41 @@ enum
/* floating point modes */
enum
{
- DRCUML_FMOD_TRUNC, /* truncate */
+ DRCUML_FMOD_TRUNC = 0, /* truncate */
DRCUML_FMOD_ROUND, /* round */
DRCUML_FMOD_CEIL, /* round up */
- DRCUML_FMOD_FLOOR /* round down */
+ DRCUML_FMOD_FLOOR, /* round down */
+ DRCUML_FMOD_DEFAULT
+};
+
+
+/* sizes */
+enum
+{
+ DRCUML_SIZE_BYTE = 0, /* 1-byte */
+ DRCUML_SIZE_WORD, /* 2-byte */
+ DRCUML_SIZE_DWORD, /* 4-byte */
+ DRCUML_SIZE_QWORD, /* 8-byte */
+ DRCUML_SIZE_SHORT = DRCUML_SIZE_DWORD,
+ DRCUML_SIZE_DOUBLE = DRCUML_SIZE_QWORD
+};
+
+
+/* size/space combinations */
+enum
+{
+ DRCUML_SPSIZE_PROGRAM_BYTE = (ADDRESS_SPACE_PROGRAM * 16) + DRCUML_SIZE_BYTE,
+ DRCUML_SPSIZE_PROGRAM_WORD = (ADDRESS_SPACE_PROGRAM * 16) + DRCUML_SIZE_WORD,
+ DRCUML_SPSIZE_PROGRAM_DWORD = (ADDRESS_SPACE_PROGRAM * 16) + DRCUML_SIZE_DWORD,
+ DRCUML_SPSIZE_PROGRAM_QWORD = (ADDRESS_SPACE_PROGRAM * 16) + DRCUML_SIZE_QWORD,
+ DRCUML_SPSIZE_DATA_BYTE = (ADDRESS_SPACE_DATA * 16) + DRCUML_SIZE_BYTE,
+ DRCUML_SPSIZE_DATA_WORD = (ADDRESS_SPACE_DATA * 16) + DRCUML_SIZE_WORD,
+ DRCUML_SPSIZE_DATA_DWORD = (ADDRESS_SPACE_DATA * 16) + DRCUML_SIZE_DWORD,
+ DRCUML_SPSIZE_DATA_QWORD = (ADDRESS_SPACE_DATA * 16) + DRCUML_SIZE_QWORD,
+ DRCUML_SPSIZE_IO_BYTE = (ADDRESS_SPACE_IO * 16) + DRCUML_SIZE_BYTE,
+ DRCUML_SPSIZE_IO_WORD = (ADDRESS_SPACE_IO * 16) + DRCUML_SIZE_WORD,
+ DRCUML_SPSIZE_IO_DWORD = (ADDRESS_SPACE_IO * 16) + DRCUML_SIZE_DWORD,
+ DRCUML_SPSIZE_IO_QWORD = (ADDRESS_SPACE_IO * 16) + DRCUML_SIZE_QWORD
};
@@ -175,50 +206,25 @@ enum _drcuml_opcode
/* Internal Register Operations */
DRCUML_OP_SETFMOD, /* SETFMOD src */
DRCUML_OP_GETFMOD, /* GETFMOD dst */
- DRCUML_OP_GETEXP, /* GETEXP dst,index */
+ DRCUML_OP_GETEXP, /* GETEXP dst */
+ DRCUML_OP_GETFLGS, /* GETFLGS dst[,f] */
DRCUML_OP_SAVE, /* SAVE mem */
DRCUML_OP_RESTORE, /* RESTORE mem */
/* Integer Operations */
- DRCUML_OP_LOAD1U, /* LOAD1U dst,base,index */
- DRCUML_OP_LOAD1S, /* LOAD1S dst,base,index */
- DRCUML_OP_LOAD2U, /* LOAD2U dst,base,index */
- DRCUML_OP_LOAD2S, /* LOAD2S dst,base,index */
- DRCUML_OP_LOAD4U, /* LOAD4U dst,base,index */
- DRCUML_OP_LOAD4S, /* LOAD4S dst,base,index */
- DRCUML_OP_LOAD8U, /* LOAD8U dst,base,index */
- DRCUML_OP_STORE1, /* STORE1 base,index,src */
- DRCUML_OP_STORE2, /* STORE2 base,index,src */
- DRCUML_OP_STORE4, /* STORE4 base,index,src */
- DRCUML_OP_STORE8, /* STORE8 base,index,src */
- DRCUML_OP_READ1U, /* READ1U dst,space,src1 */
- DRCUML_OP_READ1S, /* READ1S dst,space,src1 */
- DRCUML_OP_READ2U, /* READ2U dst,space,src1 */
- DRCUML_OP_READ2S, /* READ2S dst,space,src1 */
- DRCUML_OP_READ2M, /* READ2M dst,space,src1,mask */
- DRCUML_OP_READ4U, /* READ4U dst,space,src1 */
- DRCUML_OP_READ4S, /* READ4S dst,space,src1 */
- DRCUML_OP_READ4M, /* READ4M dst,space,src1,mask */
- DRCUML_OP_READ8U, /* READ8U dst,space,src1 */
- DRCUML_OP_READ8M, /* READ8M dst,space,src1,mask */
- DRCUML_OP_WRITE1, /* WRITE1 space,dst,src1 */
- DRCUML_OP_WRITE2, /* WRITE2 space,dst,src1 */
- DRCUML_OP_WRIT2M, /* WRIT2M space,dst,mask,src1 */
- DRCUML_OP_WRITE4, /* WRITE4 space,dst,src1 */
- DRCUML_OP_WRIT4M, /* WRIT4M space,dst,mask,src1 */
- DRCUML_OP_WRITE8, /* WRITE8 space,dst,src1 */
- DRCUML_OP_WRIT8M, /* WRIT8M space,dst,mask,src1 */
- DRCUML_OP_SETC, /* SETC src,bitnum */
- DRCUML_OP_FLAGS, /* FLAGS dst,mask,table */
+ DRCUML_OP_LOAD, /* LOAD dst,base,index,size */
+ DRCUML_OP_LOADS, /* LOADS dst,base,index,size */
+ DRCUML_OP_STORE, /* STORE base,index,src,size */
+ DRCUML_OP_READ, /* READ dst,src1,space/size */
+ DRCUML_OP_READM, /* READM dst,src1,mask,space/size */
+ DRCUML_OP_WRITE, /* WRITE dst,src1,space/size */
+ DRCUML_OP_WRITEM, /* WRITEM dst,mask,src1,space/size */
+ DRCUML_OP_CARRY, /* CARRY src,bitnum */
+ DRCUML_OP_SET, /* SET dst,c */
DRCUML_OP_MOV, /* MOV dst,src[,c] */
- DRCUML_OP_ZEXT1, /* ZEXT1 dst,src */
- DRCUML_OP_ZEXT2, /* ZEXT2 dst,src */
- DRCUML_OP_ZEXT4, /* ZEXT4 dst,src */
- DRCUML_OP_SEXT1, /* SEXT1 dst,src */
- DRCUML_OP_SEXT2, /* SEXT2 dst,src */
- DRCUML_OP_SEXT4, /* SEXT4 dst,src */
- DRCUML_OP_XTRACT, /* XTRACT dst,src,shift,mask */
- DRCUML_OP_INSERT, /* INSERT dst,src,shift,mask */
+ DRCUML_OP_SEXT, /* SEXT dst,src,size */
+ DRCUML_OP_ROLAND, /* ROLAND dst,src,shift,mask */
+ DRCUML_OP_ROLINS, /* ROLINS dst,src,shift,mask */
DRCUML_OP_ADD, /* ADD dst,src1,src2[,f] */
DRCUML_OP_ADDC, /* ADDC dst,src1,src2[,f] */
DRCUML_OP_SUB, /* SUB dst,src1,src2[,f] */
@@ -247,21 +253,11 @@ enum _drcuml_opcode
DRCUML_OP_FSTORE, /* FSTORE base,index,src */
DRCUML_OP_FREAD, /* FREAD dst,space,src1 */
DRCUML_OP_FWRITE, /* FWRITE space,dst,src1 */
- DRCUML_OP_FMOV, /* FSMOV dst,src1[,c] */
- DRCUML_OP_FTOI4, /* FTOI4 dst,src1 */
- DRCUML_OP_FTOI4T, /* FTOI4T dst,src1 */
- DRCUML_OP_FTOI4R, /* FTOI4R dst,src1 */
- DRCUML_OP_FTOI4F, /* FTOI4F dst,src1 */
- DRCUML_OP_FTOI4C, /* FTOI4C dst,src1 */
- DRCUML_OP_FTOI8, /* FTOI8 dst,src1 */
- DRCUML_OP_FTOI8T, /* FTOI8T dst,src1 */
- DRCUML_OP_FTOI8R, /* FTOI8R dst,src1 */
- DRCUML_OP_FTOI8F, /* FTOI8F dst,src1 */
- DRCUML_OP_FTOI8C, /* FTOI8C dst,src1 */
- DRCUML_OP_FFRFS, /* FFRFS dst,src1 */
- DRCUML_OP_FFRFD, /* FFRFD dst,src1 */
- DRCUML_OP_FFRI4, /* FFRI4 dst,src1 */
- DRCUML_OP_FFRI8, /* FFRI8 dst,src1 */
+ DRCUML_OP_FMOV, /* FMOV dst,src1[,c] */
+ DRCUML_OP_FTOINT, /* FTOINT dst,src1,size,round */
+ DRCUML_OP_FFRINT, /* FFRINT dst,src1,size */
+ DRCUML_OP_FFRFLT, /* FFRFLT dst,src1,size */
+ DRCUML_OP_FRNDS, /* FRNDS dst,src1 */
DRCUML_OP_FADD, /* FADD dst,src1,src2 */
DRCUML_OP_FSUB, /* FSUB dst,src1,src2 */
DRCUML_OP_FCMP, /* FCMP src1,src2 */
diff --git a/src/emu/cpu/drcumld.c b/src/emu/cpu/drcumld.c
index 127b3d8bcea..d64d50be1e2 100644
--- a/src/emu/cpu/drcumld.c
+++ b/src/emu/cpu/drcumld.c
@@ -43,7 +43,10 @@ static char *output_flags_cmptest(char *dest, int size, const drcuml_parameter *
static char *output_param(char *dest, int size, const drcuml_parameter *param);
static char *output_param_string(char *dest, int size, const drcuml_parameter *param);
static char *output_param_handle(char *dest, int size, const drcuml_parameter *param);
+static char *output_param_size(char *dest, int size, const drcuml_parameter *param);
static char *output_param_space(char *dest, int size, const drcuml_parameter *param);
+static char *output_param_space_size(char *dest, int size, const drcuml_parameter *param);
+static char *output_param_round(char *dest, int size, const drcuml_parameter *param);
@@ -89,49 +92,24 @@ static const drcuml_opdesc opcode_source_table[] =
{ DRCUML_OP_SETFMOD, "setfmod", { output_param } },
{ DRCUML_OP_GETFMOD, "getfmod", { output_param } },
{ DRCUML_OP_GETEXP, "getexp", { output_param } },
+ { DRCUML_OP_GETFLGS, "getflgs", { output_param, output_flags } },
{ DRCUML_OP_SAVE, "save", { output_param } },
{ DRCUML_OP_RESTORE, "restore", { output_param } },
/* Integer Operations */
- { DRCUML_OP_LOAD1U, "!load1u", { output_param, output_param, output_param } },
- { DRCUML_OP_LOAD1S, "!load1s", { output_param, output_param, output_param } },
- { DRCUML_OP_LOAD2U, "!load2u", { output_param, output_param, output_param } },
- { DRCUML_OP_LOAD2S, "!load2s", { output_param, output_param, output_param } },
- { DRCUML_OP_LOAD4U, "!load4u", { output_param, output_param, output_param } },
- { DRCUML_OP_LOAD4S, "!load4s", { output_param, output_param, output_param } },
- { DRCUML_OP_LOAD8U, "!load8u", { output_param, output_param, output_param } },
- { DRCUML_OP_STORE1, "!store1", { output_param, output_param, output_param } },
- { DRCUML_OP_STORE2, "!store2", { output_param, output_param, output_param } },
- { DRCUML_OP_STORE4, "!store4", { output_param, output_param, output_param } },
- { DRCUML_OP_STORE8, "!store8", { output_param, output_param, output_param } },
- { DRCUML_OP_READ1U, "!read1u", { output_param, output_param_space, output_param } },
- { DRCUML_OP_READ1S, "!read1s", { output_param, output_param_space, output_param } },
- { DRCUML_OP_READ2U, "!read2u", { output_param, output_param_space, output_param } },
- { DRCUML_OP_READ2S, "!read2s", { output_param, output_param_space, output_param } },
- { DRCUML_OP_READ2M, "!read2m", { output_param, output_param_space, output_param, output_param } },
- { DRCUML_OP_READ4U, "!read4u", { output_param, output_param_space, output_param } },
- { DRCUML_OP_READ4S, "!read4s", { output_param, output_param_space, output_param } },
- { DRCUML_OP_READ4M, "!read4m", { output_param, output_param_space, output_param, output_param } },
- { DRCUML_OP_READ8U, "!read8u", { output_param, output_param_space, output_param } },
- { DRCUML_OP_READ8M, "!read8m", { output_param, output_param_space, output_param, output_param } },
- { DRCUML_OP_WRITE1, "!write1", { output_param_space, output_param, output_param } },
- { DRCUML_OP_WRITE2, "!write2", { output_param_space, output_param, output_param } },
- { DRCUML_OP_WRIT2M, "!writ2m", { output_param_space, output_param, output_param, output_param } },
- { DRCUML_OP_WRITE4, "!write4", { output_param_space, output_param, output_param } },
- { DRCUML_OP_WRIT4M, "!writ4m", { output_param_space, output_param, output_param, output_param } },
- { DRCUML_OP_WRITE8, "!write8", { output_param_space, output_param, output_param } },
- { DRCUML_OP_WRIT8M, "!writ8m", { output_param_space, output_param, output_param, output_param } },
- { DRCUML_OP_FLAGS, "!flags", { output_param, output_param, output_param } },
- { DRCUML_OP_SETC, "!setc", { output_param, output_param } },
+ { DRCUML_OP_LOAD, "!load", { output_param, output_param, output_param, output_param_size } },
+ { DRCUML_OP_LOADS, "!loads", { output_param, output_param, output_param, output_param_size } },
+ { DRCUML_OP_STORE, "!store", { output_param, output_param, output_param, output_param_size } },
+ { DRCUML_OP_READ, "!read", { output_param, output_param, output_param_space_size } },
+ { DRCUML_OP_READM, "!readm", { output_param, output_param, output_param, output_param_space_size } },
+ { DRCUML_OP_WRITE, "!write", { output_param, output_param, output_param_space_size } },
+ { DRCUML_OP_WRITEM, "!writem", { output_param, output_param, output_param, output_param_space_size } },
+ { DRCUML_OP_CARRY, "!carry", { output_param, output_param } },
+ { DRCUML_OP_SET, "!set", { output_param, output_cond } },
{ DRCUML_OP_MOV, "!mov", { output_param, output_param, output_cond } },
- { DRCUML_OP_ZEXT1, "!zext1", { output_param, output_param } },
- { DRCUML_OP_ZEXT2, "!zext2", { output_param, output_param } },
- { DRCUML_OP_ZEXT4, "!zext4", { output_param, output_param } },
- { DRCUML_OP_SEXT1, "!sext1", { output_param, output_param } },
- { DRCUML_OP_SEXT2, "!sext2", { output_param, output_param } },
- { DRCUML_OP_SEXT4, "!sext4", { output_param, output_param } },
- { DRCUML_OP_XTRACT, "!xtract", { output_param, output_param, output_param, output_param } },
- { DRCUML_OP_INSERT, "!insert", { output_param, output_param, output_param, output_param } },
+ { DRCUML_OP_SEXT, "!sext", { output_param, output_param, output_param_size } },
+ { DRCUML_OP_ROLAND, "!roland", { output_param, output_param, output_param, output_param } },
+ { DRCUML_OP_ROLINS, "!rolins", { output_param, output_param, output_param, output_param } },
{ DRCUML_OP_ADD, "!add", { output_param, output_param, output_param, output_flags } },
{ DRCUML_OP_ADDC, "!addc", { output_param, output_param, output_param, output_flags } },
{ DRCUML_OP_SUB, "!sub", { output_param, output_param, output_param, output_flags } },
@@ -158,23 +136,13 @@ static const drcuml_opdesc opcode_source_table[] =
/* Floating-Point Operations */
{ DRCUML_OP_FLOAD, "f!load", { output_param, output_param, output_param } },
{ DRCUML_OP_FSTORE, "f!store", { output_param, output_param, output_param } },
- { DRCUML_OP_FREAD, "f!read", { output_param, output_param_space, output_param } },
- { DRCUML_OP_FWRITE, "f!write", { output_param_space, output_param, output_param } },
+ { DRCUML_OP_FREAD, "f!read", { output_param, output_param, output_param_space } },
+ { DRCUML_OP_FWRITE, "f!write", { output_param, output_param, output_param_space } },
{ DRCUML_OP_FMOV, "f!mov", { output_param, output_param, output_cond } },
- { DRCUML_OP_FTOI4, "f!toi4", { output_param, output_param } },
- { DRCUML_OP_FTOI4T, "f!toi4t", { output_param, output_param } },
- { DRCUML_OP_FTOI4R, "f!toi4r", { output_param, output_param } },
- { DRCUML_OP_FTOI4F, "f!toi4f", { output_param, output_param } },
- { DRCUML_OP_FTOI4C, "f!toi4c", { output_param, output_param } },
- { DRCUML_OP_FTOI8, "f!toi8", { output_param, output_param } },
- { DRCUML_OP_FTOI8T, "f!toi8t", { output_param, output_param } },
- { DRCUML_OP_FTOI8R, "f!toi8r", { output_param, output_param } },
- { DRCUML_OP_FTOI8F, "f!toi8f", { output_param, output_param } },
- { DRCUML_OP_FTOI8C, "f!toi8c", { output_param, output_param } },
- { DRCUML_OP_FFRFS, "f!frfs", { output_param, output_param } },
- { DRCUML_OP_FFRFD, "f!frfd", { output_param, output_param } },
- { DRCUML_OP_FFRI4, "f!fri4", { output_param, output_param } },
- { DRCUML_OP_FFRI8, "f!fri8", { output_param, output_param } },
+ { DRCUML_OP_FTOINT, "f!toint", { output_param, output_param, output_param_size, output_param_round } },
+ { DRCUML_OP_FFRINT, "f!frint", { output_param, output_param, output_param_size } },
+ { DRCUML_OP_FFRFLT, "f!frflt", { output_param, output_param, output_param_size } },
+ { DRCUML_OP_FRNDS, "f!rnds", { output_param, output_param } },
{ DRCUML_OP_FADD, "f!add", { output_param, output_param, output_param } },
{ DRCUML_OP_FSUB, "f!sub", { output_param, output_param, output_param } },
{ DRCUML_OP_FCMP, "f!cmp", { output_param, output_param, output_flags_cmptest } },
@@ -448,6 +416,22 @@ static char *output_param_handle(char *dest, int size, const drcuml_parameter *p
/*-------------------------------------------------
+ output_param_size - output parameter 0,
+ assuming it is size
+-------------------------------------------------*/
+
+static char *output_param_size(char *dest, int size, const drcuml_parameter *param)
+{
+ if (param->type == DRCUML_PTYPE_IMMEDIATE)
+ {
+ static const char *strings[] = { "byte", "word", "dword", "qword" };
+ return dest + sprintf(dest, "%s", strings[param->value & 3]);
+ }
+ return output_param(dest, size, param);
+}
+
+
+/*-------------------------------------------------
output_param_space - output parameter 0,
assuming it is an address space
-------------------------------------------------*/
@@ -458,3 +442,36 @@ static char *output_param_space(char *dest, int size, const drcuml_parameter *pa
return dest + sprintf(dest, "%s", address_space_names[param->value]);
return output_param(dest, size, param);
}
+
+
+/*-------------------------------------------------
+ output_param_space_size - output parameter 0,
+ assuming it is an address space/size combo
+-------------------------------------------------*/
+
+static char *output_param_space_size(char *dest, int size, const drcuml_parameter *param)
+{
+ if (param->type == DRCUML_PTYPE_IMMEDIATE && param->value / 16 >= ADDRESS_SPACE_PROGRAM && param->value / 16 <= ADDRESS_SPACE_IO)
+ {
+ dest += sprintf(dest, "%s_", address_space_names[param->value / 16]);
+ return output_param_size(dest, size, param);
+ }
+
+ return output_param(dest, size, param);
+}
+
+
+/*-------------------------------------------------
+ output_param_round - output parameter 0,
+ assuming it is a rounding mode
+-------------------------------------------------*/
+
+static char *output_param_round(char *dest, int size, const drcuml_parameter *param)
+{
+ if (param->type == DRCUML_PTYPE_IMMEDIATE && param->value >= DRCUML_FMOD_TRUNC && param->value <= DRCUML_FMOD_DEFAULT)
+ {
+ static const char *strings[] = { "trunc", "round", "ceil", "floor", "default" };
+ return dest + sprintf(dest, "%s", strings[param->value]);
+ }
+ return output_param(dest, size, param);
+}
diff --git a/src/emu/cpu/drcumlsh.h b/src/emu/cpu/drcumlsh.h
index a3543aaee7e..452b55ce319 100644
--- a/src/emu/cpu/drcumlsh.h
+++ b/src/emu/cpu/drcumlsh.h
@@ -132,49 +132,29 @@
#define UML_SETFMOD(block, mode) do { drcuml_block_append_1(block, DRCUML_OP_SETFMOD, 4, IF_ALWAYS, mode); } while (0)
#define UML_GETFMOD(block, dst) do { drcuml_block_append_1(block, DRCUML_OP_GETFMOD, 4, IF_ALWAYS, dst); } while (0)
#define UML_GETEXP(block, dst) do { drcuml_block_append_1(block, DRCUML_OP_GETEXP, 4, IF_ALWAYS, dst); } while (0)
+#define UML_GETFLGS(block, dst, flags) do { drcuml_block_append_1(block, DRCUML_OP_GETFLGS, 4, flags, dst); } while (0)
#define UML_SAVE(block, dst) do { drcuml_block_append_1(block, DRCUML_OP_SAVE, 4, IF_ALWAYS, MEM(dst)); } while (0)
#define UML_RESTORE(block, src) do { drcuml_block_append_1(block, DRCUML_OP_RESTORE, 4, IF_ALWAYS, MEM(src)); } while (0)
/* ----- 32-Bit Integer Operations ----- */
-#define UML_LOAD1U(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD1U, 4, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_LOAD1S(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD1S, 4, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_LOAD2U(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD2U, 4, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_LOAD2S(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD2S, 4, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_LOAD4(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD4U, 4, IF_ALWAYS, dst, MEM(base), index); } while (0)
-
-#define UML_STORE1(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_STORE1, 4, IF_ALWAYS, MEM(base), index, src1); } while (0)
-#define UML_STORE2(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_STORE2, 4, IF_ALWAYS, MEM(base), index, src1); } while (0)
-#define UML_STORE4(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_STORE4, 4, IF_ALWAYS, MEM(base), index, src1); } while (0)
-
-#define UML_READ1U(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ1U, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_READ1S(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ1S, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_READ2U(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ2U, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_READ2S(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ2S, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_READ2M(block, dst, space, src1, mask) do { drcuml_block_append_4(block, DRCUML_OP_READ2M, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1, mask); } while (0)
-#define UML_READ4(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ4U, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_READ4M(block, dst, space, src1, mask) do { drcuml_block_append_4(block, DRCUML_OP_READ4M, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1, mask); } while (0)
-
-#define UML_WRITE1(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_WRITE1, 4, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
-#define UML_WRITE2(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_WRITE2, 4, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
-#define UML_WRIT2M(block, space, dst, mask, src1) do { drcuml_block_append_4(block, DRCUML_OP_WRIT2M, 4, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, mask, src1); } while (0)
-#define UML_WRITE4(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_WRITE4, 4, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
-#define UML_WRIT4M(block, space, dst, mask, src1) do { drcuml_block_append_4(block, DRCUML_OP_WRIT4M, 4, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, mask, src1); } while (0)
-
-#define UML_FLAGS(block, dst, mask, table) do { drcuml_block_append_3(block, DRCUML_OP_FLAGS, 4, IF_ALWAYS, dst, IMM(mask), MEM(table)); } while (0)
-#define UML_SETC(block, src, bitnum) do { drcuml_block_append_2(block, DRCUML_OP_SETC, 4, IF_ALWAYS, src, bitnum); } while (0)
+#define UML_LOAD(block, dst, base, index, size) do { drcuml_block_append_4(block, DRCUML_OP_LOAD, 4, IF_ALWAYS, dst, MEM(base), index, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_LOADS(block, dst, base, index, size) do { drcuml_block_append_4(block, DRCUML_OP_LOADS, 4, IF_ALWAYS, dst, MEM(base), index, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_STORE(block, base, index, src1, size) do { drcuml_block_append_4(block, DRCUML_OP_STORE, 4, IF_ALWAYS, MEM(base), index, src1, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_READ(block, dst, src1, spsize) do { drcuml_block_append_3(block, DRCUML_OP_READ, 4, IF_ALWAYS, dst, src1, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+#define UML_READM(block, dst, src1, mask, spsize) do { drcuml_block_append_4(block, DRCUML_OP_READM, 4, IF_ALWAYS, dst, src1, mask, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+#define UML_WRITE(block, dst, src1, spsize) do { drcuml_block_append_3(block, DRCUML_OP_WRITE, 4, IF_ALWAYS, dst, src1, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+#define UML_WRITEM(block, dst, src1, mask, spsize) do { drcuml_block_append_4(block, DRCUML_OP_WRITEM, 4, IF_ALWAYS, dst, src1, mask, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+
+#define UML_CARRY(block, src, bitnum) do { drcuml_block_append_2(block, DRCUML_OP_CARRY, 4, IF_ALWAYS, src, bitnum); } while (0)
+#define UML_SETc(block, cond, dst) do { drcuml_block_append_1(block, DRCUML_OP_SET, 4, cond, dst); } while (0)
#define UML_MOV(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_MOV, 4, IF_ALWAYS, dst, src1); } while (0)
#define UML_MOVc(block, cond, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_MOV, 4, cond, dst, src1); } while (0)
+#define UML_SEXT(block, dst, src1, size) do { drcuml_block_append_3(block, DRCUML_OP_SEXT, 4, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size)); } while (0)
-#define UML_ZEXT1(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_ZEXT1, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_ZEXT2(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_ZEXT2, 4, IF_ALWAYS, dst, src1); } while (0)
-
-#define UML_SEXT1(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_SEXT1, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_SEXT2(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_SEXT2, 4, IF_ALWAYS, dst, src1); } while (0)
-
-#define UML_XTRACT(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_XTRACT, 4, IF_ALWAYS, dst, src, shift, mask); } while (0)
-#define UML_INSERT(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_INSERT, 4, IF_ALWAYS, dst, src, shift, mask); } while (0)
+#define UML_ROLAND(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_ROLAND, 4, IF_ALWAYS, dst, src, shift, mask); } while (0)
+#define UML_ROLINS(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_ROLINS, 4, IF_ALWAYS, dst, src, shift, mask); } while (0)
#define UML_NEG(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_NEG, 4, FLAGS_NONE, dst, src1); } while (0)
#define UML_NEGf(block, dst, src1, flags) do { drcuml_block_append_2(block, DRCUML_OP_NEG, 4, flags, dst, src1); } while (0)
@@ -238,53 +218,23 @@
/* ----- 64-Bit Integer Operations ----- */
-#define UML_DLOAD1U(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD1U, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_DLOAD1S(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD1S, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_DLOAD2U(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD2U, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_DLOAD2S(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD2S, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_DLOAD4U(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD4U, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_DLOAD4S(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD4S, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
-#define UML_DLOAD8(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_LOAD8U, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
-
-#define UML_DSTORE1(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_STORE1, 8, IF_ALWAYS, MEM(base), index, src1); } while (0)
-#define UML_DSTORE2(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_STORE2, 8, IF_ALWAYS, MEM(base), index, src1); } while (0)
-#define UML_DSTORE4(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_STORE4, 8, IF_ALWAYS, MEM(base), index, src1); } while (0)
-#define UML_DSTORE8(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_STORE8, 8, IF_ALWAYS, MEM(base), index, src1); } while (0)
-
-#define UML_DREAD1U(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ1U, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_DREAD1S(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ1S, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_DREAD2U(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ2U, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_DREAD2S(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ2S, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_DREAD2M(block, dst, space, src1, mask) do { drcuml_block_append_4(block, DRCUML_OP_READ2M, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1, mask); } while (0)
-#define UML_DREAD4U(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ4U, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_DREAD4S(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ4S, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_DREAD4M(block, dst, space, src1, mask) do { drcuml_block_append_4(block, DRCUML_OP_READ4M, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1, mask); } while (0)
-#define UML_DREAD8(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_READ8U, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_DREAD8M(block, dst, space, src1, mask) do { drcuml_block_append_4(block, DRCUML_OP_READ8M, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1, mask); } while (0)
-
-#define UML_DWRITE1(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_WRITE1, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
-#define UML_DWRITE2(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_WRITE2, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
-#define UML_DWRIT2M(block, space, dst, mask, src1) do { drcuml_block_append_4(block, DRCUML_OP_WRIT2M, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, mask, src1); } while (0)
-#define UML_DWRITE4(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_WRITE4, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
-#define UML_DWRIT4M(block, space, dst, mask, src1) do { drcuml_block_append_4(block, DRCUML_OP_WRIT4M, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, mask, src1); } while (0)
-#define UML_DWRITE8(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_WRITE8, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
-#define UML_DWRIT8M(block, space, dst, mask, src1) do { drcuml_block_append_4(block, DRCUML_OP_WRIT8M, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, mask, src1); } while (0)
-
-#define UML_DFLAGS(block, dst, mask, table) do { drcuml_block_append_3(block, DRCUML_OP_FLAGS, 8, IF_ALWAYS, dst, IMM(mask), MEM(table)); } while (0)
+#define UML_DLOAD(block, dst, base, index, size) do { drcuml_block_append_4(block, DRCUML_OP_LOAD, 8, IF_ALWAYS, dst, MEM(base), index, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_DLOADS(block, dst, base, index, size) do { drcuml_block_append_4(block, DRCUML_OP_LOADS, 8, IF_ALWAYS, dst, MEM(base), index, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_DSTORE(block, base, index, src1, size) do { drcuml_block_append_4(block, DRCUML_OP_STORE, 8, IF_ALWAYS, MEM(base), index, src1, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_DREAD(block, dst, src1, spsize) do { drcuml_block_append_3(block, DRCUML_OP_READ, 8, IF_ALWAYS, dst, src1, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+#define UML_DREADM(block, dst, src1, mask, spsize) do { drcuml_block_append_4(block, DRCUML_OP_READM, 8, IF_ALWAYS, dst, src1, mask, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+#define UML_DWRITE(block, dst, src1, spsize) do { drcuml_block_append_3(block, DRCUML_OP_WRITE, 8, IF_ALWAYS, dst, src1, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+#define UML_DWRITEM(block, dst, src1, mask, spsize) do { drcuml_block_append_4(block, DRCUML_OP_WRITEM, 8, IF_ALWAYS, dst, src1, mask, IMM(DRCUML_SPSIZE_##spsize)); } while (0)
+
+#define UML_DCARRY(block, src, bitnum) do { drcuml_block_append_2(block, DRCUML_OP_CARRY, 8, IF_ALWAYS, src, bitnum); } while (0)
+#define UML_DSETc(block, cond, dst) do { drcuml_block_append_1(block, DRCUML_OP_SET, 8, cond, dst); } while (0)
#define UML_DMOV(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_MOV, 8, IF_ALWAYS, dst, src1); } while (0)
#define UML_DMOVc(block, cond, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_MOV, 8, cond, dst, src1); } while (0)
+#define UML_DSEXT(block, dst, src1, size) do { drcuml_block_append_3(block, DRCUML_OP_SEXT, 8, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size)); } while (0)
-#define UML_DZEXT1(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_ZEXT1, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_DZEXT2(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_ZEXT2, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_DZEXT4(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_ZEXT4, 8, IF_ALWAYS, dst, src1); } while (0)
-
-#define UML_DSEXT1(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_SEXT1, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_DSEXT2(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_SEXT2, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_DSEXT4(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_SEXT4, 8, IF_ALWAYS, dst, src1); } while (0)
-
-#define UML_DXTRACT(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_XTRACT, 8, IF_ALWAYS, dst, src, shift, mask); } while (0)
-#define UML_DINSERT(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_INSERT, 8, IF_ALWAYS, dst, src, shift, mask); } while (0)
+#define UML_DROLAND(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_ROLAND, 8, IF_ALWAYS, dst, src, shift, mask); } while (0)
+#define UML_DROLINS(block, dst, src, shift, mask) do { drcuml_block_append_4(block, DRCUML_OP_ROLINS, 8, IF_ALWAYS, dst, src, shift, mask); } while (0)
#define UML_DNEG(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_NEG, 8, FLAGS_NONE, dst, src1); } while (0)
#define UML_DNEGf(block, dst, src1, flags) do { drcuml_block_append_2(block, DRCUML_OP_NEG, 8, flags, dst, src1); } while (0)
@@ -348,26 +298,15 @@
#define UML_FSLOAD(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_FLOAD, 4, IF_ALWAYS, dst, MEM(base), index); } while (0)
#define UML_FSSTORE(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_FSTORE, 4, IF_ALWAYS, MEM(base), index, src1); } while (0)
-#define UML_FSREAD(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_FREAD, 4, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_FSWRITE(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_FWRITE, 4, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
+#define UML_FSREAD(block, dst, src1, space) do { drcuml_block_append_3(block, DRCUML_OP_FREAD, 4, IF_ALWAYS, dst, src1, IMM(ADDRESS_SPACE_##space)); } while (0)
+#define UML_FSWRITE(block, dst, src1, space) do { drcuml_block_append_3(block, DRCUML_OP_FWRITE, 4, IF_ALWAYS, dst, src1, IMM(ADDRESS_SPACE_##space)); } while (0)
#define UML_FSMOV(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FMOV, 4, IF_ALWAYS, dst, src1); } while (0)
#define UML_FSMOVc(block, cond, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FMOV, 4, cond, dst, src1); } while (0)
-#define UML_FSTOI4(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI4T(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4T, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI4R(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4R, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI4C(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4C, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI4F(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4F, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI8(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI8T(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8T, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI8R(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8R, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI8C(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8C, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSTOI8F(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8F, 4, IF_ALWAYS, dst, src1); } while (0)
-
-#define UML_FSFRFD(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FFRFD, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSFRI4(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FFRI4, 4, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FSFRI8(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FFRI8, 4, IF_ALWAYS, dst, src1); } while (0)
+#define UML_FSTOINT(block, dst, src1, size, round) do { drcuml_block_append_4(block, DRCUML_OP_FTOINT, 4, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size), IMM(DRCUML_FMOD_##round)); } while (0)
+#define UML_FSFRINT(block, dst, src1, size) do { drcuml_block_append_3(block, DRCUML_OP_FFRINT, 4, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_FSFRFLT(block, dst, src1, size) do { drcuml_block_append_3(block, DRCUML_OP_FFRFLT, 4, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size)); } while (0)
#define UML_FSADD(block, dst, src1, src2) do { drcuml_block_append_3(block, DRCUML_OP_FADD, 4, FLAGS_NONE, dst, src1, src2); } while (0)
#define UML_FSSUB(block, dst, src1, src2) do { drcuml_block_append_3(block, DRCUML_OP_FSUB, 4, FLAGS_NONE, dst, src1, src2); } while (0)
@@ -385,26 +324,17 @@
#define UML_FDLOAD(block, dst, base, index) do { drcuml_block_append_3(block, DRCUML_OP_FLOAD, 8, IF_ALWAYS, dst, MEM(base), index); } while (0)
#define UML_FDSTORE(block, base, index, src1) do { drcuml_block_append_3(block, DRCUML_OP_FSTORE, 8, IF_ALWAYS, MEM(base), index, src1); } while (0)
-#define UML_FDREAD(block, dst, space, src1) do { drcuml_block_append_3(block, DRCUML_OP_FREAD, 8, IF_ALWAYS, dst, IMM(ADDRESS_SPACE_##space), src1); } while (0)
-#define UML_FDWRITE(block, space, dst, src1) do { drcuml_block_append_3(block, DRCUML_OP_FWRITE, 8, IF_ALWAYS, IMM(ADDRESS_SPACE_##space), dst, src1); } while (0)
+#define UML_FDREAD(block, dst, src1, space) do { drcuml_block_append_3(block, DRCUML_OP_FREAD, 8, IF_ALWAYS, dst, src1, IMM(ADDRESS_SPACE_##space)); } while (0)
+#define UML_FDWRITE(block, dst, src1, space) do { drcuml_block_append_3(block, DRCUML_OP_FWRITE, 8, IF_ALWAYS, dst, src1, IMM(ADDRESS_SPACE_##space)); } while (0)
#define UML_FDMOV(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FMOV, 8, IF_ALWAYS, dst, src1); } while (0)
#define UML_FDMOVc(block, cond, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FMOV, 8, cond, dst, src1); } while (0)
-#define UML_FDTOI4(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI4T(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4T, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI4R(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4R, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI4C(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4C, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI4F(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI4F, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI8(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI8T(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8T, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI8R(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8R, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI8C(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8C, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDTOI8F(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FTOI8F, 8, IF_ALWAYS, dst, src1); } while (0)
-
-#define UML_FDFRFS(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FFRFS, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDFRI4(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FFRI4, 8, IF_ALWAYS, dst, src1); } while (0)
-#define UML_FDFRI8(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FFRI8, 8, IF_ALWAYS, dst, src1); } while (0)
+#define UML_FDTOINT(block, dst, src1, size, round) do { drcuml_block_append_4(block, DRCUML_OP_FTOINT, 8, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size), IMM(DRCUML_FMOD_##round)); } while (0)
+#define UML_FDFRINT(block, dst, src1, size) do { drcuml_block_append_3(block, DRCUML_OP_FFRINT, 8, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size)); } while (0)
+#define UML_FDFRFLT(block, dst, src1, size) do { drcuml_block_append_3(block, DRCUML_OP_FFRFLT, 8, IF_ALWAYS, dst, src1, IMM(DRCUML_SIZE_##size)); } while (0)
+
+#define UML_FDRNDS(block, dst, src1) do { drcuml_block_append_2(block, DRCUML_OP_FRNDS, 8, FLAGS_NONE, dst, src1); } while (0)
#define UML_FDADD(block, dst, src1, src2) do { drcuml_block_append_3(block, DRCUML_OP_FADD, 8, FLAGS_NONE, dst, src1, src2); } while (0)
#define UML_FDSUB(block, dst, src1, src2) do { drcuml_block_append_3(block, DRCUML_OP_FSUB, 8, FLAGS_NONE, dst, src1, src2); } while (0)
diff --git a/src/emu/cpu/i386/i386dasm.c b/src/emu/cpu/i386/i386dasm.c
index 6de76c8f64f..a418e3233a5 100644
--- a/src/emu/cpu/i386/i386dasm.c
+++ b/src/emu/cpu/i386/i386dasm.c
@@ -1764,7 +1764,7 @@ static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
switch ((op2 >> 3) & 0x7)
{
case 0: sprintf(s, "fild dword ptr %s", modrm_string); break;
- case 1: sprintf(s, "??? (FPU)"); break;
+ case 1: sprintf(s, "fisttp dword ptr %s", modrm_string); break;
case 2: sprintf(s, "fist dword ptr %s", modrm_string); break;
case 3: sprintf(s, "fistp dword ptr %s", modrm_string); break;
case 4: sprintf(s, "??? (FPU)"); break;
@@ -1861,7 +1861,7 @@ static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
switch ((op2 >> 3) & 0x7)
{
case 0: sprintf(s, "fld qword ptr %s", modrm_string); break;
- case 1: sprintf(s, "??? (FPU)"); break;
+ case 1: sprintf(s, "fisttp qword ptr %s", modrm_string); break;
case 2: sprintf(s, "fst qword ptr %s", modrm_string); break;
case 3: sprintf(s, "fstp qword ptr %s", modrm_string); break;
case 4: sprintf(s, "frstor %s", modrm_string); break;
@@ -1954,7 +1954,7 @@ static void handle_fpu(char *s, UINT8 op1, UINT8 op2)
switch ((op2 >> 3) & 0x7)
{
case 0: sprintf(s, "fild word ptr %s", modrm_string); break;
- case 1: sprintf(s, "??? (FPU)"); break;
+ case 1: sprintf(s, "fisttp word ptr %s", modrm_string); break;
case 2: sprintf(s, "fist word ptr %s", modrm_string); break;
case 3: sprintf(s, "fistp word ptr %s", modrm_string); break;
case 4: sprintf(s, "fbld %s", modrm_string); break;
diff --git a/src/emu/cpu/mips/mips3drc.c b/src/emu/cpu/mips/mips3drc.c
index e56276e5b3a..e6f677929ab 100644
--- a/src/emu/cpu/mips/mips3drc.c
+++ b/src/emu/cpu/mips/mips3drc.c
@@ -117,7 +117,8 @@ extern unsigned dasmmips3(char *buffer, unsigned pc, UINT32 op);
#define CPR264(reg) MEM(&mips3->cpr[2][reg])
#define CCR264(reg) MEM(&mips3->ccr[2][reg])
-#define FCCMASK(which) fcc_mask[(mips3->flavor < MIPS3_TYPE_MIPS_IV) ? 0 : ((which) & 7)]
+#define FCCMASK(which) ((UINT32)(1 << fcc_shift[(mips3->flavor < MIPS3_TYPE_MIPS_IV) ? 0 : ((which) & 7)]))
+#define FCCSHIFT(which) fcc_shift[(mips3->flavor < MIPS3_TYPE_MIPS_IV) ? 0 : ((which) & 7)]
@@ -177,15 +178,6 @@ struct _mips3imp_state
/* tables */
UINT8 fpmode[4]; /* FPU mode table */
- UINT64 slt_table[32]; /* FLAGS table for slt */
- UINT64 sltu_table[32]; /* FLAGS table for sltu */
- UINT32 c_un_table[32]; /* FLAGS table for c_un */
- UINT32 c_eq_table[32]; /* FLAGS table for c_eq */
- UINT32 c_ueq_table[32]; /* FLAGS table for c_ueq */
- UINT32 c_olt_table[32]; /* FLAGS table for c_olt */
- UINT32 c_ult_table[32]; /* FLAGS table for c_ult */
- UINT32 c_ole_table[32]; /* FLAGS table for c_ole */
- UINT32 c_ule_table[32]; /* FLAGS table for c_ule */
/* register mappings */
drcuml_parameter regmap[34]; /* parameter to register mappings for all 32 integer registers */
@@ -270,7 +262,7 @@ static mips3_state *mips3;
/* bit indexes for various FCCs */
-static const UINT32 fcc_mask[8] = { 1 << 23, 1 << 25, 1 << 26, 1 << 27, 1 << 28, 1 << 29, 1 << 30, 1 << 31 };
+static const UINT8 fcc_shift[8] = { 23, 25, 26, 27, 28, 29, 30, 31 };
/* lookup table for FP modes */
static const UINT8 fpmode_source[4] =
@@ -281,339 +273,6 @@ static const UINT8 fpmode_source[4] =
DRCUML_FMOD_FLOOR
};
-/* flag lookup table for SLT */
-static const UINT64 slt_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ 0,
- /* ...V. */ 1,
- /* ...VC */ 1,
- /* ..Z.. */ 0,
- /* ..Z.C */ 0,
- /* ..ZV. */ 1,
- /* ..ZVC */ 1,
- /* .S... */ 1,
- /* .S..C */ 1,
- /* .S.V. */ 0,
- /* .S.VC */ 0,
- /* .SZ.. */ 1,
- /* .SZ.C */ 1,
- /* .SZV. */ 0,
- /* .SZVC */ 0,
- /* U.... */ 0,
- /* U...C */ 0,
- /* U..V. */ 1,
- /* U..VC */ 1,
- /* U.Z.. */ 0,
- /* U.Z.C */ 0,
- /* U.ZV. */ 1,
- /* U.ZVC */ 1,
- /* US... */ 1,
- /* US..C */ 1,
- /* US.V. */ 0,
- /* US.VC */ 0,
- /* USZ.. */ 1,
- /* USZ.C */ 1,
- /* USZV. */ 0,
- /* USZVC */ 0
-};
-
-/* flag lookup table for SLTU */
-static const UINT64 sltu_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ 1,
- /* ...V. */ 0,
- /* ...VC */ 1,
- /* ..Z.. */ 0,
- /* ..Z.C */ 1,
- /* ..ZV. */ 0,
- /* ..ZVC */ 1,
- /* .S... */ 0,
- /* .S..C */ 1,
- /* .S.V. */ 0,
- /* .S.VC */ 1,
- /* .SZ.. */ 0,
- /* .SZ.C */ 1,
- /* .SZV. */ 0,
- /* .SZVC */ 1,
- /* U.... */ 0,
- /* U...C */ 1,
- /* U..V. */ 0,
- /* U..VC */ 1,
- /* U.Z.. */ 0,
- /* U.Z.C */ 1,
- /* U.ZV. */ 0,
- /* U.ZVC */ 1,
- /* US... */ 0,
- /* US..C */ 1,
- /* US.V. */ 0,
- /* US.VC */ 1,
- /* USZ.. */ 0,
- /* USZ.C */ 1,
- /* USZV. */ 0,
- /* USZVC */ 1
-};
-
-/* flag lookup table for C.UN */
-static const UINT32 c_un_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ 0,
- /* ...V. */ 0,
- /* ...VC */ 0,
- /* ..Z.. */ 0,
- /* ..Z.C */ 0,
- /* ..ZV. */ 0,
- /* ..ZVC */ 0,
- /* .S... */ 0,
- /* .S..C */ 0,
- /* .S.V. */ 0,
- /* .S.VC */ 0,
- /* .SZ.. */ 0,
- /* .SZ.C */ 0,
- /* .SZV. */ 0,
- /* .SZVC */ 0,
- /* U.... */ ~0,
- /* U...C */ ~0,
- /* U..V. */ ~0,
- /* U..VC */ ~0,
- /* U.Z.. */ ~0,
- /* U.Z.C */ ~0,
- /* U.ZV. */ ~0,
- /* U.ZVC */ ~0,
- /* US... */ ~0,
- /* US..C */ ~0,
- /* US.V. */ ~0,
- /* US.VC */ ~0,
- /* USZ.. */ ~0,
- /* USZ.C */ ~0,
- /* USZV. */ ~0,
- /* USZVC */ ~0
-};
-
-/* flag lookup table for C.EQ */
-static const UINT32 c_eq_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ 0,
- /* ...V. */ 0,
- /* ...VC */ 0,
- /* ..Z.. */ ~0,
- /* ..Z.C */ ~0,
- /* ..ZV. */ ~0,
- /* ..ZVC */ ~0,
- /* .S... */ 0,
- /* .S..C */ 0,
- /* .S.V. */ 0,
- /* .S.VC */ 0,
- /* .SZ.. */ ~0,
- /* .SZ.C */ ~0,
- /* .SZV. */ ~0,
- /* .SZVC */ ~0,
- /* U.... */ 0,
- /* U...C */ 0,
- /* U..V. */ 0,
- /* U..VC */ 0,
- /* U.Z.. */ 0,
- /* U.Z.C */ 0,
- /* U.ZV. */ 0,
- /* U.ZVC */ 0,
- /* US... */ 0,
- /* US..C */ 0,
- /* US.V. */ 0,
- /* US.VC */ 0,
- /* USZ.. */ 0,
- /* USZ.C */ 0,
- /* USZV. */ 0,
- /* USZVC */ 0
-};
-
-/* flag lookup table for C.UEQ */
-static const UINT32 c_ueq_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ 0,
- /* ...V. */ 0,
- /* ...VC */ 0,
- /* ..Z.. */ ~0,
- /* ..Z.C */ ~0,
- /* ..ZV. */ ~0,
- /* ..ZVC */ ~0,
- /* .S... */ 0,
- /* .S..C */ 0,
- /* .S.V. */ 0,
- /* .S.VC */ 0,
- /* .SZ.. */ ~0,
- /* .SZ.C */ ~0,
- /* .SZV. */ ~0,
- /* .SZVC */ ~0,
- /* U.... */ ~0,
- /* U...C */ ~0,
- /* U..V. */ ~0,
- /* U..VC */ ~0,
- /* U.Z.. */ ~0,
- /* U.Z.C */ ~0,
- /* U.ZV. */ ~0,
- /* U.ZVC */ ~0,
- /* US... */ ~0,
- /* US..C */ ~0,
- /* US.V. */ ~0,
- /* US.VC */ ~0,
- /* USZ.. */ ~0,
- /* USZ.C */ ~0,
- /* USZV. */ ~0,
- /* USZVC */ ~0
-};
-
-/* flag lookup table for C.OLT */
-static const UINT32 c_olt_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ ~0,
- /* ...V. */ 0,
- /* ...VC */ ~0,
- /* ..Z.. */ 0,
- /* ..Z.C */ ~0,
- /* ..ZV. */ 0,
- /* ..ZVC */ ~0,
- /* .S... */ 0,
- /* .S..C */ ~0,
- /* .S.V. */ 0,
- /* .S.VC */ ~0,
- /* .SZ.. */ 0,
- /* .SZ.C */ ~0,
- /* .SZV. */ 0,
- /* .SZVC */ ~0,
- /* U.... */ 0,
- /* U...C */ 0,
- /* U..V. */ 0,
- /* U..VC */ 0,
- /* U.Z.. */ 0,
- /* U.Z.C */ 0,
- /* U.ZV. */ 0,
- /* U.ZVC */ 0,
- /* US... */ 0,
- /* US..C */ 0,
- /* US.V. */ 0,
- /* US.VC */ 0,
- /* USZ.. */ 0,
- /* USZ.C */ 0,
- /* USZV. */ 0,
- /* USZVC */ 0
-};
-
-/* flag lookup table for C.ULT */
-static const UINT32 c_ult_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ ~0,
- /* ...V. */ 0,
- /* ...VC */ ~0,
- /* ..Z.. */ 0,
- /* ..Z.C */ ~0,
- /* ..ZV. */ 0,
- /* ..ZVC */ ~0,
- /* .S... */ 0,
- /* .S..C */ ~0,
- /* .S.V. */ 0,
- /* .S.VC */ ~0,
- /* .SZ.. */ 0,
- /* .SZ.C */ ~0,
- /* .SZV. */ 0,
- /* .SZVC */ ~0,
- /* U.... */ ~0,
- /* U...C */ ~0,
- /* U..V. */ ~0,
- /* U..VC */ ~0,
- /* U.Z.. */ ~0,
- /* U.Z.C */ ~0,
- /* U.ZV. */ ~0,
- /* U.ZVC */ ~0,
- /* US... */ ~0,
- /* US..C */ ~0,
- /* US.V. */ ~0,
- /* US.VC */ ~0,
- /* USZ.. */ ~0,
- /* USZ.C */ ~0,
- /* USZV. */ ~0,
- /* USZVC */ ~0
-};
-
-/* flag lookup table for C.OLE */
-static const UINT32 c_ole_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ ~0,
- /* ...V. */ 0,
- /* ...VC */ ~0,
- /* ..Z.. */ ~0,
- /* ..Z.C */ ~0,
- /* ..ZV. */ ~0,
- /* ..ZVC */ ~0,
- /* .S... */ 0,
- /* .S..C */ ~0,
- /* .S.V. */ 0,
- /* .S.VC */ ~0,
- /* .SZ.. */ ~0,
- /* .SZ.C */ ~0,
- /* .SZV. */ ~0,
- /* .SZVC */ ~0,
- /* U.... */ 0,
- /* U...C */ 0,
- /* U..V. */ 0,
- /* U..VC */ 0,
- /* U.Z.. */ 0,
- /* U.Z.C */ 0,
- /* U.ZV. */ 0,
- /* U.ZVC */ 0,
- /* US... */ 0,
- /* US..C */ 0,
- /* US.V. */ 0,
- /* US.VC */ 0,
- /* USZ.. */ 0,
- /* USZ.C */ 0,
- /* USZV. */ 0,
- /* USZVC */ 0
-};
-
-/* flag lookup table for C.ULE */
-static const UINT32 c_ule_table_source[32] =
-{
- /* ..... */ 0,
- /* ....C */ ~0,
- /* ...V. */ 0,
- /* ...VC */ ~0,
- /* ..Z.. */ ~0,
- /* ..Z.C */ ~0,
- /* ..ZV. */ ~0,
- /* ..ZVC */ ~0,
- /* .S... */ 0,
- /* .S..C */ ~0,
- /* .S.V. */ 0,
- /* .S.VC */ ~0,
- /* .SZ.. */ ~0,
- /* .SZ.C */ ~0,
- /* .SZV. */ ~0,
- /* .SZVC */ ~0,
- /* U.... */ ~0,
- /* U...C */ ~0,
- /* U..V. */ ~0,
- /* U..VC */ ~0,
- /* U.Z.. */ ~0,
- /* U.Z.C */ ~0,
- /* U.ZV. */ ~0,
- /* U.ZVC */ ~0,
- /* US... */ ~0,
- /* US..C */ ~0,
- /* US.V. */ ~0,
- /* US.VC */ ~0,
- /* USZ.. */ ~0,
- /* USZ.C */ ~0,
- /* USZV. */ ~0,
- /* USZVC */ ~0
-};
-
/***************************************************************************
@@ -738,15 +397,6 @@ static void mips3_init(mips3_flavor flavor, int bigendian, int index, int clock,
/* allocate memory for cache-local state and initialize it */
memcpy(mips3->impstate->fpmode, fpmode_source, sizeof(fpmode_source));
- memcpy(mips3->impstate->slt_table, slt_table_source, sizeof(slt_table_source));
- memcpy(mips3->impstate->sltu_table, sltu_table_source, sizeof(sltu_table_source));
- memcpy(mips3->impstate->c_un_table, c_un_table_source, sizeof(c_un_table_source));
- memcpy(mips3->impstate->c_eq_table, c_eq_table_source, sizeof(c_eq_table_source));
- memcpy(mips3->impstate->c_ueq_table, c_ueq_table_source, sizeof(c_ueq_table_source));
- memcpy(mips3->impstate->c_olt_table, c_olt_table_source, sizeof(c_olt_table_source));
- memcpy(mips3->impstate->c_ult_table, c_ult_table_source, sizeof(c_ult_table_source));
- memcpy(mips3->impstate->c_ole_table, c_ole_table_source, sizeof(c_ole_table_source));
- memcpy(mips3->impstate->c_ule_table, c_ule_table_source, sizeof(c_ule_table_source));
/* compute the register parameters */
for (regnum = 0; regnum < 34; regnum++)
@@ -1259,7 +909,7 @@ static void static_generate_entry_point(drcuml_state *drcuml)
/* reset the FPU mode */
UML_AND(block, IREG(0), CCR132(31), IMM(3)); // and i0,ccr1[31],3
- UML_LOAD1U(block, IREG(0), &mips3->impstate->fpmode[0], IREG(0)); // load1u i0,fpmode,i0
+ UML_LOAD(block, IREG(0), &mips3->impstate->fpmode[0], IREG(0), BYTE); // load i0,fpmode,i0,byte
UML_SETFMOD(block, IREG(0)); // setfmod i0
/* load fast integer registers */
@@ -1370,7 +1020,7 @@ static void static_generate_tlb_mismatch(drcuml_state *drcuml)
UML_RECOVER(block, IREG(0), MAPVAR_PC); // recover i0,PC
UML_MOV(block, MEM(&mips3->pc), IREG(0)); // mov <pc>,i0
UML_SHR(block, IREG(1), IREG(0), IMM(12)); // shr i1,i0,12
- UML_LOAD4(block, IREG(1), mips3->tlb_table, IREG(1)); // load4 i1,[tlb_table],i1
+ UML_LOAD(block, IREG(1), mips3->tlb_table, IREG(1), DWORD); // load i1,[tlb_table],i1,dword
if (PRINTF_MMU)
{
UML_MOV(block, MEM(&mips3->impstate->arg0), IREG(0)); // mov [arg0],i0
@@ -1433,8 +1083,8 @@ static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int
if (exception == EXCEPTION_TLBLOAD || exception == EXCEPTION_TLBSTORE)
{
/* set the upper bits of EntryHi and the lower bits of Context to the fault page */
- UML_INSERT(block, CPR032(COP0_EntryHi), IREG(0), IMM(0), IMM(0xffffe000)); // insert [EntryHi],i0,0,0xffffe000
- UML_INSERT(block, CPR032(COP0_Context), IREG(0), IMM(32-9), IMM(0x7fffff)); // insert [Context],i0,32-9,0x7fffff
+ UML_ROLINS(block, CPR032(COP0_EntryHi), IREG(0), IMM(0), IMM(0xffffe000)); // rolins [EntryHi],i0,0,0xffffe000
+ UML_ROLINS(block, CPR032(COP0_Context), IREG(0), IMM(32-9), IMM(0x7fffff)); // rolins [Context],i0,32-9,0x7fffff
}
/* set the EPC and Cause registers */
@@ -1458,7 +1108,7 @@ static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int
if (exception == EXCEPTION_BADCOP)
{
UML_GETEXP(block, IREG(0)); // getexp i0
- UML_INSERT(block, CPR032(COP0_Cause), IREG(0), IMM(28), IMM(0x30000000)); // insert [Cause],i0,28,0x30000000
+ UML_ROLINS(block, CPR032(COP0_Cause), IREG(0), IMM(28), IMM(0x30000000)); // rolins [Cause],i0,28,0x30000000
}
/* set EXL in the SR */
@@ -1536,10 +1186,10 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
/* general case: assume paging and perform a translation */
UML_SHR(block, IREG(3), IREG(0), IMM(12)); // shr i3,i0,12
- UML_LOAD4(block, IREG(3), mips3->tlb_table, IREG(3)); // load4 i3,[tlb_table],i3
+ UML_LOAD(block, IREG(3), mips3->tlb_table, IREG(3), DWORD); // load i3,[tlb_table],i3,dword
UML_TEST(block, IREG(3), IMM(iswrite ? TLB_DIRTY : TLB_VALID)); // test i3,iswrite ? TLB_DIRTY : TLB_VALID
UML_JMPc(block, IF_Z, tlbmiss = label++); // jmp tlbmiss,z
- UML_INSERT(block, IREG(0), IREG(3), IMM(0), IMM(0xfffff000)); // insert i0,i3,0,0xfffff000
+ UML_ROLINS(block, IREG(0), IREG(3), IMM(0), IMM(0xfffff000)); // rolins i0,i3,0,0xfffff000
for (ramnum = 0; ramnum < MIPS3_MAX_FASTRAM; ramnum++)
if (!Machine->debug_mode && mips3->impstate->fastram[ramnum].base != NULL && (!iswrite || !mips3->impstate->fastram[ramnum].readonly))
@@ -1563,24 +1213,24 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
{
UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0)));
// xor i0,i0,bytexor
- UML_LOAD1U(block, IREG(0), fastbase, IREG(0)); // load1u i0,fastbase,i0
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), BYTE); // load i0,fastbase,i0,byte
}
else if (size == 2)
{
UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
// xor i0,i0,bytexor
- UML_LOAD2U(block, IREG(0), fastbase, IREG(0)); // load2u i0,fastbase,i0
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), WORD); // load i0,fastbase,i0,word
}
else if (size == 4)
{
UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
- UML_LOAD4(block, IREG(0), fastbase, IREG(0)); // load4 i0,fastbase,i0
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), DWORD); // load i0,fastbase,i0,dword
}
else if (size == 8)
{
UML_SHR(block, IREG(0), IREG(0), IMM(3)); // shr i0,i0,3
- UML_DLOAD8(block, IREG(0), fastbase, IREG(0)); // dload8 i0,fastbase,i0
+ UML_DLOAD(block, IREG(0), fastbase, IREG(0), QWORD); // dload i0,fastbase,i0,qword
UML_DROR(block, IREG(0), IREG(0), IMM(32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0))));
// dror i0,i0,32*bytexor
}
@@ -1592,26 +1242,26 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
{
UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0)));
// xor i0,i0,bytexor
- UML_STORE1(block, fastbase, IREG(0), IREG(1)); // store1 fastbase,i0,i1
+ UML_STORE(block, fastbase, IREG(0), IREG(1), BYTE); // store fastbase,i0,i1,byte
}
else if (size == 2)
{
UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
UML_XOR(block, IREG(0), IREG(0), IMM(mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0)));
// xor i0,i0,bytexor
- UML_STORE2(block, fastbase, IREG(0), IREG(1)); // store2 fastbase,i0,i1
+ UML_STORE(block, fastbase, IREG(0), IREG(1), WORD); // store fastbase,i0,i1,word
}
else if (size == 4)
{
UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
if (ismasked)
{
- UML_LOAD4(block, IREG(3), fastbase, IREG(0)); // load4 i3,fastbase,i0
- UML_INSERT(block, IREG(3), IREG(1), IMM(0), IREG(2)); // insert i3,i1,0,i2
- UML_STORE4(block, fastbase, IREG(0), IREG(3)); // store4 fastbase,i0,i3
+ UML_LOAD(block, IREG(3), fastbase, IREG(0), DWORD); // load i3,fastbase,i0,dword
+ UML_ROLINS(block, IREG(3), IREG(1), IMM(0), IREG(2)); // rolins i3,i1,0,i2
+ UML_STORE(block, fastbase, IREG(0), IREG(3), DWORD); // store fastbase,i0,i3,dword
}
else
- UML_STORE4(block, fastbase, IREG(0), IREG(1)); // store4 fastbase,i0,i1
+ UML_STORE(block, fastbase, IREG(0), IREG(1), DWORD); // store fastbase,i0,i1,dword
}
else if (size == 8)
{
@@ -1622,12 +1272,12 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
{
UML_DROR(block, IREG(2), IREG(2), IMM(32 * (mips3->bigendian ? BYTE_XOR_BE(0) : BYTE_XOR_LE(0))));
// dror i2,i2,32*bytexor
- UML_DLOAD8(block, IREG(3), fastbase, IREG(0)); // dload8 i3,fastbase,i0
- UML_DINSERT(block, IREG(3), IREG(1), IMM(0), IREG(2)); // dinsert i3,i1,0,i2
- UML_DSTORE8(block, fastbase, IREG(0), IREG(3)); // dstore8 fastbase,i0,i3
+ UML_DLOAD(block, IREG(3), fastbase, IREG(0), QWORD); // dload i3,fastbase,i0,qword
+ UML_DROLINS(block, IREG(3), IREG(1), IMM(0), IREG(2)); // drolins i3,i1,0,i2
+ UML_DSTORE(block, fastbase, IREG(0), IREG(3), QWORD); // dstore fastbase,i0,i3,qword
}
else
- UML_DSTORE8(block, fastbase, IREG(0), IREG(1)); // dstore8 fastbase,i0,i1
+ UML_DSTORE(block, fastbase, IREG(0), IREG(1), QWORD); // dstore fastbase,i0,i1,qword
}
UML_RET(block); // ret
}
@@ -1639,32 +1289,32 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
{
case 1:
if (iswrite)
- UML_WRITE1(block, PROGRAM, IREG(0), IREG(1)); // write1 i0,i1
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_BYTE); // write i0,i1,program_byte
else
- UML_READ1U(block, IREG(0), PROGRAM, IREG(0)); // read1u i0,i0
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_BYTE); // read i0,i0,program_byte
break;
case 2:
if (iswrite)
- UML_WRITE2(block, PROGRAM, IREG(0), IREG(1)); // write2 i0,i1
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_WORD); // write i0,i1,program_word
else
- UML_READ2U(block, IREG(0), PROGRAM, IREG(0)); // read2u i0,i0
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_WORD); // read i0,i0,program_word
break;
case 4:
if (iswrite)
{
if (!ismasked)
- UML_WRITE4(block, PROGRAM, IREG(0), IREG(1)); // write4 PROGRAM,i0,i1
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_DWORD); // write i0,i1,program_dword
else
- UML_WRIT4M(block, PROGRAM, IREG(0), IREG(2), IREG(1)); // writ4m PROGRAM,i0,i2,i1
+ UML_WRITEM(block, IREG(0), IREG(2), IREG(1), PROGRAM_DWORD); // writem i0,i2,i1,program_dword
}
else
{
if (!ismasked)
- UML_READ4(block, IREG(0), PROGRAM, IREG(0)); // read4 i0,PROGRAM,i0
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_DWORD); // read i0,i0,program_dword
else
- UML_READ4M(block, IREG(0), PROGRAM, IREG(0), IREG(2)); // read4m i0,PROGRAM,i0,i2
+ UML_READM(block, IREG(0), IREG(0), IREG(2), PROGRAM_DWORD); // readm i0,i0,i2,program_dword
}
break;
@@ -1672,16 +1322,16 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
if (iswrite)
{
if (!ismasked)
- UML_DWRITE8(block, PROGRAM, IREG(0), IREG(1)); // dwrite8 PROGRAM,i0,i1
+ UML_DWRITE(block, IREG(0), IREG(1), PROGRAM_QWORD); // dwrite i0,i1,program_qword
else
- UML_DWRIT8M(block, PROGRAM, IREG(0), IREG(2), IREG(1)); // dwrit8m PROGRAM,i0,i2,i1
+ UML_DWRITEM(block, IREG(0), IREG(2), IREG(1), PROGRAM_QWORD); // dwritem i0,i2,i1,program_qword
}
else
{
if (!ismasked)
- UML_DREAD8(block, IREG(0), PROGRAM, IREG(0)); // dread8 i0,PROGRAM,i0
+ UML_DREAD(block, IREG(0), IREG(0), PROGRAM_QWORD); // dread i0,i0,program_qword
else
- UML_DREAD8M(block, IREG(0), PROGRAM, IREG(0), IREG(2)); // dread8m i0,PROGRAM,i0,i2
+ UML_DREADM(block, IREG(0), IREG(0), IREG(2), PROGRAM_QWORD); // dreadm i0,i0,i2,program_qword
}
break;
}
@@ -1717,10 +1367,10 @@ static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int
static void generate_update_mode(drcuml_block *block)
{
- UML_XTRACT(block, IREG(2), IREG(0), IMM(32-2), IMM(0x06)); // xtract i2,i0,32-2,0x06
+ UML_ROLAND(block, IREG(2), IREG(0), IMM(32-2), IMM(0x06)); // roland i2,i0,32-2,0x06
UML_TEST(block, IREG(0), IMM(SR_EXL | SR_ERL)); // test i0,SR_EXL | SR_ERL
UML_MOVc(block, IF_NZ, IREG(2), IMM(0)); // mov i2,0,nz
- UML_INSERT(block, IREG(2), IREG(0), IMM(32-26), IMM(0x01)); // insert i2,i0,32-26,0x01
+ UML_ROLINS(block, IREG(2), IREG(0), IMM(32-26), IMM(0x01)); // rolins i2,i0,32-26,0x01
UML_MOV(block, MEM(&mips3->impstate->mode), IREG(2)); // mov [mode],i2
}
@@ -1797,7 +1447,7 @@ static void generate_checksum_block(drcuml_block *block, compiler_state *compile
{
if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
{
- UML_LOAD4(block, IREG(0), seqhead->opptr.l, IMM(0)); // load4 i0,*opptr
+ UML_LOAD(block, IREG(0), seqhead->opptr.l, IMM(0), DWORD); // load i0,*opptr,0,dword
UML_CMP(block, IREG(0), IMM(*seqhead->opptr.l)); // cmp i0,*opptr
UML_EXHc(block, IF_NE, mips3->impstate->nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc
}
@@ -1810,18 +1460,18 @@ static void generate_checksum_block(drcuml_block *block, compiler_state *compile
for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
- UML_LOAD4(block, IREG(0), curdesc->opptr.l, IMM(0)); // load4 i0,*opptr
+ UML_LOAD(block, IREG(0), curdesc->opptr.l, IMM(0), DWORD); // load i0,*opptr,0,dword
UML_CMP(block, IREG(0), IMM(*curdesc->opptr.l)); // cmp i0,*opptr
UML_EXHc(block, IF_NE, mips3->impstate->nocode, IMM(epc(seqhead))); // exne nocode,seqhead->pc
}
#else
UINT32 sum = 0;
- UML_LOAD4(block, IREG(0), seqhead->opptr.l, IMM(0)); // load4 i0,*opptr
+ UML_LOAD(block, IREG(0), seqhead->opptr.l, IMM(0), DWORD); // load i0,*opptr,0,dword
sum += *seqhead->opptr.l;
for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
- UML_LOAD4(block, IREG(1), curdesc->opptr.l, IMM(0)); // load4 i1,*opptr
+ UML_LOAD(block, IREG(1), curdesc->opptr.l, IMM(0), DWORD); // load i1,*opptr,dword
UML_ADD(block, IREG(0), IREG(0), IREG(1)); // add i0,i0,i1
sum += *curdesc->opptr.l;
}
@@ -1906,7 +1556,7 @@ static void generate_sequence_instruction(drcuml_block *block, compiler_state *c
UML_MOV(block, MEM(&mips3->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc
UML_CALLC(block, cfunc_printf_debug, "Checking TLB at @ %08X\n"); // callc printf_debug
}
- UML_LOAD4(block, IREG(0), &mips3->tlb_table[desc->pc >> 12], IMM(0)); // load4 i0,tlb_table[desc->pc >> 12]
+ UML_LOAD(block, IREG(0), &mips3->tlb_table[desc->pc >> 12], IMM(0), DWORD);// load i0,tlb_table[desc->pc >> 12],0,dword
UML_CMP(block, IREG(0), IMM(mips3->tlb_table[desc->pc >> 12])); // cmp i0,*tlbentry
UML_EXHc(block, IF_NE, mips3->impstate->tlb_mismatch, IMM(0)); // exh tlb_mismatch,0,NE
}
@@ -1951,7 +1601,7 @@ static void generate_delay_slot_and_branch(drcuml_block *block, compiler_state *
/* set the link if needed */
if (linkreg != 0)
- UML_DSEXT4(block, R64(linkreg), IMM((INT32)(desc->pc + 8))); // dsext4 <linkreg>,desc->pc + 8
+ UML_DMOV(block, R64(linkreg), IMM((INT32)(desc->pc + 8))); // dmov <linkreg>,desc->pc + 8
/* compile the delay slot using temporary compiler state */
assert(desc->delay != NULL);
@@ -2061,7 +1711,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
case 0x0f: /* LUI - MIPS I */
if (RTREG != 0)
- UML_DSEXT4(block, R64(RTREG), IMM(SIMMVAL << 16)); // dsext4 <rtreg>,SIMMVAL << 16
+ UML_DMOV(block, R64(RTREG), IMM(SIMMVAL << 16)); // dmov <rtreg>,SIMMVAL << 16
return TRUE;
case 0x08: /* ADDI - MIPS I */
@@ -2074,14 +1724,14 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
else
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
if (RTREG != 0)
- UML_DSEXT4(block, R64(RTREG), IREG(0)); // dsext4 <rtreg>,i0
+ UML_DSEXT(block, R64(RTREG), IREG(0), DWORD); // dsext <rtreg>,i0,dword
return TRUE;
case 0x09: /* ADDIU - MIPS I */
if (RTREG != 0)
{
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL,V
- UML_DSEXT4(block, R64(RTREG), IREG(0)); // dsext4 <rtreg>,i0
+ UML_DSEXT(block, R64(RTREG), IREG(0), DWORD); // dsext <rtreg>,i0,dword
}
return TRUE;
@@ -2122,8 +1772,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
if (RTREG != 0)
{
UML_DCMP(block, R64(RSREG), IMM(SIMMVAL)); // dcmp <rsreg>,SIMMVAL
- UML_DFLAGS(block, R64(RTREG), (UINT64)~0, mips3->impstate->slt_table);
- // dflags <rtreg>,~0,slt_table
+ UML_DSETc(block, IF_L, R64(RTREG)); // dset <rtreg>,l
}
return TRUE;
@@ -2131,8 +1780,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
if (RTREG != 0)
{
UML_DCMP(block, R64(RSREG), IMM(SIMMVAL)); // dcmp <rsreg>,SIMMVAL
- UML_DFLAGS(block, R64(RTREG), (UINT64)~0, mips3->impstate->sltu_table);
- // dflags <rtreg>,~0,sltu_table
+ UML_DSETc(block, IF_B, R64(RTREG)); // dset <rtreg>,b
}
return TRUE;
@@ -2143,7 +1791,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, mips3->impstate->read8[mips3->impstate->mode >> 1]); // callh read8
if (RTREG != 0)
- UML_DSEXT1(block, R64(RTREG), IREG(0)); // dsext1 <rtreg>,i0
+ UML_DSEXT(block, R64(RTREG), IREG(0), BYTE); // dsext <rtreg>,i0,byte
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
@@ -2152,7 +1800,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, mips3->impstate->read16[mips3->impstate->mode >> 1]); // callh read16
if (RTREG != 0)
- UML_DSEXT2(block, R64(RTREG), IREG(0)); // dsext2 <rtreg>,i0
+ UML_DSEXT(block, R64(RTREG), IREG(0), WORD); // dsext <rtreg>,i0,word
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
@@ -2161,7 +1809,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
if (RTREG != 0)
- UML_DSEXT4(block, R64(RTREG), IREG(0)); // dsext4 <rtreg>,i0
+ UML_DSEXT(block, R64(RTREG), IREG(0), DWORD); // dsext <rtreg>,i0
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
@@ -2170,7 +1818,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, mips3->impstate->read8[mips3->impstate->mode >> 1]); // callh read8
if (RTREG != 0)
- UML_DZEXT1(block, R64(RTREG), IREG(0)); // dzext1 <rtreg>,i0
+ UML_DAND(block, R64(RTREG), IREG(0), IMM(0xff)); // dand <rtreg>,i0,0xff
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
@@ -2179,7 +1827,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, mips3->impstate->read16[mips3->impstate->mode >> 1]); // callh read16
if (RTREG != 0)
- UML_DZEXT2(block, R64(RTREG), IREG(0)); // dzext2 <rtreg>,i0
+ UML_DAND(block, R64(RTREG), IREG(0), IMM(0xffff)); // dand <rtreg>,i0,0xffff
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
@@ -2188,7 +1836,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
if (RTREG != 0)
- UML_DZEXT4(block, R64(RTREG), IREG(0)); // dzext4 <rtreg>,i0
+ UML_DAND(block, R64(RTREG), IREG(0), IMM(0xffffffff)); // dand <rtreg>,i0,0xffffffff
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
@@ -2214,8 +1862,8 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
{
UML_SHL(block, IREG(2), IMM(~0), IREG(1)); // shl i2,~0,i1
UML_MOV(block, IREG(3), R32(RTREG)); // mov i3,<rtreg>
- UML_INSERT(block, IREG(3), IREG(0), IREG(1), IREG(2)); // insert i3,i0,i1,i2
- UML_DSEXT4(block, R64(RTREG), IREG(3)); // dsext4 <rtreg>,i3
+ UML_ROLINS(block, IREG(3), IREG(0), IREG(1), IREG(2)); // rolins i3,i0,i1,i2
+ UML_DSEXT(block, R64(RTREG), IREG(3), DWORD); // dsext <rtreg>,i3,dword
}
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
@@ -2234,8 +1882,8 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
UML_SHR(block, IREG(2), IMM(~0), IREG(1)); // shr i2,~0,i1
UML_SUB(block, IREG(1), IMM(32), IREG(1)); // sub i1,32,i1
UML_MOV(block, IREG(3), R32(RTREG)); // mov i3,<rtreg>
- UML_INSERT(block, IREG(3), IREG(0), IREG(1), IREG(2)); // insert i3,i0,i1,i2
- UML_DSEXT4(block, R64(RTREG), IREG(3)); // dsext4 <rtreg>,i3
+ UML_ROLINS(block, IREG(3), IREG(0), IREG(1), IREG(2)); // rolins i3,i0,i1,i2
+ UML_DSEXT(block, R64(RTREG), IREG(3), DWORD); // dsext <rtreg>,i3,dword
}
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
@@ -2252,7 +1900,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
if (RTREG != 0)
{
UML_DSHL(block, IREG(2), IMM((UINT64)~0), IREG(1)); // dshl i2,~0,i1
- UML_DINSERT(block, R64(RTREG), IREG(0), IREG(1), IREG(2)); // dinsert <rtreg>,i0,i1,i2
+ UML_DROLINS(block, R64(RTREG), IREG(0), IREG(1), IREG(2)); // drolins <rtreg>,i0,i1,i2
}
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
@@ -2270,7 +1918,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
{
UML_DSHR(block, IREG(2), IMM((UINT64)~0), IREG(1)); // dshr i2,~0,i1
UML_SUB(block, IREG(1), IMM(64), IREG(1)); // sub i1,64,i1
- UML_DINSERT(block, R64(RTREG), IREG(0), IREG(1), IREG(2)); // dinsert <rtreg>,i0,i1,i2
+ UML_DROLINS(block, R64(RTREG), IREG(0), IREG(1), IREG(2)); // drolins <rtreg>,i0,i1,i2
}
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
@@ -2295,7 +1943,7 @@ static int generate_opcode(drcuml_block *block, compiler_state *compiler, const
case 0x32: /* LWC2 - MIPS I */
UML_ADD(block, IREG(0), R32(RSREG), IMM(SIMMVAL)); // add i0,<rsreg>,SIMMVAL
UML_CALLH(block, mips3->impstate->read32[mips3->impstate->mode >> 1]); // callh read32
- UML_DZEXT4(block, CPR264(RTREG), IREG(0)); // dzext4 <cpr2_rt>,i0
+ UML_DAND(block, CPR264(RTREG), IREG(0), IMM(0xffffffff)); // dand <cpr2_rt>,i0,0xffffffff
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
return TRUE;
@@ -2486,7 +2134,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_SHL(block, IREG(0), R32(RTREG), IMM(SHIFT)); // shl i0,<rtreg>,<shift>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2494,7 +2142,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_SHR(block, IREG(0), R32(RTREG), IMM(SHIFT)); // shr i0,<rtreg>,<shift>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2502,7 +2150,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_SAR(block, IREG(0), R32(RTREG), IMM(SHIFT)); // sar i0,<rtreg>,<shift>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2510,7 +2158,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_SHL(block, IREG(0), R32(RTREG), R32(RSREG)); // shl i0,<rtreg>,<rsreg>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2518,7 +2166,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_SHR(block, IREG(0), R32(RTREG), R32(RSREG)); // shr i0,<rtreg>,<rsreg>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2526,7 +2174,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_SAR(block, IREG(0), R32(RTREG), R32(RSREG)); // sar i0,<rtreg>,<rsreg>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2585,12 +2233,12 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
UML_EXHc(block, IF_V, mips3->impstate->exception[EXCEPTION_OVERFLOW], IMM(0));
// exh overflow,0,V
if (RDREG != 0)
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
else if (RDREG != 0)
{
UML_ADD(block, IREG(0), R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2598,7 +2246,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_ADD(block, IREG(0), R32(RSREG), R32(RTREG)); // add i0,<rsreg>,<rtreg>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2627,12 +2275,12 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
UML_EXHc(block, IF_V, mips3->impstate->exception[EXCEPTION_OVERFLOW], IMM(0));
// exh overflow,0,V
if (RDREG != 0)
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
else if (RDREG != 0)
{
UML_SUB(block, IREG(0), R32(RSREG), R32(RTREG)); // sub i0,<rsreg>,<rtreg>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2640,7 +2288,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_SUB(block, IREG(0), R32(RSREG), R32(RTREG)); // sub i0,<rsreg>,<rtreg>
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 <rdreg>,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext <rdreg>,i0,dword
}
return TRUE;
@@ -2664,14 +2312,14 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
case 0x18: /* MULT - MIPS I */
UML_MULS(block, IREG(0), IREG(1), R32(RSREG), R32(RTREG)); // muls i0,i1,<rsreg>,<rtreg>
- UML_DSEXT4(block, LO64, IREG(0)); // dsext4 lo,i0
- UML_DSEXT4(block, HI64, IREG(1)); // dsext4 hi,i1
+ UML_DSEXT(block, LO64, IREG(0), DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, IREG(1), DWORD); // dsext hi,i1,dword
return TRUE;
case 0x19: /* MULTU - MIPS I */
UML_MULU(block, IREG(0), IREG(1), R32(RSREG), R32(RTREG)); // mulu i0,i1,<rsreg>,<rtreg>
- UML_DSEXT4(block, LO64, IREG(0)); // dsext4 lo,i0
- UML_DSEXT4(block, HI64, IREG(1)); // dsext4 hi,i1
+ UML_DSEXT(block, LO64, IREG(0), DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, IREG(1), DWORD); // dsext hi,i1,dword
return TRUE;
case 0x1c: /* DMULT - MIPS III */
@@ -2684,14 +2332,14 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
case 0x1a: /* DIV - MIPS I */
UML_DIVS(block, IREG(0), IREG(1), R32(RSREG), R32(RTREG)); // divs i0,i1,<rsreg>,<rtreg>
- UML_DSEXT4(block, LO64, IREG(0)); // dsext4 lo,i0
- UML_DSEXT4(block, HI64, IREG(1)); // dsext4 hi,i1
+ UML_DSEXT(block, LO64, IREG(0), DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, IREG(1), DWORD); // dsext hi,i1,dword
return TRUE;
case 0x1b: /* DIVU - MIPS I */
UML_DIVU(block, IREG(0), IREG(1), R32(RSREG), R32(RTREG)); // divu i0,i1,<rsreg>,<rtreg>
- UML_DSEXT4(block, LO64, IREG(0)); // dsext4 lo,i0
- UML_DSEXT4(block, HI64, IREG(1)); // dsext4 hi,i1
+ UML_DSEXT(block, LO64, IREG(0), DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, IREG(1), DWORD); // dsext hi,i1,dword
return TRUE;
case 0x1e: /* DDIV - MIPS III */
@@ -2735,7 +2383,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
- UML_DFLAGS(block, R64(RDREG), (UINT64)~0, mips3->impstate->slt_table);// dflags <rdreg>,~0,slt_table
+ UML_DSETc(block, IF_L, R64(RDREG)); // dset <rdreg>,l
}
return TRUE;
@@ -2743,7 +2391,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
if (RDREG != 0)
{
UML_DCMP(block, R64(RSREG), R64(RTREG)); // dcmp <rsreg>,<rtreg>
- UML_DFLAGS(block, R64(RDREG), (UINT64)~0, mips3->impstate->sltu_table);// dflags <rdreg>,~0,sltu_table
+ UML_DSETc(block, IF_B, R64(RDREG)); // dset <rdreg>,b
}
return TRUE;
@@ -2802,7 +2450,7 @@ static int generate_special(drcuml_block *block, compiler_state *compiler, const
case 0x01: /* MOVF/MOVT - MIPS IV */
if (RDREG != 0)
{
- UML_TEST(block, CCR132(31), IMM(fcc_mask[(op >> 18) & 7])); // test ccr31,fcc_mask[x]
+ UML_TEST(block, CCR132(31), IMM(FCCMASK(op >> 18))); // test ccr31,fcc_mask[x]
UML_DMOVc(block, ((op >> 16) & 1) ? IF_NZ : IF_Z, R64(RDREG), R64(RSREG));
// mov <rdreg>,<rsreg>,NZ/Z
}
@@ -2961,8 +2609,8 @@ static int generate_idt(drcuml_block *block, compiler_state *compiler, const opc
UML_MULS(block, IREG(0), IREG(1), R32(RSREG), R32(RTREG)); // muls i0,i1,rsreg,rtreg
UML_ADDf(block, FLAGS_C, IREG(0), IREG(0), LO32); // add i0,i0,lo
UML_ADDC(block, IREG(1), IREG(1), HI32); // addc i1,i1,hi
- UML_DSEXT4(block, LO64, IREG(0)); // dsext4 lo,i0
- UML_DSEXT4(block, HI64, IREG(1)); // dsext4 hi,i0
+ UML_DSEXT(block, LO64, IREG(0), DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, IREG(1), DWORD); // dsext hi,i1,dword
}
return TRUE;
@@ -2972,8 +2620,8 @@ static int generate_idt(drcuml_block *block, compiler_state *compiler, const opc
UML_MULU(block, IREG(0), IREG(1), R32(RSREG), R32(RTREG)); // mulu i0,i1,rsreg,rtreg
UML_ADDf(block, FLAGS_C, IREG(0), IREG(0), LO32); // add i0,i0,lo
UML_ADDC(block, IREG(1), IREG(1), HI32); // addc i1,i1,hi
- UML_DSEXT4(block, LO64, IREG(0)); // dsext4 lo,i0
- UML_DSEXT4(block, HI64, IREG(1)); // dsext4 hi,i0
+ UML_DSEXT(block, LO64, IREG(0), DWORD); // dsext lo,i0,dword
+ UML_DSEXT(block, HI64, IREG(1), DWORD); // dsext hi,i1,dword
}
return TRUE;
@@ -2981,7 +2629,7 @@ static int generate_idt(drcuml_block *block, compiler_state *compiler, const opc
if (RDREG != 0)
{
UML_MULS(block, IREG(0), IREG(0), R32(RSREG), R32(RTREG)); // muls i0,i0,rsreg,rtreg
- UML_DSEXT4(block, R64(RDREG), IREG(0)); // dsext4 rdreg,i0
+ UML_DSEXT(block, R64(RDREG), IREG(0), DWORD); // dsext rdreg,i0,dword
}
return TRUE;
}
@@ -3002,7 +2650,7 @@ static int generate_set_cop0_reg(drcuml_block *block, compiler_state *compiler,
switch (reg)
{
case COP0_Cause:
- UML_INSERT(block, CPR032(COP0_Cause), IREG(0), IMM(0), IMM(~0xfc00)); // insert [Cause],i0,0,~0xfc00
+ UML_ROLINS(block, CPR032(COP0_Cause), IREG(0), IMM(0), IMM(~0xfc00)); // rolins [Cause],i0,0,~0xfc00
compiler->checksoftints = TRUE;
if (!in_delay_slot)
generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE);
@@ -3025,7 +2673,7 @@ static int generate_set_cop0_reg(drcuml_block *block, compiler_state *compiler,
generate_update_cycles(block, compiler, IMM(desc->pc), !in_delay_slot); // <subtract cycles>
UML_MOV(block, CPR032(COP0_Count), IREG(0)); // mov [Count],i0
UML_CALLC(block, cfunc_get_cycles, &mips3->impstate->numcycles); // callc cfunc_get_cycles,&mips3->impstate->numcycles
- UML_DZEXT4(block, IREG(0), IREG(0)); // dzext4 i0,i0
+ UML_DAND(block, IREG(0), IREG(0), IMM(0xffffffff)); // and i0,i0,0xffffffff
UML_DADD(block, IREG(0), IREG(0), IREG(0)); // dadd i0,i0,i0
UML_DSUB(block, MEM(&mips3->count_zero_time), MEM(&mips3->impstate->numcycles), IREG(0));
// dsub [count_zero_time],[mips3->impstate->numcycles],i0
@@ -3043,7 +2691,7 @@ static int generate_set_cop0_reg(drcuml_block *block, compiler_state *compiler,
return TRUE;
case COP0_Config:
- UML_INSERT(block, CPR032(COP0_Config), IREG(0), IMM(0), IMM(0x0007)); // insert [Config],i0,0,0x0007
+ UML_ROLINS(block, CPR032(COP0_Config), IREG(0), IMM(0), IMM(0x0007)); // rolins [Config],i0,0,0x0007
return TRUE;
case COP0_EntryHi:
@@ -3080,7 +2728,7 @@ static int generate_get_cop0_reg(drcuml_block *block, compiler_state *compiler,
UML_DSUB(block, IREG(0), MEM(&mips3->impstate->numcycles), MEM(&mips3->count_zero_time));
// dsub i0,[numcycles],[count_zero_time]
UML_DSHR(block, IREG(0), IREG(0), IMM(1)); // dshr i0,i0,1
- UML_DSEXT4(block, IREG(0), IREG(0)); // dsext4 i0,i0
+ UML_DSEXT(block, IREG(0), IREG(0), DWORD); // dsext i0,i0,dword
return TRUE;
case COP0_Random:
@@ -3091,18 +2739,18 @@ static int generate_get_cop0_reg(drcuml_block *block, compiler_state *compiler,
UML_AND(block, IREG(1), CPR032(COP0_Wired), IMM(0x3f)); // and i1,[Wired],0x3f
UML_SUBf(block, IREG(2), IMM(48), IREG(1), FLAGS_BE); // sub i2,48,i1,ALL
UML_JMPc(block, IF_BE, link1 = compiler->labelnum++); // jmp link1,BE
- UML_DZEXT4(block, IREG(2), IREG(2)); // dzext4 i2,i2
+ UML_DAND(block, IREG(2), IREG(2), IMM(0xffffffff)); // dand i2,i2,0xffffffff
UML_DDIVU(block, IREG(0), IREG(2), IREG(0), IREG(2)); // ddivu i0,i2,i0,i2
UML_ADD(block, IREG(0), IREG(2), IREG(1)); // add i0,i2,i1
UML_DAND(block, IREG(0), IREG(0), IMM(0x3f)); // dand i0,i0,0x3f
UML_JMP(block, link2 = compiler->labelnum++); // jmp link2
UML_LABEL(block, link1); // link1:
- UML_DSEXT4(block, IREG(0), IMM(47)); // dsext4 i0,47
+ UML_DMOV(block, IREG(0), IMM(47)); // dmov i0,47
UML_LABEL(block, link2); // link2:
return TRUE;
default:
- UML_DSEXT4(block, IREG(0), CPR032(reg)); // dsext4 i0,cpr0[reg]
+ UML_DSEXT(block, IREG(0), CPR032(reg), DWORD); // dsext i0,cpr0[reg],dword
return TRUE;
}
}
@@ -3131,7 +2779,7 @@ static int generate_cop0(drcuml_block *block, compiler_state *compiler, const op
if (RTREG != 0)
{
generate_get_cop0_reg(block, compiler, desc, RDREG); // <get cop0 reg>
- UML_DSEXT4(block, R64(RTREG), IREG(0)); // dsext4 <rtreg>,i0
+ UML_DSEXT(block, R64(RTREG), IREG(0), DWORD); // dsext <rtreg>,i0,dword
}
return TRUE;
@@ -3145,11 +2793,11 @@ static int generate_cop0(drcuml_block *block, compiler_state *compiler, const op
case 0x02: /* CFCz */
if (RTREG != 0)
- UML_DSEXT4(block, R64(RTREG), CCR032(RDREG)); // dsext4 <rtreg>,ccr0[rdreg]
+ UML_DSEXT(block, R64(RTREG), CCR032(RDREG), DWORD); // dsext <rtreg>,ccr0[rdreg],dword
return TRUE;
case 0x04: /* MTCz */
- UML_DSEXT4(block, IREG(0), R32(RTREG)); // dsext4 i0,<rtreg>
+ UML_DSEXT(block, IREG(0), R32(RTREG), DWORD); // dsext i0,<rtreg>,dword
generate_set_cop0_reg(block, compiler, desc, RDREG); // <set cop0 reg>
return TRUE;
@@ -3159,7 +2807,7 @@ static int generate_cop0(drcuml_block *block, compiler_state *compiler, const op
return TRUE;
case 0x06: /* CTCz */
- UML_DSEXT4(block, CCR064(RDREG), R32(RTREG)); // dsext4 ccr0[rdreg],<rtreg>
+ UML_DSEXT(block, CCR064(RDREG), R32(RTREG), DWORD); // dsext ccr0[rdreg],<rtreg>,dword
return TRUE;
case 0x10:
@@ -3254,7 +2902,7 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
{
case 0x00: /* MFCz - MIPS I */
if (RTREG != 0)
- UML_DSEXT4(block, R64(RTREG), FPR32(RDREG)); // dsext4 <rtreg>,fpr[rdreg]
+ UML_DSEXT(block, R64(RTREG), FPR32(RDREG), DWORD); // dsext <rtreg>,fpr[rdreg],dword
return TRUE;
case 0x01: /* DMFCz - MIPS III */
@@ -3264,7 +2912,7 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
case 0x02: /* CFCz - MIPS I */
if (RTREG != 0)
- UML_DSEXT4(block, R64(RTREG), CCR132(RDREG)); // dsext4 <rtreg>,ccr132[rdreg]
+ UML_DSEXT(block, R64(RTREG), CCR132(RDREG), DWORD); // dsext <rtreg>,ccr132[rdreg],dword
return TRUE;
case 0x04: /* MTCz - MIPS I */
@@ -3277,15 +2925,15 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
case 0x06: /* CTCz - MIPS I */
if (RDREG != 31)
- UML_DSEXT4(block, CCR164(RDREG), R32(RTREG)); // dsext4 ccr1[rdreg],<rtreg>
+ UML_DSEXT(block, CCR164(RDREG), R32(RTREG), DWORD); // dsext ccr1[rdreg],<rtreg>,dword
else
{
UML_XOR(block, IREG(0), CCR132(31), R32(RTREG)); // xor i0,ccr1[31],<rtreg>
- UML_DSEXT4(block, CCR164(31), R32(RTREG)); // dsext4 ccr1[31],<rtreg>
+ UML_DSEXT(block, CCR164(31), R32(RTREG), DWORD); // dsext ccr1[31],<rtreg>,dword
UML_TEST(block, IREG(0), IMM(3)); // test i0,3
UML_JMPc(block, IF_Z, skip = compiler->labelnum++); // jmp skip,Z
UML_AND(block, IREG(0), CCR132(31), IMM(3)); // and i0,ccr1[31],3
- UML_LOAD1U(block, IREG(0), &mips3->impstate->fpmode[0], IREG(0)); // load1u i0,fpmode,i0
+ UML_LOAD(block, IREG(0), &mips3->impstate->fpmode[0], IREG(0), BYTE);// load i0,fpmode,i0,byte
UML_SETFMOD(block, IREG(0)); // setfmod i0
UML_LABEL(block, skip); // skip:
}
@@ -3373,58 +3021,58 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
case 0x08:
if (IS_SINGLE(op)) /* ROUND.L.S - MIPS III */
- UML_FSTOI8R(block, FPR64(FDREG), FPR32(FSREG)); // fstoi8r <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), QWORD, ROUND);// fstoint <fdreg>,<fsreg>,qword,round
else /* ROUND.L.D - MIPS III */
- UML_FDTOI8R(block, FPR64(FDREG), FPR64(FSREG)); // fdtoi8r <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), QWORD, ROUND);// fdtoint <fdreg>,<fsreg>,qword,round
return TRUE;
case 0x09:
if (IS_SINGLE(op)) /* TRUNC.L.S - MIPS III */
- UML_FSTOI8T(block, FPR64(FDREG), FPR32(FSREG)); // fstoi8t <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), QWORD, TRUNC);// fstoint <fdreg>,<fsreg>,qword,trunc
else /* TRUNC.L.D - MIPS III */
- UML_FDTOI8T(block, FPR64(FDREG), FPR64(FSREG)); // fdtoi8t <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), QWORD, TRUNC);// fdtoint <fdreg>,<fsreg>,qword,trunc
return TRUE;
case 0x0a:
if (IS_SINGLE(op)) /* CEIL.L.S - MIPS III */
- UML_FSTOI8C(block, FPR64(FDREG), FPR32(FSREG)); // fstoi8c <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), QWORD, CEIL);// fstoint <fdreg>,<fsreg>,qword,ceil
else /* CEIL.L.D - MIPS III */
- UML_FDTOI8C(block, FPR64(FDREG), FPR64(FSREG)); // fdtoi8c <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), QWORD, CEIL);// fdtoint <fdreg>,<fsreg>,qword,ceil
return TRUE;
case 0x0b:
if (IS_SINGLE(op)) /* FLOOR.L.S - MIPS III */
- UML_FSTOI8F(block, FPR64(FDREG), FPR32(FSREG)); // fstoi8f <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), QWORD, FLOOR);// fstoint <fdreg>,<fsreg>,qword,floor
else /* FLOOR.L.D - MIPS III */
- UML_FDTOI8F(block, FPR64(FDREG), FPR64(FSREG)); // fdtoi8f <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), QWORD, FLOOR);// fdtoint <fdreg>,<fsreg>,qword,floor
return TRUE;
case 0x0c:
if (IS_SINGLE(op)) /* ROUND.W.S - MIPS II */
- UML_FSTOI4R(block, FPR32(FDREG), FPR32(FSREG)); // fstoi4r <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), DWORD, ROUND);// fstoint <fdreg>,<fsreg>,dword,round
else /* ROUND.W.D - MIPS II */
- UML_FDTOI4R(block, FPR32(FDREG), FPR64(FSREG)); // fdtoi4r <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), DWORD, ROUND);// fdtoint <fdreg>,<fsreg>,dword,round
return TRUE;
case 0x0d:
if (IS_SINGLE(op)) /* TRUNC.W.S - MIPS II */
- UML_FSTOI4T(block, FPR32(FDREG), FPR32(FSREG)); // fstoi4t <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), DWORD, TRUNC);// fstoint <fdreg>,<fsreg>,dword,trunc
else /* TRUNC.W.D - MIPS II */
- UML_FDTOI4T(block, FPR32(FDREG), FPR64(FSREG)); // fdtoi4t <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), DWORD, TRUNC);// fdtoint <fdreg>,<fsreg>,dword,trunc
return TRUE;
case 0x0e:
if (IS_SINGLE(op)) /* CEIL.W.S - MIPS II */
- UML_FSTOI4C(block, FPR32(FDREG), FPR32(FSREG)); // fstoi4c <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), DWORD, CEIL);// fstoint <fdreg>,<fsreg>,dword,ceil
else /* CEIL.W.D - MIPS II */
- UML_FDTOI4C(block, FPR32(FDREG), FPR64(FSREG)); // fdtoi4c <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), DWORD, CEIL);// fdtoint <fdreg>,<fsreg>,dword,ceil
return TRUE;
case 0x0f:
if (IS_SINGLE(op)) /* FLOOR.W.S - MIPS II */
- UML_FSTOI4F(block, FPR32(FDREG), FPR32(FSREG)); // fstoi4f <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), DWORD, FLOOR);// fstoint <fdreg>,<fsreg>,dword,floor
else /* FLOOR.W.D - MIPS II */
- UML_FDTOI4F(block, FPR32(FDREG), FPR64(FSREG)); // fdtoi4f <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), DWORD, FLOOR);// fdtoint <fdreg>,<fsreg>,dword,floor
return TRUE;
case 0x11:
@@ -3470,38 +3118,38 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
if (IS_INTEGRAL(op))
{
if (IS_SINGLE(op)) /* CVT.S.W - MIPS I */
- UML_FSFRI4(block, FPR32(FDREG), FPR32(FSREG)); // fsfri4 <fdreg>,<fsreg>
+ UML_FSFRINT(block, FPR32(FDREG), FPR32(FSREG), DWORD); // fsfrint <fdreg>,<fsreg>,dword
else /* CVT.S.L - MIPS I */
- UML_FSFRI8(block, FPR32(FDREG), FPR64(FSREG)); // fsfri8 <fdreg>,<fsreg>
+ UML_FSFRINT(block, FPR32(FDREG), FPR64(FSREG), QWORD); // fsfrint <fdreg>,<fsreg>,qword
}
else /* CVT.S.D - MIPS I */
- UML_FSFRFD(block, FPR32(FDREG), FPR64(FSREG)); // fsfrfd <fdreg>,<fsreg>
+ UML_FSFRFLT(block, FPR32(FDREG), FPR64(FSREG), QWORD); // fsfrflt <fdreg>,<fsreg>,qword
return TRUE;
case 0x21:
if (IS_INTEGRAL(op))
{
if (IS_SINGLE(op)) /* CVT.D.W - MIPS I */
- UML_FDFRI4(block, FPR64(FDREG), FPR32(FSREG)); // fdfri4 <fdreg>,<fsreg>
+ UML_FDFRINT(block, FPR64(FDREG), FPR32(FSREG), DWORD); // fdfrint <fdreg>,<fsreg>,dword
else /* CVT.D.L - MIPS I */
- UML_FDFRI8(block, FPR64(FDREG), FPR64(FSREG)); // fdfri8 <fdreg>,<fsreg>
+ UML_FDFRINT(block, FPR64(FDREG), FPR64(FSREG), QWORD); // fdfrint <fdreg>,<fsreg>,qword
}
else /* CVT.D.S - MIPS I */
- UML_FDFRFS(block, FPR64(FDREG), FPR32(FSREG)); // fdfrfs <fdreg>,<fsreg>
+ UML_FDFRFLT(block, FPR64(FDREG), FPR32(FSREG), DWORD); // fdfrflt <fdreg>,<fsreg>,dword
return TRUE;
case 0x24:
if (IS_SINGLE(op)) /* CVT.W.S - MIPS I */
- UML_FSTOI4(block, FPR32(FDREG), FPR32(FSREG)); // fstoi4 <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR32(FDREG), FPR32(FSREG), DWORD, DEFAULT);// fstoint <fdreg>,<fsreg>,dword,default
else /* CVT.W.D - MIPS I */
- UML_FDTOI4(block, FPR32(FDREG), FPR64(FSREG)); // fdtoi4 <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR32(FDREG), FPR64(FSREG), DWORD, DEFAULT);// fdtoint <fdreg>,<fsreg>,dword,default
return TRUE;
case 0x25:
if (IS_SINGLE(op)) /* CVT.L.S - MIPS I */
- UML_FSTOI8(block, FPR64(FDREG), FPR32(FSREG)); // fstoi8 <fdreg>,<fsreg>
+ UML_FSTOINT(block, FPR64(FDREG), FPR32(FSREG), QWORD, DEFAULT);// fstoint <fdreg>,<fsreg>,qword,default
else /* CVT.L.D - MIPS I */
- UML_FDTOI8(block, FPR64(FDREG), FPR64(FSREG)); // fdtoi8 <fdreg>,<fsreg>
+ UML_FDTOINT(block, FPR64(FDREG), FPR64(FSREG), QWORD, DEFAULT);// fdtoint <fdreg>,<fsreg>,qword,default
return TRUE;
case 0x30:
@@ -3515,8 +3163,9 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
else /* C.UN.D - MIPS I */
UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
- UML_FLAGS(block, CCR132(31), FCCMASK(op >> 8), mips3->impstate->c_un_table);
- // flags ccr31,fccmask[op],c_eq_table
+ UML_SETc(block, IF_U, IREG(0)); // set i0,u
+ UML_ROLINS(block, CCR132(31), IREG(0), IMM(FCCSHIFT(op >> 8)), IMM(FCCMASK(op >> 8)));
+ // rolins ccr31,i0,fccshift,fcc
return TRUE;
case 0x32:
@@ -3525,8 +3174,9 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
else /* C.EQ.D - MIPS I */
UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
- UML_FLAGS(block, CCR132(31), FCCMASK(op >> 8), mips3->impstate->c_eq_table);
- // flags ccr31,fccmask[op],c_eq_table
+ UML_SETc(block, IF_E, IREG(0)); // set i0,e
+ UML_ROLINS(block, CCR132(31), IREG(0), IMM(FCCSHIFT(op >> 8)), IMM(FCCMASK(op >> 8)));
+ // rolins ccr31,i0,fccshift,fcc
return TRUE;
case 0x33:
@@ -3535,8 +3185,11 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
else /* C.UEQ.D - MIPS I */
UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
- UML_FLAGS(block, CCR132(31), FCCMASK(op >> 8), mips3->impstate->c_ueq_table);
- // flags ccr31,fccmask[op],c_eq_table
+ UML_SETc(block, IF_U, IREG(0)); // set i0,u
+ UML_SETc(block, IF_E, IREG(1)); // set i1,e
+ UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
+ UML_ROLINS(block, CCR132(31), IREG(0), IMM(FCCSHIFT(op >> 8)), IMM(FCCMASK(op >> 8)));
+ // rolins ccr31,i0,fccshift,fcc
return TRUE;
case 0x34:
@@ -3545,8 +3198,9 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
else /* C.OLT.D - MIPS I */
UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
- UML_FLAGS(block, CCR132(31), FCCMASK(op >> 8), mips3->impstate->c_olt_table);
- // flags ccr31,fccmask[op],c_lt_table
+ UML_SETc(block, IF_B, IREG(0)); // set i0,b
+ UML_ROLINS(block, CCR132(31), IREG(0), IMM(FCCSHIFT(op >> 8)), IMM(FCCMASK(op >> 8)));
+ // rolins ccr31,i0,fccshift,fcc
return TRUE;
case 0x35:
@@ -3555,8 +3209,11 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
else /* C.ULT.D - MIPS I */
UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
- UML_FLAGS(block, CCR132(31), FCCMASK(op >> 8), mips3->impstate->c_ult_table);
- // flags ccr31,fccmask[op],c_lt_table
+ UML_SETc(block, IF_U, IREG(0)); // set i0,u
+ UML_SETc(block, IF_B, IREG(1)); // set i1,b
+ UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
+ UML_ROLINS(block, CCR132(31), IREG(0), IMM(FCCSHIFT(op >> 8)), IMM(FCCMASK(op >> 8)));
+ // rolins ccr31,i0,fccshift,fcc
return TRUE;
case 0x36:
@@ -3565,8 +3222,9 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
else /* C.OLE.D - MIPS I */
UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
- UML_FLAGS(block, CCR132(31), FCCMASK(op >> 8), mips3->impstate->c_ole_table);
- // flags ccr31,fccmask[op],c_le_table
+ UML_SETc(block, IF_BE, IREG(0)); // set i0,be
+ UML_ROLINS(block, CCR132(31), IREG(0), IMM(FCCSHIFT(op >> 8)), IMM(FCCMASK(op >> 8)));
+ // rolins ccr31,i0,fccshift,fcc
return TRUE;
case 0x37:
@@ -3575,8 +3233,11 @@ static int generate_cop1(drcuml_block *block, compiler_state *compiler, const op
UML_FSCMP(block, FPR32(FSREG), FPR32(FTREG)); // fscmp <fsreg>,<ftreg>
else /* C.ULE.D - MIPS I */
UML_FDCMP(block, FPR64(FSREG), FPR64(FTREG)); // fdcmp <fsreg>,<ftreg>
- UML_FLAGS(block, CCR132(31), FCCMASK(op >> 8), mips3->impstate->c_ule_table);
- // flags ccr31,fccmask[op],c_le_table
+ UML_SETc(block, IF_U, IREG(0)); // set i0,u
+ UML_SETc(block, IF_BE, IREG(1)); // set i1,be
+ UML_OR(block, IREG(0), IREG(0), IREG(1)); // or i0,i0,i1
+ UML_ROLINS(block, CCR132(31), IREG(0), IMM(FCCSHIFT(op >> 8)), IMM(FCCMASK(op >> 8)));
+ // rolins ccr31,i0,fccshift,fcc
return TRUE;
}
break;
diff --git a/src/emu/cpu/powerpc/ppc.c b/src/emu/cpu/powerpc/ppc.c
index b70785941ca..80b4a3087a4 100644
--- a/src/emu/cpu/powerpc/ppc.c
+++ b/src/emu/cpu/powerpc/ppc.c
@@ -4,6 +4,79 @@
#include "ppc.h"
#include "debugger.h"
+// PLL Configuration based on the table in MPC603EUM page 7-31
+static const int mpc603e_pll_config[12][9] =
+{
+ // 16, 20, 25, 33, 40, 50, 60, 66, 75
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, -1, 0x0, -1 },
+ { -1, -1, -1, -1, -1, 0xc, -1, 0xc, -1 },
+ { 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, -1, -1, -1 },
+ { -1, -1, -1, 0x6, 0x6, -1, -1, -1, -1 },
+ { -1, -1, 0x8, 0x8, -1, -1, -1, -1, -1 },
+ { -1, 0xe, 0xe, -1, -1, -1, -1, -1, -1 },
+ { 0xa, 0xa, 0xa, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+};
+
+// PLL Configuration based on the table in MPC603E7VEC page 29
+static const int mpc603ev_pll_config[12][9] =
+{
+ // 16, 20, 25, 33, 40, 50, 60, 66, 75
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ // 2:1
+ { -1, -1, -1, -1, -1, -1, -1, 0x4, 0x4 },
+ // 2.5:1
+ { -1, -1, -1, -1, -1, 0x6, 0x6, 0x6, 0x6 },
+ // 3:1
+ { -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8, 0x8 },
+ // 3.5:1
+ { -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe, -1 },
+ // 4:1
+ { -1, -1, -1, 0xa, 0xa, 0xa, 0xa, -1, -1 },
+ // 4.5:1
+ { -1, -1, -1, 0x7, 0x7, 0x7, -1, -1, -1 },
+ // 5:1
+ { -1, -1, 0xb, 0xb, 0xb, -1, -1, -1, -1 },
+ // 5.5:1
+ { -1, -1, 0x9, 0x9, 0x9, -1, -1, -1, -1 },
+ // 6:1
+ { -1, -1, 0xd, 0xd, 0xd, -1, -1, -1, -1 }
+};
+
+// PLL Configuration based on the table in MPC603E7TEC page 23
+static const int mpc603r_pll_config[12][9] =
+{
+ // 16, 20, 25, 33, 40, 50, 60, 66, 75
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
+ // 2:1
+ { -1, -1, -1, -1, 0x5, 0x5, 0x5, 0x5, 0x5 },
+ // 2.5:1
+ { -1, -1, -1, -1, -1, -1, 0x6, 0x6, 0x6 },
+ // 3:1
+ { -1, -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8 },
+ // 3.5:1
+ { -1, -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe },
+ // 4:1
+ { -1, -1, -1, -1, 0xa, 0xa, 0xa, 0xa, 0xa },
+ // 4.5:1
+ { -1, -1, -1, 0x7, 0x7, 0x7, 0x7, 0x7, -1 },
+ // 5:1
+ { -1, -1, -1, 0xb, 0xb, 0xb, 0xb, -1, -1 },
+ // 5.5:1
+ { -1, -1, -1, 0x9, 0x9, 0x9, -1, -1, -1 },
+ // 6:1
+ { -1, -1, 0xd, 0xd, 0xd, 0xd, -1, -1, -1 },
+};
+
+
#if (HAS_PPC603 || HAS_PPC601 || HAS_PPC604)
static void ppc603_exception(int exception);
#endif
diff --git a/src/emu/cpu/powerpc/ppc.h b/src/emu/cpu/powerpc/ppc.h
index ac00204fd2f..161ac2dbd92 100644
--- a/src/emu/cpu/powerpc/ppc.h
+++ b/src/emu/cpu/powerpc/ppc.h
@@ -1,164 +1,24 @@
-#ifndef _PPC_H
-#define _PPC_H
+/***************************************************************************
+
+ ppc.h
+ Interface file for the portable MIPS III/IV emulator.
+ Written by Aaron Giles
+
+***************************************************************************/
+
+#ifndef __PPC_H__
+#define __PPC_H__
#include "cpuintrf.h"
-#define SPR_XER 1 /* Fixed Point Exception Register Read / Write */
-#define SPR_LR 8 /* Link Register Read / Write */
-#define SPR_CTR 9 /* Count Register Read / Write */
-#define SPR_SRR0 26 /* Save/Restore Register 0 Read / Write */
-#define SPR_SRR1 27 /* Save/Restore Register 1 Read / Write */
-#define SPR_SPRG0 272 /* SPR General 0 Read / Write */
-#define SPR_SPRG1 273 /* SPR General 1 Read / Write */
-#define SPR_SPRG2 274 /* SPR General 2 Read / Write */
-#define SPR_SPRG3 275 /* SPR General 3 Read / Write */
-#define SPR_PVR 287 /* Processor Version Number Read Only */
-
-#define SPR403_ICDBDR 0x3D3 /* 406GA Instruction Cache Debug Data Register Rad Only */
-#define SPR403_ESR 0x3D4 /* 406GA Exception Syndrome Register Read / Write */
-#define SPR403_DEAR 0x3D5 /* 406GA Data Exception Address Register Read Only */
-#define SPR403_EVPR 0x3D6 /* 406GA Exception Vector Prefix Register Read / Write */
-#define SPR403_CDBCR 0x3D7 /* 406GA Cache Debug Control Register Read/Write */
-#define SPR403_TSR 0x3D8 /* 406GA Timer Status Register Read / Clear */
-#define SPR403_TCR 0x3DA /* 406GA Timer Control Register Read / Write */
-#define SPR403_PIT 0x3DB /* 406GA Programmable Interval Timer Read / Write */
-#define SPR403_TBHI 988 /* 406GA Time Base High Read / Write */
-#define SPR403_TBLO 989 /* 406GA Time Base Low Read / Write */
-#define SPR403_SRR2 0x3DE /* 406GA Save/Restore Register 2 Read / Write */
-#define SPR403_SRR3 0x3DF /* 406GA Save/Restore Register 3 Read / Write */
-#define SPR403_DBSR 0x3F0 /* 406GA Debug Status Register Read / Clear */
-#define SPR403_DBCR 0x3F2 /* 406GA Debug Control Register Read / Write */
-#define SPR403_IAC1 0x3F4 /* 406GA Instruction Address Compare 1 Read / Write */
-#define SPR403_IAC2 0x3F5 /* 406GA Instruction Address Compare 2 Read / Write */
-#define SPR403_DAC1 0x3F6 /* 406GA Data Address Compare 1 Read / Write */
-#define SPR403_DAC2 0x3F7 /* 406GA Data Address Compare 2 Read / Write */
-#define SPR403_DCCR 0x3FA /* 406GA Data Cache Cacheability Register Read / Write */
-#define SPR403_ICCR 0x3FB /* 406GA I Cache Cacheability Registe Read / Write */
-#define SPR403_PBL1 0x3FC /* 406GA Protection Bound Lower 1 Read / Write */
-#define SPR403_PBU1 0x3FD /* 406GA Protection Bound Upper 1 Read / Write */
-#define SPR403_PBL2 0x3FE /* 406GA Protection Bound Lower 2 Read / Write */
-#define SPR403_PBU2 0x3FF /* 406GA Protection Bound Upper 2 Read / Write */
-
-#define SPR403_SGR 0x3b9 /* 403GCX Storage Guarded Register */
-#define SPR403_DCWR 0x3ba /* 403GCX Data Cache Write Through */
-#define SPR403_PID 0x3b1 /* 403GCX Process ID */
-#define SPR403_TBHU 0x3cc /* 403GCX Time Base High User-mode */
-#define SPR403_TBLU 0x3cd /* 403GCX Time Base Low User-mode */
-
-#define SPR603E_DSISR 18 /* 603E */
-#define SPR603E_DAR 19 /* 603E */
-#define SPR603E_DEC 22 /* 603E */
-#define SPR603E_SDR1 25 /* 603E */
-#define SPR603E_TBL_R 268 /* 603E Time Base Low (Read-only) */
-#define SPR603E_TBU_R 269 /* 603E Time Base High (Read-only) */
-#define SPR603E_TBL_W 284 /* 603E Time Base Low (Write-only) */
-#define SPR603E_TBU_W 285 /* 603E Time Base Hight (Write-only) */
-#define SPR603E_EAR 282 /* 603E */
-#define SPR603E_IBAT0U 528 /* 603E */
-#define SPR603E_IBAT0L 529 /* 603E */
-#define SPR603E_IBAT1U 530 /* 603E */
-#define SPR603E_IBAT1L 531 /* 603E */
-#define SPR603E_IBAT2U 532 /* 603E */
-#define SPR603E_IBAT2L 533 /* 603E */
-#define SPR603E_IBAT3U 534 /* 603E */
-#define SPR603E_IBAT3L 535 /* 603E */
-#define SPR603E_DBAT0U 536 /* 603E */
-#define SPR603E_DBAT0L 537 /* 603E */
-#define SPR603E_DBAT1U 538 /* 603E */
-#define SPR603E_DBAT1L 539 /* 603E */
-#define SPR603E_DBAT2U 540 /* 603E */
-#define SPR603E_DBAT2L 541 /* 603E */
-#define SPR603E_DBAT3U 542 /* 603E */
-#define SPR603E_DBAT3L 543 /* 603E */
-#define SPR603E_DABR 1013 /* 603E */
-#define SPR603E_DMISS 0x3d0 /* 603E */
-#define SPR603E_DCMP 0x3d1 /* 603E */
-#define SPR603E_HASH1 0x3d2 /* 603E */
-#define SPR603E_HASH2 0x3d3 /* 603E */
-#define SPR603E_IMISS 0x3d4 /* 603E */
-#define SPR603E_ICMP 0x3d5 /* 603E */
-#define SPR603E_RPA 0x3d6 /* 603E */
-#define SPR603E_HID0 1008 /* 603E */
-#define SPR603E_HID1 1009 /* 603E */
-#define SPR603E_IABR 1010 /* 603E */
-#define SPR603E_HID2 1011 /* 603E */
-
-#define SPR602_TCR 984 /* 602 */
-#define SPR602_IBR 986 /* 602 */
-#define SPR602_ESASRR 987 /* 602 */
-#define SPR602_SEBR 990 /* 602 */
-#define SPR602_SER 991 /* 602 */
-#define SPR602_SP 1021 /* 602 */
-#define SPR602_LT 1022 /* 602 */
-
-
-#define DCR_BEAR 0x90 /* bus error address */
-#define DCR_BESR 0x91 /* bus error syndrome */
-#define DCR_BR0 0x80 /* bank */
-#define DCR_BR1 0x81 /* bank */
-#define DCR_BR2 0x82 /* bank */
-#define DCR_BR3 0x83 /* bank */
-#define DCR_BR4 0x84 /* bank */
-#define DCR_BR5 0x85 /* bank */
-#define DCR_BR6 0x86 /* bank */
-#define DCR_BR7 0x87 /* bank */
-#define DCR_DMACC0 0xc4 /* dma chained count */
-#define DCR_DMACC1 0xcc /* dma chained count */
-#define DCR_DMACC2 0xd4 /* dma chained count */
-#define DCR_DMACC3 0xdc /* dma chained count */
-#define DCR_DMACR0 0xc0 /* dma channel control */
-#define DCR_DMACR1 0xc8 /* dma channel control */
-#define DCR_DMACR2 0xd0 /* dma channel control */
-#define DCR_DMACR3 0xd8 /* dma channel control */
-#define DCR_DMACT0 0xc1 /* dma destination address */
-#define DCR_DMACT1 0xc9 /* dma destination address */
-#define DCR_DMACT2 0xd1 /* dma destination address */
-#define DCR_DMACT3 0xd9 /* dma destination address */
-#define DCR_DMADA0 0xc2 /* dma destination address */
-#define DCR_DMADA1 0xca /* dma destination address */
-#define DCR_DMADA2 0xd2 /* dma source address */
-#define DCR_DMADA3 0xda /* dma source address */
-#define DCR_DMASA0 0xc3 /* dma source address */
-#define DCR_DMASA1 0xcb /* dma source address */
-#define DCR_DMASA2 0xd3 /* dma source address */
-#define DCR_DMASA3 0xdb /* dma source address */
-#define DCR_DMASR 0xe0 /* dma status */
-#define DCR_EXIER 0x42 /* external interrupt enable */
-#define DCR_EXISR 0x40 /* external interrupt status */
-#define DCR_IOCR 0xa0 /* io configuration */
-
-enum {
- EXCEPTION_IRQ = 1,
- EXCEPTION_DECREMENTER = 2,
- EXCEPTION_TRAP = 3,
- EXCEPTION_SYSTEM_CALL = 4,
- EXCEPTION_SMI = 5,
- EXCEPTION_DSI = 6,
- EXCEPTION_ISI = 7,
- EXCEPTION_PROGRAMMABLE_INTERVAL_TIMER = 20,
- EXCEPTION_FIXED_INTERVAL_TIMER = 21,
- EXCEPTION_WATCHDOG_TIMER = 22,
- EXCEPTION_CRITICAL_INTERRUPT = 23,
-};
-enum {
- PPC_INPUT_LINE_SMI = 10,
- PPC_INPUT_LINE_TLBISYNC
-};
+/***************************************************************************
+ REGISTER ENUMERATION
+***************************************************************************/
-enum {
- PPC_PC=1,
- PPC_MSR,
- PPC_CR,
- PPC_LR,
- PPC_CTR,
- PPC_XER,
- PPC_DEC,
- PPC_SRR0,
- PPC_SRR1,
- PPC_EXIER,
- PPC_EXISR,
- PPC_IBR,
+enum
+{
+ PPC_PC = 1,
PPC_R0,
PPC_R1,
PPC_R2,
@@ -190,158 +50,95 @@ enum {
PPC_R28,
PPC_R29,
PPC_R30,
- PPC_R31
+ PPC_R31,
+ PPC_CR,
+ PPC_LR,
+ PPC_CTR,
+ PPC_XER,
+ PPC_MSR,
+ PPC_SRR0,
+ PPC_SRR1,
+ PPC_SPRG0,
+ PPC_SPRG1,
+ PPC_SPRG2,
+ PPC_SPRG3,
+ PPC_SDR1,
+ PPC_EXIER,
+ PPC_EXISR,
+ PPC_EVPR,
+ PPC_IOCR
};
-typedef enum {
- PPC_MODEL_403GA = 0x00200000,
- PPC_MODEL_403GB = 0x00200100,
- PPC_MODEL_403GC = 0x00200200,
- PPC_MODEL_403GCX = 0x00201400,
- PPC_MODEL_405GP = 0x40110000,
- PPC_MODEL_601 = 0x00010000,
- PPC_MODEL_603 = 0x00030000, /* "Wart" */
- PPC_MODEL_604 = 0x00040000, /* "Zephyr" */
- PPC_MODEL_602 = 0x00050200, /* "Galahad" */
- PPC_MODEL_603E = 0x00060103, /* "Stretch", version 1.3 */
- PPC_MODEL_603EV = 0x00070000, /* "Valiant" */
- PPC_MODEL_603R = 0x00071202, /* "Goldeneye", version 2.1 */
- PPC_MODEL_740 = 0x00080301, /* "Arthur", version 3.1 */
- PPC_MODEL_750 = PPC_MODEL_740,
- PPC_MODEL_740P = 0x00080202, /* "Conan Doyle", version 1.2 */
- PPC_MODEL_750P = PPC_MODEL_740P,
- PPC_MODEL_755 = 0x00083203, /* "Goldfinger", version 2.3 */
- PPC_MODEL_7400 = 0x000c0209, /* "Max", version 2.9 */
- PPC_MODEL_7410 = 0x800c1104, /* "Nitro", version 3.4 */
- PPC_MODEL_7450 = 0x80000201, /* "Vger", version 2.1 */
- PPC_MODEL_7451 = 0x80000203, /* "Vger", version 2.3 */
- PPC_MODEL_7441 = PPC_MODEL_7451,
- PPC_MODEL_7455 = 0x80010303, /* "Apollo 6", version 3.3 */
- PPC_MODEL_7445 = PPC_MODEL_7455,
- PPC_MODEL_7457 = 0x80020101, /* "Apollo 7", version 1.1 */
- PPC_MODEL_MPC8240 = 0x00810101, /* "Kahlua" */
- PPC_MODEL_MPC8241 = 0x80811014, /* "Kahlua Lt" */
- PPC_MODEL_MPC8245 = 0x80811014, /* "Kahlua II" */
-} PPC_MODEL;
-
-typedef enum {
- BUS_FREQUENCY_16MHZ = 0,
- BUS_FREQUENCY_20MHZ,
- BUS_FREQUENCY_25MHZ,
- BUS_FREQUENCY_33MHZ,
- BUS_FREQUENCY_40MHZ,
- BUS_FREQUENCY_50MHZ,
- BUS_FREQUENCY_60MHZ,
- BUS_FREQUENCY_66MHZ,
- BUS_FREQUENCY_75MHZ,
-} PPC_BUS_FREQUENCY;
-
-// PLL Configuration based on the table in MPC603EUM page 7-31
-static const int mpc603e_pll_config[12][9] =
-{
- // 16, 20, 25, 33, 40, 50, 60, 66, 75
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, -1, 0x0, -1 },
- { -1, -1, -1, -1, -1, 0xc, -1, 0xc, -1 },
- { 0x5, 0x5, 0x5, 0x4, 0x4, 0x4, -1, -1, -1 },
- { -1, -1, -1, 0x6, 0x6, -1, -1, -1, -1 },
- { -1, -1, 0x8, 0x8, -1, -1, -1, -1, -1 },
- { -1, 0xe, 0xe, -1, -1, -1, -1, -1, -1 },
- { 0xa, 0xa, 0xa, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
-};
-// PLL Configuration based on the table in MPC603E7VEC page 29
-static const int mpc603ev_pll_config[12][9] =
-{
- // 16, 20, 25, 33, 40, 50, 60, 66, 75
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- // 2:1
- { -1, -1, -1, -1, -1, -1, -1, 0x4, 0x4 },
- // 2.5:1
- { -1, -1, -1, -1, -1, 0x6, 0x6, 0x6, 0x6 },
- // 3:1
- { -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8, 0x8 },
- // 3.5:1
- { -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe, -1 },
- // 4:1
- { -1, -1, -1, 0xa, 0xa, 0xa, 0xa, -1, -1 },
- // 4.5:1
- { -1, -1, -1, 0x7, 0x7, 0x7, -1, -1, -1 },
- // 5:1
- { -1, -1, 0xb, 0xb, 0xb, -1, -1, -1, -1 },
- // 5.5:1
- { -1, -1, 0x9, 0x9, 0x9, -1, -1, -1, -1 },
- // 6:1
- { -1, -1, 0xd, 0xd, 0xd, -1, -1, -1, -1 }
-};
+#define PPC_MAX_FASTRAM 4
+#define PPC_MAX_HOTSPOTS 16
+
-// PLL Configuration based on the table in MPC603E7TEC page 23
-static const int mpc603r_pll_config[12][9] =
+enum
{
- // 16, 20, 25, 33, 40, 50, 60, 66, 75
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- { -1, -1, -1, -1, -1, -1, -1, -1, -1 },
- // 2:1
- { -1, -1, -1, -1, 0x5, 0x5, 0x5, 0x5, 0x5 },
- // 2.5:1
- { -1, -1, -1, -1, -1, -1, 0x6, 0x6, 0x6 },
- // 3:1
- { -1, -1, -1, -1, -1, 0x8, 0x8, 0x8, 0x8 },
- // 3.5:1
- { -1, -1, -1, -1, -1, 0xe, 0xe, 0xe, 0xe },
- // 4:1
- { -1, -1, -1, -1, 0xa, 0xa, 0xa, 0xa, 0xa },
- // 4.5:1
- { -1, -1, -1, 0x7, 0x7, 0x7, 0x7, 0x7, -1 },
- // 5:1
- { -1, -1, -1, 0xb, 0xb, 0xb, 0xb, -1, -1 },
- // 5.5:1
- { -1, -1, -1, 0x9, 0x9, 0x9, -1, -1, -1 },
- // 6:1
- { -1, -1, 0xd, 0xd, 0xd, 0xd, -1, -1, -1 },
+ CPUINFO_INT_PPC_DRC_OPTIONS = CPUINFO_INT_CPU_SPECIFIC,
+
+ CPUINFO_INT_PPC_FASTRAM_SELECT,
+ CPUINFO_INT_PPC_FASTRAM_START,
+ CPUINFO_INT_PPC_FASTRAM_END,
+ CPUINFO_INT_PPC_FASTRAM_READONLY,
+
+ CPUINFO_INT_PPC_HOTSPOT_SELECT,
+ CPUINFO_INT_PPC_HOTSPOT_PC,
+ CPUINFO_INT_PPC_HOTSPOT_OPCODE,
+ CPUINFO_INT_PPC_HOTSPOT_CYCLES,
+
+ CPUINFO_INT_PPC_RX_DATA,
+
+ CPUINFO_PTR_PPC_FASTRAM_BASE = CPUINFO_PTR_CPU_SPECIFIC,
+
+ CPUINFO_PTR_SPU_RX_HANDLER,
+ CPUINFO_PTR_SPU_TX_HANDLER,
+
+ CPUINFO_PTR_CONTEXT /* temporary */
};
-#define PPCDRC_OPTIONS_CHECK_SELFMOD_CODE 0x1
-enum
+
+/***************************************************************************
+ INTERRUPT CONSTANTS
+***************************************************************************/
+
+#define PPC_IRQ 0 /* external IRQ */
+#define PPC_IRQ_LINE_0 0 /* (4XX) external IRQ0 */
+#define PPC_IRQ_LINE_1 1 /* (4XX) external IRQ1 */
+#define PPC_IRQ_LINE_2 2 /* (4XX) external IRQ2 */
+#define PPC_IRQ_LINE_3 3 /* (4XX) external IRQ3 */
+#define PPC_IRQ_LINE_4 4 /* (4XX) external IRQ4 */
+
+
+
+/***************************************************************************
+ STRUCTURES
+***************************************************************************/
+
+typedef struct _powerpc_config powerpc_config;
+struct _powerpc_config
{
- CPUINFO_INT_PPC_DRC_OPTIONS = CPUINFO_INT_CPU_SPECIFIC,
+ UINT32 bus_frequency;
};
-typedef struct {
- PPC_MODEL pvr;
- int bus_frequency_multiplier;
- PPC_BUS_FREQUENCY bus_frequency;
-} ppc_config;
-
-#if (HAS_PPC403)
-typedef UINT8 (* SPU_RX_HANDLER)(void);
-typedef void (* SPU_TX_HANDLER)(UINT8);
-typedef void (* PPC_DMA_HANDLER)(int);
-
-void ppc403_spu_rx(UINT8 data);
-void ppc403_install_spu_rx_handler(SPU_RX_HANDLER rx_handler);
-void ppc403_install_spu_tx_handler(SPU_TX_HANDLER tx_handler);
-void ppc403_install_spu_rx_dma_handler(PPC_DMA_HANDLER rx_dma_handler, UINT8 *buffer);
-void ppc403_install_spu_tx_dma_handler(PPC_DMA_HANDLER tx_dma_handler, UINT8 *buffer);
-void ppc403_install_dma_read_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer);
-void ppc403_install_dma_write_handler(int ch, PPC_DMA_HANDLER dma_handler, UINT8 *buffer);
-
-#define PPC403_SPU_RX 5
-#define PPC403_SPU_TX 6
-#define PPC403_CRITICAL_IRQ 7
+
+/***************************************************************************
+ PUBLIC FUNCTIONS
+***************************************************************************/
+
+#if (HAS_PPC403GA)
+void ppc403ga_get_info(UINT32 state, cpuinfo *info);
#endif
-#if (HAS_PPC403)
-void ppc403_get_info(UINT32 state, cpuinfo *info);
+#if (HAS_PPC403GCX)
+void ppc403gcx_get_info(UINT32 state, cpuinfo *info);
+#endif
+
+#if (HAS_PPC601)
+void ppc601_get_info(UINT32 state, cpuinfo *info);
#endif
#if (HAS_PPC602)
@@ -352,20 +149,32 @@ void ppc602_get_info(UINT32 state, cpuinfo *info);
void ppc603_get_info(UINT32 state, cpuinfo *info);
#endif
-#if (HAS_MPC8240)
-void mpc8240_get_info(UINT32 state, cpuinfo *info);
+#if (HAS_PPC603E)
+void ppc603e_get_info(UINT32 state, cpuinfo *info);
#endif
-#if (HAS_PPC601)
-void ppc601_get_info(UINT32 state, cpuinfo *info);
+#if (HAS_PPC603R)
+void ppc603r_get_info(UINT32 state, cpuinfo *info);
#endif
#if (HAS_PPC604)
void ppc604_get_info(UINT32 state, cpuinfo *info);
#endif
-#ifdef ENABLE_DEBUGGER
-extern offs_t ppc_dasm_one(char *buffer, offs_t pc, UINT32 op);
+#if (HAS_MPC8240)
+void mpc8240_get_info(UINT32 state, cpuinfo *info);
#endif
-#endif /* _PPC_H */
+
+
+/***************************************************************************
+ COMPILER-SPECIFIC OPTIONS
+***************************************************************************/
+
+#define PPCDRC_STRICT_VERIFY 0x0001 /* verify all instructions */
+#define PPCDRC_FLUSH_PC 0x0002 /* flush the PC value before each memory access */
+
+#define PPCDRC_COMPATIBLE_OPTIONS (PPCDRC_STRICT_VERIFY | PPCDRC_FLUSH_PC)
+#define PPCDRC_FASTEST_OPTIONS (0)
+
+#endif /* __PPC_H__ */
diff --git a/src/emu/cpu/powerpc/ppc403.c b/src/emu/cpu/powerpc/ppc403.c
index 5bfaac3dd90..85183e65b94 100644
--- a/src/emu/cpu/powerpc/ppc403.c
+++ b/src/emu/cpu/powerpc/ppc403.c
@@ -434,7 +434,7 @@ static void ppc403_set_irq_line(int irqline, int state)
ppc.exisr &= ~mask;
}
}
- else if (irqline == PPC403_SPU_RX)
+ else if (irqline == PPC_IRQ_SPU_RX)
{
UINT32 mask = 0x08000000;
if (state) {
@@ -444,7 +444,7 @@ static void ppc403_set_irq_line(int irqline, int state)
}
}
}
- else if (irqline == PPC403_SPU_TX)
+ else if (irqline == PPC_IRQ_SPU_TX)
{
UINT32 mask = 0x04000000;
if (state) {
@@ -454,7 +454,7 @@ static void ppc403_set_irq_line(int irqline, int state)
}
}
}
- else if (irqline == PPC403_CRITICAL_IRQ)
+ else if (irqline == PPC_IRQ_CRITICAL)
{
if (state) {
if (EXIER & 0x80000000) {
@@ -661,9 +661,9 @@ static void ppc403_spu_w(UINT32 a, UINT8 d)
ppc.spu.spls = 0x80;
#ifndef PPC_DRC
- ppc403_set_irq_line(PPC403_SPU_RX, ASSERT_LINE);
+ ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
#else
- ppcdrc403_set_irq_line(PPC403_SPU_RX, ASSERT_LINE);
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
#endif
}
}
@@ -698,9 +698,9 @@ void ppc403_spu_rx(UINT8 data)
/* generate interrupt if DMA is disabled and RBR interrupt is enabled */
if (((ppc.spu.sprc >> 5) & 0x3) == 0x01) {
#ifndef PPC_DRC
- ppc403_set_irq_line(PPC403_SPU_RX, ASSERT_LINE);
+ ppc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
#else
- ppcdrc403_set_irq_line(PPC403_SPU_RX, ASSERT_LINE);
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_RX, ASSERT_LINE);
#endif
}
}
@@ -722,9 +722,9 @@ static TIMER_CALLBACK( ppc403_spu_tx_callback )
/* generate interrupt if DMA is disabled and TBR interrupt is enabled */
if (((ppc.spu.sptc >> 5) & 0x3) == 0x01) {
#ifndef PPC_DRC
- ppc403_set_irq_line(PPC403_SPU_TX, ASSERT_LINE);
+ ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
#else
- ppcdrc403_set_irq_line(PPC403_SPU_TX, ASSERT_LINE);
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
#endif
}
}
@@ -826,9 +826,9 @@ static void ppc403_dma_exec(int ch)
}
#ifndef PPC_DRC
- ppc403_set_irq_line(PPC403_SPU_TX, ASSERT_LINE);
+ ppc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
#else
- ppcdrc403_set_irq_line(PPC403_SPU_TX, ASSERT_LINE);
+ ppcdrc403_set_irq_line(PPC_IRQ_SPU_TX, ASSERT_LINE);
#endif
}
else {
diff --git a/src/emu/cpu/powerpc/ppc_dasm.c b/src/emu/cpu/powerpc/ppc_dasm.c
index 2f24713bab8..ae81392f268 100644
--- a/src/emu/cpu/powerpc/ppc_dasm.c
+++ b/src/emu/cpu/powerpc/ppc_dasm.c
@@ -15,96 +15,7 @@
#include "cpuintrf.h"
#include "debugger.h"
-
-/*
- * Masks
- *
- * These masks isolate fields in an instruction word.
- */
-
-#define M_LI 0x03fffffc
-#define M_AA 0x00000002
-#define M_LK 0x00000001
-#define M_BO 0x03e00000
-#define M_BI 0x001f0000
-#define M_BD 0x0000fffc
-#define M_RT 0x03e00000
-#define M_RA 0x001f0000
-#define M_RB 0x0000f800
-#define M_CRFD 0x03800000
-#define M_L 0x00200000
-#define M_TO 0x03e00000
-#define M_D 0x0000ffff
-#define M_SIMM 0x0000ffff
-#define M_UIMM 0x0000ffff
-#define M_NB 0x0000f800
-#define M_SR 0x000f0000
-#define M_SH 0x0000f800
-#define M_CRFS 0x001c0000
-#define M_IMM 0x0000f000
-#define M_CRBD 0x03e00000
-#define M_RC 0x00000001
-#define M_CRBA 0x001f0000
-#define M_CRBB 0x0000f800
-#define M_SPR 0x001FF800
-#define M_TBR 0x001FF800
-#define M_CRM 0x000FF000
-#define M_DCR 0x001FF800
-#define M_FM 0x01FE0000
-#define M_OE 0x00000400
-#define M_REGC 0x000007c0
-#define M_MB 0x000007c0
-#define M_ME 0x0000003e
-#define M_XO 0x000007fe
-
-/*
- * Field Defining Macros
- *
- * These macros generate instruction words with their associated fields filled
- * in with the passed value.
- */
-
-#define D_OP(op) ((op & 0x3f) << 26)
-#define D_XO(xo) ((xo & 0x3ff) << 1)
-#define D_RT(r) ((r & 0x1f) << (31 - 10))
-#define D_RA(r) ((r & 0x1f) << (31 - 15))
-#define D_UIMM(u) (u & 0xffff)
-
-/*
- * Macros to Get Field Values
- *
- * These macros return the values of fields in an opcode. They all return
- * unsigned values and do not perform any sign extensions.
- */
-
-#define G_RT(op) ((op & M_RT) >> (31 - 10))
-#define G_RA(op) ((op & M_RA) >> (31 - 15))
-#define G_RB(op) ((op & M_RB) >> (31 - 20))
-#define G_SIMM(op) (op & M_SIMM)
-#define G_UIMM(op) (op & M_UIMM)
-#define G_LI(op) ((op & M_LI) >> 2)
-#define G_BO(op) ((op & M_BO) >> (31 - 10))
-#define G_BI(op) ((op & M_BI) >> (31 - 15))
-#define G_BD(op) ((op & M_BD) >> 2)
-#define G_CRFD(op) ((op & M_CRFD) >> (31 - 8))
-#define G_L(op) ((op & M_L) >> (31 - 10))
-#define G_CRBD(op) ((op & M_CRBD) >> (31 - 10))
-#define G_CRBA(op) ((op & M_CRBA) >> (31 - 15))
-#define G_CRBB(op) ((op & M_CRBB) >> (31 - 20))
-#define G_REGC(op) ((op & M_REGC) >> (31 - 25))
-#define G_D(op) (op & M_D)
-#define G_NB(op) ((op & M_NB) >> (31 - 20))
-#define G_CRFS(op) ((op & M_CRFS) >> (31 - 13))
-#define G_SPR(op) ((op & M_SPR) >> (31 - 20))
-#define G_DCR(op) ((op & M_DCR) >> (31 - 20))
-#define G_SR(op) ((op & M_SR) >> (31 - 15))
-#define G_CRM(op) ((op & M_CRM) >> (31 - 19))
-#define G_FM(op) ((op & M_FM) >> (31 - 14))
-#define G_IMM(op) ((op & M_IMM) >> (31 - 19))
-#define G_SH(op) ((op & M_SH) >> (31 - 20))
-#define G_MB(op) ((op & M_MB) >> (31 - 25))
-#define G_ME(op) ((op & M_ME) >> 1)
-#define G_TO(op) ((op & M_TO) >> (31 - 10))
+#include "ppccom.h"
/*
* Operand Formats
@@ -227,10 +138,14 @@ static const IDESCR itab[] =
{ "bc", D_OP(16), M_BO|M_BI|M_BD|M_AA|M_LK, F_BCx, FL_AA|FL_LK },
{ "bcctr", D_OP(19)|D_XO(528), M_BO|M_BI|M_LK, F_BO_BI, FL_LK },
{ "bclr", D_OP(19)|D_XO(16), M_BO|M_BI|M_LK, F_BO_BI, FL_LK|FL_SO },
- { "cmp", D_OP(31)|D_XO(0), M_CRFD|M_L|M_RA|M_RB, F_CMP, 0 },
- { "cmpi", D_OP(11), M_CRFD|M_L|M_RA|M_SIMM, F_CMP_SIMM, 0 },
- { "cmpl", D_OP(31)|D_XO(32), M_CRFD|M_L|M_RA|M_RB, F_CMP, 0 },
- { "cmpli", D_OP(10), M_CRFD|M_L|M_RA|M_UIMM, F_CMP_UIMM, 0 },
+ { "cmp", D_OP(31)|D_XO(0), M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpd", D_OP(31)|D_XO(0)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpi", D_OP(11), M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0 },
+ { "cmpdi", D_OP(11)|M_L, M_CRFD|M_RA|M_SIMM, F_CMP_SIMM, 0 },
+ { "cmpl", D_OP(31)|D_XO(32), M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpld", D_OP(31)|D_XO(32)|M_L,M_CRFD|M_RA|M_RB, F_CMP, 0 },
+ { "cmpli", D_OP(10), M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0 },
+ { "cmpldi", D_OP(10)|M_L, M_CRFD|M_RA|M_UIMM, F_CMP_UIMM, 0 },
{ "cntlzw", D_OP(31)|D_XO(26), M_RT|M_RA|M_RC, F_RA_RT, FL_RC },
{ "crand", D_OP(19)|D_XO(257), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
{ "crandc", D_OP(19)|D_XO(129), M_CRBD|M_CRBA|M_CRBB, F_CRBD_CRBA_CRBB, 0 },
@@ -424,6 +339,7 @@ static const IDESCR itab[] =
*/
static const char *const crbit[4] = { "lt", "gt", "eq", "so" };
+static const char *const crnbit[4] = { "ge", "le", "ne", "nso" };
/*
@@ -450,61 +366,88 @@ static void SPR(char *dest, int spr_field)
switch (spr)
{
- case 1: strcat(dest, "xer"); break;
- case 8: strcat(dest, "lr"); break;
- case 9: strcat(dest, "ctr"); break;
- case 18: strcat(dest, "dsisr"); break;
- case 19: strcat(dest, "dar"); break;
- case 22: strcat(dest, "dec"); break;
- case 25: strcat(dest, "sdr1"); break;
- case 26: strcat(dest, "srr0"); break;
- case 27: strcat(dest, "srr1"); break;
- case 272: strcat(dest, "sprg0"); break;
- case 273: strcat(dest, "sprg1"); break;
- case 274: strcat(dest, "sprg2"); break;
- case 275: strcat(dest, "sprg3"); break;
- case 282: strcat(dest, "ear"); break;
- case 287: strcat(dest, "pvr"); break;
- case 528: strcat(dest, "ibat0u"); break;
- case 529: strcat(dest, "ibat0l"); break;
- case 530: strcat(dest, "ibat1u"); break;
- case 531: strcat(dest, "ibat1l"); break;
- case 532: strcat(dest, "ibat2u"); break;
- case 533: strcat(dest, "ibat2l"); break;
- case 534: strcat(dest, "ibat3u"); break;
- case 535: strcat(dest, "ibat3l"); break;
- case 536: strcat(dest, "dbat0u"); break;
- case 537: strcat(dest, "dbat0l"); break;
- case 538: strcat(dest, "dbat1u"); break;
- case 539: strcat(dest, "dbat1l"); break;
- case 540: strcat(dest, "dbat2u"); break;
- case 541: strcat(dest, "dbat2l"); break;
- case 542: strcat(dest, "dbat3u"); break;
- case 543: strcat(dest, "dbat3l"); break;
- case 1013: strcat(dest, "dabr"); break; // unsupported on 603e/EC603e
-
- /*
- * Some PowerPC implementations may implement MFTB and MFSPR identically,
- * therefore TBR registers are also decoded here
- */
-
- case 268: strcat(dest, "tbl"); break;
- case 269: strcat(dest, "tbu"); break;
-
- /*
- * PowerPC 603e/EC603e-specific registers
- */
-
- case 1008: strcat(dest, "hid0"); break;
- case 1009: strcat(dest, "hid1"); break;
- case 976: strcat(dest, "dmiss"); break;
- case 977: strcat(dest, "dcmp"); break;
- case 978: strcat(dest, "hash2"); break;
- case 979: strcat(dest, "hash2"); break;
- case 980: strcat(dest, "imiss"); break;
- case 981: strcat(dest, "icmp"); break;
- case 982: strcat(dest, "rpa"); break;
- case 1010: strcat(dest, "iabr"); break;
+ /* UISA SPR register indexes */
+ case SPR_XER: strcat(dest, "xer"); break;
+ case SPR_LR: strcat(dest, "lr"); break;
+ case SPR_CTR: strcat(dest, "ctr"); break;
+
+ /* VEA SPR register indexes */
+ case SPRVEA_TBL_R: strcat(dest, "tbl"); break;
+ case SPRVEA_TBU_R: strcat(dest, "tbu"); break;
+
+ /* OEA SPR register indexes */
+ case SPROEA_DSISR: strcat(dest, "dsisr"); break;
+ case SPROEA_DAR: strcat(dest, "dar"); break;
+ case SPROEA_DEC: strcat(dest, "dec"); break;
+ case SPROEA_SDR1: strcat(dest, "sdr1"); break;
+ case SPROEA_SRR0: strcat(dest, "srr0"); break;
+ case SPROEA_SRR1: strcat(dest, "srr1"); break;
+ case SPROEA_SPRG0: strcat(dest, "sprg0"); break;
+ case SPROEA_SPRG1: strcat(dest, "sprg1"); break;
+ case SPROEA_SPRG2: strcat(dest, "sprg2"); break;
+ case SPROEA_SPRG3: strcat(dest, "sprg3"); break;
+ case SPROEA_ASR: strcat(dest, "asr"); break;
+ case SPROEA_EAR: strcat(dest, "ear"); break;
+ case SPROEA_PVR: strcat(dest, "pvr"); break;
+ case SPROEA_IBAT0U: strcat(dest, "ibat0u"); break;
+ case SPROEA_IBAT0L: strcat(dest, "ibat0l"); break;
+ case SPROEA_IBAT1U: strcat(dest, "ibat1u"); break;
+ case SPROEA_IBAT1L: strcat(dest, "ibat1l"); break;
+ case SPROEA_IBAT2U: strcat(dest, "ibat2u"); break;
+ case SPROEA_IBAT2L: strcat(dest, "ibat2l"); break;
+ case SPROEA_IBAT3U: strcat(dest, "ibat3u"); break;
+ case SPROEA_IBAT3L: strcat(dest, "ibat3l"); break;
+ case SPROEA_DBAT0U: strcat(dest, "dbat0u"); break;
+ case SPROEA_DBAT0L: strcat(dest, "dbat0l"); break;
+ case SPROEA_DBAT1U: strcat(dest, "dbat1u"); break;
+ case SPROEA_DBAT1L: strcat(dest, "dbat1l"); break;
+ case SPROEA_DBAT2U: strcat(dest, "dbat2u"); break;
+ case SPROEA_DBAT2L: strcat(dest, "dbat2l"); break;
+ case SPROEA_DBAT3U: strcat(dest, "dbat3u"); break;
+ case SPROEA_DBAT3L: strcat(dest, "dbat3l"); break;
+ case SPROEA_DABR: strcat(dest, "dabr/iac2"); break; // unsupported on 603e/EC603e
+
+ /* PowerPC 603E SPR register indexes */
+ case SPR603_HID0: strcat(dest, "hid0/dbsr"); break;
+ case SPR603_HID1: strcat(dest, "hid1"); break;
+ case SPR603_DMISS: strcat(dest, "dmiss"); break;
+ case SPR603_DCMP: strcat(dest, "dcmp"); break;
+ case SPR603_HASH1: strcat(dest, "hash1"); break;
+ case SPR603_HASH2: strcat(dest, "hash2/icdbdr"); break;
+ case SPR603_IMISS: strcat(dest, "imiss"); break;
+ case SPR603_ICMP: strcat(dest, "icmp/dear"); break;
+ case SPR603_RPA: strcat(dest, "rpa/evpr"); break;
+ case SPR603_IABR: strcat(dest, "iabr/dbcr"); break;
+
+ /* PowerPC 4XX SPR register indexes */
+ case SPR4XX_SGR: strcat(dest, "sgr"); break;
+ case SPR4XX_DCWR: strcat(dest, "dcwr"); break;
+ case SPR4XX_PID: strcat(dest, "pid"); break;
+ case SPR4XX_TBHU: strcat(dest, "tbhu"); break;
+ case SPR4XX_TBLU: strcat(dest, "tblu"); break;
+// case SPR4XX_ICDBDR: strcat(dest, "icdbdr"); break; // same as SPR603E_HASH2
+// case SPR4XX_DEAR: strcat(dest, "dear"); break; // same as SPR603E_ICMP
+// case SPR4XX_EVPR: strcat(dest, "evpr"); break; // same as SPR603E_RPA
+ case SPR4XX_CDBCR: strcat(dest, "cdbcr"); break;
+ case SPR4XX_TSR: strcat(dest, "tsr"); break;
+ case SPR4XX_TCR: strcat(dest, "tcr"); break;
+ case SPR4XX_PIT: strcat(dest, "pit"); break;
+ case SPR4XX_TBHI: strcat(dest, "tbhi"); break;
+ case SPR4XX_TBLO: strcat(dest, "tblo"); break;
+ case SPR4XX_SRR2: strcat(dest, "srr2"); break;
+ case SPR4XX_SRR3: strcat(dest, "srr3"); break;
+// case SPR4XX_DBSR: strcat(dest, "dbsr"); break; // same as SPR603E_HID0
+// case SPR4XX_DBCR: strcat(dest, "dbcr"); break; // same as SPR603E_IABR
+ case SPR4XX_IAC1: strcat(dest, "iac1"); break;
+// case SPR4XX_IAC2: strcat(dest, "iac2"); break; // same as SPROEA_DABR
+ case SPR4XX_DAC1: strcat(dest, "dac1"); break;
+ case SPR4XX_DAC2: strcat(dest, "dac2"); break;
+ case SPR4XX_DCCR: strcat(dest, "dccr"); break;
+ case SPR4XX_ICCR: strcat(dest, "iccr"); break;
+ case SPR4XX_PBL1: strcat(dest, "pbl1"); break;
+ case SPR4XX_PBU1: strcat(dest, "pbu1"); break;
+ case SPR4XX_PBL2: strcat(dest, "pbl2"); break;
+ case SPR4XX_PBU2: strcat(dest, "pbu2"); break;
default: sprintf(dest, "%s%d", dest, spr); break;
}
@@ -805,17 +748,23 @@ static int Simplified(UINT32 op, UINT32 vpc, char *signed16, char *mnem, char *o
switch (G_BO(op))
{
- case 0x04: // branch if condition is false
- case 0x05:
- case 0x06:
- case 0x07:
- strcat(mnem, "bf");
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ strcat(mnem, "b");
+ strcat(mnem, crnbit[G_BI(op) & 3]);
+ break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ strcat(mnem, "b");
+ strcat(mnem, crbit[G_BI(op) & 3]);
break;
- case 0x0c:
- case 0x0d:
- case 0x0e:
- case 0x0f:
- strcat(mnem, "bt");
+ case 0x10: case 0x11: case 0x18: case 0x19:
+ strcat(mnem, "bdnz");
+ break;
+ case 0x12: case 0x13: case 0x1a: case 0x1b:
+ strcat(mnem, "bdz");
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ strcat(mnem, "b");
break;
default:
return 0;
@@ -824,7 +773,43 @@ static int Simplified(UINT32 op, UINT32 vpc, char *signed16, char *mnem, char *o
if (op & M_LK) strcat(mnem, "l");
if (op & M_AA) strcat(mnem, "a");
- sprintf(oprs, "cr%d[%s],0x%08X", G_BI(op) / 4, crbit[G_BI(op) & 3], disp + ((op & M_AA) ? 0 : vpc));
+ if (!(G_BO(op) & 0x10) && G_BI(op) / 4 != 0)
+ sprintf(oprs, "cr%d,0x%08X", G_BI(op) / 4, disp + ((op & M_AA) ? 0 : vpc));
+ else
+ sprintf(oprs, "0x%08X", disp + ((op & M_AA) ? 0 : vpc));
+ }
+ else if ((op & ~(M_BO|M_BI|M_LK)) == (D_OP(19)|D_XO(528)) || (op & ~(M_BO|M_BI|M_LK)) == (D_OP(19)|D_XO(16)))
+ {
+ switch (G_BO(op))
+ {
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ strcat(mnem, "b");
+ strcat(mnem, crnbit[G_BI(op) & 3]);
+ break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ strcat(mnem, "b");
+ strcat(mnem, crbit[G_BI(op) & 3]);
+ break;
+ case 0x10: case 0x11: case 0x18: case 0x19:
+ strcat(mnem, "bdnz");
+ break;
+ case 0x12: case 0x13: case 0x1a: case 0x1b:
+ strcat(mnem, "bdz");
+ break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ case 0x1c: case 0x1d: case 0x1e: case 0x1f:
+ strcat(mnem, "b");
+ break;
+ default:
+ return 0;
+ }
+
+ strcat(mnem, (G_XO(op) == 528) ? "ctr" : "lr");
+ if (op & M_LK) strcat(mnem, "l");
+ if (op & M_AA) strcat(mnem, "a");
+
+ if (!(G_BO(op) & 0x10) && G_BI(op) / 4 != 0)
+ sprintf(oprs, "cr%d", G_BI(op) / 4);
}
else if ((op & ~(M_RT|M_RA|M_RB|M_OE|M_RC)) == (D_OP(31)|D_XO(40)))
{
@@ -961,15 +946,30 @@ offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op)
break;
case F_CMP:
- sprintf(oprs, "cr%d,%d,r%d,r%d", G_CRFD(op), G_L(op), G_RA(op), G_RB(op));
+ if (G_L(op))
+ strcat(mnem, "d");
+ if (G_CRFD(op) == 0)
+ sprintf(oprs, "r%d,r%d", G_RA(op), G_RB(op));
+ else
+ sprintf(oprs, "cr%d,r%d,r%d", G_CRFD(op), G_RA(op), G_RB(op));
break;
case F_CMP_SIMM:
- sprintf(oprs, "cr%d,%d,r%d,%s", G_CRFD(op), G_L(op), G_RA(op), signed16);
+ if (G_L(op))
+ strcat(mnem, "d");
+ if (G_CRFD(op) == 0)
+ sprintf(oprs, "r%d,%s", G_RA(op), signed16);
+ else
+ sprintf(oprs, "cr%d,r%d,%s", G_CRFD(op), G_RA(op), signed16);
break;
case F_CMP_UIMM:
- sprintf(oprs, "cr%d,%d,r%d,0x%04X", G_CRFD(op), G_L(op), G_RA(op), G_UIMM(op));
+ if (G_L(op))
+ strcat(mnem, "d");
+ if (G_CRFD(op) == 0)
+ sprintf(oprs, "r%d,0x%04X", G_RA(op), G_UIMM(op));
+ else
+ sprintf(oprs, "cr%d,r%d,0x%04X", G_CRFD(op), G_RA(op), G_UIMM(op));
break;
case F_RA_RT:
diff --git a/src/emu/cpu/powerpc/ppc_mem.c b/src/emu/cpu/powerpc/ppc_mem.c
index 47f9b2f17f2..c96002751ab 100644
--- a/src/emu/cpu/powerpc/ppc_mem.c
+++ b/src/emu/cpu/powerpc/ppc_mem.c
@@ -297,7 +297,7 @@ exception:
}
#if (HAS_PPC602||HAS_PPC603)
-static int ppc_translate_address_cb(int space, int intention, offs_t *addr)
+static int ppc_translate_address_cb(int space, offs_t *addr)
{
int success = 1;
diff --git a/src/emu/cpu/powerpc/ppccom.c b/src/emu/cpu/powerpc/ppccom.c
new file mode 100644
index 00000000000..1eadcd33776
--- /dev/null
+++ b/src/emu/cpu/powerpc/ppccom.c
@@ -0,0 +1,1792 @@
+/***************************************************************************
+
+ ppccom.c
+
+ Common PowerPC definitions and functions
+
+***************************************************************************/
+
+#include "ppccom.h"
+#include "deprecat.h"
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define PRINTF_TLB_FILL (0)
+#define PRINTF_SPU (0)
+#define PRINTF_DECREMENTER (0)
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static TIMER_CALLBACK( ppc4xx_fit_callback );
+static TIMER_CALLBACK( ppc4xx_pit_callback );
+static TIMER_CALLBACK( ppc4xx_spu_callback );
+static TIMER_CALLBACK( decrementer_int_callback );
+
+static void ppc4xx_set_irq_line(powerpc_state *ppc, UINT32 bitmask, int state);
+
+static void ppc4xx_dma_update_irq_states(powerpc_state *ppc);
+static int ppc4xx_dma_fetch_transmit_byte(powerpc_state *ppc, int dmachan, UINT8 *byte);
+static int ppc4xx_dma_handle_receive_byte(powerpc_state *ppc, int dmachan, UINT8 byte);
+static void ppc4xx_dma_exec(powerpc_state *ppc, int dmachan);
+
+static void ppc4xx_spu_update_irq_states(powerpc_state *ppc);
+static void ppc4xx_spu_timer_reset(powerpc_state *ppc);
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ page_access_allowed - return true if we are
+ allowed to access memory based on the type
+ of access and the protection bits
+-------------------------------------------------*/
+
+INLINE int page_access_allowed(int transtype, UINT8 key, UINT8 protbits)
+{
+ if (key == 0)
+ return (transtype == TRANSLATE_WRITE) ? (protbits != 3) : TRUE;
+ else
+ return (transtype == TRANSLATE_WRITE) ? (protbits == 2) : (protbits != 0);
+}
+
+
+/*-------------------------------------------------
+ tlb_entry_free - free an entry from the TLB,
+ by index
+-------------------------------------------------*/
+
+INLINE void tlb_entry_free(powerpc_state *ppc, int entrynum)
+{
+ int oldentry = ppc->tlb_entries[entrynum];
+
+ /* if we're mapped to something, free the entry in the table */
+ if (oldentry != 0)
+ {
+ ppc->tlb_table[oldentry - 1] = 0;
+ ppc->tlb_entries[entrynum] = 0;
+ }
+}
+
+
+/*-------------------------------------------------
+ tlb_entry_allocate - allocate a TLB entry
+ for the given address, if needed, and set its
+ new value
+-------------------------------------------------*/
+
+INLINE int tlb_entry_allocate(powerpc_state *ppc, int entrynum, offs_t address, UINT32 value)
+{
+ UINT32 *entry = &ppc->tlb_table[address >> 12];
+ int allocated = FALSE;
+
+ /* only need to allocate if we are empty */
+ if (*entry == 0)
+ {
+ /* if there's already a TLB entry at the current index, zap it */
+ tlb_entry_free(ppc, entrynum);
+
+ /* allocate a new entry and advance to the next one */
+ ppc->tlb_entries[entrynum] = (address >> 12) + 1;
+ allocated = TRUE;
+ }
+ *entry = value;
+
+ return allocated;
+}
+
+
+/*-------------------------------------------------
+ get_timebase - return the current timebase
+ value
+-------------------------------------------------*/
+
+INLINE UINT64 get_timebase(powerpc_state *ppc)
+{
+ return (cpunum_gettotalcycles(ppc->cpunum) - ppc->tb_zero_cycles) / ppc->tb_divisor;
+}
+
+
+/*-------------------------------------------------
+ set_timebase - set the timebase
+-------------------------------------------------*/
+
+INLINE void set_timebase(powerpc_state *ppc, UINT64 newtb)
+{
+ ppc->tb_zero_cycles = activecpu_gettotalcycles() - newtb * ppc->tb_divisor;
+}
+
+
+/*-------------------------------------------------
+ get_decremeter - return the current
+ decrementer value
+-------------------------------------------------*/
+
+INLINE UINT32 get_decrementer(powerpc_state *ppc)
+{
+ INT64 cycles_until_zero = ppc->dec_zero_cycles - cpunum_gettotalcycles(ppc->cpunum);
+ cycles_until_zero = MAX(cycles_until_zero, 0);
+ return cycles_until_zero / ppc->tb_divisor;
+}
+
+
+/*-------------------------------------------------
+ set_decrementer - set the decremeter
+-------------------------------------------------*/
+
+INLINE void set_decrementer(powerpc_state *ppc, UINT32 newdec)
+{
+ UINT64 cycles_until_done = ((UINT64)newdec + 1) * ppc->tb_divisor;
+ UINT32 curdec = get_decrementer(ppc);
+
+ if (PRINTF_DECREMENTER)
+ {
+ UINT64 total = cpunum_gettotalcycles(ppc->cpunum);
+ mame_printf_debug("set_decrementer: olddec=%08X newdec=%08X divisor=%d totalcyc=%08X%08X timer=%08X%08X\n",
+ curdec, newdec, ppc->tb_divisor,
+ (UINT32)(total >> 32), (UINT32)total, (UINT32)(cycles_until_done >> 32), (UINT32)cycles_until_done);
+ }
+
+ ppc->dec_zero_cycles = cpunum_gettotalcycles(ppc->cpunum) + cycles_until_done;
+ timer_adjust_oneshot(ppc->decrementer_int_timer, ATTOTIME_IN_CYCLES(cycles_until_done, ppc->cpunum), 0);
+
+ if ((INT32)curdec >= 0 && (INT32)newdec < 0)
+ ppc->irq_pending |= 0x02;
+}
+
+
+
+/***************************************************************************
+ INITIALIZATION AND SHUTDOWN
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_init - initialize the powerpc_state
+ structure based on the configured type
+-------------------------------------------------*/
+
+size_t ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, int clock, const powerpc_config *config, int (*irqcallback)(int), void *memory)
+{
+ /* if no memory, return the amount needed */
+ if (memory == NULL)
+ return sizeof(ppc->tlb_table[0]) * (POWERPC_TLB_ENTRIES + PPC603_FIXED_TLB_ENTRIES + (1 << (32 - POWERPC_MIN_PAGE_SHIFT)));
+
+ /* initialize based on the config */
+ memset(ppc, 0, sizeof(*ppc));
+ ppc->cpunum = cpu_getactivecpu();
+ ppc->flavor = flavor;
+ ppc->cap = cap;
+ ppc->cache_line_size = 32;
+ ppc->tb_divisor = tb_divisor;
+ ppc->cpu_clock = clock;
+ ppc->irq_callback = irqcallback;
+ ppc->system_clock = (config != NULL) ? config->bus_frequency : clock;
+ ppc->tb_divisor = (ppc->tb_divisor * clock + ppc->system_clock / 2 - 1) / ppc->system_clock;
+
+ /* initialize the TLB state */
+ ppc->tlb_entries = memory;
+ ppc->tlb_table = ppc->tlb_entries + POWERPC_TLB_ENTRIES + PPC603_FIXED_TLB_ENTRIES;
+
+ /* allocate a timer for the compare interrupt */
+ if (cap & PPCCAP_OEA)
+ ppc->decrementer_int_timer = timer_alloc(decrementer_int_callback, ppc);
+
+ /* and for the 4XX interrupts if needed */
+ if (cap & PPCCAP_4XX)
+ {
+ ppc->fit_timer = timer_alloc(ppc4xx_fit_callback, ppc);
+ ppc->pit_timer = timer_alloc(ppc4xx_pit_callback, ppc);
+ ppc->spu.timer = timer_alloc(ppc4xx_spu_callback, ppc);
+ }
+
+ /* reset the state */
+ ppccom_reset(ppc);
+ return 0;
+}
+
+
+/*-------------------------------------------------
+ ppccom_reset - reset the state of all the
+ registers
+-------------------------------------------------*/
+
+void ppccom_reset(powerpc_state *ppc)
+{
+ /* initialize the OEA state */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ /* PC to the reset vector; MSR has IP set to start */
+ ppc->pc = 0xfff00100;
+ ppc->msr = MSROEA_IP;
+
+ /* reset the decrementer */
+ ppc->dec_zero_cycles = cpunum_gettotalcycles(ppc->cpunum);
+ decrementer_int_callback(Machine, ppc, 0);
+ }
+
+ /* initialize the 4XX state */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ /* PC to the last word; MSR to 0 */
+ ppc->pc = 0xfffffffc;
+ ppc->msr = 0;
+
+ /* reset the SPU status */
+ ppc->spr[SPR4XX_TCR] &= ~PPC4XX_TCR_WRC_MASK;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] = 0x06;
+ }
+
+ /* time base starts here */
+ ppc->tb_zero_cycles = cpunum_gettotalcycles(ppc->cpunum);
+
+ /* clear interrupts */
+ ppc->irq_pending = 0;
+
+ /* flush the TLB */
+ ppc->tlb_index = 0;
+ memset(ppc->tlb_entries, 0, sizeof(ppc->tlb_entries[0]) * (POWERPC_TLB_ENTRIES + PPC603_FIXED_TLB_ENTRIES));
+ memset(ppc->tlb_table, 0, sizeof(ppc->tlb_table[0]) * (1 << (32 - POWERPC_MIN_PAGE_SHIFT)));
+}
+
+
+/*-------------------------------------------------
+ ppccom_dasm - handle disassembly for a
+ CPU
+-------------------------------------------------*/
+
+#ifdef ENABLE_DEBUGGER
+offs_t ppccom_dasm(powerpc_state *ppc, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ extern offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op);
+ UINT32 op = *(UINT32 *)oprom;
+ op = BIG_ENDIANIZE_INT32(op);
+ return ppc_dasm_one(buffer, pc, op);
+}
+#endif /* ENABLE_DEBUGGER */
+
+
+
+/***************************************************************************
+ TLB HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_translate_address_internal - translate
+ an address from logical to physical; shared
+ between external requests and internal TLB
+ filling
+-------------------------------------------------*/
+
+static UINT32 ppccom_translate_address_internal(powerpc_state *ppc, int intention, offs_t *address)
+{
+ int transpriv = ((intention & TRANSLATE_USER_MASK) == 0);
+ int transtype = intention & TRANSLATE_TYPE_MASK;
+ offs_t hash, hashbase, hashmask;
+ int batbase, batnum, hashnum;
+ UINT32 segreg;
+
+ /* only applies if we support the OEA */
+ if (!(ppc->cap & PPCCAP_OEA))
+ return 0x001;
+
+ /* also no translation necessary if translation is disabled */
+ if ((transtype == TRANSLATE_FETCH && (ppc->msr & MSROEA_IR) == 0) || (transtype != TRANSLATE_FETCH && (ppc->msr & MSROEA_DR) == 0))
+ return 0x001;
+
+ /* first scan the appropriate BAT */
+ batbase = (transtype == TRANSLATE_FETCH) ? SPROEA_IBAT0U : SPROEA_DBAT0U;
+ for (batnum = 0; batnum < 4; batnum++)
+ {
+ UINT32 upper = ppc->spr[batbase + 2*batnum + 0];
+
+ /* check user/supervisor valid bit */
+ if ((upper >> transpriv) & 0x01)
+ {
+ UINT32 mask = (~upper << 15) & 0xfffe0000;
+
+ /* check for a hit against this bucket */
+ if ((*address & mask) == (upper & mask))
+ {
+ UINT32 lower = ppc->spr[batbase + 2*batnum + 1];
+
+ /* verify protection; if we fail, return false and indicate a protection violation */
+ if (!page_access_allowed(transtype, 1, lower & 3))
+ return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+
+ /* otherwise we're good */
+ *address = (lower & mask) | (*address & ~mask);
+ return 0x001;
+ }
+ }
+ }
+
+ /* look up the segment register */
+ segreg = ppc->sr[*address >> 28];
+ if (transtype == TRANSLATE_FETCH && (segreg & 0x10000000))
+ return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+
+ /* get hash table information from SD1 */
+ hashbase = ppc->spr[SPROEA_SDR1] & 0xffff0000;
+ hashmask = ((ppc->spr[SPROEA_SDR1] & 0x1ff) << 16) | 0xffff;
+ hash = (segreg & 0x7ffff) ^ ((*address >> 12) & 0xffff);
+
+ /* if we're simulating the 603 MMU, fill in the data and stop here */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ ppc->mmu603_cmp = 0x80000000 | ((segreg & 0xffffff) << 7) | (0 << 6) | ((*address >> 22) & 0x3f);
+ ppc->mmu603_hash[0] = hashbase | ((hash << 6) & hashmask);
+ ppc->mmu603_hash[1] = hashbase | ((~hash << 6) & hashmask);
+ return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+ }
+
+ /* loop twice over hashes */
+ for (hashnum = 0; hashnum < 2; hashnum++)
+ {
+ offs_t ptegaddr = hashbase | ((hash << 6) & hashmask);
+ UINT32 *ptegptr = memory_get_read_ptr(cpu_getactivecpu(), ADDRESS_SPACE_PROGRAM, ptegaddr);
+
+ /* should only have valid memory here, but make sure */
+ if (ptegptr != NULL)
+ {
+ UINT32 targetupper = 0x80000000 | ((segreg & 0xffffff) << 7) | (hashnum << 6) | ((*address >> 22) & 0x3f);
+ int ptenum;
+
+ /* scan PTEs */
+ for (ptenum = 0; ptenum < 8; ptenum++)
+ if (ptegptr[BYTE_XOR_BE(ptenum * 2)] == targetupper)
+ {
+ UINT32 pteglower = ptegptr[BYTE_XOR_BE(ptenum * 2 + 1)];
+
+ /* verify protection; if we fail, return false and indicate a protection violation */
+ if (!page_access_allowed(transtype, (segreg >> (29 + transpriv)) & 1, pteglower & 3))
+ return DSISR_PROTECTED | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+
+ /* update page table bits */
+ if (!(intention & TRANSLATE_DEBUG_MASK))
+ {
+ pteglower |= 0x100;
+ if (transtype == TRANSLATE_WRITE)
+ pteglower |= 0x080;
+ ptegptr[BYTE_XOR_BE(ptenum * 2 + 1)] = pteglower;
+ }
+
+ /* otherwise we're good */
+ *address = (pteglower & 0xfffff000) | (*address & 0x00000fff);
+ return (pteglower >> 7) & 1;
+ }
+ }
+
+ /* invert the hash after the first round */
+ hash = ~hash;
+ }
+
+ /* we failed to find any match: not found */
+ return DSISR_NOT_FOUND | ((transtype == TRANSLATE_WRITE) ? DSISR_STORE : 0);
+}
+
+
+/*-------------------------------------------------
+ ppccom_translate_address - translate an address
+ from logical to physical
+-------------------------------------------------*/
+
+int ppccom_translate_address(powerpc_state *ppc, int space, int intention, offs_t *address)
+{
+ /* only applies to the program address space */
+ if (space != ADDRESS_SPACE_PROGRAM)
+ return TRUE;
+
+ /* translation is successful if the internal routine returns 0 or 1 */
+ return (ppccom_translate_address_internal(ppc, intention, address) <= 1);
+}
+
+
+/*-------------------------------------------------
+ ppccom_tlb_fill - handle a missing TLB entry
+-------------------------------------------------*/
+
+void ppccom_tlb_fill(powerpc_state *ppc)
+{
+ int transuser = (ppc->msr & MSR_PR) ? TRANSLATE_USER_MASK : 0;
+ offs_t address = ppc->param0;
+ int transtype = ppc->param1;
+ offs_t transaddr = address;
+ UINT32 entryval;
+
+ /* allow for an implementation-specific override */
+ if (ppc->tlb_fill != NULL && (*ppc->tlb_fill)(ppc))
+ return;
+
+ /* if we can't translate the address, just return (and fail) */
+ ppc->param0 = ppccom_translate_address_internal(ppc, transtype | transuser, &transaddr);
+ if (PRINTF_TLB_FILL)
+ printf("tlb_fill: %08X (%s%s) -> ", address, (transtype == TRANSLATE_READ) ? "R" : (transtype == TRANSLATE_WRITE) ? "W" : "F", transuser ? " U" : "S");
+ if (ppc->param0 > 1)
+ {
+ if (PRINTF_TLB_FILL)
+ printf("failed(%08X)\n", ppc->param0);
+ return;
+ }
+
+ /* if we did translate the address, get a pointer to our entry in the TLB table and fill it in */
+ if (PRINTF_TLB_FILL)
+ printf("succeeded(%d) -> %08X\n", ppc->param0, transaddr);
+ entryval = (transaddr & 0xfffff000) | TLB_READ | ((ppc->param0 & 1) ? TLB_WRITE : 0);
+ if (tlb_entry_allocate(ppc, ppc->tlb_index, address, entryval))
+ ppc->tlb_index = (ppc->tlb_index + 1) % POWERPC_TLB_ENTRIES;
+}
+
+
+/*-------------------------------------------------
+ ppccom_tlb_flush - flush the entire TLB,
+ including fixed entries
+-------------------------------------------------*/
+
+void ppccom_tlb_flush(powerpc_state *ppc)
+{
+ int entnum;
+
+ /* iterate over entries and invalidate them */
+ for (entnum = 0; entnum < POWERPC_TLB_ENTRIES; entnum++)
+ tlb_entry_free(ppc, entnum);
+}
+
+
+
+/***************************************************************************
+ OPCODE HANDLING
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_execute_tlbie - execute a TLBIE
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_tlbie(powerpc_state *ppc)
+{
+ offs_t address = ppc->param0;
+
+ /* just nuke it in the table; we may have spare entries referencing it, but no harm */
+ ppc->tlb_table[address >> 12] = 0;
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_tlbia - execute a TLBIA
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_tlbia(powerpc_state *ppc)
+{
+ ppccom_tlb_flush(ppc);
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_tlbl - execute a TLBLD/TLBLI
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_tlbl(powerpc_state *ppc)
+{
+ UINT32 address = ppc->param0;
+ int isitlb = ppc->param1;
+ UINT32 entrynum, entryval;
+
+ /* determine entry number; we use rand() for associativity */
+ entrynum = ((address >> 12) & 0x1f) | (mame_rand(Machine) & 0x20) | (isitlb ? 0x40 : 0);
+
+ /* invalidate any existing TLB entry here */
+ ppc->tlb_table[address >> 12] = 0;
+
+ /* allocate this entry */
+ entryval = (ppc->spr[SPR603_RPA] & 0xfffff000) | TLB_READ | ((ppc->spr[SPR603_RPA] & 0x80) ? TLB_WRITE : 0);
+ tlb_entry_allocate(ppc, POWERPC_TLB_ENTRIES + entrynum, address, entryval);
+ if (PRINTF_TLB_FILL)
+ printf("tlb_load: %08X (%sS) -> %08X\n", address, isitlb ? "F" : "R", ppc->spr[SPR603_RPA] & 0xfffff000);
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mftb - execute an MFTB
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mftb(powerpc_state *ppc)
+{
+ switch (ppc->param0)
+ {
+ /* user mode timebase read */
+ case SPRVEA_TBL_R:
+ ppc->param1 = get_timebase(ppc);
+ break;
+ case SPRVEA_TBU_R:
+ ppc->param1 = get_timebase(ppc) >> 32;
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mfspr - execute an MFSPR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mfspr(powerpc_state *ppc)
+{
+ /* handle OEA SPRs */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case SPROEA_DSISR:
+ case SPROEA_DAR:
+ case SPROEA_SDR1:
+ case SPROEA_SRR0:
+ case SPROEA_SRR1:
+ case SPROEA_EAR:
+ case SPROEA_IBAT0L:
+ case SPROEA_IBAT0U:
+ case SPROEA_IBAT1L:
+ case SPROEA_IBAT1U:
+ case SPROEA_IBAT2L:
+ case SPROEA_IBAT2U:
+ case SPROEA_IBAT3L:
+ case SPROEA_IBAT3U:
+ case SPROEA_DBAT0L:
+ case SPROEA_DBAT0U:
+ case SPROEA_DBAT1L:
+ case SPROEA_DBAT1U:
+ case SPROEA_DBAT2L:
+ case SPROEA_DBAT2U:
+ case SPROEA_DBAT3L:
+ case SPROEA_DBAT3U:
+ case SPROEA_DABR:
+ ppc->param1 = ppc->spr[ppc->param0];
+ return;
+
+ /* decrementer */
+ case SPROEA_DEC:
+ ppc->param1 = get_decrementer(ppc);
+ return;
+ }
+ }
+
+ /* handle 603 SPRs */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case SPR603_DMISS:
+ case SPR603_DCMP:
+ case SPR603_HASH1:
+ case SPR603_HASH2:
+ case SPR603_IMISS:
+ case SPR603_ICMP:
+ case SPR603_RPA:
+ case SPR603_HID0:
+ case SPR603_HID1:
+ case SPR603_IABR:
+ case SPR603_HID2:
+ ppc->param1 = ppc->spr[ppc->param0];
+ return;
+
+ /* timebase */
+ case SPR603_TBL_R:
+ ppc->param1 = get_timebase(ppc);
+ return;
+ case SPR603_TBU_R:
+ ppc->param1 = (get_timebase(ppc) >> 32) & 0xffffff;
+ return;
+ }
+ }
+
+ /* handle 4XX SPRs */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case SPR4XX_EVPR:
+ case SPR4XX_ESR:
+ case SPR4XX_DCCR:
+ case SPR4XX_ICCR:
+ case SPR4XX_SRR0:
+ case SPR4XX_SRR1:
+ case SPR4XX_SRR2:
+ case SPR4XX_SRR3:
+ case SPR4XX_TCR:
+ case SPR4XX_TSR:
+ ppc->param1 = ppc->spr[ppc->param0];
+ return;
+
+ /* timebase */
+ case SPR4XX_TBLO:
+ case SPR4XX_TBLU:
+ ppc->param1 = get_timebase(ppc);
+ return;
+ case SPR4XX_TBHI:
+ case SPR4XX_TBHU:
+ ppc->param1 = (get_timebase(ppc) >> 32) & 0xffffff;
+ return;
+ }
+ }
+
+ /* default handling */
+ mame_printf_debug("SPR %03X read\n", ppc->param0);
+ ppc->param1 = ppc->spr[ppc->param0];
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mtspr - execute an MTSPR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mtspr(powerpc_state *ppc)
+{
+ /* handle OEA SPRs */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ switch (ppc->param0)
+ {
+ /* write-through no-ops */
+ case SPROEA_DSISR:
+ case SPROEA_DAR:
+ case SPROEA_SRR0:
+ case SPROEA_SRR1:
+ case SPROEA_EAR:
+ case SPROEA_DABR:
+ ppc->spr[ppc->param0] = ppc->param1;
+ return;
+
+ /* registers that affect the memory map */
+ case SPROEA_SDR1:
+ case SPROEA_IBAT0L:
+ case SPROEA_IBAT0U:
+ case SPROEA_IBAT1L:
+ case SPROEA_IBAT1U:
+ case SPROEA_IBAT2L:
+ case SPROEA_IBAT2U:
+ case SPROEA_IBAT3L:
+ case SPROEA_IBAT3U:
+ case SPROEA_DBAT0L:
+ case SPROEA_DBAT0U:
+ case SPROEA_DBAT1L:
+ case SPROEA_DBAT1U:
+ case SPROEA_DBAT2L:
+ case SPROEA_DBAT2U:
+ case SPROEA_DBAT3L:
+ case SPROEA_DBAT3U:
+ ppc->spr[ppc->param0] = ppc->param1;
+ ppccom_tlb_flush(ppc);
+ return;
+
+ /* decrementer */
+ case SPROEA_DEC:
+ set_decrementer(ppc, ppc->param1);
+ return;
+ }
+ }
+
+ /* handle 603 SPRs */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ switch (ppc->param0)
+ {
+ /* read-only */
+ case SPR603_DMISS:
+ case SPR603_DCMP:
+ case SPR603_HASH1:
+ case SPR603_HASH2:
+ case SPR603_IMISS:
+ case SPR603_ICMP:
+ return;
+
+ /* write-through no-ops */
+ case SPR603_RPA:
+ case SPR603_HID0:
+ case SPR603_HID1:
+ case SPR603_IABR:
+ case SPR603_HID2:
+ ppc->spr[ppc->param0] = ppc->param1;
+ return;
+
+ /* timebase */
+ case SPR603_TBL_W:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0xffffffff00000000)) | ppc->param1);
+ return;
+ case SPR603_TBU_W:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00000000ffffffff)) | ((UINT64)ppc->param1 << 32));
+ return;
+ }
+ }
+
+ /* handle 4XX SPRs */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ UINT32 oldval = ppc->spr[ppc->param0];
+ switch (ppc->param0)
+ {
+ /* write-through no-ops */
+ case SPR4XX_EVPR:
+ case SPR4XX_ESR:
+ case SPR4XX_DCCR:
+ case SPR4XX_ICCR:
+ case SPR4XX_SRR0:
+ case SPR4XX_SRR1:
+ case SPR4XX_SRR2:
+ case SPR4XX_SRR3:
+ ppc->spr[ppc->param0] = ppc->param1;
+ return;
+
+ /* timer control register */
+ case SPR4XX_TCR:
+ ppc->spr[SPR4XX_TCR] = ppc->param1 | (oldval & PPC4XX_TCR_WRC_MASK);
+ if ((oldval ^ ppc->spr[SPR4XX_TCR]) & PPC4XX_TCR_FIE)
+ ppc4xx_fit_callback(Machine, ppc, FALSE);
+ if ((oldval ^ ppc->spr[SPR4XX_TCR]) & PPC4XX_TCR_PIE)
+ ppc4xx_pit_callback(Machine, ppc, FALSE);
+ return;
+
+ /* timer status register */
+ case SPR4XX_TSR:
+ ppc->spr[SPR4XX_TSR] &= ~ppc->param1;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ return;
+
+ /* PIT */
+ case SPR4XX_PIT:
+ ppc->spr[SPR4XX_PIT] = ppc->param1;
+ ppc->pit_reload = ppc->param1;
+ ppc4xx_pit_callback(Machine, ppc, FALSE);
+ return;
+
+ /* timebase */
+ case SPR4XX_TBLO:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00ffffff00000000)) | ppc->param1);
+ return;
+ case SPR4XX_TBHI:
+ set_timebase(ppc, (get_timebase(ppc) & ~U64(0x00000000ffffffff)) | ((UINT64)(ppc->param1 & 0x00ffffff) << 32));
+ return;
+ }
+ }
+
+ /* default handling */
+ mame_printf_debug("SPR %03X write = %08X\n", ppc->param0, ppc->param1);
+ ppc->spr[ppc->param0] = ppc->param1;
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mfdcr - execute an MFDCR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mfdcr(powerpc_state *ppc)
+{
+ /* handle various DCRs */
+ switch (ppc->param0)
+ {
+ /* read-through no-ops */
+ case DCR4XX_BR0:
+ case DCR4XX_BR1:
+ case DCR4XX_BR2:
+ case DCR4XX_BR3:
+ case DCR4XX_BR4:
+ case DCR4XX_BR5:
+ case DCR4XX_BR6:
+ case DCR4XX_BR7:
+ case DCR4XX_BESR:
+ case DCR4XX_DMASR:
+ case DCR4XX_DMACT0:
+ case DCR4XX_DMADA0:
+ case DCR4XX_DMASA0:
+ case DCR4XX_DMACC0:
+ case DCR4XX_DMACT1:
+ case DCR4XX_DMADA1:
+ case DCR4XX_DMASA1:
+ case DCR4XX_DMACC1:
+ case DCR4XX_DMACT2:
+ case DCR4XX_DMADA2:
+ case DCR4XX_DMASA2:
+ case DCR4XX_DMACC2:
+ case DCR4XX_DMACT3:
+ case DCR4XX_DMADA3:
+ case DCR4XX_DMASA3:
+ case DCR4XX_DMACC3:
+ case DCR4XX_EXIER:
+ case DCR4XX_EXISR:
+ case DCR4XX_IOCR:
+ ppc->param1 = ppc->dcr[ppc->param0];
+ return;
+ }
+
+ /* default handling */
+ mame_printf_debug("DCR %03X read\n", ppc->param0);
+ if (ppc->param0 < ARRAY_LENGTH(ppc->dcr))
+ ppc->param1 = ppc->dcr[ppc->param0];
+ else
+ ppc->param1 = 0;
+}
+
+
+/*-------------------------------------------------
+ ppccom_execute_mtdcr - execute an MTDCR
+ instruction
+-------------------------------------------------*/
+
+void ppccom_execute_mtdcr(powerpc_state *ppc)
+{
+ UINT8 oldval;
+
+ /* handle various DCRs */
+ switch (ppc->param0)
+ {
+ /* write-through no-ops */
+ case DCR4XX_BR0:
+ case DCR4XX_BR1:
+ case DCR4XX_BR2:
+ case DCR4XX_BR3:
+ case DCR4XX_BR4:
+ case DCR4XX_BR5:
+ case DCR4XX_BR6:
+ case DCR4XX_BR7:
+ case DCR4XX_BESR:
+ case DCR4XX_DMACT0:
+ case DCR4XX_DMADA0:
+ case DCR4XX_DMASA0:
+ case DCR4XX_DMACC0:
+ case DCR4XX_DMACT1:
+ case DCR4XX_DMADA1:
+ case DCR4XX_DMASA1:
+ case DCR4XX_DMACC1:
+ case DCR4XX_DMACT2:
+ case DCR4XX_DMADA2:
+ case DCR4XX_DMASA2:
+ case DCR4XX_DMACC2:
+ case DCR4XX_DMACT3:
+ case DCR4XX_DMADA3:
+ case DCR4XX_DMASA3:
+ case DCR4XX_DMACC3:
+ ppc->dcr[ppc->param0] = ppc->param1;
+ return;
+
+ /* DMA status */
+ case DCR4XX_DMASR:
+ ppc->dcr[DCR4XX_DMASR] &= ~(ppc->param1 & 0xfff80070);
+ ppc4xx_dma_update_irq_states(ppc);
+ return;
+
+ /* interrupt enables */
+ case DCR4XX_EXIER:
+ ppc->dcr[DCR4XX_EXIER] = ppc->param1;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ return;
+
+ /* interrupt clear */
+ case DCR4XX_EXISR:
+ ppc->dcr[ppc->param0] &= ~ppc->param1;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ return;
+
+ /* DMA controls */
+ case DCR4XX_DMACR0:
+ case DCR4XX_DMACR1:
+ case DCR4XX_DMACR2:
+ case DCR4XX_DMACR3:
+ ppc->dcr[ppc->param0] = ppc->param1;
+ if (ppc->param1 & PPC4XX_DMACR_CE)
+ ppc4xx_dma_exec(ppc, (ppc->param0 - DCR4XX_DMACR0) / 8);
+ ppc4xx_dma_update_irq_states(ppc);
+ return;
+
+ /* I/O control */
+ case DCR4XX_IOCR:
+ oldval = ppc->dcr[ppc->param0];
+ ppc->dcr[ppc->param0] = ppc->param1;
+ if ((oldval ^ ppc->param1) & 0x02)
+ ppc4xx_spu_timer_reset(ppc);
+ return;
+ }
+
+ /* default handling */
+ mame_printf_debug("DCR %03X write = %08X\n", ppc->param0, ppc->param1);
+ if (ppc->param0 < ARRAY_LENGTH(ppc->dcr))
+ ppc->dcr[ppc->param0] = ppc->param1;
+}
+
+
+
+/***************************************************************************
+ COMMON GET/SET INFO
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppccom_set_info - set information about
+ a PowerPC CPU
+-------------------------------------------------*/
+
+void ppccom_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ: ppc->irq_pending = (ppc->irq_pending & ~1) | (info->i != CLEAR_LINE); break;
+
+ 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_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_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;
+ case CPUINFO_INT_REGISTER + PPC_SPRG1: ppc->spr[SPROEA_SPRG1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG2: ppc->spr[SPROEA_SPRG2] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG3: ppc->spr[SPROEA_SPRG3] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_SDR1: ppc->spr[SPROEA_SDR1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_EXIER: ppc->dcr[DCR4XX_EXIER] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_EXISR: ppc->dcr[DCR4XX_EXISR] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_EVPR: ppc->spr[SPR4XX_EVPR] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_IOCR: ppc->dcr[DCR4XX_IOCR] = info->i; break;
+
+ case CPUINFO_INT_REGISTER + PPC_R0: ppc->r[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R1: ppc->r[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R2: ppc->r[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R3: ppc->r[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R4: ppc->r[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R5: ppc->r[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R6: ppc->r[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R7: ppc->r[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R8: ppc->r[8] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R9: ppc->r[9] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R10: ppc->r[10] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R11: ppc->r[11] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R12: ppc->r[12] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R13: ppc->r[13] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R14: ppc->r[14] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R15: ppc->r[15] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R16: ppc->r[16] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R17: ppc->r[17] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R18: ppc->r[18] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R19: ppc->r[19] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R20: ppc->r[20] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R21: ppc->r[21] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R22: ppc->r[22] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R23: ppc->r[23] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R24: ppc->r[24] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R25: ppc->r[25] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R26: ppc->r[26] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R27: ppc->r[27] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R28: ppc->r[28] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R29: ppc->r[29] = info->i; break;
+ case CPUINFO_INT_REGISTER + PPC_R30: ppc->r[30] = info->i; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PPC_R31: ppc->r[31] = info->i; break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppccom_get_info - get information about
+ a PowerPC CPU
+-------------------------------------------------*/
+
+void ppccom_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: /* provided by core */ break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = POWERPC_MIN_PAGE_SHIFT;break;
+
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ: info->i = ppc->irq_pending ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: /* optionally implemented */ break;
+
+ 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_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_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;
+ case CPUINFO_INT_REGISTER + PPC_SPRG1: info->i = ppc->spr[SPROEA_SPRG1]; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG2: info->i = ppc->spr[SPROEA_SPRG2]; break;
+ case CPUINFO_INT_REGISTER + PPC_SPRG3: info->i = ppc->spr[SPROEA_SPRG3]; break;
+ case CPUINFO_INT_REGISTER + PPC_SDR1: info->i = ppc->spr[SPROEA_SDR1]; break;
+ case CPUINFO_INT_REGISTER + PPC_EXIER: info->i = ppc->dcr[DCR4XX_EXIER]; break;
+ case CPUINFO_INT_REGISTER + PPC_EXISR: info->i = ppc->dcr[DCR4XX_EXISR]; break;
+ case CPUINFO_INT_REGISTER + PPC_EVPR: info->i = ppc->spr[SPR4XX_EVPR]; break;
+ case CPUINFO_INT_REGISTER + PPC_IOCR: info->i = ppc->dcr[DCR4XX_IOCR]; break;
+
+ case CPUINFO_INT_REGISTER + PPC_R0: info->i = ppc->r[0]; break;
+ case CPUINFO_INT_REGISTER + PPC_R1: info->i = ppc->r[1]; break;
+ case CPUINFO_INT_REGISTER + PPC_R2: info->i = ppc->r[2]; break;
+ case CPUINFO_INT_REGISTER + PPC_R3: info->i = ppc->r[3]; break;
+ case CPUINFO_INT_REGISTER + PPC_R4: info->i = ppc->r[4]; break;
+ case CPUINFO_INT_REGISTER + PPC_R5: info->i = ppc->r[5]; break;
+ case CPUINFO_INT_REGISTER + PPC_R6: info->i = ppc->r[6]; break;
+ case CPUINFO_INT_REGISTER + PPC_R7: info->i = ppc->r[7]; break;
+ case CPUINFO_INT_REGISTER + PPC_R8: info->i = ppc->r[8]; break;
+ case CPUINFO_INT_REGISTER + PPC_R9: info->i = ppc->r[9]; break;
+ case CPUINFO_INT_REGISTER + PPC_R10: info->i = ppc->r[10]; break;
+ case CPUINFO_INT_REGISTER + PPC_R11: info->i = ppc->r[11]; break;
+ case CPUINFO_INT_REGISTER + PPC_R12: info->i = ppc->r[12]; break;
+ case CPUINFO_INT_REGISTER + PPC_R13: info->i = ppc->r[13]; break;
+ case CPUINFO_INT_REGISTER + PPC_R14: info->i = ppc->r[14]; break;
+ case CPUINFO_INT_REGISTER + PPC_R15: info->i = ppc->r[15]; break;
+ case CPUINFO_INT_REGISTER + PPC_R16: info->i = ppc->r[16]; break;
+ case CPUINFO_INT_REGISTER + PPC_R17: info->i = ppc->r[17]; break;
+ case CPUINFO_INT_REGISTER + PPC_R18: info->i = ppc->r[18]; break;
+ case CPUINFO_INT_REGISTER + PPC_R19: info->i = ppc->r[19]; break;
+ case CPUINFO_INT_REGISTER + PPC_R20: info->i = ppc->r[20]; break;
+ case CPUINFO_INT_REGISTER + PPC_R21: info->i = ppc->r[21]; break;
+ case CPUINFO_INT_REGISTER + PPC_R22: info->i = ppc->r[22]; break;
+ case CPUINFO_INT_REGISTER + PPC_R23: info->i = ppc->r[23]; break;
+ case CPUINFO_INT_REGISTER + PPC_R24: info->i = ppc->r[24]; break;
+ case CPUINFO_INT_REGISTER + PPC_R25: info->i = ppc->r[25]; break;
+ case CPUINFO_INT_REGISTER + PPC_R26: info->i = ppc->r[26]; break;
+ case CPUINFO_INT_REGISTER + PPC_R27: info->i = ppc->r[27]; break;
+ case CPUINFO_INT_REGISTER + PPC_R28: info->i = ppc->r[28]; break;
+ case CPUINFO_INT_REGISTER + PPC_R29: info->i = ppc->r[29]; break;
+ case CPUINFO_INT_REGISTER + PPC_R30: info->i = ppc->r[30]; break;
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + PPC_R31: info->i = ppc->r[31]; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: /* provided by core */ break;
+ case CPUINFO_PTR_GET_CONTEXT: /* provided by core */ break;
+ case CPUINFO_PTR_SET_CONTEXT: /* provided by core */ break;
+ case CPUINFO_PTR_INIT: /* provided by core */ break;
+ case CPUINFO_PTR_RESET: /* provided by core */ break;
+ case CPUINFO_PTR_EXIT: /* provided by core */ break;
+ case CPUINFO_PTR_EXECUTE: /* provided by core */ break;
+ case CPUINFO_PTR_TRANSLATE: /* provided by core */ break;
+ case CPUINFO_PTR_DISASSEMBLE: /* provided by core */ break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ppc->icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "PowerPC"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "2.0"); break;
+ case CPUINFO_STR_CORE_FILE: /* provided by core */ break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Aaron Giles"); break;
+
+ case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
+
+ 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_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_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;
+ case CPUINFO_STR_REGISTER + PPC_SPRG1: sprintf(info->s, "SPRG1: %08X", ppc->spr[SPROEA_SPRG1]); break;
+ case CPUINFO_STR_REGISTER + PPC_SPRG2: sprintf(info->s, "SPRG2: %08X", ppc->spr[SPROEA_SPRG2]); break;
+ case CPUINFO_STR_REGISTER + PPC_SPRG3: sprintf(info->s, "SPRG3: %08X", ppc->spr[SPROEA_SPRG3]); break;
+ case CPUINFO_STR_REGISTER + PPC_SDR1: sprintf(info->s, "SDR1: %08X", ppc->spr[SPROEA_SDR1]); break;
+ case CPUINFO_STR_REGISTER + PPC_EXIER: sprintf(info->s, "EXIER: %08X", ppc->dcr[DCR4XX_EXIER]); break;
+ case CPUINFO_STR_REGISTER + PPC_EXISR: sprintf(info->s, "EXISR: %08X", ppc->dcr[DCR4XX_EXISR]); break;
+ case CPUINFO_STR_REGISTER + PPC_EVPR: sprintf(info->s, "EVPR: %08X", ppc->spr[SPR4XX_EVPR]); break;
+ case CPUINFO_STR_REGISTER + PPC_IOCR: sprintf(info->s, "IOCR: %08X", ppc->dcr[DCR4XX_EXISR]); break;
+
+ case CPUINFO_STR_REGISTER + PPC_R0: sprintf(info->s, "R0: %08X", ppc->r[0]); break;
+ case CPUINFO_STR_REGISTER + PPC_R1: sprintf(info->s, "R1: %08X", ppc->r[1]); break;
+ case CPUINFO_STR_REGISTER + PPC_R2: sprintf(info->s, "R2: %08X", ppc->r[2]); break;
+ case CPUINFO_STR_REGISTER + PPC_R3: sprintf(info->s, "R3: %08X", ppc->r[3]); break;
+ case CPUINFO_STR_REGISTER + PPC_R4: sprintf(info->s, "R4: %08X", ppc->r[4]); break;
+ case CPUINFO_STR_REGISTER + PPC_R5: sprintf(info->s, "R5: %08X", ppc->r[5]); break;
+ case CPUINFO_STR_REGISTER + PPC_R6: sprintf(info->s, "R6: %08X", ppc->r[6]); break;
+ case CPUINFO_STR_REGISTER + PPC_R7: sprintf(info->s, "R7: %08X", ppc->r[7]); break;
+ case CPUINFO_STR_REGISTER + PPC_R8: sprintf(info->s, "R8: %08X", ppc->r[8]); break;
+ case CPUINFO_STR_REGISTER + PPC_R9: sprintf(info->s, "R9: %08X", ppc->r[9]); break;
+ case CPUINFO_STR_REGISTER + PPC_R10: sprintf(info->s, "R10:%08X", ppc->r[10]); break;
+ case CPUINFO_STR_REGISTER + PPC_R11: sprintf(info->s, "R11:%08X", ppc->r[11]); break;
+ case CPUINFO_STR_REGISTER + PPC_R12: sprintf(info->s, "R12:%08X", ppc->r[12]); break;
+ case CPUINFO_STR_REGISTER + PPC_R13: sprintf(info->s, "R13:%08X", ppc->r[13]); break;
+ case CPUINFO_STR_REGISTER + PPC_R14: sprintf(info->s, "R14:%08X", ppc->r[14]); break;
+ case CPUINFO_STR_REGISTER + PPC_R15: sprintf(info->s, "R15:%08X", ppc->r[15]); break;
+ case CPUINFO_STR_REGISTER + PPC_R16: sprintf(info->s, "R16:%08X", ppc->r[16]); break;
+ case CPUINFO_STR_REGISTER + PPC_R17: sprintf(info->s, "R17:%08X", ppc->r[17]); break;
+ case CPUINFO_STR_REGISTER + PPC_R18: sprintf(info->s, "R18:%08X", ppc->r[18]); break;
+ case CPUINFO_STR_REGISTER + PPC_R19: sprintf(info->s, "R19:%08X", ppc->r[19]); break;
+ case CPUINFO_STR_REGISTER + PPC_R20: sprintf(info->s, "R20:%08X", ppc->r[20]); break;
+ case CPUINFO_STR_REGISTER + PPC_R21: sprintf(info->s, "R21:%08X", ppc->r[21]); break;
+ case CPUINFO_STR_REGISTER + PPC_R22: sprintf(info->s, "R22:%08X", ppc->r[22]); break;
+ case CPUINFO_STR_REGISTER + PPC_R23: sprintf(info->s, "R23:%08X", ppc->r[23]); break;
+ case CPUINFO_STR_REGISTER + PPC_R24: sprintf(info->s, "R24:%08X", ppc->r[24]); break;
+ case CPUINFO_STR_REGISTER + PPC_R25: sprintf(info->s, "R25:%08X", ppc->r[25]); break;
+ case CPUINFO_STR_REGISTER + PPC_R26: sprintf(info->s, "R26:%08X", ppc->r[26]); break;
+ case CPUINFO_STR_REGISTER + PPC_R27: sprintf(info->s, "R27:%08X", ppc->r[27]); break;
+ case CPUINFO_STR_REGISTER + PPC_R28: sprintf(info->s, "R28:%08X", ppc->r[28]); break;
+ case CPUINFO_STR_REGISTER + PPC_R29: sprintf(info->s, "R29:%08X", ppc->r[29]); break;
+ case CPUINFO_STR_REGISTER + PPC_R30: sprintf(info->s, "R30:%08X", ppc->r[30]); break;
+ case CPUINFO_STR_REGISTER + PPC_R31: sprintf(info->s, "R31:%08X", ppc->r[31]); break;
+ }
+}
+
+
+
+/***************************************************************************
+ OEA HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ decrementer_int_callback - callback that fires
+ whenever a decrementer interrupt is generated
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( decrementer_int_callback )
+{
+ powerpc_state *ppc = ptr;
+ UINT64 cycles_until_next;
+
+ /* set the decrementer IRQ state */
+ ppc->irq_pending |= 0x02;
+
+ /* advance by another full rev */
+ ppc->dec_zero_cycles += (UINT64)ppc->tb_divisor << 32;
+ cycles_until_next = ppc->dec_zero_cycles - cpunum_gettotalcycles(ppc->cpunum);
+ timer_adjust_oneshot(ppc->decrementer_int_timer, ATTOTIME_IN_CYCLES(cycles_until_next, ppc->cpunum), 0);
+}
+
+
+
+/***************************************************************************
+ EMBEDDED 4XX HELPERS
+***************************************************************************/
+
+#if (HAS_PPC403GA || HAS_PPC403GCX)
+
+/*-------------------------------------------------
+ ppc4xx_set_irq_line - PowerPC 4XX-specific
+ IRQ line management
+-------------------------------------------------*/
+
+static void ppc4xx_set_irq_line(powerpc_state *ppc, UINT32 bitmask, int state)
+{
+ UINT32 oldstate = ppc->irqstate;
+ UINT32 levelmask;
+
+ /* set or clear the appropriate bit */
+ if (state != CLEAR_LINE)
+ ppc->irqstate |= bitmask;
+ else
+ ppc->irqstate &= ~bitmask;
+
+ /* if the state changed to on, edge trigger the interrupt */
+ if (((ppc->irqstate ^ oldstate) & bitmask) && (ppc->irqstate & bitmask))
+ ppc->dcr[DCR4XX_EXISR] |= bitmask;
+
+ /* pass through all level-triggered interrupts */
+ levelmask = PPC4XX_IRQ_BIT_CRITICAL | PPC4XX_IRQ_BIT_SPUR | PPC4XX_IRQ_BIT_SPUT;
+ levelmask |= PPC4XX_IRQ_BIT_JTAGR | PPC4XX_IRQ_BIT_JTAGT;
+ levelmask |= PPC4XX_IRQ_BIT_DMA0 | PPC4XX_IRQ_BIT_DMA1 | PPC4XX_IRQ_BIT_DMA2 | PPC4XX_IRQ_BIT_DMA3;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x80000000)) levelmask |= PPC4XX_IRQ_BIT_EXT0;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x20000000)) levelmask |= PPC4XX_IRQ_BIT_EXT1;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x08000000)) levelmask |= PPC4XX_IRQ_BIT_EXT2;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x02000000)) levelmask |= PPC4XX_IRQ_BIT_EXT3;
+ if (!(ppc->dcr[DCR4XX_IOCR] & 0x00800000)) levelmask |= PPC4XX_IRQ_BIT_EXT4;
+ ppc->dcr[DCR4XX_EXISR] = (ppc->dcr[DCR4XX_EXISR] & ~levelmask) | (ppc->irqstate & levelmask);
+
+ /* update the IRQ status */
+ ppc->irq_pending = ((ppc->dcr[DCR4XX_EXISR] & ppc->dcr[DCR4XX_EXIER]) != 0);
+ if ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_FIE) && (ppc->spr[SPR4XX_TSR] & PPC4XX_TSR_FIS))
+ ppc->irq_pending = TRUE;
+ if ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_PIE) && (ppc->spr[SPR4XX_TSR] & PPC4XX_TSR_PIS))
+ ppc->irq_pending = TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_get_irq_line - PowerPC 4XX-specific
+ IRQ line state getter
+-------------------------------------------------*/
+
+static int ppc4xx_get_irq_line(powerpc_state *ppc, UINT32 bitmask)
+{
+ return (ppc->irqstate & bitmask) ? ASSERT_LINE : CLEAR_LINE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_update_irq_states - update the IRQ
+ state for each DMA channel
+-------------------------------------------------*/
+
+static void ppc4xx_dma_update_irq_states(powerpc_state *ppc)
+{
+ int dmachan;
+
+ /* update the IRQ state for each DMA channel */
+ for (dmachan = 0; dmachan < 4; dmachan++)
+ if ((ppc->dcr[DCR4XX_DMACR0 + 8 * dmachan] & PPC4XX_DMACR_CIE) && (ppc->dcr[DCR4XX_DMASR] & (1 << (27 - dmachan))))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_DMA(dmachan), ASSERT_LINE);
+ else
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_DMA(dmachan), CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_decrement_count - decrement the
+ count on a channel and interrupt if configured
+ to do so
+-------------------------------------------------*/
+
+static int ppc4xx_dma_decrement_count(powerpc_state *ppc, int dmachan)
+{
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+
+ /* decrement the counter */
+ dmaregs[DCR4XX_DMACT0]--;
+
+ /* if non-zero, we keep going */
+ if ((dmaregs[DCR4XX_DMACT0] & 0xffff) != 0)
+ return FALSE;
+
+ /* set the complete bit and handle interrupts */
+ ppc->dcr[DCR4XX_DMASR] |= 1 << (27 - dmachan);
+ ppc4xx_dma_update_irq_states(ppc);
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_fetch_transmit_byte - fetch a byte
+ to send to a peripheral
+-------------------------------------------------*/
+
+static int ppc4xx_dma_fetch_transmit_byte(powerpc_state *ppc, int dmachan, UINT8 *byte)
+{
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+
+ /* if the channel is not enabled, fail */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CE))
+ return FALSE;
+
+ /* if no transfers remaining, fail */
+ if ((dmaregs[DCR4XX_DMACT0] & 0xffff) == 0)
+ return FALSE;
+
+ /* fetch the data */
+ cpuintrf_push_context(ppc->cpunum);
+ *byte = program_read_byte(dmaregs[DCR4XX_DMADA0]++);
+ ppc4xx_dma_decrement_count(ppc, dmachan);
+ cpuintrf_pop_context();
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_handle_receive_byte - receive a byte
+ transmitted by a peripheral
+-------------------------------------------------*/
+
+static int ppc4xx_dma_handle_receive_byte(powerpc_state *ppc, int dmachan, UINT8 byte)
+{
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+
+ /* if the channel is not enabled, fail */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CE))
+ return FALSE;
+
+ /* if no transfers remaining, fail */
+ if ((dmaregs[DCR4XX_DMACT0] & 0xffff) == 0)
+ return FALSE;
+
+ /* store the data */
+ cpuintrf_push_context(ppc->cpunum);
+ program_write_byte(dmaregs[DCR4XX_DMADA0]++, byte);
+ ppc4xx_dma_decrement_count(ppc, dmachan);
+ cpuintrf_pop_context();
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_dma_execute - execute a DMA operation
+ if one is pending
+-------------------------------------------------*/
+
+static void ppc4xx_dma_exec(powerpc_state *ppc, int dmachan)
+{
+ static const UINT8 dma_transfer_width[4] = { 1, 2, 4, 16 };
+ UINT32 *dmaregs = &ppc->dcr[8 * dmachan];
+ INT32 destinc, srcinc;
+ UINT8 width;
+
+ /* skip if not enabled */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CE))
+ return;
+
+ /* check for unsupported features */
+ if (!(dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_TCE))
+ fatalerror("ppc4xx_dma_exec: DMA_TCE == 0");
+ if (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_CH)
+ fatalerror("ppc4xx_dma_exec: DMA chaining not implemented");
+
+ /* transfer mode */
+ switch ((dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_TM_MASK) >> 21)
+ {
+ /* buffered mode DMA */
+ case 0:
+ /* nothing to do; this happens asynchronously and is driven by the SPU */
+ break;
+
+ /* fly-by mode DMA */
+ case 1:
+ fatalerror("ppc4xx_dma_exec: fly-by DMA not implemented");
+ break;
+
+ /* software initiated memory-to-memory mode DMA */
+ case 2:
+ width = dma_transfer_width[(dmaregs[DCR4XX_DMACR0] >> 26) & 0x3];
+ srcinc = (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_SAI) ? width : 0;
+ destinc = (dmaregs[DCR4XX_DMACR0] & PPC4XX_DMACR_DAI) ? width : 0;
+
+ switch (width)
+ {
+ /* byte transfer */
+ case 1:
+ do
+ {
+ program_write_byte(dmaregs[DCR4XX_DMADA0], program_read_byte(dmaregs[DCR4XX_DMASA0]));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* word transfer */
+ case 2:
+ do
+ {
+ program_write_word(dmaregs[DCR4XX_DMADA0], program_read_word(dmaregs[DCR4XX_DMASA0]));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* dword transfer */
+ case 4:
+ do
+ {
+ program_write_dword(dmaregs[DCR4XX_DMADA0], program_read_dword(dmaregs[DCR4XX_DMASA0]));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+
+ /* 16-byte transfer */
+ case 16:
+ do
+ {
+ program_write_qword(dmaregs[DCR4XX_DMADA0], program_read_qword(dmaregs[DCR4XX_DMASA0]));
+ program_write_qword(dmaregs[DCR4XX_DMADA0] + 8, program_read_qword(dmaregs[DCR4XX_DMASA0] + 8));
+ dmaregs[DCR4XX_DMASA0] += srcinc;
+ dmaregs[DCR4XX_DMADA0] += destinc;
+ } while (!ppc4xx_dma_decrement_count(ppc, dmachan));
+ break;
+ }
+ break;
+
+ /* hardware initiated memory-to-memory mode DMA */
+ case 3:
+ fatalerror("ppc4xx_dma_exec: HW mem-to-mem DMA not implemented");
+ break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_fit_callback - FIT timer callback
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( ppc4xx_fit_callback )
+{
+ powerpc_state *ppc = ptr;
+
+ /* if this is a real callback and we are enabled, signal an interrupt */
+ if (param)
+ {
+ ppc->spr[SPR4XX_TSR] |= PPC4XX_TSR_FIS;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ }
+
+ /* update ourself for the next interval if we are enabled */
+ if (ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_FIE)
+ {
+ UINT32 timebase = get_timebase(ppc);
+ UINT32 interval = 0x200 << (4 * ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_FP_MASK) >> 24));
+ UINT32 target = (timebase + interval) & ~(interval - 1);
+ timer_adjust_oneshot(ppc->fit_timer, ATTOTIME_IN_CYCLES((target + 1 - timebase) / ppc->tb_divisor, ppc->cpunum), TRUE);
+ }
+
+ /* otherwise, turn ourself off */
+ else
+ timer_adjust_oneshot(ppc->fit_timer, attotime_never, FALSE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_pit_callback - PIT timer callback
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( ppc4xx_pit_callback )
+{
+ powerpc_state *ppc = ptr;
+
+ /* if this is a real callback and we are enabled, signal an interrupt */
+ if (param)
+ {
+ ppc->spr[SPR4XX_TSR] |= PPC4XX_TSR_PIS;
+ ppc4xx_set_irq_line(ppc, 0, 0);
+ }
+
+ /* update ourself for the next interval if we are enabled and we are either being
+ forced to update, or we are in auto-reload mode */
+ if ((ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_PIE) && ppc->pit_reload != 0 && (!param || (ppc->spr[SPR4XX_TCR] & PPC4XX_TCR_ARE)))
+ {
+ UINT32 timebase = get_timebase(ppc);
+ UINT32 interval = ppc->pit_reload;
+ UINT32 target = timebase + interval;
+ timer_adjust_oneshot(ppc->pit_timer, ATTOTIME_IN_CYCLES((target + 1 - timebase) / ppc->tb_divisor, ppc->cpunum), TRUE);
+ }
+
+ /* otherwise, turn ourself off */
+ else
+ timer_adjust_oneshot(ppc->pit_timer, attotime_never, FALSE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_update_irq_states - update the IRQ
+ state for the SPU
+-------------------------------------------------*/
+
+static void ppc4xx_spu_update_irq_states(powerpc_state *ppc)
+{
+ /* check for receive buffer full interrupt */
+ if ((ppc->spu.regs[SPU4XX_RX_COMMAND] & 0x60) == 0x20 && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x80))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUR, ASSERT_LINE);
+
+ /* check for receive error interrupt */
+ else if ((ppc->spu.regs[SPU4XX_RX_COMMAND] & 0x10) && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x78))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUR, ASSERT_LINE);
+
+ /* clear otherwise */
+ else
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUR, CLEAR_LINE);
+
+ /* check for transmit buffer empty interrupt */
+ if ((ppc->spu.regs[SPU4XX_TX_COMMAND] & 0x60) == 0x20 && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x04))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUT, ASSERT_LINE);
+
+ /* check for shift register empty interrupt */
+ else if ((ppc->spu.regs[SPU4XX_TX_COMMAND] & 0x10) && (ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x02))
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUT, ASSERT_LINE);
+
+ /* clear otherwise */
+ else
+ ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_SPUT, CLEAR_LINE);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_rx_data - serial port data receive
+-------------------------------------------------*/
+
+static void ppc4xx_spu_rx_data(powerpc_state *ppc, UINT8 data)
+{
+ fatalerror("ppc4xx_spu_rx_data unimplemented\n");
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_timer_reset - reset and recompute
+ the transmit/receive timer
+-------------------------------------------------*/
+
+static void ppc4xx_spu_timer_reset(powerpc_state *ppc)
+{
+ UINT8 enabled = (ppc->spu.regs[SPU4XX_RX_COMMAND] | ppc->spu.regs[SPU4XX_TX_COMMAND]) & 0x80;
+
+ /* if we're enabled, reset at the current baud rate */
+ if (enabled)
+ {
+ attotime clockperiod = ATTOTIME_IN_HZ((ppc->dcr[DCR4XX_IOCR] & 0x02) ? 3686400 : 33333333);
+ int divisor = ((ppc->spu.regs[SPU4XX_BAUD_DIVISOR_H] * 256 + ppc->spu.regs[SPU4XX_BAUD_DIVISOR_L]) & 0xfff) + 1;
+ int bpc = 7 + ((ppc->spu.regs[SPU4XX_CONTROL] & 8) >> 3) + 1 + (ppc->spu.regs[SPU4XX_CONTROL] & 1);
+ attotime charperiod = attotime_mul(clockperiod, divisor * 16 * bpc);
+ timer_adjust_periodic(ppc->spu.timer, charperiod, 0, charperiod);
+ if (PRINTF_SPU)
+ mame_printf_debug("ppc4xx_spu_timer_reset: baud rate = %.0f\n", ATTOSECONDS_TO_HZ(charperiod.attoseconds) * bpc);
+ }
+
+ /* otherwise, disable the timer */
+ else
+ timer_adjust_oneshot(ppc->spu.timer, attotime_never, 0);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_callback - serial port send/receive
+ timer
+-------------------------------------------------*/
+
+static TIMER_CALLBACK( ppc4xx_spu_callback )
+{
+ powerpc_state *ppc = ptr;
+ UINT8 rxbyte;
+
+ /* transmit enabled? */
+ if (ppc->spu.regs[SPU4XX_TX_COMMAND] & 0x80)
+ {
+ int operation = (ppc->spu.regs[SPU4XX_TX_COMMAND] >> 5) & 3;
+
+ /* if we have data to transmit, do it now */
+ if (!(ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x04))
+ {
+ /* if we have a transmit handler, send it that way */
+ if (ppc->spu.tx_handler != NULL)
+ (*ppc->spu.tx_handler)(ppc->spu.txbuf);
+
+ /* indicate that we have moved it to the shift register */
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x04;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x02;
+ }
+
+ /* otherwise, clear the shift register */
+ else if (!(ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x02))
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x02;
+
+ /* handle DMA */
+ if (operation >= 2 && ppc4xx_dma_fetch_transmit_byte(ppc, operation, &ppc->spu.txbuf))
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x04;
+ }
+
+ /* receive enabled? */
+ if (ppc->spu.regs[SPU4XX_RX_COMMAND] & 0x80)
+ if (ppc->spu.rx_handler != NULL && (*ppc->spu.rx_handler)(&rxbyte))
+ {
+ int operation = (ppc->spu.regs[SPU4XX_RX_COMMAND] >> 5) & 3;
+
+ /* if we're not full, copy data to the buffer and update the line status */
+ if (!(ppc->spu.regs[SPU4XX_LINE_STATUS] & 0x80))
+ {
+ ppc->spu.rxbuf = rxbyte;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x80;
+ }
+
+ /* otherwise signal an overrun */
+ else
+ {
+ ppc->spu.regs[SPU4XX_LINE_STATUS] |= 0x20;
+ goto updateirq;
+ }
+
+ /* handle DMA */
+ if (operation >= 2 && ppc4xx_dma_handle_receive_byte(ppc, operation, ppc->spu.rxbuf))
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x80;
+ }
+
+ /* update the final IRQ states */
+updateirq:
+ ppc4xx_spu_update_irq_states(ppc);
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_r - serial port read handler
+-------------------------------------------------*/
+
+static READ8_HANDLER( ppc4xx_spu_r )
+{
+ powerpc_state *ppc = activecpu_get_info_ptr(CPUINFO_PTR_CONTEXT);
+ UINT8 result = 0xff;
+
+ switch (offset)
+ {
+ case SPU4XX_BUFFER:
+ result = ppc->spu.rxbuf;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x80;
+ break;
+
+ default:
+ if (offset < ARRAY_LENGTH(ppc->spu.regs))
+ result = ppc->spu.regs[offset];
+ break;
+ }
+ if (PRINTF_SPU)
+ mame_printf_debug("spu_r(%d) = %02X\n", offset, result);
+ return result;
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_spu_w - serial port write handler
+-------------------------------------------------*/
+
+static WRITE8_HANDLER( ppc4xx_spu_w )
+{
+ powerpc_state *ppc = activecpu_get_info_ptr(CPUINFO_PTR_CONTEXT);
+ UINT8 oldstate, newstate;
+
+ if (PRINTF_SPU)
+ mame_printf_debug("spu_w(%d) = %02X\n", offset, data);
+ switch (offset)
+ {
+ /* clear error bits */
+ case SPU4XX_LINE_STATUS:
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~(data & 0xf8);
+ ppc4xx_spu_update_irq_states(ppc);
+ break;
+
+ /* enable/disable the timer if one of these is enabled */
+ case SPU4XX_RX_COMMAND:
+ case SPU4XX_TX_COMMAND:
+ oldstate = ppc->spu.regs[SPU4XX_RX_COMMAND] | ppc->spu.regs[SPU4XX_TX_COMMAND];
+ ppc->spu.regs[offset] = data;
+ newstate = ppc->spu.regs[SPU4XX_RX_COMMAND] | ppc->spu.regs[SPU4XX_TX_COMMAND];
+ if ((oldstate ^ newstate) & 0x80)
+ ppc4xx_spu_timer_reset(ppc);
+ ppc4xx_spu_update_irq_states(ppc);
+ break;
+
+ /* if the divisor changes, we need to update the timer */
+ case SPU4XX_BAUD_DIVISOR_H:
+ case SPU4XX_BAUD_DIVISOR_L:
+ if (data != ppc->spu.regs[offset])
+ {
+ ppc->spu.regs[offset] = data;
+ ppc4xx_spu_timer_reset(ppc);
+ }
+ break;
+
+ /* if the number of data bits or stop bits changes, we need to update the timer */
+ case SPU4XX_CONTROL:
+ oldstate = ppc->spu.regs[offset];
+ ppc->spu.regs[offset] = data;
+ if ((oldstate ^ data) & 0x09)
+ ppc4xx_spu_timer_reset(ppc);
+ break;
+
+ break;
+
+ case SPU4XX_BUFFER:
+ /* write to the transmit buffer and mark it full */
+ ppc->spu.txbuf = data;
+ ppc->spu.regs[SPU4XX_LINE_STATUS] &= ~0x04;
+ break;
+
+ default:
+ if (offset < ARRAY_LENGTH(ppc->spu.regs))
+ ppc->spu.regs[offset] = data;
+ break;
+ }
+}
+
+
+
+/*-------------------------------------------------
+ internal_ppc4xx - internal address map for
+ the 4XX
+-------------------------------------------------*/
+
+static ADDRESS_MAP_START( internal_ppc4xx, ADDRESS_SPACE_PROGRAM, 32 )
+ AM_RANGE(0x40000000, 0x4000000f) AM_READWRITE8(ppc4xx_spu_r, ppc4xx_spu_w, 0xffffffff)
+ADDRESS_MAP_END
+
+
+
+/*-------------------------------------------------
+ ppc4xx_set_info - PowerPC 4XX-specific
+ information setter
+-------------------------------------------------*/
+
+void ppc4xx_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_0: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_1: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_2: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_3: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT3, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_4: ppc4xx_set_irq_line(ppc, PPC4XX_IRQ_BIT_EXT4, info->i); break;
+ case CPUINFO_INT_PPC_RX_DATA: ppc4xx_spu_rx_data(ppc, info->i); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SPU_RX_HANDLER: ppc->spu.rx_handler = (ppc4xx_spu_rx_handler)info->f; break;
+ case CPUINFO_PTR_SPU_TX_HANDLER: ppc->spu.tx_handler = (ppc4xx_spu_tx_handler)info->f; break;
+
+ /* --- everything else is handled generically --- */
+ default: ppccom_set_info(ppc, state, info); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppc4xx_get_info - PowerPC 4XX-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc4xx_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_0: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT0); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_1: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT1); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_2: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT2); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_3: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT3); break;
+ case CPUINFO_INT_INPUT_STATE + PPC_IRQ_LINE_4: info->i = ppc4xx_get_irq_line(ppc, PPC4XX_IRQ_BIT_EXT4); break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
+ case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+ case CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: /* provided per-CPU */ break;
+ case CPUINFO_PTR_INTERNAL_MEMORY_MAP + ADDRESS_SPACE_PROGRAM: info->internal_map32 = address_map_internal_ppc4xx; break;
+
+ /* --- everything else is handled generically --- */
+ default: ppccom_get_info(ppc, state, info); break;
+ }
+}
+
+#endif
diff --git a/src/emu/cpu/powerpc/ppccom.h b/src/emu/cpu/powerpc/ppccom.h
new file mode 100644
index 00000000000..9f78534c559
--- /dev/null
+++ b/src/emu/cpu/powerpc/ppccom.h
@@ -0,0 +1,611 @@
+/***************************************************************************
+
+ ppccom.h
+
+ Common PowerPC definitions and functions
+
+***************************************************************************/
+
+#ifndef __PPCCOM_H__
+#define __PPCCOM_H__
+
+#include "cpuintrf.h"
+#include "ppc.h"
+
+
+/***************************************************************************
+ WIDE-SCALE CONTROLS
+***************************************************************************/
+
+#define SIMULATE_603_TLB (0)
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* core parameters */
+#define POWERPC_MIN_PAGE_SHIFT 12
+#define POWERPC_MIN_PAGE_SIZE (1 << POWERPC_MIN_PAGE_SHIFT)
+#define POWERPC_MIN_PAGE_MASK (POWERPC_MIN_PAGE_SIZE - 1)
+#define POWERPC_TLB_ENTRIES 128
+#define PPC603_FIXED_TLB_ENTRIES 128
+
+
+/* internal capabilities flags */
+#define PPCCAP_OEA 0x01 /* TRUE if we conform to the OEA */
+#define PPCCAP_VEA 0x02 /* TRUE if we conform to the VEA */
+#define PPCCAP_FPU 0x04 /* TRUE if we have an FPU */
+#define PPCCAP_MISALIGNED 0x08 /* TRUE if misaligned accesses are supported */
+#define PPCCAP_4XX 0x10 /* TRUE if we are a non-OEA 4XX class chip */
+#define PPCCAP_603_MMU 0x20 /* TRUE if we have 603-class MMU features */
+
+
+/* bits in our internal TLB */
+#define TLB_READ 0x01 /* reads are allowed */
+#define TLB_WRITE 0x02 /* writes are allowed */
+
+
+/* PowerPC flavors */
+enum _powerpc_flavor
+{
+ PPC_MODEL_403GA = 0x00200000,
+ PPC_MODEL_403GB = 0x00200100,
+ PPC_MODEL_403GC = 0x00200200,
+ PPC_MODEL_403GCX = 0x00201400,
+ PPC_MODEL_405GP = 0x40110000,
+ PPC_MODEL_601 = 0x00010000,
+ PPC_MODEL_603 = 0x00030000, /* "Wart" */
+ PPC_MODEL_604 = 0x00040000, /* "Zephyr" */
+ PPC_MODEL_602 = 0x00050200, /* "Galahad" */
+ PPC_MODEL_603E = 0x00060103, /* "Stretch", version 1.3 */
+ PPC_MODEL_603EV = 0x00070000, /* "Valiant" */
+ PPC_MODEL_603R = 0x00071202, /* "Goldeneye", version 2.1 */
+ PPC_MODEL_740 = 0x00080301, /* "Arthur", version 3.1 */
+ PPC_MODEL_750 = PPC_MODEL_740,
+ PPC_MODEL_740P = 0x00080202, /* "Conan Doyle", version 1.2 */
+ PPC_MODEL_750P = PPC_MODEL_740P,
+ PPC_MODEL_755 = 0x00083203, /* "Goldfinger", version 2.3 */
+ PPC_MODEL_7400 = 0x000c0209, /* "Max", version 2.9 */
+ PPC_MODEL_7410 = 0x800c1104, /* "Nitro", version 3.4 */
+ PPC_MODEL_7450 = 0x80000201, /* "Vger", version 2.1 */
+ PPC_MODEL_7451 = 0x80000203, /* "Vger", version 2.3 */
+ PPC_MODEL_7441 = PPC_MODEL_7451,
+ PPC_MODEL_7455 = 0x80010303, /* "Apollo 6", version 3.3 */
+ PPC_MODEL_7445 = PPC_MODEL_7455,
+ PPC_MODEL_7457 = 0x80020101, /* "Apollo 7", version 1.1 */
+ PPC_MODEL_MPC8240 = 0x00810101, /* "Kahlua" */
+ PPC_MODEL_MPC8241 = 0x80811014, /* "Kahlua Lt" */
+ PPC_MODEL_MPC8245 = 0x80811014, /* "Kahlua II" */
+};
+typedef enum _powerpc_flavor powerpc_flavor;
+
+
+/* exception types */
+enum
+{
+ EXCEPTION_RESET = 1,
+ EXCEPTION_MACHCHECK = 2,
+ EXCEPTION_DSI = 3,
+ EXCEPTION_ISI = 4,
+ EXCEPTION_EI = 5,
+ EXCEPTION_ALIGN = 6,
+ EXCEPTION_PROGRAM = 7,
+ EXCEPTION_NOFPU = 8,
+ EXCEPTION_DECREMENT = 9,
+ EXCEPTION_SYSCALL = 12,
+ EXCEPTION_TRACE = 13,
+ EXCEPTION_FPASSIST = 14,
+ EXCEPTION_ITLBMISS = 16, /* PPCCAP_603_MMU */
+ EXCEPTION_DTLBMISSL = 17, /* PPCCAP_603_MMU */
+ EXCEPTION_DTLBMISSS = 18, /* PPCCAP_603_MMU */
+ EXCEPTION_COUNT
+};
+
+
+/* SPRs */
+enum
+{
+ /* UISA SPR register indexes */
+ SPR_XER = 0x001, /* R/W Fixed Point Exception Register */
+ SPR_LR = 0x008, /* R/W Link Register */
+ SPR_CTR = 0x009, /* R/W Count Register */
+
+ /* VEA SPR register indexes */
+ SPRVEA_TBL_R = 0x10c, /* R Time Base Low */
+ SPRVEA_TBU_R = 0x10d, /* R Time Base High */
+
+ /* OEA SPR register indexes */
+ SPROEA_DSISR = 0x012, /* R/W DSI Status Register */
+ SPROEA_DAR = 0x013, /* R/W Data Address Register */
+ SPROEA_DEC = 0x016, /* R/W Decrementer Register */
+ SPROEA_SDR1 = 0x019, /* R/W Page Table Configuration */
+ SPROEA_SRR0 = 0x01a, /* R/W Machine Status Save/Restore Register 0 */
+ SPROEA_SRR1 = 0x01b, /* R/W Machine Status Save/Restore Register 1 */
+ SPROEA_SPRG0 = 0x110, /* R/W SPR General 0 */
+ SPROEA_SPRG1 = 0x111, /* R/W SPR General 1 */
+ SPROEA_SPRG2 = 0x112, /* R/W SPR General 2 */
+ SPROEA_SPRG3 = 0x113, /* R/W SPR General 3 */
+ SPROEA_ASR = 0x118, /* R/W Address Space Register (64-bit only) */
+ SPROEA_EAR = 0x11a, /* R/W External Access Register */
+ SPROEA_PVR = 0x11f, /* R Processor Version Number */
+ SPROEA_IBAT0U = 0x210, /* R/W Instruction BAT 0 Upper */
+ SPROEA_IBAT0L = 0x211, /* R/W Instruction BAT 0 Lower */
+ SPROEA_IBAT1U = 0x212, /* R/W Instruction BAT 1 Upper */
+ SPROEA_IBAT1L = 0x213, /* R/W Instruction BAT 1 Lower */
+ SPROEA_IBAT2U = 0x214, /* R/W Instruction BAT 2 Upper */
+ SPROEA_IBAT2L = 0x215, /* R/W Instruction BAT 2 Lower */
+ SPROEA_IBAT3U = 0x216, /* R/W Instruction BAT 3 Upper */
+ SPROEA_IBAT3L = 0x217, /* R/W Instruction BAT 3 Lower */
+ SPROEA_DBAT0U = 0x218, /* R/W Data BAT 0 Upper */
+ SPROEA_DBAT0L = 0x219, /* R/W Data BAT 0 Lower */
+ SPROEA_DBAT1U = 0x21a, /* R/W Data BAT 1 Upper */
+ SPROEA_DBAT1L = 0x21b, /* R/W Data BAT 1 Lower */
+ SPROEA_DBAT2U = 0x21c, /* R/W Data BAT 2 Upper */
+ SPROEA_DBAT2L = 0x21d, /* R/W Data BAT 2 Lower */
+ SPROEA_DBAT3U = 0x21e, /* R/W Data BAT 3 Upper */
+ SPROEA_DBAT3L = 0x21f, /* R/W Data BAT 3 Lower */
+ SPROEA_DABR = 0x3f5, /* R/W Data Address Breakpoint Register */
+
+ /* PowerPC 4XX SPR register indexes */
+ SPR4XX_SRR0 = 0x01a, /* R/W 403GA Machine Status Save/Restore Register 0 */
+ SPR4XX_SRR1 = 0x01b, /* R/W 403GA Machine Status Save/Restore Register 1 */
+ SPR4XX_SPRG0 = 0x110, /* R/W 403GA SPR General 0 */
+ SPR4XX_SPRG1 = 0x111, /* R/W 403GA SPR General 1 */
+ SPR4XX_SPRG2 = 0x112, /* R/W 403GA SPR General 2 */
+ SPR4XX_SPRG3 = 0x113, /* R/W 403GA SPR General 3 */
+ SPR4XX_PVR = 0x11f, /* R 403GA Processor Version Number */
+ SPR4XX_SGR = 0x3b9, /* R/W 403GCX Storage Guarded Register */
+ SPR4XX_DCWR = 0x3ba, /* R/W 403GCX Data Cache Write Through */
+ SPR4XX_PID = 0x3b1, /* R/W 403GCX Process ID */
+ SPR4XX_TBHU = 0x3cc, /* R/W 403GCX Time Base High User-mode */
+ SPR4XX_TBLU = 0x3cd, /* R/W 403GCX Time Base Low User-mode */
+ SPR4XX_ICDBDR = 0x3d3, /* R 403GA 406GA Instruction Cache Debug Data Register */
+ SPR4XX_ESR = 0x3d4, /* R/W 403GA 406GA Exception Syndrome Register */
+ SPR4XX_DEAR = 0x3d5, /* R 403GA 406GA Data Exception Address Register */
+ SPR4XX_EVPR = 0x3d6, /* R/W 403GA 406GA Exception Vector Prefix Register */
+ SPR4XX_CDBCR = 0x3d7, /* R/W 403GA 406GA Cache Debug Control Register */
+ SPR4XX_TSR = 0x3d8, /* R/C 403GA 406GA Timer Status Register */
+ SPR4XX_TCR = 0x3da, /* R/W 403GA 406GA Timer Control Register */
+ SPR4XX_PIT = 0x3db, /* R/W 403GA 406GA Programmable Interval Timer */
+ SPR4XX_TBHI = 0x3dc, /* R/W 403GA 406GA Time Base High */
+ SPR4XX_TBLO = 0x3dd, /* R/W 403GA 406GA Time Base Low */
+ SPR4XX_SRR2 = 0x3de, /* R/W 403GA 406GA Machine Status Save/Restore Register 2 */
+ SPR4XX_SRR3 = 0x3df, /* R/W 403GA 406GA Machine Status Save/Restore Register 3 */
+ SPR4XX_DBSR = 0x3f0, /* R/C 403GA 406GA Debug Status Register */
+ SPR4XX_DBCR = 0x3f2, /* R/W 403GA 406GA Debug Control Register */
+ SPR4XX_IAC1 = 0x3f4, /* R/W 403GA 406GA Instruction Address Compare 1 */
+ SPR4XX_IAC2 = 0x3f5, /* R/W 403GA 406GA Instruction Address Compare 2 */
+ SPR4XX_DAC1 = 0x3f6, /* R/W 403GA 406GA Data Address Compare 1 */
+ SPR4XX_DAC2 = 0x3f7, /* R/W 403GA 406GA Data Address Compare 2 */
+ SPR4XX_DCCR = 0x3fa, /* R/W 403GA 406GA Data Cache Cacheability Register */
+ SPR4XX_ICCR = 0x3fb, /* R/W 403GA 406GA Instruction Cache Cacheability Registe */
+ SPR4XX_PBL1 = 0x3fc, /* R/W 403GA 406GA Protection Bound Lower 1 */
+ SPR4XX_PBU1 = 0x3fd, /* R/W 403GA 406GA Protection Bound Upper 1 */
+ SPR4XX_PBL2 = 0x3fe, /* R/W 403GA 406GA Protection Bound Lower 2 */
+ SPR4XX_PBU2 = 0x3ff, /* R/W 403GA 406GA Protection Bound Upper 2 */
+
+ /* PowerPC 602 SPR register indexes */
+ SPR602_TCR = 0x3d8, /* 602 */
+ SPR602_IBR = 0x3da, /* 602 */
+ SPR602_ESASRR = 0x3db, /* 602 */
+ SPR602_SEBR = 0x3de, /* 602 */
+ SPR602_SER = 0x3df, /* 602 */
+ SPR602_SP = 0x3fd, /* 602 */
+ SPR602_LT = 0x3fe, /* 602 */
+
+ /* PowerPC 603 SPR register indexes */
+ SPR603_TBL_R = 0x10c, /* R 603 Time Base Low (Read-only) */
+ SPR603_TBU_R = 0x10d, /* R 603 Time Base High (Read-only) */
+ SPR603_TBL_W = 0x11c, /* W 603 Time Base Low (Write-only) */
+ SPR603_TBU_W = 0x11d, /* W 603 Time Base Hight (Write-only) */
+ SPR603_DMISS = 0x3d0, /* R 603 Data TLB Miss Address Register */
+ SPR603_DCMP = 0x3d1, /* R 603 Data TLB Compare Register */
+ SPR603_HASH1 = 0x3d2, /* R 603 Primary Hash Address Register */
+ SPR603_HASH2 = 0x3d3, /* R 603 Secondary Hash Address Register */
+ SPR603_IMISS = 0x3d4, /* R 603 Instruction TLB Miss Address Register */
+ SPR603_ICMP = 0x3d5, /* R 603 Instruction TLB Compare Register */
+ SPR603_RPA = 0x3d6, /* R/W 603 Required Physical Address Register */
+ SPR603_HID0 = 0x3f0, /* R/W 603 Hardware Implementation Register 0 */
+ SPR603_HID1 = 0x3f1, /* R/W 603 Hardware Implementation Register 1 */
+ SPR603_IABR = 0x3f2, /* R/W 603 Instruction Address Breakpoint Register */
+ SPR603_HID2 = 0x3f3 /* R/W 603 */
+};
+
+
+/* PowerPC 4XX DCR register indexes */
+enum
+{
+ DCR4XX_EXISR = 0x040, /* external interrupt status */
+ DCR4XX_EXIER = 0x042, /* external interrupt enable */
+ DCR4XX_BR0 = 0x080, /* bank */
+ DCR4XX_BR1 = 0x081, /* bank */
+ DCR4XX_BR2 = 0x082, /* bank */
+ DCR4XX_BR3 = 0x083, /* bank */
+ DCR4XX_BR4 = 0x084, /* bank */
+ DCR4XX_BR5 = 0x085, /* bank */
+ DCR4XX_BR6 = 0x086, /* bank */
+ DCR4XX_BR7 = 0x087, /* bank */
+ DCR4XX_BEAR = 0x090, /* bus error address */
+ DCR4XX_BESR = 0x091, /* bus error syndrome */
+ DCR4XX_IOCR = 0x0a0, /* io configuration */
+ DCR4XX_DMACR0 = 0x0c0, /* dma channel control */
+ DCR4XX_DMACT0 = 0x0c1, /* dma destination address */
+ DCR4XX_DMADA0 = 0x0c2, /* dma destination address */
+ DCR4XX_DMASA0 = 0x0c3, /* dma source address */
+ DCR4XX_DMACC0 = 0x0c4, /* dma chained count */
+ DCR4XX_DMACR1 = 0x0c8, /* dma channel control */
+ DCR4XX_DMACT1 = 0x0c9, /* dma destination address */
+ DCR4XX_DMADA1 = 0x0ca, /* dma destination address */
+ DCR4XX_DMASA1 = 0x0cb, /* dma source address */
+ DCR4XX_DMACC1 = 0x0cc, /* dma chained count */
+ DCR4XX_DMACR2 = 0x0d0, /* dma channel control */
+ DCR4XX_DMACT2 = 0x0d1, /* dma destination address */
+ DCR4XX_DMADA2 = 0x0d2, /* dma source address */
+ DCR4XX_DMASA2 = 0x0d3, /* dma source address */
+ DCR4XX_DMACC2 = 0x0d4, /* dma chained count */
+ DCR4XX_DMACR3 = 0x0d8, /* dma channel control */
+ DCR4XX_DMACT3 = 0x0d9, /* dma destination address */
+ DCR4XX_DMADA3 = 0x0da, /* dma source address */
+ DCR4XX_DMASA3 = 0x0db, /* dma source address */
+ DCR4XX_DMACC3 = 0x0dc, /* dma chained count */
+ DCR4XX_DMASR = 0x0e0 /* dma status */
+};
+
+
+/* PowerPC 4XX SPU register indexes */
+enum
+{
+ SPU4XX_LINE_STATUS = 0x00,
+ SPU4XX_HANDSHAKE_STATUS = 0x02,
+ SPU4XX_BAUD_DIVISOR_H = 0x04,
+ SPU4XX_BAUD_DIVISOR_L = 0x05,
+ SPU4XX_CONTROL = 0x06,
+ SPU4XX_RX_COMMAND = 0x07,
+ SPU4XX_TX_COMMAND = 0x08,
+ SPU4XX_BUFFER = 0x09
+};
+
+
+/* FPSCR register bits */
+#define FPSCR_FX 0x80000000
+#define FPSCR_FEX 0x40000000
+#define FPSCR_VX 0x20000000
+#define FPSCR_OX 0x10000000
+#define FPSCR_UX 0x08000000
+#define FPSCR_ZX 0x04000000
+#define FPSCR_XX 0x02000000
+
+
+/* XER register bits */
+#define XER_SO 0x80000000
+#define XER_OV 0x40000000
+#define XER_CA 0x20000000
+
+
+/* Machine State Register bits - common */
+#define MSR_ILE 0x00010000 /* Interrupt Little Endian Mode */
+#define MSR_EE 0x00008000 /* External Interrupt Enable */
+#define MSR_PR 0x00004000 /* Problem State */
+#define MSR_ME 0x00001000 /* Machine Check Enable */
+#define MSR_LE 0x00000001 /* Little Endian */
+
+/* Machine State Register bits - OEA */
+#define MSROEA_POW 0x00040000 /* Power Management Enable */
+#define MSROEA_FP 0x00002000 /* Floating Point Available */
+#define MSROEA_FE0 0x00000800 /* FP Exception Mode 0 */
+#define MSROEA_SE 0x00000400 /* Single Step Trace Enable */
+#define MSROEA_BE 0x00000200 /* Branch Trace Enable */
+#define MSROEA_FE1 0x00000100 /* FP Exception Mode 1 */
+#define MSROEA_IP 0x00000040 /* Interrupt Prefix */
+#define MSROEA_IR 0x00000020 /* Instruction Relocate */
+#define MSROEA_DR 0x00000010 /* Data Relocate */
+#define MSROEA_RI 0x00000002 /* Recoverable Interrupt Enable */
+
+/* Machine State Register bits - 4XX */
+#define MSR4XX_WE 0x00040000 /* Wait State Enable */
+#define MSR4XX_CE 0x00020000 /* Critical Interrupt Enable */
+#define MSR4XX_DE 0x00000200 /* Debug Exception Enable */
+#define MSR4XX_PE 0x00000008 /* Protection Enable (reserved for others) */
+#define MSR4XX_PX 0x00000004 /* Protection Exclusive Mode (reserved for others) */
+
+/* Machine State Register bits - 602 */
+#define MSR602_AP 0x00800000 /* Access privilege state */
+#define MSR602_SA 0x00400000 /* Supervisor access mode */
+
+/* Machine State Register bits - 603 */
+#define MSR603_TGPR 0x00020000 /* Temporary GPR Remapping */
+
+
+/* DSISR bits for DSI/alignment exceptions */
+#define DSISR_DIRECT 0x00000001 /* DSI: direct-store exception? */
+#define DSISR_NOT_FOUND 0x00000002 /* DSI: not found in HTEG or DBAT */
+#define DSISR_PROTECTED 0x00000010 /* DSI: exception due to protection */
+#define DSISR_CACHE_ERROR 0x00000020 /* DSI: operation on incorrect cache type */
+#define DSISR_STORE 0x00000040 /* DSI: store (1) or load (0) */
+#define DSISR_DABR 0x00000200 /* DSI: DABR match occurred */
+#define DSISR_NO_SEGMENT 0x00000400 /* DSI: no segment match found (64-bit only) */
+#define DSISR_INVALID_ECWX 0x00000800 /* DSI: ECIWX or ECOWX used with EAR[E] = 0 */
+#define DSISR_INSTRUCTION 0xfffff000 /* align: instruction decoding bits */
+
+
+/* PowerPC 4XX IRQ bits */
+#define PPC4XX_IRQ_BIT_CRITICAL (0x80000000 >> 0)
+#define PPC4XX_IRQ_BIT_SPUR (0x80000000 >> 4)
+#define PPC4XX_IRQ_BIT_SPUT (0x80000000 >> 5)
+#define PPC4XX_IRQ_BIT_JTAGR (0x80000000 >> 6)
+#define PPC4XX_IRQ_BIT_JTAGT (0x80000000 >> 7)
+#define PPC4XX_IRQ_BIT_DMA0 (0x80000000 >> 8)
+#define PPC4XX_IRQ_BIT_DMA1 (0x80000000 >> 9)
+#define PPC4XX_IRQ_BIT_DMA2 (0x80000000 >> 10)
+#define PPC4XX_IRQ_BIT_DMA3 (0x80000000 >> 11)
+#define PPC4XX_IRQ_BIT_EXT0 (0x80000000 >> 27)
+#define PPC4XX_IRQ_BIT_EXT1 (0x80000000 >> 28)
+#define PPC4XX_IRQ_BIT_EXT2 (0x80000000 >> 29)
+#define PPC4XX_IRQ_BIT_EXT3 (0x80000000 >> 30)
+#define PPC4XX_IRQ_BIT_EXT4 (0x80000000 >> 31)
+
+#define PPC4XX_IRQ_BIT_EXT(n) (PPC4XX_IRQ_BIT_EXT0 >> (n))
+#define PPC4XX_IRQ_BIT_DMA(n) (PPC4XX_IRQ_BIT_DMA0 >> (n))
+
+
+/* PowerPC 4XX DMA control bits */
+#define PPC4XX_DMACR_CE 0x80000000 /* channel enable */
+#define PPC4XX_DMACR_CIE 0x40000000 /* channel interrupt enable */
+#define PPC4XX_DMACR_TD 0x20000000 /* transfer direction */
+#define PPC4XX_DMACR_PL 0x10000000 /* peripheral location */
+#define PPC4XX_DMACR_PW_MASK 0x0c000000 /* peripheral width */
+#define PPC4XX_DMACR_DAI 0x02000000 /* destination address increment */
+#define PPC4XX_DMACR_SAI 0x01000000 /* source address increment */
+#define PPC4XX_DMACR_CP 0x00800000 /* channel priority */
+#define PPC4XX_DMACR_TM_MASK 0x00600000 /* transfer mode */
+#define PPC4XX_DMACR_PSC_MASK 0x00180000 /* peripheral setup cycles */
+#define PPC4XX_DMACR_PWC_MASK 0x0007e000 /* peripheral wait cycles */
+#define PPC4XX_DMACR_PHC_MASK 0x00001c00 /* peripheral hold cycles */
+#define PPC4XX_DMACR_ETD 0x00000200 /* end-of-transfer pin direction */
+#define PPC4XX_DMACR_TCE 0x00000100 /* terminal count enable */
+#define PPC4XX_DMACR_CH 0x00000080 /* chaining enable */
+#define PPC4XX_DMACR_BME 0x00000040 /* burst mode enable */
+#define PPC4XX_DMACR_ECE 0x00000020 /* EOT chain mode enable */
+#define PPC4XX_DMACR_TCD 0x00000010 /* TC chain mode disable */
+#define PPC4XX_DMACR_PCE 0x00000008
+
+
+/* PowerPC 4XX Timer control register bits */
+#define PPC4XX_TCR_WP_MASK 0xc0000000 /* watchdog period */
+#define PPC4XX_TCR_WRC_MASK 0x30000000 /* watchdog reset control */
+#define PPC4XX_TCR_WIE 0x08000000 /* watchdog interrupt enable */
+#define PPC4XX_TCR_PIE 0x04000000 /* PIT interrupt enable */
+#define PPC4XX_TCR_FP_MASK 0x03000000 /* FIT period */
+#define PPC4XX_TCR_FIE 0x00800000 /* FIT interrupt enable */
+#define PPC4XX_TCR_ARE 0x00400000 /* auto reload enable */
+
+
+/* PowerPC 4XX Timer status register bits */
+#define PPC4XX_TSR_ENW 0x80000000 /* enable next watchdog */
+#define PPC4XX_TSR_WIS 0x40000000 /* watchdog interrupt status */
+#define PPC4XX_TSR_WRS_MASK 0x30000000 /* watchdog reset status */
+#define PPC4XX_TSR_PIS 0x08000000 /* PIT interrupt status */
+#define PPC4XX_TSR_FIS 0x04000000 /* FIT interrupt status */
+
+
+/* instruction decoding masks */
+#define M_LI 0x03fffffc
+#define M_AA 0x00000002
+#define M_LK 0x00000001
+#define M_BO 0x03e00000
+#define M_BI 0x001f0000
+#define M_BD 0x0000fffc
+#define M_RT 0x03e00000
+#define M_RD 0x03e00000
+#define M_RS 0x03e00000
+#define M_RA 0x001f0000
+#define M_RB 0x0000f800
+#define M_CRFD 0x03800000
+#define M_L 0x00200000
+#define M_TO 0x03e00000
+#define M_D 0x0000ffff
+#define M_SIMM 0x0000ffff
+#define M_UIMM 0x0000ffff
+#define M_NB 0x0000f800
+#define M_SR 0x000f0000
+#define M_SH 0x0000f800
+#define M_CRFS 0x001c0000
+#define M_IMM 0x0000f000
+#define M_CRBD 0x03e00000
+#define M_RC 0x00000001
+#define M_CRBA 0x001f0000
+#define M_CRBB 0x0000f800
+#define M_SPR 0x001FF800
+#define M_TBR 0x001FF800
+#define M_CRM 0x000FF000
+#define M_DCR 0x001FF800
+#define M_FM 0x01FE0000
+#define M_OE 0x00000400
+#define M_REGC 0x000007c0
+#define M_MB 0x000007c0
+#define M_ME 0x0000003e
+#define M_XO 0x000007fe
+
+
+
+/***************************************************************************
+ HELPER MACROS
+***************************************************************************/
+
+/*
+ * Field Defining Macros
+ *
+ * These macros generate instruction words with their associated fields filled
+ * in with the passed value.
+ */
+
+#define D_OP(op) ((op & 0x3f) << 26)
+#define D_XO(xo) ((xo & 0x3ff) << 1)
+#define D_RT(r) ((r & 0x1f) << (31 - 10))
+#define D_RA(r) ((r & 0x1f) << (31 - 15))
+#define D_UIMM(u) (u & 0xffff)
+
+/*
+ * Macros to Get Field Values
+ *
+ * These macros return the values of fields in an opcode. They all return
+ * unsigned values and do not perform any sign extensions.
+ */
+
+#define G_RT(op) ((op & M_RT) >> (31 - 10))
+#define G_RD(op) ((op & M_RD) >> (31 - 10))
+#define G_RS(op) ((op & M_RS) >> (31 - 10))
+#define G_RA(op) ((op & M_RA) >> (31 - 15))
+#define G_RB(op) ((op & M_RB) >> (31 - 20))
+#define G_SIMM(op) (op & M_SIMM)
+#define G_UIMM(op) (op & M_UIMM)
+#define G_LI(op) ((op & M_LI) >> 2)
+#define G_BO(op) ((op & M_BO) >> (31 - 10))
+#define G_BI(op) ((op & M_BI) >> (31 - 15))
+#define G_BD(op) ((op & M_BD) >> 2)
+#define G_CRFD(op) ((op & M_CRFD) >> (31 - 8))
+#define G_L(op) ((op & M_L) >> (31 - 10))
+#define G_CRBD(op) ((op & M_CRBD) >> (31 - 10))
+#define G_CRBA(op) ((op & M_CRBA) >> (31 - 15))
+#define G_CRBB(op) ((op & M_CRBB) >> (31 - 20))
+#define G_REGC(op) ((op & M_REGC) >> (31 - 25))
+#define G_D(op) (op & M_D)
+#define G_NB(op) ((op & M_NB) >> (31 - 20))
+#define G_CRFS(op) ((op & M_CRFS) >> (31 - 13))
+#define G_SPR(op) ((op & M_SPR) >> (31 - 20))
+#define G_TBR(op) ((op & M_TBR) >> (31 - 20))
+#define G_DCR(op) ((op & M_DCR) >> (31 - 20))
+#define G_SR(op) ((op & M_SR) >> (31 - 15))
+#define G_CRM(op) ((op & M_CRM) >> (31 - 19))
+#define G_FM(op) ((op & M_FM) >> (31 - 14))
+#define G_IMM(op) ((op & M_IMM) >> (31 - 19))
+#define G_SH(op) ((op & M_SH) >> (31 - 20))
+#define G_MB(op) ((op & M_MB) >> (31 - 25))
+#define G_ME(op) ((op & M_ME) >> 1)
+#define G_TO(op) ((op & M_TO) >> (31 - 10))
+#define G_XO(op) ((op & M_XO) >> (31 - 30))
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+typedef int (*ppc4xx_spu_rx_handler)(UINT8 *data);
+typedef void (*ppc4xx_spu_tx_handler)(UINT8 data);
+
+
+/* PowerPC 4XX-specific serial port state */
+typedef struct _ppc4xx_spu_state ppc4xx_spu_state;
+struct _ppc4xx_spu_state
+{
+ UINT8 regs[9];
+ UINT8 txbuf;
+ UINT8 rxbuf;
+ emu_timer * timer;
+ ppc4xx_spu_rx_handler rx_handler;
+ ppc4xx_spu_tx_handler tx_handler;
+};
+
+
+/* forward declaration of implementation-specific state */
+typedef struct _ppcimp_state ppcimp_state;
+
+
+/* PowerPC state */
+typedef struct _powerpc_state powerpc_state;
+struct _powerpc_state
+{
+ /* core registers */
+ UINT32 pc;
+ int icount;
+ UINT32 r[32];
+ double f[32];
+ UINT32 cr;
+ UINT32 fpscr;
+ UINT32 msr;
+ UINT32 sr[16];
+ UINT32 spr[1024];
+ UINT32 dcr[256];
+
+ /* parameters for calls */
+ UINT32 param0;
+ UINT32 param1;
+
+ /* MMU */
+ UINT32 * tlb_table;
+ UINT32 * tlb_entries;
+ UINT32 tlb_index;
+
+ /* architectural distinctions */
+ powerpc_flavor flavor;
+ UINT8 cap;
+ UINT8 cache_line_size;
+ UINT32 tb_divisor;
+ int (*spr_read)(powerpc_state *ppc);
+ int (*spr_write)(powerpc_state *ppc);
+ int (*tlb_fill)(powerpc_state *ppc);
+
+ /* PowerPC 4xx-specific state */
+ ppc4xx_spu_state spu;
+ emu_timer * fit_timer;
+ emu_timer * pit_timer;
+ emu_timer * wdog_timer;
+ UINT32 pit_reload;
+ UINT32 irqstate;
+
+ /* PowerPC 603-specific state */
+ UINT32 mmu603_cmp;
+ UINT32 mmu603_hash[2];
+ UINT32 mmu603_r[4];
+
+ /* internal stuff */
+ int cpunum;
+ int (*irq_callback)(int irqline);
+ UINT32 irq_pending;
+ UINT32 system_clock;
+ UINT32 cpu_clock;
+ UINT64 tb_zero_cycles;
+ UINT64 dec_zero_cycles;
+ emu_timer * decrementer_int_timer;
+
+ /* for use by specific implementations */
+ ppcimp_state * impstate;
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+size_t ppccom_init(powerpc_state *ppc, powerpc_flavor flavor, UINT8 cap, int tb_divisor, int clock, const powerpc_config *config, int (*irqcallback)(int), void *memory);
+void ppccom_reset(powerpc_state *ppc);
+#ifdef ENABLE_DEBUGGER
+offs_t ppccom_dasm(powerpc_state *ppc, char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram);
+#endif
+void ppccom_update_cycle_counting(powerpc_state *ppc);
+
+int ppccom_translate_address(powerpc_state *ppc, int space, int intention, offs_t *address);
+
+void ppccom_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+void ppccom_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+
+void ppccom_tlb_fill(powerpc_state *ppc);
+void ppccom_tlb_flush(powerpc_state *ppc);
+
+void ppccom_execute_tlbie(powerpc_state *ppc);
+void ppccom_execute_tlbia(powerpc_state *ppc);
+void ppccom_execute_tlbl(powerpc_state *ppc);
+void ppccom_execute_mftb(powerpc_state *ppc);
+void ppccom_execute_mfspr(powerpc_state *ppc);
+void ppccom_execute_mtspr(powerpc_state *ppc);
+void ppccom_execute_mfdcr(powerpc_state *ppc);
+void ppccom_execute_mtdcr(powerpc_state *ppc);
+
+void ppc4xx_set_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+void ppc4xx_get_info(powerpc_state *ppc, UINT32 state, cpuinfo *info);
+
+#endif
diff --git a/src/emu/cpu/powerpc/ppcdrc.c b/src/emu/cpu/powerpc/ppcdrc.c
new file mode 100644
index 00000000000..45afbbd3e67
--- /dev/null
+++ b/src/emu/cpu/powerpc/ppcdrc.c
@@ -0,0 +1,4337 @@
+/***************************************************************************
+
+ ppcdrc.c
+
+ Universal machine language-based PowerPC emulator.
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+****************************************************************************
+
+ Future improvements/changes:
+
+ * Timing for long instructions (stmw/lmw/mul/div/stswi)
+
+ * Eliminate unnecessary flag calculations using information from the
+ frontend
+
+***************************************************************************/
+
+#include <stddef.h>
+#include "cpuintrf.h"
+#include "debugger.h"
+#include "ppccom.h"
+#include "ppcfe.h"
+#include "deprecat.h"
+#include "cpu/drcfe.h"
+#include "cpu/drcuml.h"
+#include "cpu/drcumlsh.h"
+
+extern offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op);
+
+
+
+/***************************************************************************
+ DEBUGGING
+***************************************************************************/
+
+#define FORCE_C_BACKEND (0)
+#define LOG_UML (0)
+#define LOG_NATIVE (0)
+
+#define DISABLE_FAST_REGISTERS (0)
+#define SINGLE_INSTRUCTION_MODE (0)
+
+#define PRINTF_EXCEPTIONS (0)
+#define PRINTF_MMU (0)
+
+#define PROBE_ADDRESS ~0
+
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* map variables */
+#define MAPVAR_PC MVAR(0)
+#define MAPVAR_CYCLES MVAR(1)
+#define MAPVAR_DSISR MVAR(2)
+
+/* mode bits */
+#define MODE_LITTLE_ENDIAN 0x01
+#define MODE_DATA_TRANSLATION 0x02
+#define MODE_USER 0x04
+
+/* size of the execution code cache */
+#define CACHE_SIZE (32 * 1024 * 1024)
+
+/* compilation boundaries -- how far back/forward does the analysis extend? */
+#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
+
+/* exit codes */
+#define EXECUTE_OUT_OF_CYCLES 0
+#define EXECUTE_MISSING_CODE 1
+#define EXECUTE_UNMAPPED_CODE 2
+#define EXECUTE_RESET_CACHE 3
+
+
+
+/***************************************************************************
+ MACROS
+***************************************************************************/
+
+#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 FPSCR32 MEM(&ppc->fpscr)
+#define MSR32 MEM(&ppc->msr)
+#define SR32(reg) MEM(&ppc->sr[reg])
+#define SPR32(reg) MEM(&ppc->spr[reg])
+
+#define CRMASK(reg) (0xf0000000 >> ((reg) * 4))
+
+#define FLAGS_RC(op) ((op & M_RC) ? (DRCUML_FLAG_S | DRCUML_FLAG_Z) : 0)
+#define FLAGS_OE(op) ((op & M_OE) ? DRCUML_FLAG_V : 0)
+#define FLAGS_RCOE(op) (FLAGS_RC(op) | FLAGS_OE(op))
+#define FLAGS_RCOECA(op) (FLAGS_RCOE(op) | DRCUML_FLAG_C)
+
+/* DSISR values for various addressing types */
+#define DSISR_IMM(op) ((0) | /* bits 15-16: cleared */ \
+ ((((op) >> (31- 5)) & 0x01) << (31-17)) | /* bit 17: opcode bit 5 */ \
+ ((((op) >> (31- 4)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 1-4 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ (0)) /* bits 27-31: undefined */
+
+#define DSISR_IMMU(op) ((0) | /* bits 15-16: cleared */ \
+ ((((op) >> (31- 5)) & 0x01) << (31-17)) | /* bit 17: opcode bit 5 */ \
+ ((((op) >> (31- 4)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 1-4 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ ((((op) >> (31-15)) & 0x1f) << (31-31))) /* bits 27-31: opcode bits 11-15 */
+
+#define DSISR_IDX(op) (((((op) >> (31-30)) & 0x03) << (31-16)) | /* bits 15-16: opcode bits 29-30 */ \
+ ((((op) >> (31-25)) & 0x01) << (31-17)) | /* bit 17: opcode bit 25 */ \
+ ((((op) >> (31-24)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 21-24 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ (0)) /* bits 27-31: undefined */
+
+#define DSISR_IDXU(op) (((((op) >> (31-30)) & 0x03) << (31-16)) | /* bits 15-16: opcode bits 29-30 */ \
+ ((((op) >> (31-25)) & 0x01) << (31-17)) | /* bit 17: opcode bit 25 */ \
+ ((((op) >> (31-24)) & 0x0f) << (31-21)) | /* bits 18-21: opcode bits 21-24 */ \
+ ((((op) >> (31-10)) & 0x1f) << (31-26)) | /* bits 22-26: opcode bits 6-10 */ \
+ ((((op) >> (31-15)) & 0x1f) << (31-31))) /* bits 27-31: opcode bits 11-15 */
+
+
+
+/***************************************************************************
+ STRUCTURES & TYPEDEFS
+***************************************************************************/
+
+/* fast RAM info */
+typedef struct _fast_ram_info fast_ram_info;
+struct _fast_ram_info
+{
+ offs_t start; /* start of the RAM block */
+ offs_t end; /* end of the RAM block */
+ UINT8 readonly; /* TRUE if read-only */
+ void * base; /* base in memory where the RAM lives */
+};
+
+
+/* hotspot info */
+typedef struct _hotspot_info hotspot_info;
+struct _hotspot_info
+{
+ offs_t pc; /* PC to consider */
+ UINT32 opcode; /* required opcode at that PC */
+ UINT32 cycles; /* number of cycles to eat when hit */
+};
+
+
+/* internal compiler state */
+typedef struct _compiler_state compiler_state;
+struct _compiler_state
+{
+ UINT32 cycles; /* accumulated cycles */
+ UINT8 checkints; /* need to check interrupts before next instruction */
+ UINT8 checksoftints; /* need to check software interrupts before next instruction */
+ drcuml_codelabel labelnum; /* index for local labels */
+};
+
+
+/* PowerPC implementation state */
+struct _ppcimp_state
+{
+ /* core state */
+ drccache * cache; /* pointer to the DRC code cache */
+ drcuml_state * drcuml; /* DRC UML generator state */
+ drcfe_state * drcfe; /* pointer to the DRC front-end state */
+ UINT32 drcoptions; /* configurable DRC options */
+
+ /* parameters for subroutines */
+ UINT64 numcycles; /* return value from gettotalcycles */
+ UINT32 mode; /* current global mode */
+ UINT32 arg0; /* print_debug argument 1 */
+ UINT32 arg1; /* print_debug argument 2 */
+ UINT32 updateaddr; /* update address storage */
+ UINT32 swcount; /* counter for sw instructions */
+ UINT32 swreg; /* reg index for sw instructions */
+ UINT32 tempaddr; /* temporary address storage */
+ UINT64 tempdata; /* temporary data storage */
+ double fp0; /* floating point 0 */
+
+ /* 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 */
+
+ /* internal stuff */
+ UINT8 cache_dirty; /* true if we need to flush the cache */
+
+ /* register mappings */
+ drcuml_parameter regmap[32]; /* parameter to register mappings for all 32 integer registers */
+ drcuml_parameter fsregmap[32]; /* parameter to register mappings for all 32 floating point registers */
+ drcuml_parameter fdregmap[32]; /* parameter to register mappings for all 32 floating point registers */
+
+ /* subroutines */
+ drcuml_codehandle * entry; /* entry point */
+ drcuml_codehandle * nocode; /* nocode exception handler */
+ drcuml_codehandle * out_of_cycles; /* out of cycles exception handler */
+ drcuml_codehandle * tlb_mismatch; /* tlb mismatch handler */
+ drcuml_codehandle * swap_tgpr; /* swap TGPR handler */
+ drcuml_codehandle * read8[4]; /* read byte */
+ drcuml_codehandle * write8[4]; /* write byte */
+ drcuml_codehandle * read16[4]; /* read half */
+ drcuml_codehandle * read16mask[4]; /* read half */
+ drcuml_codehandle * write16[4]; /* write half */
+ drcuml_codehandle * write16mask[4]; /* write half */
+ drcuml_codehandle * read32[4]; /* read word */
+ drcuml_codehandle * read32align[4]; /* read word aligned */
+ drcuml_codehandle * read32mask[4]; /* read word */
+ drcuml_codehandle * write32[4]; /* write word */
+ drcuml_codehandle * write32align[4]; /* write word aligned */
+ drcuml_codehandle * write32mask[4]; /* write word */
+ drcuml_codehandle * read64[4]; /* read double */
+ drcuml_codehandle * read64mask[4]; /* read double */
+ drcuml_codehandle * write64[4]; /* write double */
+ drcuml_codehandle * write64mask[4]; /* write double */
+ drcuml_codehandle * exception[EXCEPTION_COUNT]; /* array of exception handlers */
+ drcuml_codehandle * exception_norecover[EXCEPTION_COUNT]; /* array of exception handlers */
+
+ /* fast RAM */
+ UINT32 fastram_select;
+ fast_ram_info fastram[PPC_MAX_FASTRAM];
+
+ /* hotspots */
+ UINT32 hotspot_select;
+ hotspot_info hotspot[PPC_MAX_HOTSPOTS];
+};
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static void code_flush_cache(drcuml_state *drcuml);
+static void code_compile_block(drcuml_state *drcuml, UINT8 mode, offs_t pc);
+
+static void cfunc_printf_exception(void *param);
+static void cfunc_printf_probe(void *param);
+
+static void static_generate_entry_point(drcuml_state *drcuml);
+static void static_generate_nocode_handler(drcuml_state *drcuml);
+static void static_generate_out_of_cycles(drcuml_state *drcuml);
+static void static_generate_tlb_mismatch(drcuml_state *drcuml);
+static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int recover, const char *name);
+static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int size, int iswrite, int ismasked, const char *name, drcuml_codehandle **handleptr, drcuml_codehandle *masked);
+static void static_generate_swap_tgpr(drcuml_state *drcuml);
+
+static void generate_update_mode(drcuml_block *block);
+static void generate_update_cycles(drcuml_block *block, compiler_state *compiler, drcuml_ptype ptype, UINT64 pvalue, int allow_exception);
+static void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
+static void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_13(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_3b(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+static int generate_instruction_3f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc);
+
+static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op);
+static const char *log_desc_flags_to_string(UINT32 flags);
+static void log_register_list(drcuml_state *drcuml, const char *string, UINT64 gprmask, UINT64 fprmask);
+static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent);
+
+
+
+/***************************************************************************
+ PRIVATE GLOBAL VARIABLES
+***************************************************************************/
+
+static powerpc_state *ppc;
+
+
+/* lookup table for FP modes */
+static const UINT8 fpmode_source[4] =
+{
+ DRCUML_FMOD_ROUND,
+ DRCUML_FMOD_TRUNC,
+ DRCUML_FMOD_CEIL,
+ DRCUML_FMOD_FLOOR
+};
+
+/* flag lookup table for SZ */
+static const UINT32 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
+};
+
+/* flag lookup table for CMP */
+static const UINT32 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
+};
+
+/* flag lookup table for CMPL */
+static const UINT32 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
+};
+
+/* flag lookup table for FCMP */
+static const UINT32 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
+};
+
+
+
+/***************************************************************************
+ INLINE FUNCTIONS
+***************************************************************************/
+
+/*-------------------------------------------------
+ alloc_handle - allocate a handle if not
+ already allocated
+-------------------------------------------------*/
+
+INLINE void alloc_handle(drcuml_state *drcuml, drcuml_codehandle **handleptr, const char *name)
+{
+ if (*handleptr == NULL)
+ *handleptr = drcuml_handle_alloc(drcuml, name);
+}
+
+
+/*-------------------------------------------------
+ load_fast_iregs - load any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void load_fast_iregs(drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(ppc->impstate->regmap); regnum++)
+ if (ppc->impstate->regmap[regnum].type == DRCUML_PTYPE_INT_REGISTER)
+ UML_MOV(block, IREG(ppc->impstate->regmap[regnum].value - DRCUML_REG_I0), MEM(&ppc->r[regnum]));
+}
+
+
+/*-------------------------------------------------
+ save_fast_iregs - save any fast integer
+ registers
+-------------------------------------------------*/
+
+INLINE void save_fast_iregs(drcuml_block *block)
+{
+ int regnum;
+
+ for (regnum = 0; regnum < ARRAY_LENGTH(ppc->impstate->regmap); regnum++)
+ if (ppc->impstate->regmap[regnum].type == DRCUML_PTYPE_INT_REGISTER)
+ UML_MOV(block, MEM(&ppc->r[regnum]), IREG(ppc->impstate->regmap[regnum].value - DRCUML_REG_I0));
+}
+
+
+/*-------------------------------------------------
+ compute_rlw_mask - compute the 32-bit mask
+ for an rlw* instruction
+-------------------------------------------------*/
+
+INLINE UINT32 compute_rlw_mask(UINT8 mb, UINT8 me)
+{
+ if (mb <= me)
+ return (0xffffffff >> mb) & (0xffffffff << (31 - me));
+ else
+ return (0xffffffff >> mb) | (0xffffffff << (31 - me));
+}
+
+
+/*-------------------------------------------------
+ compute_crf_mask - compute the 32-bit mask
+ for a mtcrf/mfcrf instruction
+-------------------------------------------------*/
+
+INLINE UINT32 compute_crf_mask(UINT8 crm)
+{
+ UINT32 mask = 0;
+ if (crm & 0x80) mask |= 0xf0000000;
+ if (crm & 0x40) mask |= 0x0f000000;
+ if (crm & 0x20) mask |= 0x00f00000;
+ if (crm & 0x10) mask |= 0x000f0000;
+ if (crm & 0x08) mask |= 0x0000f000;
+ if (crm & 0x04) mask |= 0x00000f00;
+ if (crm & 0x02) mask |= 0x000000f0;
+ if (crm & 0x01) mask |= 0x0000000f;
+ return mask;
+}
+
+
+/*-------------------------------------------------
+ compute_spr - compute the SPR index from the
+ SPR field of an opcode
+-------------------------------------------------*/
+
+INLINE UINT32 compute_spr(UINT32 spr)
+{
+ return ((spr >> 5) | (spr << 5)) & 0x3ff;
+}
+
+
+
+/***************************************************************************
+ CORE CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppcdrc_init - initialize the processor
+-------------------------------------------------*/
+
+static void ppcdrc_init(powerpc_flavor flavor, UINT8 cap, int tb_divisor, int clock, const powerpc_config *config, int (*irqcallback)(int))
+{
+ drcfe_config feconfig =
+ {
+ COMPILE_BACKWARDS_BYTES, /* code window start offset = startpc - window_start */
+ COMPILE_FORWARDS_BYTES, /* code window end offset = startpc + window_end */
+ COMPILE_MAX_SEQUENCE, /* maximum instructions to include in a sequence */
+ ppcfe_describe /* callback to describe a single instruction */
+ };
+ drcbe_info beinfo;
+ UINT32 flags = 0;
+ size_t extrasize;
+ drccache *cache;
+ void *extramem;
+ int regnum;
+
+ /* determine how much memory beyond the core size we need */
+ extrasize = ppccom_init(NULL, flavor, cap, tb_divisor, clock, config, irqcallback, NULL);
+
+ /* allocate enough space for the cache and the core */
+ cache = drccache_alloc(CACHE_SIZE + sizeof(*ppc) + extrasize);
+ if (cache == NULL)
+ fatalerror("Unable to allocate cache of size %d", (UINT32)(CACHE_SIZE + sizeof(*ppc) + extrasize));
+
+ /* allocate the core from the near cache, and the extra memory from the full cache */
+ ppc = drccache_memory_alloc_near(cache, sizeof(*ppc));
+ memset(ppc, 0, sizeof(*ppc));
+ extramem = drccache_memory_alloc(cache, extrasize);
+ memset(extramem, 0, extrasize);
+
+ /* initialize the core */
+ ppccom_init(ppc, flavor, cap, tb_divisor, clock, config, irqcallback, extramem);
+
+ /* allocate the implementation-specific state from the full cache */
+ ppc->impstate = drccache_memory_alloc_near(cache, sizeof(*ppc->impstate));
+ memset(ppc->impstate, 0, sizeof(*ppc->impstate));
+ ppc->impstate->cache = cache;
+
+ /* initialize the UML generator */
+ if (FORCE_C_BACKEND)
+ flags |= DRCUML_OPTION_USE_C;
+ if (LOG_UML)
+ flags |= DRCUML_OPTION_LOG_UML;
+ if (LOG_NATIVE)
+ flags |= DRCUML_OPTION_LOG_NATIVE;
+ ppc->impstate->drcuml = drcuml_alloc(cache, flags, 8, 32, 2);
+ if (ppc->impstate->drcuml == NULL)
+ fatalerror("Error initializing the UML");
+
+ /* initialize the front-end helper */
+ if (SINGLE_INSTRUCTION_MODE)
+ feconfig.max_sequence = 1;
+ ppc->impstate->drcfe = drcfe_init(&feconfig, ppc);
+
+ /* initialize the implementation state tables */
+ memcpy(ppc->impstate->fpmode, fpmode_source, sizeof(fpmode_source));
+ memcpy(ppc->impstate->sz_cr_table, sz_cr_table_source, sizeof(sz_cr_table_source));
+ memcpy(ppc->impstate->cmp_cr_table, cmp_cr_table_source, sizeof(cmp_cr_table_source));
+ memcpy(ppc->impstate->cmpl_cr_table, cmpl_cr_table_source, sizeof(cmpl_cr_table_source));
+ memcpy(ppc->impstate->fcmp_cr_table, fcmp_cr_table_source, sizeof(fcmp_cr_table_source));
+
+ /* compute the register parameters */
+ for (regnum = 0; regnum < 32; regnum++)
+ {
+ ppc->impstate->regmap[regnum].type = DRCUML_PTYPE_MEMORY;
+ ppc->impstate->regmap[regnum].value = (FPTR)&ppc->r[regnum];
+ ppc->impstate->fsregmap[regnum].type = DRCUML_PTYPE_MEMORY;
+ ppc->impstate->fsregmap[regnum].value = (FPTR)((UINT32 *)&ppc->f[regnum] + BYTE_XOR_LE(0));
+ ppc->impstate->fdregmap[regnum].type = DRCUML_PTYPE_MEMORY;
+ ppc->impstate->fdregmap[regnum].value = (FPTR)&ppc->f[regnum];
+ }
+
+ /* if we have registers to spare, assign r0, r1, r2 to leftovers */
+ if (!DISABLE_FAST_REGISTERS)
+ {
+ drcuml_get_backend_info(ppc->impstate->drcuml, &beinfo);
+ if (beinfo.direct_iregs > 5)
+ {
+ ppc->impstate->regmap[0].type = DRCUML_PTYPE_INT_REGISTER;
+ ppc->impstate->regmap[0].value = DRCUML_REG_I5;
+ }
+ if (beinfo.direct_iregs > 6)
+ {
+ ppc->impstate->regmap[1].type = DRCUML_PTYPE_INT_REGISTER;
+ ppc->impstate->regmap[1].value = DRCUML_REG_I6;
+ }
+ if (beinfo.direct_iregs > 7)
+ {
+ ppc->impstate->regmap[2].type = DRCUML_PTYPE_INT_REGISTER;
+ ppc->impstate->regmap[2].value = DRCUML_REG_I7;
+ }
+ }
+
+ /* mark the cache dirty so it is updated on next execute */
+ ppc->impstate->cache_dirty = TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_reset - reset the processor
+-------------------------------------------------*/
+
+static void ppcdrc_reset(void)
+{
+ /* reset the common code and mark the cache dirty */
+ ppccom_reset(ppc);
+ ppc->impstate->mode = 0;
+ ppc->impstate->cache_dirty = TRUE;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_execute - execute the CPU for the
+ specified number of cycles
+-------------------------------------------------*/
+
+static int ppcdrc_execute(int cycles)
+{
+ drcuml_state *drcuml = ppc->impstate->drcuml;
+ int execute_result;
+
+ /* reset the cache if dirty */
+ if (ppc->impstate->cache_dirty)
+ code_flush_cache(drcuml);
+ ppc->impstate->cache_dirty = FALSE;
+
+ /* execute */
+ ppc->icount = cycles;
+ do
+ {
+ /* run as much as we can */
+ execute_result = drcuml_execute(drcuml, ppc->impstate->entry);
+
+ /* if we need to recompile, do it */
+ if (execute_result == EXECUTE_MISSING_CODE)
+ code_compile_block(drcuml, ppc->impstate->mode, ppc->pc);
+ else if (execute_result == EXECUTE_UNMAPPED_CODE)
+ fatalerror("Attempted to execute unmapped code at PC=%08X\n", ppc->pc);
+ else if (execute_result == EXECUTE_RESET_CACHE)
+ code_flush_cache(drcuml);
+
+ } while (execute_result != EXECUTE_OUT_OF_CYCLES);
+
+ /* return the number of cycles executed */
+ return cycles - ppc->icount;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_exit - cleanup from execution
+-------------------------------------------------*/
+
+static void ppcdrc_exit(void)
+{
+ /* clean up the DRC */
+ drcfe_exit(ppc->impstate->drcfe);
+ drcuml_free(ppc->impstate->drcuml);
+ drccache_free(ppc->impstate->cache);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_get_context - return a copy of the
+ current context
+-------------------------------------------------*/
+
+static void ppcdrc_get_context(void *dst)
+{
+ if (dst != NULL)
+ *(powerpc_state **)dst = ppc;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_set_context - copy the current context
+ into the global state
+-------------------------------------------------*/
+
+static void ppcdrc_set_context(void *src)
+{
+ if (src != NULL)
+ ppc = *(powerpc_state **)src;
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_translate - perform virtual-to-physical
+ address translation
+-------------------------------------------------*/
+
+static int ppcdrc_translate(int space, int intention, offs_t *address)
+{
+ return ppccom_translate_address(ppc, space, intention, address);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_dasm - disassemble an instruction
+-------------------------------------------------*/
+
+#ifdef ENABLE_DEBUGGER
+static offs_t ppcdrc_dasm(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram)
+{
+ return ppccom_dasm(ppc, buffer, pc, oprom, opram);
+}
+#endif /* ENABLE_DEBUGGER */
+
+
+/*-------------------------------------------------
+ ppcdrc_set_info - set information about a given
+ CPU instance
+-------------------------------------------------*/
+
+static void ppcdrc_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_PPC_DRC_OPTIONS: ppc->impstate->drcoptions = info->i; break;
+
+ case CPUINFO_INT_PPC_FASTRAM_SELECT: if (info->i >= 0 && info->i < PPC_MAX_FASTRAM) ppc->impstate->fastram_select = info->i; ppc->impstate->cache_dirty = TRUE; break;
+ case CPUINFO_INT_PPC_FASTRAM_START: ppc->impstate->fastram[ppc->impstate->fastram_select].start = info->i; ppc->impstate->cache_dirty = TRUE; break;
+ case CPUINFO_INT_PPC_FASTRAM_END: ppc->impstate->fastram[ppc->impstate->fastram_select].end = info->i; ppc->impstate->cache_dirty = TRUE; break;
+ case CPUINFO_INT_PPC_FASTRAM_READONLY: ppc->impstate->fastram[ppc->impstate->fastram_select].readonly = info->i; ppc->impstate->cache_dirty = TRUE; break;
+
+ case CPUINFO_INT_PPC_HOTSPOT_SELECT: if (info->i >= 0 && info->i < PPC_MAX_HOTSPOTS) ppc->impstate->hotspot_select = info->i; ppc->impstate->cache_dirty = TRUE; break;
+ case CPUINFO_INT_PPC_HOTSPOT_PC: ppc->impstate->hotspot[ppc->impstate->hotspot_select].pc = info->i; ppc->impstate->cache_dirty = TRUE; break;
+ case CPUINFO_INT_PPC_HOTSPOT_OPCODE: ppc->impstate->hotspot[ppc->impstate->hotspot_select].opcode = info->i; ppc->impstate->cache_dirty = TRUE; break;
+ case CPUINFO_INT_PPC_HOTSPOT_CYCLES: ppc->impstate->hotspot[ppc->impstate->hotspot_select].cycles = info->i; ppc->impstate->cache_dirty = TRUE; break;
+
+ /* --- the following bits of info are set as pointers to data or functions --- */
+ case CPUINFO_PTR_PPC_FASTRAM_BASE: ppc->impstate->fastram[ppc->impstate->fastram_select].base = info->p; break;
+
+ /* --- everything else is handled generically --- */
+ default: ppccom_set_info(ppc, state, info); break;
+ }
+}
+
+
+/*-------------------------------------------------
+ ppcdrc_get_info - return information about a given
+ CPU instance
+-------------------------------------------------*/
+
+static void ppcdrc_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ppc); break;
+ case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = ppcdrc_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = ppcdrc_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = ppcdrc_set_context; break;
+ case CPUINFO_PTR_INIT: /* provided per-CPU */ break;
+ case CPUINFO_PTR_RESET: info->reset = ppcdrc_reset; break;
+ case CPUINFO_PTR_EXIT: info->exit = ppcdrc_exit; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = ppcdrc_execute; break;
+#ifdef ENABLE_DEBUGGER
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = ppcdrc_dasm; break;
+#endif /* ENABLE_DEBUGGER */
+ case CPUINFO_PTR_TRANSLATE: info->translate = ppcdrc_translate; break;
+ case CPUINFO_PTR_CONTEXT: info->p = ppc; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppccom_get_info(ppc, state, info); break;
+ }
+}
+
+
+
+/***************************************************************************
+ CACHE MANAGEMENT
+***************************************************************************/
+
+/*-------------------------------------------------
+ code_flush_cache - flush the cache and
+ regenerate static code
+-------------------------------------------------*/
+
+static void code_flush_cache(drcuml_state *drcuml)
+{
+ int mode;
+
+ /* empty the transient cache contents */
+ drcuml_reset(drcuml);
+
+ /* generate the entry point and out-of-cycles handlers */
+ static_generate_entry_point(drcuml);
+ static_generate_nocode_handler(drcuml);
+ static_generate_out_of_cycles(drcuml);
+ static_generate_tlb_mismatch(drcuml);
+ if (ppc->cap & PPCCAP_603_MMU)
+ static_generate_swap_tgpr(drcuml);
+
+ /* append exception handlers for various types */
+ static_generate_exception(drcuml, EXCEPTION_RESET, TRUE, "exception_reset");
+ static_generate_exception(drcuml, EXCEPTION_MACHCHECK, TRUE, "exception_machine_check");
+ static_generate_exception(drcuml, EXCEPTION_DSI, TRUE, "exception_dsi");
+ static_generate_exception(drcuml, EXCEPTION_ISI, TRUE, "exception_isi");
+ static_generate_exception(drcuml, EXCEPTION_EI, TRUE, "exception_ei");
+ static_generate_exception(drcuml, EXCEPTION_EI, FALSE, "exception_ei_norecover");
+ static_generate_exception(drcuml, EXCEPTION_ALIGN, TRUE, "exception_align");
+ static_generate_exception(drcuml, EXCEPTION_PROGRAM, TRUE, "exception_program");
+ static_generate_exception(drcuml, EXCEPTION_NOFPU, TRUE, "exception_fpu_unavailable");
+ static_generate_exception(drcuml, EXCEPTION_DECREMENT, TRUE, "exception_decrementer");
+ static_generate_exception(drcuml, EXCEPTION_SYSCALL, TRUE, "exception_syscall");
+ static_generate_exception(drcuml, EXCEPTION_TRACE, TRUE, "exception_trace");
+ static_generate_exception(drcuml, EXCEPTION_FPASSIST, TRUE, "exception_floating_point_assist");
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ static_generate_exception(drcuml, EXCEPTION_ITLBMISS, TRUE, "exception_itlb_miss");
+ static_generate_exception(drcuml, EXCEPTION_DTLBMISSL, TRUE, "exception_dtlb_miss_load");
+ static_generate_exception(drcuml, EXCEPTION_DTLBMISSS, TRUE, "exception_dtlb_miss_store");
+ }
+
+ /* add subroutines for memory accesses */
+ for (mode = 0; mode < 4; mode++)
+ {
+ static_generate_memory_accessor(drcuml, mode, 1, FALSE, FALSE, "read8", &ppc->impstate->read8[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 1, TRUE, FALSE, "write8", &ppc->impstate->write8[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 2, FALSE, TRUE, "read16mask", &ppc->impstate->read16mask[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 2, FALSE, FALSE, "read16", &ppc->impstate->read16[mode], ppc->impstate->read16mask[mode]);
+ static_generate_memory_accessor(drcuml, mode, 2, TRUE, TRUE, "write16mask", &ppc->impstate->write16mask[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 2, TRUE, FALSE, "write16", &ppc->impstate->write16[mode], ppc->impstate->write16mask[mode]);
+ static_generate_memory_accessor(drcuml, mode, 4, FALSE, TRUE, "read32mask", &ppc->impstate->read32mask[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 4, FALSE, FALSE, "read32align", &ppc->impstate->read32align[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 4, FALSE, FALSE, "read32", &ppc->impstate->read32[mode], ppc->impstate->read32mask[mode]);
+ static_generate_memory_accessor(drcuml, mode, 4, TRUE, TRUE, "write32mask", &ppc->impstate->write32mask[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 4, TRUE, FALSE, "write32align",&ppc->impstate->write32align[mode],NULL);
+ static_generate_memory_accessor(drcuml, mode, 4, TRUE, FALSE, "write32", &ppc->impstate->write32[mode], ppc->impstate->write32mask[mode]);
+ static_generate_memory_accessor(drcuml, mode, 8, FALSE, TRUE, "read64mask", &ppc->impstate->read64mask[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 8, FALSE, FALSE, "read64", &ppc->impstate->read64[mode], ppc->impstate->read64mask[mode]);
+ static_generate_memory_accessor(drcuml, mode, 8, TRUE, TRUE, "write64mask", &ppc->impstate->write64mask[mode], NULL);
+ static_generate_memory_accessor(drcuml, mode, 8, TRUE, FALSE, "write64", &ppc->impstate->write64[mode], ppc->impstate->write64mask[mode]);
+ }
+}
+
+
+/*-------------------------------------------------
+ code_compile_block - compile a block of the
+ given mode at the specified pc
+-------------------------------------------------*/
+
+static void code_compile_block(drcuml_state *drcuml, UINT8 mode, offs_t pc)
+{
+ compiler_state compiler = { 0 };
+ const opcode_desc *seqhead, *seqlast;
+ const opcode_desc *desclist;
+ int override = FALSE;
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* get a description of this sequence */
+ desclist = drcfe_describe_code(ppc->impstate->drcfe, pc);
+ if (LOG_UML || LOG_NATIVE)
+ log_opcode_desc(drcuml, desclist, 0);
+
+ /* if we get an error back, flush the cache and try again */
+ if (setjmp(errorbuf) != 0)
+ code_flush_cache(drcuml);
+
+ /* start the block */
+ block = drcuml_block_begin(drcuml, 4096, &errorbuf);
+
+ /* loop until we get through all instruction sequences */
+ for (seqhead = desclist; seqhead != NULL; seqhead = seqlast->next)
+ {
+ const opcode_desc *curdesc;
+ UINT32 nextpc;
+
+ /* add a code log entry */
+ if (LOG_UML)
+ UML_COMMENT(block, "-------------------------"); // comment
+
+ /* determine the last instruction in this sequence */
+ for (seqlast = seqhead; seqlast != NULL; seqlast = seqlast->next)
+ if (seqlast->flags & OPFLAG_END_SEQUENCE)
+ break;
+ assert(seqlast != NULL);
+
+ /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
+ if (override || !drcuml_hash_exists(drcuml, mode, seqhead->pc))
+ UML_HASH(block, mode, 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, mode, 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 | 0x80000000
+ UML_HASHJMP(block, IMM(ppc->impstate->mode), IMM(seqhead->pc), ppc->impstate->nocode);
+ // hashjmp <mode>,seqhead->pc,nocode
+ continue;
+ }
+
+ /* validate this code block if we're not pointing into ROM */
+ if (memory_get_write_ptr(cpu_getactivecpu(), ADDRESS_SPACE_PROGRAM, seqhead->physpc) != NULL)
+ generate_checksum_block(block, &compiler, seqhead, seqlast); // <checksum>
+
+ /* 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 | 0x80000000
+
+ /* iterate over instructions in the sequence and compile them */
+ for (curdesc = seqhead; curdesc != seqlast->next; curdesc = curdesc->next)
+ generate_sequence_instruction(block, &compiler, curdesc); // <instruction>
+
+ /* 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) * 4;
+
+ /* count off cycles and go there */
+ generate_update_cycles(block, &compiler, IMM(nextpc), TRUE); // <subtract cycles>
+
+ /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
+ if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES)
+ UML_HASHJMP(block, MEM(&ppc->impstate->mode), IMM(nextpc), ppc->impstate->nocode);// hashjmp <mode>,nextpc,nocode
+ else if (seqlast->next == NULL || seqlast->next->pc != nextpc)
+ UML_HASHJMP(block, IMM(ppc->impstate->mode), IMM(nextpc), ppc->impstate->nocode);// hashjmp <mode>,nextpc,nocode
+ }
+
+ /* end the sequence */
+ drcuml_block_end(block);
+}
+
+
+
+/***************************************************************************
+ C FUNCTION CALLBACKS
+***************************************************************************/
+
+/*-------------------------------------------------
+ cfunc_printf_exception - log any exceptions that
+ aren't interrupts
+-------------------------------------------------*/
+
+static void cfunc_printf_exception(void *param)
+{
+ printf("Exception: type=%2d EPC=%08X MSR=%08X\n", ppc->param0, ppc->spr[SPROEA_SRR0], ppc->spr[SPROEA_SRR1]);
+ cfunc_printf_probe((void *)(FPTR)ppc->spr[SPROEA_SRR0]);
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_debug - generic printf for
+ debugging
+-------------------------------------------------*/
+
+static void cfunc_printf_debug(void *param)
+{
+ const char *format = param;
+ printf(format, ppc->impstate->arg0, ppc->impstate->arg1);
+}
+
+
+/*-------------------------------------------------
+ cfunc_printf_probe - print the current CPU
+ state and return
+-------------------------------------------------*/
+
+static void cfunc_printf_probe(void *param)
+{
+ UINT32 pc = (UINT32)(FPTR)param;
+
+ printf(" PC=%08X\n", pc);
+ printf(" r0=%08X r1=%08X r2=%08X r3=%08X\n",
+ ppc->r[0], ppc->r[1], ppc->r[2], ppc->r[3]);
+ printf(" r4=%08X r5=%08X r6=%08X r7=%08X\n",
+ ppc->r[4], ppc->r[5], ppc->r[6], ppc->r[7]);
+ printf(" r8=%08X r9=%08X r10=%08X r11=%08X\n",
+ ppc->r[8], ppc->r[9], ppc->r[10], ppc->r[11]);
+ printf("r12=%08X r13=%08X r14=%08X r15=%08X\n",
+ ppc->r[12], ppc->r[13], ppc->r[14], ppc->r[15]);
+ printf("r16=%08X r17=%08X r18=%08X r19=%08X\n",
+ ppc->r[16], ppc->r[17], ppc->r[18], ppc->r[19]);
+ printf("r20=%08X r21=%08X r22=%08X r23=%08X\n",
+ ppc->r[20], ppc->r[21], ppc->r[22], ppc->r[23]);
+ printf("r24=%08X r25=%08X r26=%08X r27=%08X\n",
+ ppc->r[24], ppc->r[25], ppc->r[26], ppc->r[27]);
+ printf("r28=%08X r29=%08X r30=%08X r31=%08X\n",
+ ppc->r[28], ppc->r[29], ppc->r[30], ppc->r[31]);
+}
+
+
+/*-------------------------------------------------
+ cfunc_unimplemented - handler for
+ unimplemented opcdes
+-------------------------------------------------*/
+
+static void cfunc_unimplemented(void *param)
+{
+ UINT32 opcode = (FPTR)param;
+ fatalerror("PC=%08X: Unimplemented op %08X", ppc->pc, opcode);
+}
+
+
+
+/***************************************************************************
+ STATIC CODEGEN
+***************************************************************************/
+
+/*-------------------------------------------------
+ static_generate_entry_point - generate a
+ static entry point
+-------------------------------------------------*/
+
+static void static_generate_entry_point(drcuml_state *drcuml)
+{
+ drcuml_codelabel skip = 1;
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_entry_point");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 20, &errorbuf);
+
+ /* forward references */
+ alloc_handle(drcuml, &ppc->impstate->nocode, "nocode");
+ alloc_handle(drcuml, &ppc->impstate->exception_norecover[EXCEPTION_EI], "exception_ei_norecover");
+
+ alloc_handle(drcuml, &ppc->impstate->entry, "entry");
+ UML_HANDLE(block, ppc->impstate->entry); // handle entry
+
+ /* reset the FPU mode */
+ UML_AND(block, IREG(0), FPSCR32, IMM(3)); // and i0,fpscr,3
+ UML_LOAD(block, IREG(0), &ppc->impstate->fpmode[0], IREG(0), BYTE); // load i0,fpmode,i0,byte
+ UML_SETFMOD(block, IREG(0)); // setfmod i0
+
+ /* load fast integer registers */
+ load_fast_iregs(block); // <load fastregs>
+
+ /* check for interrupts */
+ UML_TEST(block, MEM(&ppc->irq_pending), IMM(~0)); // test [irq_pending],0
+ UML_JMPc(block, IF_Z, skip); // jmp skip,Z
+ UML_TEST(block, MSR32, IMM(MSR_EE)); // test msr,MSR_EE
+ UML_JMPc(block, IF_Z, skip); // jmp skip,Z
+ UML_MOV(block, IREG(0), MEM(&ppc->pc)); // mov i0,pc
+ UML_MOV(block, IREG(1), IMM(0)); // mov i1,0
+ UML_CALLH(block, ppc->impstate->exception_norecover[EXCEPTION_EI]); // callh exception_norecover
+ UML_LABEL(block, skip); // skip:
+
+ /* generate a hash jump via the current mode and PC */
+ UML_HASHJMP(block, MEM(&ppc->impstate->mode), MEM(&ppc->pc), ppc->impstate->nocode); // hashjmp <mode>,<pc>,nocode
+
+ drcuml_block_end(block);
+}
+
+
+/*-------------------------------------------------
+ static_generate_nocode_handler - generate an
+ exception handler for "out of code"
+-------------------------------------------------*/
+
+static void static_generate_nocode_handler(drcuml_state *drcuml)
+{
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_nocode_handler");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 10, &errorbuf);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->nocode, "nocode");
+ UML_HANDLE(block, ppc->impstate->nocode); // handle nocode
+ UML_GETEXP(block, IREG(0)); // getexp i0
+ UML_MOV(block, MEM(&ppc->pc), IREG(0)); // mov [pc],i0
+ save_fast_iregs(block); // <save fastregs>
+ UML_EXIT(block, IMM(EXECUTE_MISSING_CODE)); // exit EXECUTE_MISSING_CODE
+
+ drcuml_block_end(block);
+}
+
+
+/*-------------------------------------------------
+ static_generate_out_of_cycles - generate an
+ out of cycles exception handler
+-------------------------------------------------*/
+
+static void static_generate_out_of_cycles(drcuml_state *drcuml)
+{
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_out_of_cycles");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 10, &errorbuf);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->out_of_cycles, "out_of_cycles");
+ UML_HANDLE(block, ppc->impstate->out_of_cycles); // handle out_of_cycles
+ UML_GETEXP(block, IREG(0)); // getexp i0
+ UML_MOV(block, MEM(&ppc->pc), IREG(0)); // mov <pc>,i0
+ save_fast_iregs(block); // <save fastregs>
+ UML_EXIT(block, IMM(EXECUTE_OUT_OF_CYCLES)); // exit EXECUTE_OUT_OF_CYCLES
+
+ drcuml_block_end(block);
+}
+
+
+/*-------------------------------------------------
+ static_generate_tlb_mismatch - generate a
+ TLB mismatch handler
+-------------------------------------------------*/
+
+static void static_generate_tlb_mismatch(drcuml_state *drcuml)
+{
+ drcuml_block *block;
+ jmp_buf errorbuf;
+ int isi, label = 1;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_tlb_mismatch");
+
+ /* forward references */
+ alloc_handle(drcuml, &ppc->impstate->exception[EXCEPTION_ISI], "exception_isi");
+ if (ppc->cap & PPCCAP_603_MMU)
+ alloc_handle(drcuml, &ppc->impstate->exception[EXCEPTION_ITLBMISS], "exception_itlb_miss");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 20, &errorbuf);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->tlb_mismatch, "tlb_mismatch");
+ UML_HANDLE(block, ppc->impstate->tlb_mismatch); // handle tlb_mismatch
+ UML_RECOVER(block, IREG(0), MAPVAR_PC); // recover i0,PC
+ UML_MOV(block, MEM(&ppc->param0), IREG(0)); // mov [param0],i0
+ UML_MOV(block, MEM(&ppc->param1), IMM(TRANSLATE_FETCH)); // mov [param1],TRANSLATE_FETCH
+ UML_CALLC(block, ppccom_tlb_fill, ppc); // callc tlbfill,ppc
+ UML_CMP(block, MEM(&ppc->param0), IMM(1)); // cmp [param0],1
+ UML_JMPc(block, IF_A, isi = label++); // jmp isi,A
+ save_fast_iregs(block); // <save fastregs>
+ UML_EXIT(block, IMM(EXECUTE_MISSING_CODE)); // exit EXECUTE_MISSING_CODE
+ UML_LABEL(block, isi); // isi:
+ if (!(ppc->cap & PPCCAP_603_MMU))
+ {
+ UML_MOV(block, SPR32(SPROEA_DSISR), MEM(&ppc->param0)); // mov [dsisr],[param0]
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_ISI], IREG(0)); // exh isi,i0
+ }
+ else
+ {
+ UML_MOV(block, SPR32(SPR603_IMISS), IREG(0)); // mov [imiss],i0
+ UML_MOV(block, SPR32(SPR603_ICMP), MEM(&ppc->mmu603_cmp)); // mov [icmp],[mmu603_cmp]
+ UML_MOV(block, SPR32(SPR603_HASH1), MEM(&ppc->mmu603_hash[0])); // mov [hash1],[mmu603_hash][0]
+ UML_MOV(block, SPR32(SPR603_HASH2), MEM(&ppc->mmu603_hash[1])); // mov [hash2],[mmu603_hash][1]
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_ITLBMISS], IREG(0)); // exh itlbmiss,i0
+ }
+
+ drcuml_block_end(block);
+}
+
+
+/*-------------------------------------------------
+ static_generate_exception - generate a static
+ exception handler
+-------------------------------------------------*/
+
+static void static_generate_exception(drcuml_state *drcuml, UINT8 exception, int recover, const char *name)
+{
+ drcuml_codehandle **exception_handle = recover ? &ppc->impstate->exception[exception] : &ppc->impstate->exception_norecover[exception];
+ UINT32 vector = exception << 8;
+ drcuml_codelabel label = 1;
+ drcuml_block *block;
+ jmp_buf errorbuf;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_exception");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 1024, &errorbuf);
+
+ /* add a global entry for this */
+ alloc_handle(drcuml, exception_handle, name);
+ UML_HANDLE(block, *exception_handle); // handle name
+
+ /* exception parameter is expected to be the fault address in this case */
+ if (exception == EXCEPTION_ISI || exception == EXCEPTION_DSI)
+ {
+ UML_GETEXP(block, IREG(0)); // getexp i0
+ UML_MOV(block, SPR32(SPROEA_DAR), IREG(0)); // mov [dar],i0
+ }
+
+ /* fetch the PC and uncounted cycles */
+ if (recover)
+ {
+ UML_RECOVER(block, IREG(0), MAPVAR_PC); // recover i0,PC
+ UML_RECOVER(block, IREG(1), MAPVAR_CYCLES); // recover i1,CYCLES
+ }
+
+ /* OEA handling of SRR exceptions */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ UINT32 msrandmask = MSROEA_POW | MSR_EE | MSR_PR | MSROEA_FP | MSROEA_FE0 | MSROEA_SE | MSROEA_BE | MSROEA_FE1 | MSROEA_IR | MSROEA_DR | MSROEA_RI | MSR_LE;
+ UINT32 msrormask = 0;
+
+ /* check registers to see the real source of our exception (EI exceptions only) */
+ UML_MOV(block, IREG(3), IMM(vector)); // mov i3,vector
+ if (exception == EXCEPTION_EI)
+ {
+ drcuml_codelabel not_decrementer;
+
+ UML_TEST(block, MEM(&ppc->irq_pending), IMM(0x01)); // test [irq_pending],0x01
+ UML_JMPc(block, IF_NZ, not_decrementer = label++); // jmp not_decrementer,nz
+ UML_MOV(block, IREG(3), IMM(EXCEPTION_DECREMENT << 8)); // mov i3,EXCEPTION_DECREMENT << 8
+ UML_AND(block, MEM(&ppc->irq_pending), MEM(&ppc->irq_pending), IMM(~0x02)); // and [irq_pending],[irq_pending],~0x02
+ UML_LABEL(block, not_decrementer); // not_decrementer:
+ }
+
+ /* exception PC goes into SRR0 */
+ UML_MOV(block, SPR32(SPROEA_SRR0), IREG(0)); // mov [srr0],i0
+
+ /* MSR bits go into SRR1, along with some exception-specific data */
+ UML_AND(block, SPR32(SPROEA_SRR1), MSR32, IMM(0x87c0ffff)); // and [srr1],[msr],0x87c0ffff
+ if (exception == EXCEPTION_PROGRAM)
+ {
+ UML_GETEXP(block, IREG(1)); // getexp i1
+ UML_OR(block, SPR32(SPROEA_SRR1), SPR32(SPROEA_SRR1), IREG(1)); // or [srr1],[srr1],i1
+ }
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ if (exception == EXCEPTION_ITLBMISS)
+ UML_OR(block, SPR32(SPROEA_SRR1), SPR32(SPROEA_SRR1), IMM(0x00040000)); // or [srr1],0x00040000
+ 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)
+ }
+
+ /* update MSR */
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ if (exception == EXCEPTION_ITLBMISS || exception == EXCEPTION_DTLBMISSL || exception == EXCEPTION_DTLBMISSS)
+ msrormask |= MSR603_TGPR;
+ else
+ msrandmask |= MSR603_TGPR;
+ UML_MOV(block, IREG(0), MSR32); // mov i0,[msr]
+ }
+ UML_AND(block, IREG(2), MSR32, IMM(~msrandmask)); // and i2,[msr],~andmask
+ UML_OR(block, IREG(2), IREG(2), IMM(msrormask)); // or i2,i2,ormask
+ UML_ROLINS(block, IREG(2), IREG(2), IMM(16), IMM(MSR_LE)); // rolins i2,u2,16,MSR_LE
+ UML_MOV(block, MSR32, IREG(2)); // mov [msr],i2
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ UML_XOR(block, IREG(0), IREG(0), IREG(2)); // xor i0,i0,i2
+ UML_TEST(block, IREG(0), IMM(MSR603_TGPR)); // test i0,tgpr
+ UML_CALLHc(block, IF_NZ, ppc->impstate->swap_tgpr); // callh swap_tgpr,nz
+ }
+ generate_update_mode(block); // <update mode>
+
+ /* determine our target PC */
+ UML_MOV(block, IREG(0), IMM(0x00000000)); // mov i0,0x00000000
+ UML_TEST(block, MSR32, IMM(MSROEA_IP)); // test [msr],IP
+ UML_MOVc(block, IF_NZ, IREG(0), IMM(0xfff00000)); // mov i0,0xfff00000,nz
+ UML_OR(block, IREG(0), IREG(0), IREG(3)); // or i0,i0,i3
+ }
+
+ /* 4XX handling of exceptions */
+ if (ppc->cap & PPCCAP_4XX)
+ {
+ /* check registers to see the real source of our exception (EI exceptions only) */
+ UML_MOV(block, IREG(3), IMM(vector)); // mov i3,vector
+ if (exception == EXCEPTION_EI)
+ {
+ drcuml_codelabel notwdog, common;
+
+ UML_TEST(block, SPR32(SPR4XX_TSR), IMM(PPC4XX_TSR_PIS)); // test [tsr],PIS
+ UML_MOVc(block, IF_NZ, IREG(3), IMM(0x1000)); // mov i3,0x1000,NZ
+ UML_TEST(block, SPR32(SPR4XX_TSR), IMM(PPC4XX_TSR_FIS)); // test [tsr],FIS
+ UML_MOVc(block, IF_NZ, IREG(3), IMM(0x1010)); // mov i3,0x1010,NZ
+ UML_TEST(block, SPR32(DCR4XX_EXISR), SPR32(DCR4XX_EXIER)); // test [exisr],[exier]
+ UML_MOVc(block, IF_NZ, IREG(3), IMM(vector)); // mov i3,vector,NZ
+ UML_TEST(block, SPR32(SPR4XX_TSR), IMM(PPC4XX_TSR_WIS)); // test [tsr],WIS
+ UML_JMPc(block, IF_Z, notwdog = label++); // jz notwdog
+ UML_MOV(block, IREG(3), IMM(0x1020)); // mov i3,0x1020
+
+ /* exception PC goes into SRR2, MSR goes to SRR3 */
+ UML_MOV(block, SPR32(SPR4XX_SRR2), IREG(0)); // mov [srr2],i0
+ UML_MOV(block, SPR32(SPR4XX_SRR3), MSR32); // mov [srr3],[msr]
+ UML_AND(block, IREG(2), MSR32, IMM(~(MSR4XX_WE | MSR_PR | MSR4XX_CE | MSR_EE | MSR4XX_DE | MSR4XX_PE)));
+ UML_JMP(block, common = label++); // jmp common
+
+ /* exception PC goes into SRR0, MSR goes to SRR1 */
+ UML_LABEL(block, notwdog); // notwdog:
+ UML_MOV(block, SPR32(SPR4XX_SRR0), IREG(0)); // mov [srr0],i0
+ UML_MOV(block, SPR32(SPR4XX_SRR1), MSR32); // mov [srr1],[msr]
+ UML_AND(block, IREG(2), MSR32, IMM(~(MSR4XX_WE | MSR_PR | MSR_EE | MSR4XX_PE)));// and i2,[msr],~(bunch-o-flags)
+ UML_LABEL(block, common); // common:
+ }
+ else
+ {
+ /* exception PC goes into SRR0, MSR goes to SRR1 */
+ UML_MOV(block, SPR32(SPR4XX_SRR0), IREG(0)); // mov [srr0],i0
+ UML_MOV(block, SPR32(SPR4XX_SRR1), MSR32); // mov [srr1],[msr]
+ UML_AND(block, IREG(2), MSR32, IMM(~(MSR4XX_WE | MSR_PR | MSR_EE | MSR4XX_PE)));// and i2,[msr],~(bunch-o-flags)
+ }
+
+ /* finish updating MSR */
+ UML_ROLINS(block, IREG(2), IREG(2), IMM(16), IMM(MSR_LE)); // rolins i2,u2,16,MSR_LE
+ UML_MOV(block, MSR32, IREG(2)); // mov [msr],i2
+ generate_update_mode(block); // <update mode>
+
+ /* program exception flags go to ESR */
+ if (exception == EXCEPTION_PROGRAM)
+ {
+ UML_GETEXP(block, IREG(1)); // getexp i1
+ UML_SHL(block, SPR32(SPR4XX_ESR), IREG(1), IMM(8)); // shl [esr],i1,8
+ }
+
+ /* determine our target PC */
+ UML_ROLINS(block, IREG(3), SPR32(SPR4XX_EVPR), IMM(0), IMM(0xffff0000)); // rolins i3,[evpr],0,0xffff0000
+ UML_MOV(block, IREG(0), IREG(3)); // mov i0,i3
+ }
+
+ /* optionally print exceptions */
+ if ((PRINTF_EXCEPTIONS && exception != EXCEPTION_EI && exception != EXCEPTION_SYSCALL) ||
+ (PRINTF_MMU && (exception == EXCEPTION_ISI || exception == EXCEPTION_DSI)))
+ {
+ UML_MOV(block, MEM(&ppc->param0), IMM(exception)); // mov [param0],exception
+ UML_CALLC(block, cfunc_printf_exception, NULL); // callc cfunc_printf_exception,NULL
+ }
+
+ /* adjust cycles */
+ UML_SUBf(block, MEM(&ppc->icount), MEM(&ppc->icount), IREG(1), FLAGS_S); // sub icount,icount,cycles,S
+ UML_EXHc(block, IF_S, ppc->impstate->out_of_cycles, IREG(0)); // exh out_of_cycles,i0
+ UML_HASHJMP(block, MEM(&ppc->impstate->mode), IREG(0), ppc->impstate->nocode); // hashjmp <mode>,i0,nocode
+
+ drcuml_block_end(block);
+}
+
+
+/*------------------------------------------------------------------
+ static_generate_memory_accessor
+------------------------------------------------------------------*/
+
+static void static_generate_memory_accessor(drcuml_state *drcuml, int mode, int size, int iswrite, int ismasked, const char *name, drcuml_codehandle **handleptr, drcuml_codehandle *masked)
+{
+ /* on entry, address is in I0; data for writes is in I1; masks are in I2 */
+ /* on exit, read result is in I0 */
+ /* routine trashes I0-I3 */
+ int fastxor = BYTE8_XOR_BE(0) >> (activecpu_databus_width(ADDRESS_SPACE_PROGRAM) < 64);
+ drcuml_block *block;
+ jmp_buf errorbuf;
+ int tlbreturn = 0;
+ int unaligned = 0;
+ int alignex = 0;
+ int tlbmiss = 0;
+ int label = 1;
+ int ramnum;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_exception");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 1024, &errorbuf);
+
+ /* add a global entry for this */
+ alloc_handle(drcuml, handleptr, name);
+ UML_HANDLE(block, *handleptr); // handle *handleptr
+
+ /* 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 == NULL || !(ppc->cap & PPCCAP_MISALIGNED))
+ {
+ UML_TEST(block, IREG(0), IMM(size - 1)); // test i0,size-1
+ UML_JMPc(block, IF_NZ, alignex = label++); // jmp alignex,nz
+ }
+
+ /* in big-endian mode, it's more complicated */
+ else
+ {
+ /* 8-byte accesses must be word-aligned */
+ if (size == 8)
+ {
+ UML_TEST(block, IREG(0), IMM(3)); // test i0,3
+ UML_JMPc(block, IF_NZ, alignex = label++); // jmp alignex,nz
+ }
+
+ /* unaligned 2 and 4 byte accesses need to be broken up */
+ else
+ {
+ UML_TEST(block, IREG(0), IMM(size - 1)); // test i0,size-1
+ UML_JMPc(block, IF_NZ, unaligned = label++); // jmp unaligned,nz
+ }
+ }
+ }
+
+ /* general case: assume paging and perform a translation */
+ if ((ppc->cap & PPCCAP_OEA) && (mode & MODE_DATA_TRANSLATION))
+ {
+ 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_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:
+ UML_ROLINS(block, IREG(0), IREG(3), IMM(0), IMM(0xfffff000)); // rolins i0,i3,0,0xfffff000
+ }
+ UML_XOR(block, IREG(0), IREG(0), IMM((mode & MODE_LITTLE_ENDIAN) ? (8 - size) : 0)); // xor i0,i0,8-size
+
+ for (ramnum = 0; ramnum < PPC_MAX_FASTRAM; ramnum++)
+ if (!Machine->debug_mode && ppc->impstate->fastram[ramnum].base != NULL && (!iswrite || !ppc->impstate->fastram[ramnum].readonly))
+ {
+ void *fastbase = (UINT8 *)ppc->impstate->fastram[ramnum].base - ppc->impstate->fastram[ramnum].start;
+ UINT32 skip = label++;
+
+ if (ppc->impstate->fastram[ramnum].end != 0xffffffff)
+ {
+ UML_CMP(block, IREG(0), IMM(ppc->impstate->fastram[ramnum].end)); // cmp i0,end
+ UML_JMPc(block, IF_A, skip); // ja skip
+ }
+ if (ppc->impstate->fastram[ramnum].start != 0x00000000)
+ {
+ UML_CMP(block, IREG(0), IMM(ppc->impstate->fastram[ramnum].start)); // cmp i0,fastram_start
+ UML_JMPc(block, IF_B, skip); // jb skip
+ }
+
+ if (!iswrite)
+ {
+ if (size == 1)
+ {
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 0)); // xor i0,i0,fastxor >> 0
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), BYTE); // load i0,fastbase,i0,byte
+ }
+ else if (size == 2)
+ {
+ UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 1)); // xor i0,i0,fastxor >> 1
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), WORD); // load i0,fastbase,i0,word
+ }
+ else if (size == 4)
+ {
+ UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 2)); // xor i0,i0,fastxor >> 2
+ UML_LOAD(block, IREG(0), fastbase, IREG(0), DWORD); // load i0,fastbase,i0,dword
+ }
+ else if (size == 8)
+ {
+ UML_SHR(block, IREG(0), IREG(0), IMM(3)); // shr i0,i0,3
+ UML_DLOAD(block, IREG(0), fastbase, IREG(0), QWORD); // dload i0,fastbase,i0,qword
+ }
+ UML_RET(block); // ret
+ }
+ else
+ {
+ if (size == 1)
+ {
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 0)); // xor i0,i0,fastxor >> 0
+ UML_STORE(block, fastbase, IREG(0), IREG(1), BYTE); // store fastbase,i0,i1,byte
+ }
+ else if (size == 2)
+ {
+ UML_SHR(block, IREG(0), IREG(0), IMM(1)); // shr i0,i0,1
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 1)); // xor i0,i0,fastxor >> 1
+ UML_STORE(block, fastbase, IREG(0), IREG(1), WORD); // store fastbase,i0,i1,word
+ }
+ else if (size == 4)
+ {
+ UML_SHR(block, IREG(0), IREG(0), IMM(2)); // shr i0,i0,2
+ UML_XOR(block, IREG(0), IREG(0), IMM(fastxor >> 2)); // xor i0,i0,fastxor >> 2
+ if (ismasked)
+ {
+ UML_LOAD(block, IREG(3), fastbase, IREG(0), DWORD); // load i3,fastbase,i0,dword
+ UML_AND(block, IREG(1), IREG(1), IREG(2)); // and i1,i1,i2
+ UML_XOR(block, IREG(2), IREG(2), IMM(0xffffffff)); // xor i2,i2,0xfffffffff
+ UML_AND(block, IREG(3), IREG(3), IREG(2)); // and i3,i3,i2
+ UML_OR(block, IREG(1), IREG(1), IREG(3)); // or i1,i1,i3
+ }
+ UML_STORE(block, fastbase, IREG(0), IREG(1), DWORD); // store fastbase,i0,i1,dword
+ }
+ else if (size == 8)
+ {
+ UML_SHR(block, IREG(0), IREG(0), IMM(3)); // shr i0,i0,3
+ if (ismasked)
+ {
+ UML_DLOAD(block, IREG(3), fastbase, IREG(0), QWORD); // dload i3,fastbase,i0,qword
+ UML_DAND(block, IREG(1), IREG(1), IREG(2)); // dand i1,i1,i2
+ UML_DXOR(block, IREG(2), IREG(2), IMM(U64(0xffffffffffffffff))); // dxor i2,i2,0xfffffffffffffffff
+ UML_DAND(block, IREG(3), IREG(3), IREG(2)); // dand i3,i3,i2
+ UML_DOR(block, IREG(1), IREG(1), IREG(3)); // dor i1,i1,i3
+ }
+ UML_DSTORE(block, fastbase, IREG(0), IREG(1), QWORD); // dstore fastbase,i0,i1,qword
+ }
+ UML_RET(block); // ret
+ }
+
+ UML_LABEL(block, skip); // skip:
+ }
+
+ switch (size)
+ {
+ case 1:
+ if (iswrite)
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_BYTE); // write i0,i1,program_byte
+ else
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_BYTE); // read i0,i0,program_byte
+ break;
+
+ case 2:
+ if (iswrite)
+ {
+ if (!ismasked)
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_WORD); // write i0,i1,program_word
+ else
+ UML_WRITEM(block, IREG(0), IREG(2), IREG(1), PROGRAM_WORD); // writem i0,i2,i1,program_word
+ }
+ else
+ {
+ if (!ismasked)
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_WORD); // read i0,i0,program_word
+ else
+ UML_READM(block, IREG(0), IREG(0), IREG(2), PROGRAM_WORD); // readm i0,i0,i2,program_word
+ }
+ break;
+
+ case 4:
+ if (iswrite)
+ {
+ if (!ismasked)
+ UML_WRITE(block, IREG(0), IREG(1), PROGRAM_DWORD); // write i0,i1,program_dword
+ else
+ UML_WRITEM(block, IREG(0), IREG(2), IREG(1), PROGRAM_DWORD); // writem i0,i2,i1,program_dword
+ }
+ else
+ {
+ if (!ismasked)
+ UML_READ(block, IREG(0), IREG(0), PROGRAM_DWORD); // read i0,i0,program_dword
+ else
+ UML_READM(block, IREG(0), IREG(0), IREG(2), PROGRAM_DWORD); // readm i0,i0,i2,program_dword
+ }
+ break;
+
+ case 8:
+ if (iswrite)
+ {
+ if (!ismasked)
+ UML_DWRITE(block, IREG(0), IREG(1), PROGRAM_QWORD); // dwrite i0,i1,program_qword
+ else
+ UML_DWRITEM(block, IREG(0), IREG(2), IREG(1), PROGRAM_QWORD); // dwritem i0,i2,i1,program_qword
+ }
+ else
+ {
+ if (!ismasked)
+ UML_DREAD(block, IREG(0), IREG(0), PROGRAM_QWORD); // dread i0,i0,program_qword
+ else
+ UML_DREADM(block, IREG(0), IREG(0), IREG(2), PROGRAM_QWORD); // dreadm i0,i0,i2,program_qword
+ }
+ break;
+ }
+ UML_RET(block); // ret
+
+ /* handle unaligned accesses */
+ if (unaligned != 0)
+ {
+ UML_LABEL(block, unaligned); // unaligned:
+ if (size == 2)
+ {
+ if (iswrite)
+ {
+ UML_MOV(block, MEM(&ppc->impstate->tempaddr), IREG(0)); // mov [tempaddr],i0
+ UML_MOV(block, MEM(&ppc->impstate->tempdata), IREG(1)); // mov [tempdata],i1
+ UML_SUB(block, IREG(0), IREG(0), IMM(1)); // sub i0,i0,1
+ UML_SHR(block, IREG(1), IREG(1), IMM(8)); // shr i1,i1,8
+ UML_MOV(block, IREG(2), IMM(0x00ff)); // mov i2,0x00ff
+ UML_CALLH(block, masked); // callh masked
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(1)); // add i0,[tempaddr],1
+ UML_SHL(block, IREG(1), MEM(&ppc->impstate->tempdata), IMM(8)); // shl i1,[tempdata],8
+ UML_MOV(block, IREG(2), IMM(0xff00)); // mov i2,0xff00
+ UML_CALLH(block, masked); // callh masked
+ }
+ else
+ {
+ UML_MOV(block, MEM(&ppc->impstate->tempaddr), IREG(0)); // mov [tempaddr],i0
+ UML_SUB(block, IREG(0), IREG(0), IMM(1)); // sub i0,i0,1
+ UML_MOV(block, IREG(2), IMM(0x00ff)); // mov i2,0x00ff
+ UML_CALLH(block, masked); // callh masked
+ UML_SHL(block, MEM(&ppc->impstate->tempdata), IREG(0), IMM(8)); // shl [tempdata],i0,8
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(1)); // add i0,[tempaddr],1
+ UML_MOV(block, IREG(2), IMM(0xff00)); // mov i2,0xff00
+ UML_CALLH(block, masked); // callh masked
+ UML_SHR(block, IREG(0), IREG(0), IMM(8)); // shr i0,i0,8
+ UML_OR(block, IREG(0), IREG(0), MEM(&ppc->impstate->tempdata)); // or i0,i0,[tempdata]
+ }
+ }
+ else if (size == 4)
+ {
+ int offs2, offs3;
+ if (iswrite)
+ {
+ UML_MOV(block, MEM(&ppc->impstate->tempaddr), IREG(0)); // mov [tempaddr],i0
+ UML_MOV(block, MEM(&ppc->impstate->tempdata), IREG(1)); // mov [tempdata],i1
+ UML_TEST(block, IREG(0), IMM(2)); // test i0,i0,2
+ UML_JMPc(block, IF_NZ, offs2 = label++); // jnz offs2
+ UML_SUB(block, IREG(0), IREG(0), IMM(1)); // sub i0,i0,1
+ UML_SHR(block, IREG(1), IREG(1), IMM(8)); // shr i1,i1,8
+ UML_MOV(block, IREG(2), IMM(0x00ffffff)); // mov i2,0x00ffffff
+ UML_CALLH(block, masked); // callh masked
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(3)); // add i0,[tempaddr],3
+ UML_SHL(block, IREG(1), MEM(&ppc->impstate->tempdata), IMM(24)); // shl i1,[tempdata],24
+ UML_MOV(block, IREG(2), IMM(0xff000000)); // mov i2,0xff000000
+ UML_CALLH(block, masked); // callh masked
+ UML_RET(block); // ret
+ UML_LABEL(block, offs2); // offs2:
+ UML_TEST(block, IREG(0), IMM(1)); // test i0,i0,1
+ UML_JMPc(block, IF_NZ, offs3 = label++); // jnz offs3
+ UML_SUB(block, IREG(0), IREG(0), IMM(2)); // sub i0,i0,2
+ UML_SHR(block, IREG(1), IREG(1), IMM(16)); // shr i1,i1,16
+ UML_MOV(block, IREG(2), IMM(0x0000ffff)); // mov i2,0x0000ffff
+ UML_CALLH(block, masked); // callh masked
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(2)); // add i0,[tempaddr],2
+ UML_SHL(block, IREG(1), MEM(&ppc->impstate->tempdata), IMM(16)); // shl i1,[tempdata],16
+ UML_MOV(block, IREG(2), IMM(0xffff0000)); // mov i2,0xffff0000
+ UML_CALLH(block, masked); // callh masked
+ UML_RET(block); // ret
+ UML_LABEL(block, offs3); // offs3:
+ UML_SUB(block, IREG(0), IREG(0), IMM(3)); // sub i0,i0,3
+ UML_SHR(block, IREG(1), IREG(1), IMM(24)); // shr i1,i1,24
+ UML_MOV(block, IREG(2), IMM(0x000000ff)); // mov i2,0x000000ff
+ UML_CALLH(block, masked); // callh masked
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(1)); // add i0,[tempaddr],1
+ UML_SHL(block, IREG(1), MEM(&ppc->impstate->tempdata), IMM(8)); // shl i1,[tempdata],8
+ UML_MOV(block, IREG(2), IMM(0xffffff00)); // mov i2,0xffffff00
+ UML_CALLH(block, masked); // callh masked
+ }
+ else
+ {
+ UML_MOV(block, MEM(&ppc->impstate->tempaddr), IREG(0)); // mov [tempaddr],i0
+ UML_TEST(block, IREG(0), IMM(2)); // test i0,i0,2
+ UML_JMPc(block, IF_NZ, offs2 = label++); // jnz offs2
+ UML_SUB(block, IREG(0), IREG(0), IMM(1)); // sub i0,i0,1
+ UML_MOV(block, IREG(2), IMM(0x00ffffff)); // mov i2,0x00ffffff
+ UML_CALLH(block, masked); // callh masked
+ UML_SHL(block, MEM(&ppc->impstate->tempdata), IREG(0), IMM(8)); // shl [tempdata],i0,8
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(3)); // add i0,[tempaddr],3
+ UML_MOV(block, IREG(2), IMM(0xff000000)); // mov i2,0xff000000
+ UML_CALLH(block, masked); // callh masked
+ UML_SHR(block, IREG(0), IREG(0), IMM(24)); // shr i0,i0,24
+ UML_OR(block, IREG(0), IREG(0), MEM(&ppc->impstate->tempdata)); // or i0,i0,[tempdata]
+ UML_RET(block); // ret
+ UML_LABEL(block, offs2); // offs2:
+ UML_TEST(block, IREG(0), IMM(1)); // test i0,i0,1
+ UML_JMPc(block, IF_NZ, offs3 = label++); // jnz offs3
+ UML_SUB(block, IREG(0), IREG(0), IMM(2)); // sub i0,i0,2
+ UML_MOV(block, IREG(2), IMM(0x0000ffff)); // mov i2,0x0000ffff
+ UML_CALLH(block, masked); // callh masked
+ UML_SHL(block, MEM(&ppc->impstate->tempdata), IREG(0), IMM(16)); // shl [tempdata],i0,16
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(2)); // add i0,[tempaddr],2
+ UML_MOV(block, IREG(2), IMM(0xffff0000)); // mov i2,0xffff0000
+ UML_CALLH(block, masked); // callh masked
+ UML_SHR(block, IREG(0), IREG(0), IMM(16)); // shr i0,i0,16
+ UML_OR(block, IREG(0), IREG(0), MEM(&ppc->impstate->tempdata)); // or i0,i0,[tempdata]
+ UML_RET(block); // ret
+ UML_LABEL(block, offs3); // offs3:
+ UML_SUB(block, IREG(0), IREG(0), IMM(3)); // sub i0,i0,3
+ UML_MOV(block, IREG(2), IMM(0x000000ff)); // mov i2,0x000000ff
+ UML_CALLH(block, masked); // callh masked
+ UML_SHL(block, MEM(&ppc->impstate->tempdata), IREG(0), IMM(24)); // shl [tempdata],i0,24
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(1)); // add i0,[tempaddr],1
+ UML_MOV(block, IREG(2), IMM(0xffffff00)); // mov i2,0xffffff00
+ UML_CALLH(block, masked); // callh masked
+ UML_SHR(block, IREG(0), IREG(0), IMM(8)); // shr i0,i0,8
+ UML_OR(block, IREG(0), IREG(0), MEM(&ppc->impstate->tempdata)); // or i0,i0,[tempdata]
+ }
+ }
+ UML_RET(block); // ret
+ }
+
+ /* handle an alignment exception */
+ if (alignex != 0)
+ {
+ UML_LABEL(block, alignex); // alignex:
+ UML_RECOVER(block, SPR32(SPROEA_DSISR), MAPVAR_DSISR); // recover [dsisr],DSISR
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_ALIGN], IREG(0)); // exh align,i0
+ }
+
+ /* handle a TLB miss */
+ if (tlbmiss != 0)
+ {
+ int dsi;
+
+ UML_LABEL(block, tlbmiss); // tlbmiss:
+ UML_MOV(block, MEM(&ppc->param0), IREG(0)); // mov [param0],i0
+ UML_MOV(block, MEM(&ppc->param1), IMM(iswrite ? TRANSLATE_WRITE : TRANSLATE_READ)); // mov [param1],TRANSLATE_READ/WRITE
+ UML_CALLC(block, ppccom_tlb_fill, ppc); // callc tlbfill,ppc
+ 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_JMP(block, tlbreturn); // jmp tlbreturn
+ UML_LABEL(block, dsi); // dsi:
+ if (!(ppc->cap & PPCCAP_603_MMU))
+ {
+ UML_MOV(block, SPR32(SPROEA_DSISR), MEM(&ppc->param0)); // mov [dsisr],[param0]
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_DSI], IREG(0)); // exh dsi,i0
+ }
+ else
+ {
+ UML_MOV(block, SPR32(SPR603_DMISS), IREG(0)); // mov [dmiss],i0
+ UML_MOV(block, SPR32(SPR603_DCMP), MEM(&ppc->mmu603_cmp)); // mov [dcmp],[mmu603_cmp]
+ UML_MOV(block, SPR32(SPR603_HASH1), MEM(&ppc->mmu603_hash[0])); // mov [hash1],[mmu603_hash][0]
+ UML_MOV(block, SPR32(SPR603_HASH2), MEM(&ppc->mmu603_hash[1])); // mov [hash2],[mmu603_hash][1]
+ if (iswrite)
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_DTLBMISSS], IREG(0)); // exh dtlbmisss,i0
+ else
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_DTLBMISSL], IREG(0)); // exh dtlbmissl,i0
+ }
+ }
+
+ drcuml_block_end(block);
+}
+
+
+/*-------------------------------------------------
+ static_generate_swap_tgpr - generate a
+ subroutine to swap GPR0-3 with TGPR0-3
+-------------------------------------------------*/
+
+static void static_generate_swap_tgpr(drcuml_state *drcuml)
+{
+ drcuml_block *block;
+ jmp_buf errorbuf;
+ int regnum;
+
+ /* if we get an error back, we're screwed */
+ if (setjmp(errorbuf) != 0)
+ fatalerror("Unrecoverable error in static_generate_swap_tgpr");
+
+ /* begin generating */
+ block = drcuml_block_begin(drcuml, 30, &errorbuf);
+
+ /* generate a hash jump via the current mode and PC */
+ alloc_handle(drcuml, &ppc->impstate->swap_tgpr, "swap_tgpr");
+ UML_HANDLE(block, ppc->impstate->swap_tgpr); // handle swap_tgpr
+ for (regnum = 0; regnum < 4; regnum++)
+ {
+ UML_MOV(block, IREG(1), R32(regnum)); // mov i1,r[regnum]
+ UML_MOV(block, R32(regnum), MEM(&ppc->mmu603_r[regnum])); // mov r[regnum],mmu603_r[regnum]
+ UML_MOV(block, MEM(&ppc->mmu603_r[regnum]), IREG(1)); // mov mmu603_r[regnum],i1
+ }
+ UML_RET(block); // ret
+
+ drcuml_block_end(block);
+}
+
+
+
+/***************************************************************************
+ CODE GENERATION
+***************************************************************************/
+
+/*-------------------------------------------------
+ generate_update_mode - update the mode based
+ on the MSR
+-------------------------------------------------*/
+
+static void generate_update_mode(drcuml_block *block)
+{
+ UML_AND(block, IREG(0), MSR32, IMM(MSR_LE)); // and i0,msr,MSR_LE
+ UML_AND(block, IREG(1), MSR32, IMM(MSROEA_DR)); // and i1,msr,MSR_DR
+ 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_AND(block, IREG(1), MSR32, IMM(MSR_PR)); // and i1,msr,MSR_PR
+ UML_SHR(block, IREG(1), IREG(1), IMM(12)); // shr i1,i1,12
+ UML_OR(block, MEM(&ppc->impstate->mode), IREG(0), IREG(1)); // or [mode],i0,i1
+}
+
+
+/*-------------------------------------------------
+ generate_update_cycles - generate code to
+ subtract cycles from the icount and generate
+ an exception if out
+-------------------------------------------------*/
+
+static void generate_update_cycles(drcuml_block *block, compiler_state *compiler, drcuml_ptype ptype, UINT64 pvalue, int allow_exception)
+{
+ /* check full interrupts if pending */
+ if (compiler->checkints)
+ {
+ drcuml_codelabel skip;
+
+ compiler->checkints = FALSE;
+ UML_TEST(block, MEM(&ppc->irq_pending), IMM(~0)); // test [irq_pending],0
+ UML_JMPc(block, IF_Z, skip = compiler->labelnum++); // jmp skip,Z
+ UML_TEST(block, MSR32, IMM(MSR_EE)); // test [msr],MSR_EE
+ UML_JMPc(block, IF_Z, skip); // jmp skip,Z
+ UML_MOV(block, IREG(0), PARAM(ptype, pvalue)); // mov i0,nextpc
+ UML_MOV(block, IREG(1), IMM(compiler->cycles)); // mov i1,cycles
+ UML_CALLH(block, ppc->impstate->exception_norecover[EXCEPTION_EI]); // callh interrupt_norecover
+ UML_LABEL(block, skip); // skip:
+ }
+
+ /* account for cycles */
+ if (compiler->cycles > 0)
+ {
+ UML_SUBf(block, MEM(&ppc->icount), MEM(&ppc->icount), MAPVAR_CYCLES, allow_exception ? FLAGS_S : 0);
+ // sub icount,icount,cycles,S
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ if (allow_exception)
+ UML_EXHc(block, IF_S, ppc->impstate->out_of_cycles, PARAM(ptype, pvalue)); // exh out_of_cycles,nextpc
+ }
+ compiler->cycles = 0;
+}
+
+
+/*-------------------------------------------------
+ generate_checksum_block - generate code to
+ validate a sequence of opcodes
+-------------------------------------------------*/
+
+static void generate_checksum_block(drcuml_block *block, compiler_state *compiler, const opcode_desc *seqhead, const opcode_desc *seqlast)
+{
+ const opcode_desc *curdesc;
+ if (LOG_UML)
+ UML_COMMENT(block, "[Validation for %08X]", seqhead->pc); // comment
+
+ /* loose verify or single instruction: just compare and fail */
+ if (!(ppc->impstate->drcoptions & PPCDRC_STRICT_VERIFY) || seqhead->next == NULL)
+ {
+ if (!(seqhead->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ UML_LOAD(block, IREG(0), seqhead->opptr.l, IMM(0), DWORD); // load i0,*opptr,dword
+ UML_CMP(block, IREG(0), IMM(*seqhead->opptr.l)); // cmp i0,*opptr
+ UML_EXHc(block, IF_NE, ppc->impstate->nocode, IMM(seqhead->pc)); // exne nocode,seqhead->pc
+ }
+ }
+
+ /* full verification; sum up everything */
+ else
+ {
+#if 0
+ for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ UML_LOAD(block, IREG(0), curdesc->opptr.l, IMM(0), DWORD); // load i0,*opptr,dword
+ UML_CMP(block, IREG(0), IMM(*curdesc->opptr.l)); // cmp i0,*opptr
+ UML_EXHc(block, IF_NE, ppc->impstate->nocode, IMM(seqhead->pc)); // exne nocode,seqhead->pc
+ }
+#else
+ UINT32 sum = 0;
+ UML_LOAD(block, IREG(0), seqhead->opptr.l, IMM(0), DWORD); // load i0,*opptr,dword
+ sum += *seqhead->opptr.l;
+ for (curdesc = seqhead->next; curdesc != seqlast->next; curdesc = curdesc->next)
+ if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ UML_LOAD(block, IREG(1), curdesc->opptr.l, IMM(0), DWORD); // load i1,*opptr,dword
+ UML_ADD(block, IREG(0), IREG(0), IREG(1)); // add i0,i0,i1
+ sum += *curdesc->opptr.l;
+ }
+ UML_CMP(block, IREG(0), IMM(sum)); // cmp i0,sum
+ UML_EXHc(block, IF_NE, ppc->impstate->nocode, IMM(seqhead->pc)); // exne nocode,seqhead->pc
+#endif
+ }
+}
+
+
+/*-------------------------------------------------
+ generate_sequence_instruction - generate code
+ for a single instruction in a sequence
+-------------------------------------------------*/
+
+static void generate_sequence_instruction(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ int hotnum;
+
+ /* add an entry for the log */
+ if (LOG_UML && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ log_add_disasm_comment(block, desc->pc, *desc->opptr.l);
+
+ /* set the PC map variable */
+ UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc
+
+ /* accumulate total cycles */
+ compiler->cycles += desc->cycles;
+
+ /* is this a hotspot? */
+ for (hotnum = 0; hotnum < PPC_MAX_HOTSPOTS; hotnum++)
+ if (ppc->impstate->hotspot[hotnum].pc != 0 && desc->pc == ppc->impstate->hotspot[hotnum].pc && *desc->opptr.l == ppc->impstate->hotspot[hotnum].opcode)
+ {
+ compiler->cycles += ppc->impstate->hotspot[hotnum].cycles;
+ break;
+ }
+
+ /* update the icount map variable */
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
+
+ /* if we want a probe, add it here */
+ if (desc->pc == PROBE_ADDRESS)
+ UML_CALLC(block, cfunc_printf_probe, desc->pc); // callc cfunc_printf_probe,desc->pc
+
+ /* if we are debugging, call the debugger */
+ if (Machine->debug_mode)
+ {
+ UML_MOV(block, MEM(&ppc->pc), IMM(desc->pc)); // mov [pc],desc->pc
+ save_fast_iregs(block); // <save fastregs>
+ UML_DEBUG(block, IMM(desc->pc)); // debug desc->pc
+ }
+
+ /* if we hit an unmapped address, fatal error */
+ if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
+ {
+ UML_MOV(block, MEM(&ppc->pc), IMM(desc->pc)); // mov [pc],desc->pc
+ save_fast_iregs(block); // <save fastregs>
+ UML_EXIT(block, IMM(EXECUTE_UNMAPPED_CODE)); // exit EXECUTE_UNMAPPED_CODE
+ }
+
+ /* if we hit a compiler page fault, it's just like a TLB mismatch */
+ if (desc->flags & OPFLAG_COMPILER_PAGE_FAULT)
+ {
+ if (PRINTF_MMU)
+ {
+ UML_MOV(block, MEM(&ppc->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, "Compiler page fault @ %08X\n"); // callc printf_debug
+ }
+ UML_EXH(block, ppc->impstate->tlb_mismatch, IMM(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) && (ppc->impstate->mode & MODE_DATA_TRANSLATION))
+ {
+ /* if we currently have a valid TLB read entry, we just verify */
+ if (ppc->tlb_table[desc->pc >> 12] != 0)
+ {
+ if (PRINTF_MMU)
+ {
+ UML_MOV(block, MEM(&ppc->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, "Checking TLB at @ %08X\n"); // callc printf_debug
+ }
+ UML_LOAD(block, IREG(0), &ppc->tlb_table[desc->pc >> 12], IMM(0), DWORD); // load i0,tlb_table[desc->pc >> 12],dword
+ UML_CMP(block, IREG(0), IMM(ppc->tlb_table[desc->pc >> 12])); // cmp i0,*tlbentry
+ UML_EXHc(block, IF_NE, ppc->impstate->tlb_mismatch, IMM(0)); // exh tlb_mismatch,0,NE
+ }
+
+ /* otherwise, we generate an unconditional exception */
+ else
+ {
+ if (PRINTF_MMU)
+ {
+ UML_MOV(block, MEM(&ppc->impstate->arg0), IMM(desc->pc)); // mov [arg0],desc->pc
+ UML_CALLC(block, cfunc_printf_debug, "No valid TLB @ %08X\n"); // callc printf_debug
+ }
+ UML_EXH(block, ppc->impstate->tlb_mismatch, IMM(0)); // exh tlb_mismatch,0
+ }
+ }
+
+ /* if this is an invalid opcode, generate the exception now */
+ if (desc->flags & OPFLAG_INVALID_OPCODE)
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x80000)); // exh exception_program,0x80000
+
+ /* if this is a privileged opcode in user mode, generate the exception */
+ else if ((desc->flags & OPFLAG_PRIVILEGED) && (ppc->impstate->mode & MODE_USER))
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x40000)); // exh exception_program,0x40000
+
+ /* otherwise, unless this is a virtual no-op, it's a regular instruction */
+ else if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
+ {
+ /* compile the instruction */
+ if (!generate_opcode(block, compiler, desc))
+ {
+ UML_MOV(block, MEM(&ppc->pc), IMM(desc->pc)); // mov [pc],desc->pc
+ UML_CALLC(block, cfunc_unimplemented, (void *)(FPTR)*desc->opptr.l); // callc cfunc_unimplemented
+ }
+ }
+}
+
+
+/*------------------------------------------------------------------
+ generate_compute_flags - compute CR0 and/or XER flags
+------------------------------------------------------------------*/
+
+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)
+ return;
+
+ /* 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
+ return;
+ }
+
+ /* semi-easy case: xer only */
+ if (!updatecr)
+ {
+ if (xermask & XER_OV)
+ {
+ UML_MOV(block, IREG(0), SPR32(SPR_XER)); // mov i0,[xer]
+ UML_GETFLGS(block, IREG(1), xerflags); // getflgs i1,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
+ }
+ else
+ {
+ UML_SETc(block, invertcarry ? IF_NC : IF_C, IREG(0)); // setc i0,nc/c
+ UML_ROLINS(block, SPR32(SPR_XER), IREG(0), IMM(29), IMM(XER_CA)); // rolins [xer],i0,29,XER_CA
+ }
+ return;
+ }
+
+ /* tricky case: both */
+ UML_GETFLGS(block, IREG(0), DRCUML_FLAG_S | DRCUML_FLAG_Z | xerflags); // getflgs i0,sz|xerflags
+ if (invertcarry)
+ UML_XOR(block, IREG(2), IREG(2), IMM(DRCUML_FLAG_C)); // xor i2,i2,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_AND(block, IREG(1), CR32, IMM(~CRMASK(0))); // and i1,[cr],~crmask(0)
+ UML_AND(block, IREG(0), IREG(0), IMM(CRMASK(0))); // and i0,i0,crmask(0)
+ UML_OR(block, CR32, IREG(0), IREG(1)); // or cr32,i0,i1
+}
+
+
+/*-------------------------------------------------
+ generate_branch - generate an unconditional
+ branch
+-------------------------------------------------*/
+
+static void generate_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, int source, UINT8 link)
+{
+ compiler_state compiler_temp = *compiler;
+
+ /* set the link if needed */
+ if (link)
+ UML_MOV(block, SPR32(SPR_LR), IMM(desc->pc + 4)); // mov [lr],desc->pc + 4
+
+ /* update the cycles and jump through the hash table to the target */
+ if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
+ {
+ generate_update_cycles(block, &compiler_temp, IMM(desc->targetpc), TRUE); // <subtract cycles>
+ if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
+ UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000
+ else
+ UML_HASHJMP(block, IMM(ppc->impstate->mode), IMM(desc->targetpc), ppc->impstate->nocode); // hashjmp <mode>,desc->targetpc,nocode
+ }
+ else
+ {
+UML_CMP(block, SPR32(source), IMM(0xb032));
+UML_MOV(block, MEM(&ppc->impstate->arg0), IMM(desc->pc));
+UML_CALLCc(block, IF_E, cfunc_printf_debug, "b032 @ PC=%08X\n");
+
+ generate_update_cycles(block, &compiler_temp, SPR32(source), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, IMM(ppc->impstate->mode), SPR32(source), ppc->impstate->nocode); // hashjmp <mode>,<rsreg>,nocode
+ }
+
+ /* update the label */
+ compiler->labelnum = compiler_temp.labelnum;
+
+ /* reset the mapvar to the current cycles */
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
+}
+
+
+/*-------------------------------------------------
+ generate_branch_bo - generate a conditional
+ branch based on the BO and BI fields
+-------------------------------------------------*/
+
+static void generate_branch_bo(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc, UINT32 bo, UINT32 bi, int source, int link)
+{
+ int skip = compiler->labelnum++;
+
+ if (!(bo & 0x04))
+ {
+ UML_SUBf(block, SPR32(SPR_CTR), SPR32(SPR_CTR), IMM(1), FLAGS_Z); // sub [ctr],[ctr],1,z
+ UML_JMPc(block, (bo & 0x02) ? IF_NZ : IF_Z, skip); // jmp skip,nz/z
+ }
+ if (!(bo & 0x10))
+ {
+ UML_TEST(block, CR32, IMM(0x80000000 >> bi)); // test cr32,0x80000000 >> bi
+ UML_JMPc(block, (bo & 0x08) ? IF_Z : IF_NZ, skip); // jmp skip,z/nz
+ }
+ generate_branch(block, compiler, desc, source, link); // <branch>
+ UML_LABEL(block, skip); // skip:
+}
+
+
+/*-------------------------------------------------
+ generate_opcode - generate code for a specific
+ opcode
+-------------------------------------------------*/
+
+static int generate_opcode(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = *desc->opptr.l;
+ UINT32 opswitch = op >> 26;
+ int regnum;
+
+ switch (opswitch)
+ {
+ case 0x02: /* TDI - 64-bit only */
+ case 0x1e: /* 0x1e group - 64-bit only */
+ case 0x3a: /* 0x3a group - 64-bit only */
+ case 0x3e: /* 0x3e group - 64-bit only */
+ return FALSE;
+
+ case 0x03: /* TWI */
+ UML_CMP(block, R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // cmp ra,simm
+ if (G_TO(op) & 0x10)
+ UML_EXHc(block, IF_L, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,l
+ if (G_TO(op) & 0x08)
+ UML_EXHc(block, IF_G, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,g
+ if (G_TO(op) & 0x04)
+ UML_EXHc(block, IF_E, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,e
+ if (G_TO(op) & 0x02)
+ UML_EXHc(block, IF_B, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,b
+ if (G_TO(op) & 0x01)
+ UML_EXHc(block, IF_A, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,a
+ return TRUE;
+
+ case 0x07: /* MULLI */
+ UML_MULS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), IMM((INT16)G_SIMM(op)));
+ // muls rd,rd,ra,simm
+ return TRUE;
+
+ case 0x0e: /* ADDI */
+ UML_ADD(block, R32(G_RD(op)), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add rd,ra,simm
+ return TRUE;
+
+ case 0x0f: /* ADDIS */
+ UML_ADD(block, R32(G_RD(op)), R32Z(G_RA(op)), IMM(G_SIMM(op) << 16)); // add rd,ra,simm << 16
+ return TRUE;
+
+ 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, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
+ 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, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
+ return TRUE;
+
+ case 0x08: /* SUBFIC */
+ UML_SUBf(block, R32(G_RD(op)), IMM((INT16)G_SIMM(op)), R32(G_RA(op)), FLAGS_C); // sub rd,simm,ra,c
+ generate_compute_flags(block, FALSE, XER_CA, TRUE); // <update flags>
+ return TRUE;
+
+ case 0x0c: /* ADDIC */
+ UML_ADDf(block, R32(G_RD(op)), R32(G_RA(op)), IMM((INT16)G_SIMM(op)), FLAGS_C); // add rd,ra,simm,c
+ generate_compute_flags(block, FALSE, XER_CA, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x0d: /* ADDIC. */
+ UML_ADDf(block, R32(G_RD(op)), R32(G_RA(op)), IMM((INT16)G_SIMM(op)), FLAGS_C); // add rd,ra,simm,c
+ generate_compute_flags(block, TRUE, XER_CA, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x10: /* BCx */
+ generate_branch_bo(block, compiler, desc, G_BO(op), G_BI(op), 0, op & M_LK); // <branch conditional>
+ return TRUE;
+
+ case 0x11: /* SC */
+ UML_EXH(block, ppc->impstate->exception[EXCEPTION_SYSCALL], IMM(0)); // exh syscall,0
+ return TRUE;
+
+ case 0x12: /* Bx */
+ generate_branch(block, compiler, desc, 0, op & M_LK); // <branch>
+ return TRUE;
+
+ case 0x13: /* 0x13 group */
+ return generate_instruction_13(block, compiler, desc); // <group13>
+
+ case 0x14: /* RLWIMIx */
+ UML_ROLINS(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_SH(op)), IMM(compute_rlw_mask(G_MB(op), G_ME(op))));
+ // rolins ra,rs,sh,mask
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RA(op)), IMM(~0)); // test ra,~0
+ generate_compute_flags(block, TRUE, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x15: /* RLWINMx */
+ UML_ROLAND(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_SH(op)), IMM(compute_rlw_mask(G_MB(op), G_ME(op))));
+ // roland ra,rs,sh,mask
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RA(op)), IMM(~0)); // test ra,~0
+ generate_compute_flags(block, TRUE, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x17: /* RLWNMx */
+ UML_ROLAND(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op)), IMM(compute_rlw_mask(G_MB(op), G_ME(op))));
+ // roland ra,rs,rb,mask
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RA(op)), IMM(~0)); // test ra,~0
+ generate_compute_flags(block, TRUE, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x18: /* ORI */
+ UML_OR(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_UIMM(op))); // or ra,rs,uimm
+ return TRUE;
+
+ case 0x19: /* ORIS */
+ UML_OR(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_UIMM(op) << 16)); // or ra,rs,uimm << 16
+ return TRUE;
+
+ case 0x1a: /* XORI */
+ UML_XOR(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_UIMM(op))); // xor ra,rs,uimm
+ return TRUE;
+
+ case 0x1b: /* XORIS */
+ UML_XOR(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_UIMM(op) << 16)); // xor ra,rs,uimm << 16
+ return TRUE;
+
+ case 0x1c: /* ANDI. */
+ UML_ANDf(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_UIMM(op)), FLAGS_RC(op)); // and ra,rs,uimm,FLAGS_RC
+ generate_compute_flags(block, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1d: /* ANDIS. */
+ UML_ANDf(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_UIMM(op) << 16), FLAGS_RC(op));// and ra,rs,uimm << 16,FLAGS_RC
+ generate_compute_flags(block, TRUE, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1f: /* 0x1f group */
+ return generate_instruction_1f(block, compiler, desc); // <group1f>
+
+ case 0x22: /* LBZ */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x28: /* LHZ */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2a: /* LHA */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x20: /* LWZ */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x23: /* LBZU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x29: /* LHZU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2b: /* LHAU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x21: /* LWZU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x26: /* STB */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2c: /* STH */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs,0xffff
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x24: /* STW */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x27: /* STBU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2d: /* STHU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs,0xffff
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x25: /* STWU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2e: /* LMW */
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ for (regnum = G_RD(op); regnum < 32; regnum++)
+ {
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op) + 4 * (regnum - G_RD(op))));
+ // add i0,ra,simm + 4*(regnum-rd)
+ UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode & 3]); // callh read32align
+ UML_MOV(block, R32(regnum), IREG(0)); // mov regnum,i0
+ }
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2f: /* STMW */
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ for (regnum = G_RS(op); regnum < 32; regnum++)
+ {
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op) + 4 * (regnum - G_RS(op))));
+ // add i0,ra,simm + 4*(regnum-rs)
+ UML_MOV(block, IREG(1), R32(regnum)); // mov i1,regnum
+ UML_CALLH(block, ppc->impstate->write32align[ppc->impstate->mode & 3]); // callh write32align
+ }
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x30: /* LFS */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata), DWORD); // fdfrflt fd,[tempdata],dword
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x32: /* LFD */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64
+ UML_DMOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata)); // fdmov fd,[tempdata]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x31: /* LFSU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata), DWORD); // fdfrflt fd,[tempdata],dword
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x33: /* LFDU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64
+ UML_DMOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata)); // fdmov fd,[tempdata]
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x34: /* STFS */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_FSFRFLT(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op)), QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // mov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x36: /* STFD */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_FDMOV(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // dmov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMM(op)); // mapvar dsisr,DSISR_IMM(op)
+ UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x35: /* STFSU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_FSFRFLT(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op)), QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // mov i1,[tempdata]
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x37: /* STFDU */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), IMM((INT16)G_SIMM(op))); // add i0,ra,simm
+ UML_FDMOV(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // dmov i1,[tempdata]
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IMMU(op)); // mapvar dsisr,DSISR_IMMU(op)
+ UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x3b: /* 0x3b group */
+ return generate_instruction_3b(block, compiler, desc); // <group3b>
+
+ case 0x3f: /* 0x3f group */
+ return generate_instruction_3f(block, compiler, desc); // <group3f>
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_instruction_13 - compile opcodes in
+ the 0x13 group
+-------------------------------------------------*/
+
+static int generate_instruction_13(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = *desc->opptr.l;
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ switch (opswitch)
+ {
+ case 0x010: /* BCLRx */
+ generate_branch_bo(block, compiler, desc, G_BO(op), G_BI(op), SPR_LR, op & M_LK);// <branch conditional>
+ return TRUE;
+
+ case 0x210: /* BCCTRx */
+ generate_branch_bo(block, compiler, desc, G_BO(op), G_BI(op), SPR_CTR, op & M_LK);
+ // <branch conditional>
+ 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]
+ 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_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
+ 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_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
+ 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_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
+ 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_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
+ 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_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
+ 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_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
+ 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_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
+ 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_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
+ return TRUE;
+
+ case 0x032: /* RFI */
+ if (ppc->cap & PPCCAP_OEA)
+ {
+ if (!(ppc->cap & PPCCAP_603_MMU))
+ UML_ROLINS(block, MSR32, SPR32(SPROEA_SRR1), IMM(0), IMM(0x87c0ffff)); // rolins [msr],[srr1],0,0x87c0ffff
+ else
+ {
+ UML_MOV(block, IREG(0), MSR32); // mov i0,[msr]
+ UML_ROLINS(block, MSR32, SPR32(SPROEA_SRR1), IMM(0), IMM(0x87c0ffff | MSR603_TGPR));
+ // rolins [msr],[srr1],0,0x87c0ffff | MSR603_TGPR
+ UML_XOR(block, IREG(0), IREG(0), MSR32); // xor i0,i0,[msr]
+ UML_TEST(block, IREG(0), IMM(MSR603_TGPR)); // test i0,tgpr
+ UML_CALLHc(block, IF_NZ, ppc->impstate->swap_tgpr); // callh swap_tgpr,nz
+ }
+ }
+ else if (ppc->cap & PPCCAP_4XX)
+ UML_MOV(block, MSR32, SPR32(SPR4XX_SRR1)); // mov [msr],[srr1]
+ generate_update_mode(block); // <update mode>
+ compiler->checkints = TRUE;
+ generate_update_cycles(block, compiler, SPR32(SPROEA_SRR0), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, MEM(&ppc->impstate->mode), SPR32(SPROEA_SRR0), ppc->impstate->nocode);
+ // hashjmp mode,[srr0],nocode
+ return TRUE;
+
+ case 0x033: /* RFCI */
+ assert(ppc->cap & PPCCAP_4XX);
+ UML_MOV(block, MSR32, SPR32(SPR4XX_SRR3)); // mov [msr],[srr3]
+ generate_update_mode(block); // <update mode>
+ compiler->checkints = TRUE;
+ generate_update_cycles(block, compiler, SPR32(SPR4XX_SRR2), TRUE); // <subtract cycles>
+ UML_HASHJMP(block, MEM(&ppc->impstate->mode), SPR32(SPR4XX_SRR2), ppc->impstate->nocode);
+ // hashjmp mode,[srr2],nocode
+ return TRUE;
+
+ case 0x096: /* ISYNC */
+ /* effective no-op */
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_instruction_1f - compile opcodes in
+ the 0x1f group
+-------------------------------------------------*/
+
+static int generate_instruction_1f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = *desc->opptr.l;
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+ drcuml_codelabel swloop, swloopend;
+ int item;
+
+ switch (opswitch)
+ {
+ case 0x009: /* MULHDUx - 64-bit only */
+ case 0x015: /* LDX - 64-bit only */
+ case 0x01b: /* SLDx - 64-bit only */
+ case 0x035: /* LDUX - 64-bit only */
+ case 0x03a: /* CNTLZDx - 64-bit only */
+ case 0x044: /* TD - 64-bit only */
+ case 0x049: /* MULHDx - 64-bit only */
+ case 0x054: /* LDARX - 64-bit only */
+ case 0x095: /* STDX - 64-bit only */
+ case 0x0b5: /* STDUX - 64-bit only */
+ case 0x0d6: /* STDCX. - 64-bit only */
+ case 0x0e9: /* MULLD - 64-bit only */
+ case 0x2e9: /* MULLDO - 64-bit only */
+ case 0x155: /* LWAX - 64-bit only */
+ case 0x175: /* LWAUX - 64-bit only */
+ case 0x33a: /* SRADIx - 64-bit only */
+ case 0x33b: /* SRADIx - 64-bit only */
+ case 0x1b2: /* SLBIE - 64-bit only */
+ case 0x1c9: /* DIVDUx - 64-bit only */
+ case 0x3c9: /* DIVDUOx - 64-bit only */
+ case 0x1e9: /* DIVDx - 64-bit only */
+ case 0x3e9: /* DIVDOx - 64-bit only */
+ case 0x1f2: /* SLBIA - 64-bit only */
+ case 0x21b: /* SRDx - 64-bit only */
+ case 0x31a: /* SRADx - 64-bit only */
+ case 0x3da: /* EXTSW - 64-bit only */
+ return FALSE;
+
+ case 0x004: /* TW */
+ UML_CMP(block, R32(G_RA(op)), R32(G_RB(op))); // cmp ra,rb
+ if (G_TO(op) & 0x10)
+ UML_EXHc(block, IF_L, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,l
+ if (G_TO(op) & 0x08)
+ UML_EXHc(block, IF_G, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,g
+ if (G_TO(op) & 0x04)
+ UML_EXHc(block, IF_E, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,e
+ if (G_TO(op) & 0x02)
+ UML_EXHc(block, IF_B, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,b
+ if (G_TO(op) & 0x01)
+ UML_EXHc(block, IF_A, ppc->impstate->exception[EXCEPTION_PROGRAM], IMM(0x20000));// exh program,0x20000,a
+ return TRUE;
+
+ case 0x10a: /* ADDx */
+ case 0x30a: /* ADDOx */
+ UML_ADDf(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RCOE(op)); // add rd,ra,rb,FLAGS_RCOE(op)
+ generate_compute_flags(block, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE); // <update flags>
+ return TRUE;
+
+ case 0x00a: /* ADDCx */
+ case 0x20a: /* ADDCOx */
+ UML_ADDf(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RCOECA(op)); // add rd,ra,rb,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+ return TRUE;
+
+ case 0x08a: /* ADDEx */
+ case 0x28a: /* ADDEOx */
+ UML_CARRY(block, SPR32(SPR_XER), IMM(29)); // carry [xer],XER_CA
+ UML_ADDCf(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RCOECA(op));// addc rd,ra,rb,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+ return TRUE;
+
+ case 0x0ca: /* ADDZEx */
+ case 0x2ca: /* ADDZEOx */
+ UML_CARRY(block, SPR32(SPR_XER), IMM(29)); // carry [xer],XER_CA
+ UML_ADDCf(block, R32(G_RD(op)), R32(G_RA(op)), IMM(0), FLAGS_RCOECA(op)); // addc rd,ra,0,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+ return TRUE;
+
+ case 0x0ea: /* ADDMEx */
+ case 0x2ea: /* ADDMEOx */
+ UML_CARRY(block, SPR32(SPR_XER), IMM(29)); // carry [xer],XER_CA
+ UML_ADDCf(block, R32(G_RD(op)), R32(G_RA(op)), IMM(-1), FLAGS_RCOE(op)); // addc rd,ra,-1,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), FALSE);// <update flags>
+ return TRUE;
+
+ case 0x028: /* SUBFx */
+ case 0x228: /* SUBFOx */
+ UML_SUBf(block, R32(G_RD(op)), R32(G_RB(op)), R32(G_RA(op)), FLAGS_RCOE(op)); // sub rd,rb,ra,FLAGS_RCOE(op)
+ generate_compute_flags(block, op & M_RC, (op & M_OE) ? XER_OV : 0, TRUE); // <update flags>
+ return TRUE;
+
+ case 0x008: /* SUBFCx */
+ case 0x208: /* SUBFCOx */
+ UML_SUBf(block, R32(G_RD(op)), R32(G_RB(op)), R32(G_RA(op)), FLAGS_RCOECA(op)); // sub rd,rb,ra,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);// <update flags>
+ return TRUE;
+
+ case 0x088: /* SUBFEx */
+ case 0x288: /* SUBFEOx */
+ UML_XOR(block, IREG(0), SPR32(SPR_XER), IMM(XER_CA)); // xor i0,[xer],XER_CA
+ UML_CARRY(block, IREG(0), IMM(29)); // carry i0,XER_CA
+ UML_SUBBf(block, R32(G_RD(op)), R32(G_RB(op)), R32(G_RA(op)), FLAGS_RCOECA(op));// subc rd,rb,ra,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);// <update flags>
+ return TRUE;
+
+ case 0x0c8: /* SUBFZEx */
+ case 0x2c8: /* SUBFZEOx */
+ UML_XOR(block, IREG(0), SPR32(SPR_XER), IMM(XER_CA)); // xor i0,[xer],XER_CA
+ UML_CARRY(block, IREG(0), IMM(29)); // carry i0,XER_CA
+ UML_SUBBf(block, R32(G_RD(op)), IMM(0), R32(G_RA(op)), FLAGS_RCOECA(op)); // subc rd,0,ra,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);// <update flags>
+ return TRUE;
+
+ case 0x0e8: /* SUBFMEx */
+ case 0x2e8: /* SUBFMEOx */
+ UML_XOR(block, IREG(0), SPR32(SPR_XER), IMM(XER_CA)); // xor i0,[xer],XER_CA
+ UML_CARRY(block, IREG(0), IMM(29)); // carry i0,XER_CA
+ UML_SUBBf(block, R32(G_RD(op)), IMM(-1), R32(G_RA(op)), FLAGS_RCOECA(op)); // subc rd,-1,ra,,FLAGS_RCOECA(op)
+ generate_compute_flags(block, op & M_RC, XER_CA | ((op & M_OE) ? XER_OV : 0), TRUE);// <update flags>
+ return TRUE;
+
+ case 0x068: /* NEGx */
+ case 0x268: /* NEGOx */
+ UML_SUBf(block, R32(G_RD(op)), IMM(0), R32(G_RA(op)), FLAGS_RCOE(op)); // sub rd,0,ra,FLAGS_RCOE(op)
+ generate_compute_flags(block, op & M_RC, (op & M_OE) ? XER_OV : 0, TRUE); // <update flags>
+ return TRUE;
+
+ 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, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
+ 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, CR32, IREG(0), IMM(0), IMM(CRMASK(G_CRFD(op)))); // rolins cr,i0,0,crmask[cr]
+ return TRUE;
+
+ case 0x00b: /* MULHWUx */
+ UML_MULUf(block, IREG(0), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RC(op));
+ // mulu i0,rd,ra,rb,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x04b: /* MULHWx */
+ UML_MULSf(block, IREG(0), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RC(op));
+ // muls i0,rd,ra,rb,,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x0eb: /* MULLWx */
+ case 0x2eb: /* MULLWOx */
+ if (!(op & M_OE))
+ {
+ UML_MULSf(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RC(op));
+ // muls rd,rd,ra,rb,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ }
+ else
+ {
+ UML_MULSf(block, IREG(0), IREG(1), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RC(op));
+ // muls i0,i1,ra,rb
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0
+ UML_SAR(block, IREG(0), IREG(0), IMM(31)); // sar i0,i0,31
+ UML_AND(block, SPR32(SPR_XER), SPR32(SPR_XER), IMM(XER_OV)); // and [xer],[xer],XER_OV
+ UML_XORf(block, IREG(0), IREG(0), IREG(1), FLAGS_Z); // xor i0,i0,i1,Z
+ UML_MOVc(block, IF_NZ, IREG(0), IMM(XER_OV | XER_SO)); // mov i0,XER_OV | XER_SO,NZ
+ UML_OR(block, SPR32(SPR_XER), SPR32(SPR_XER), IREG(0)); // or [xer],[xer],i0
+ }
+ return TRUE;
+
+ case 0x1cb: /* DIVWUx */
+ case 0x3cb: /* DIVWUOx */
+ UML_DIVUf(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RCOE(op));
+ // divu rd,rd,ra,rb,FLAGS_RCOE(op)
+ generate_compute_flags(block, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1eb: /* DIVWx */
+ case 0x3eb: /* DIVWOx */
+ UML_DIVSf(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op)), FLAGS_RCOE(op));
+ // divs rd,rd,ra,rb,FLAGS_RCOE(op)
+ generate_compute_flags(block, op & M_RC, ((op & M_OE) ? XER_OV : 0), FALSE); // <update flags>
+ return TRUE;
+
+ case 0x01c: /* ANDx */
+ UML_ANDf(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op)), FLAGS_RC(op)); // and ra,rs,rb,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x03c: /* ANDCx */
+ UML_XOR(block, IREG(0), R32(G_RB(op)), IMM(~0)); // xor i0,rb,~0
+ UML_ANDf(block, R32(G_RA(op)), R32(G_RS(op)), IREG(0), FLAGS_RC(op)); // and ra,rs,i0,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1dc: /* NANDx */
+ UML_AND(block, IREG(0), R32(G_RS(op)), R32(G_RB(op))); // and i0,rs,rb
+ UML_XORf(block, R32(G_RA(op)), IREG(0), IMM(~0), FLAGS_RC(op)); // xor ra,i0,~0,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x1bc: /* ORx */
+ UML_ORf(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op)), FLAGS_RC(op)); // or ra,rs,rb,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x19c: /* ORCx */
+ UML_XORf(block, IREG(0), R32(G_RB(op)), IMM(~0), FLAGS_RC(op)); // xor i0,rb,~0,FLAGS_RC(op)
+ UML_OR(block, R32(G_RA(op)), R32(G_RS(op)), IREG(0)); // or ra,rs,i0
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x07c: /* NORx */
+ UML_OR(block, IREG(0), R32(G_RS(op)), R32(G_RB(op))); // or i0,rs,rb
+ UML_XORf(block, R32(G_RA(op)), IREG(0), IMM(~0), FLAGS_RC(op)); // xor ra,i0,~0,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x13c: /* XORx */
+ UML_XORf(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op)), FLAGS_RC(op)); // xor ra,rs,rb,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x11c: /* EQVx */
+ UML_XOR(block, IREG(0), R32(G_RS(op)), R32(G_RB(op))); // xor i0,rs,rb
+ UML_XORf(block, R32(G_RA(op)), IREG(0), IMM(~0), FLAGS_RC(op)); // xor ra,i0,~0,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x018: /* SLWx */
+ UML_SHL(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op))); // shl ra,rs,rb
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x218: /* SRWx */
+ UML_SHRf(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op)), FLAGS_RC(op)); // shr ra,rs,rb,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x318: /* SRAWx */
+ UML_SHL(block, IREG(1), IMM(0xffffffff), R32(G_RB(op))); // shl i1,0xffffffff,rb
+ UML_XOR(block, IREG(1), IREG(1), IMM(~0)); // xor i1,i1,~0
+ UML_AND(block, IREG(0), R32(G_RS(op)), IREG(1)); // and i0,rs,i1
+ UML_SAR(block, IREG(1), R32(G_RS(op)), IMM(31)); // sar i1,rs,31
+ UML_ANDf(block, IREG(0), IREG(0), IREG(1), DRCUML_FLAG_Z); // and i0,i0,i1,z
+ UML_SETc(block, IF_NZ, IREG(0)); // set i0,nz
+ UML_ROLINS(block, SPR32(SPR_XER), IREG(0), IMM(29), IMM(XER_CA)); // rolins [xer],i0,29,XER_CA
+ UML_SARf(block, R32(G_RA(op)), R32(G_RS(op)), R32(G_RB(op)), FLAGS_RC(op)); // sar ra,rs,rb,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x338: /* SRAWIx */
+ UML_AND(block, IREG(0), R32(G_RS(op)), IMM(~(0xffffffff << (G_SH(op) & 31)))); // and i0,rs,~(0xffffffff << (sh & 31))
+ UML_SAR(block, IREG(1), R32(G_RS(op)), IMM(31)); // sar i1,rs,31
+ UML_ANDf(block, IREG(0), IREG(0), IREG(1), DRCUML_FLAG_Z); // and i0,i0,i1,z
+ UML_SETc(block, IF_NZ, IREG(0)); // set i0,nz
+ UML_ROLINS(block, SPR32(SPR_XER), IREG(0), IMM(29), IMM(XER_CA)); // rolins [xer],i0,29,XER_CA
+ UML_SARf(block, R32(G_RA(op)), R32(G_RS(op)), IMM(G_SH(op)), FLAGS_RC(op)); // sar ra,rs,sh,FLAGS_RC(op)
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ return TRUE;
+
+ case 0x01a: /* CNTLZWx */
+ UML_LZCNT(block, R32(G_RA(op)), R32(G_RS(op))); // lzcnt ra,rs,rb
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RA(op)), IMM(~0)); // test ra,~0
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x3ba: /* EXTSBx */
+ UML_SEXT(block, R32(G_RA(op)), R32(G_RS(op)), BYTE); // sext ra,rs,byte
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RA(op)), IMM(~0)); // test ra,~0
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x39a: /* EXTSHx */
+ UML_SEXT(block, R32(G_RA(op)), R32(G_RS(op)), WORD); // sext ra,rs,word
+ if (op & M_RC)
+ {
+ UML_TEST(block, R32(G_RA(op)), IMM(~0)); // test ra,~0
+ generate_compute_flags(block, op & M_RC, 0, FALSE); // <update flags>
+ }
+ return TRUE;
+
+ case 0x057: /* LBZX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x117: /* LHZX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x157: /* LHAX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x017: /* LWZX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x217: /* LFSX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata), DWORD); // fdfrflt fd,[tempdata],dword
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x257: /* LFDX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64
+ UML_DMOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata)); // fdmov fd,[tempdata]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x316: /* LHBRX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_BSWAP(block, IREG(0), IREG(0)); // bswap i0,i0
+ UML_SHR(block, R32(G_RD(op)), IREG(0), IMM(16)); // shr rd,i0,16
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x216: /* LWBRX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode & 3]); // callh read32align
+ UML_BSWAP(block, R32(G_RD(op)), IREG(0)); // bswap rd,i0
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x077: /* LBZUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xff)); // and rd,i0,0xff
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x137: /* LHZUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_AND(block, R32(G_RD(op)), IREG(0), IMM(0xffff)); // and rd,i0,0xffff
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x177: /* LHAUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, ppc->impstate->read16[ppc->impstate->mode & 3]); // callh read16
+ UML_SEXT(block, R32(G_RD(op)), IREG(0), WORD); // sext rd,i0,word
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x037: /* LWZUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x237: /* LFSUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read32[ppc->impstate->mode & 3]); // callh read32
+ UML_MOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // mov [tempdata],i0
+ UML_FDFRFLT(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata), DWORD); // fdfrflt fd,[tempdata],dword
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x277: /* LFDUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read64[ppc->impstate->mode & 3]); // callh read64
+ UML_DMOV(block, MEM(&ppc->impstate->tempdata), IREG(0)); // dmov [tempdata],i0
+ UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata)); // fdmov fd,[tempdata]
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x014: /* LWARX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->read32align[ppc->impstate->mode & 3]); // callh read32align
+ UML_MOV(block, R32(G_RD(op)), IREG(0)); // mov rd,i0
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x255: /* LSWI */
+ UML_MOV(block, MEM(&ppc->impstate->swcount), IMM(((G_NB(op) - 1) & 0x1f) + 1)); // mov [swcount],[xer],G_NB
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op))); // mov [updateaddr],ra
+ UML_MOV(block, MEM(&ppc->impstate->swreg), IMM(4 * G_RD(op))); // mov [swreg],4*G_RD(op)
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ save_fast_iregs(block); // <save fastregs>
+ UML_LABEL(block, swloop = compiler->labelnum++); // swloop:
+ UML_MOV(block, IREG(0), MEM(&ppc->impstate->updateaddr)); // mov i0,[updateaddr]
+ UML_ADD(block, MEM(&ppc->impstate->updateaddr), IREG(0), IMM(1)); // add [updateaddr],i0,1
+ UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->swreg)); // mov i1,[swreg]
+ UML_ADD(block, IREG(2), IREG(1), IMM(1)); // add i2,i1,1
+ UML_AND(block, MEM(&ppc->impstate->swreg), IREG(2), IMM(0x7f)); // and [swreg],i2,0x7f
+ UML_XOR(block, IREG(1), IREG(1), IMM(BYTE4_XOR_BE(0))); // xor i1,i1,be_xor(0)
+ UML_STORE(block, &ppc->r[0], IREG(1), IREG(0), BYTE); // store &r0,i1,i0,byte
+ UML_SUBf(block, MEM(&ppc->impstate->swcount), MEM(&ppc->impstate->swcount), IMM(1), FLAGS_Z);
+ // sub [swcount],[swcount],1,Z
+ UML_JMPc(block, IF_NZ, swloop); // jmp swloop,NZ
+ load_fast_iregs(block); // <load fastregs>
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x215: /* LSWX */
+ UML_ANDf(block, FLAGS_Z, MEM(&ppc->impstate->swcount), SPR32(SPR_XER), IMM(0x7f));// and [swcount],[xer],0x7f,Z
+ UML_JMPc(block, IF_Z, swloopend = compiler->labelnum++); // jmp swloopend,Z
+ UML_ADD(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->swreg), IMM(4 * G_RD(op))); // mov [swreg],4*G_RD(op)
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ save_fast_iregs(block); // <save fastregs>
+ UML_LABEL(block, swloop = compiler->labelnum++); // swloop:
+ UML_MOV(block, IREG(0), MEM(&ppc->impstate->updateaddr)); // mov i0,[updateaddr]
+ UML_ADD(block, MEM(&ppc->impstate->updateaddr), IREG(0), IMM(1)); // add [updateaddr],i0,1
+ UML_CALLH(block, ppc->impstate->read8[ppc->impstate->mode & 3]); // callh read8
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->swreg)); // mov i1,[swreg]
+ UML_ADD(block, IREG(2), IREG(1), IMM(1)); // add i2,i1,1
+ UML_AND(block, MEM(&ppc->impstate->swreg), IREG(2), IMM(0x7f)); // and [swreg],i2,0x7f
+ UML_XOR(block, IREG(1), IREG(1), IMM(BYTE4_XOR_BE(0))); // xor i1,i1,be_xor(0)
+ UML_STORE(block, &ppc->r[0], IREG(1), IREG(0), BYTE); // store &r0,i1,i0,byte
+ UML_SUBf(block, MEM(&ppc->impstate->swcount), MEM(&ppc->impstate->swcount), IMM(1), FLAGS_Z);
+ // sub [swcount],[swcount],1,Z
+ UML_JMPc(block, IF_NZ, swloop); // jmp swloop,NZ
+ UML_LABEL(block, swloopend); // swloopend:
+ load_fast_iregs(block); // <load fastregs>
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x136: /* ECIWX */
+ /* not implemented */
+ return FALSE;
+
+ case 0x0d7: /* STBX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x197: /* STHX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x097: /* STWX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ 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->write32[ppc->impstate->mode & 3]); // callh write32
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x297: /* STFSX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FSFRFLT(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op)), QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // mov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x3d7: /* STFIWX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FDMOV(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_MOV(block, IREG(1), MEM((UINT32 *)&ppc->impstate->tempdata + BYTE_XOR_LE(0)));// mov i1,[tempdata.lo]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2d7: /* STFDX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FDMOV(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // dmov i1,[tempdata]
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x396: /* STHBRX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_BSWAP(block, IREG(1), R32(G_RS(op))); // bswap i1,rs
+ UML_SHR(block, IREG(1), IREG(1), IMM(16)); // shr i1,i1,16
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x296: /* STWBRX */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_BSWAP(block, IREG(1), R32(G_RS(op))); // bswap i1,rs
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x0f7: /* STBUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xff)); // and i1,rs,0xff
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x1b7: /* STHUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, IREG(1), R32(G_RS(op)), IMM(0xffff)); // and i1,rs,0xffff
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write16[ppc->impstate->mode & 3]); // callh write16
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x0b7: /* STWUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_MOV(block, IREG(1), R32(G_RS(op))); // mov i1,rs
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDXU(op)); // mapvar dsisr,DSISR_IDXU(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2b7: /* STFSUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FSFRFLT(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op)), QWORD); // fsfrflt [tempdata],rs,qword
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // mov i1,[tempdata]
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write32[ppc->impstate->mode & 3]); // callh write32
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x2f7: /* STFDUX */
+ UML_ADD(block, IREG(0), R32(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_FDMOV(block, MEM(&ppc->impstate->tempdata), F64(G_RS(op))); // fdmov [tempdata],rs
+ UML_DMOV(block, IREG(1), MEM(&ppc->impstate->tempdata)); // dmov i1,[tempdata]
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), IREG(0)); // mov [updateaddr],i0
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64
+ UML_MOV(block, R32(G_RA(op)), MEM(&ppc->impstate->updateaddr)); // mov ra,[updateaddr]
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x096: /* STWCX. */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ 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>
+ return TRUE;
+
+ case 0x2d5: /* STSWI */
+ UML_MOV(block, MEM(&ppc->impstate->swcount), IMM(((G_NB(op) - 1) & 0x1f) + 1)); // mov [swcount],[xer],G_NB
+ UML_MOV(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op))); // mov [updateaddr],ra
+ UML_MOV(block, MEM(&ppc->impstate->swreg), IMM(4 * G_RS(op))); // mov [swreg],4*G_RS(op)
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ save_fast_iregs(block); // <save fastregs>
+ UML_LABEL(block, swloop = compiler->labelnum++); // swloop:
+ UML_MOV(block, IREG(0), MEM(&ppc->impstate->updateaddr)); // mov i0,[updateaddr]
+ UML_ADD(block, MEM(&ppc->impstate->updateaddr), IREG(0), IMM(1)); // add [updateaddr],i0,1
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->swreg)); // mov i1,[swreg]
+ UML_ADD(block, IREG(2), IREG(1), IMM(1)); // add i2,i1,1
+ UML_AND(block, MEM(&ppc->impstate->swreg), IREG(2), IMM(0x7f)); // and [swreg],i2,0x7f
+ UML_XOR(block, IREG(1), IREG(1), IMM(BYTE4_XOR_BE(0))); // xor i1,i1,be_xor(0)
+ UML_LOAD(block, IREG(1), &ppc->r[0], IREG(1), BYTE); // load i1,&r0,i1,byte
+ UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8
+ UML_SUBf(block, MEM(&ppc->impstate->swcount), MEM(&ppc->impstate->swcount), IMM(1), FLAGS_Z);
+ // sub [swcount],[swcount],1,Z
+ UML_JMPc(block, IF_NZ, swloop); // jmp swloop,NZ
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x295: /* STSWX */
+ UML_ANDf(block, FLAGS_Z, MEM(&ppc->impstate->swcount), SPR32(SPR_XER), IMM(0x7f));// and [swcount],[xer],0x7f,Z
+ UML_JMPc(block, IF_Z, swloopend = compiler->labelnum++); // jmp swloopend,Z
+ UML_ADD(block, MEM(&ppc->impstate->updateaddr), R32Z(G_RA(op)), R32(G_RB(op))); // add [updateaddr],ra,rb
+ UML_MOV(block, MEM(&ppc->impstate->swreg), IMM(4 * G_RS(op))); // mov [swreg],4*G_RS(op)
+ UML_MAPVAR(block, MAPVAR_DSISR, DSISR_IDX(op)); // mapvar dsisr,DSISR_IDX(op)
+ save_fast_iregs(block); // <save fastregs>
+ UML_LABEL(block, swloop = compiler->labelnum++); // swloop:
+ UML_MOV(block, IREG(0), MEM(&ppc->impstate->updateaddr)); // mov i0,[updateaddr]
+ UML_ADD(block, MEM(&ppc->impstate->updateaddr), IREG(0), IMM(1)); // add [updateaddr],i0,1
+ UML_MOV(block, IREG(1), MEM(&ppc->impstate->swreg)); // mov i1,[swreg]
+ UML_ADD(block, IREG(2), IREG(1), IMM(1)); // add i2,i1,1
+ UML_AND(block, MEM(&ppc->impstate->swreg), IREG(2), IMM(0x7f)); // and [swreg],i2,0x7f
+ UML_XOR(block, IREG(1), IREG(1), IMM(BYTE4_XOR_BE(0))); // xor i1,i1,be_xor(0)
+ UML_LOAD(block, IREG(1), &ppc->r[0], IREG(1), BYTE); // load i1,&r0,i1,byte
+ UML_CALLH(block, ppc->impstate->write8[ppc->impstate->mode & 3]); // callh write8
+ UML_SUBf(block, MEM(&ppc->impstate->swcount), MEM(&ppc->impstate->swcount), IMM(1), FLAGS_Z);
+ // sub [swcount],[swcount],1,Z
+ UML_JMPc(block, IF_NZ, swloop); // jmp swloop,NZ
+ UML_LABEL(block, swloopend); // swloopend:
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x1b6: /* ECOWX */
+ /* not implemented */
+ return FALSE;
+
+ case 0x036: /* DCBST */
+ case 0x056: /* DCBF */
+ case 0x0f6: /* DCBTST */
+ case 0x116: /* DCBT */
+ case 0x3d6: /* ICBI */
+ case 0x256: /* SYNC */
+ case 0x356: /* EIEIO */
+ case 0x1d6: /* DCBI */
+ case 0x236: /* TLBSYNC */
+ /* effective no-ops */
+ return TRUE;
+
+ case 0x3f6: /* DCBZ */
+ UML_ADD(block, IREG(0), R32Z(G_RA(op)), R32(G_RB(op))); // add i0,ra,rb
+ UML_AND(block, MEM(&ppc->impstate->tempaddr), IREG(0), IMM(~(ppc->cache_line_size - 1)));
+ // and [tempaddr],i0,~(cache_line_size - 1)
+ for (item = 0; item < ppc->cache_line_size / 8; item++)
+ {
+ UML_ADD(block, IREG(0), MEM(&ppc->impstate->tempaddr), IMM(8 * item)); // add i0,[tempaddr],8*item
+ UML_DMOV(block, IREG(1), IMM(0)); // dmov i1,0
+ UML_CALLH(block, ppc->impstate->write64[ppc->impstate->mode & 3]); // callh write64
+ }
+ return TRUE;
+
+ case 0x132: /* TLBIE */
+ UML_MOV(block, MEM(&ppc->param0), R32(G_RB(op))); // mov [param0],rb
+ UML_CALLC(block, ppccom_execute_tlbie, ppc); // callc ppccom_execute_tlbie,ppc
+ return TRUE;
+
+ case 0x172: /* TLBIA */
+ UML_CALLC(block, ppccom_execute_tlbia, ppc); // callc ppccom_execute_tlbia,ppc
+ return TRUE;
+
+ case 0x3d2: /* TLBLD */
+ assert(ppc->cap & PPCCAP_603_MMU);
+ UML_MOV(block, MEM(&ppc->param0), R32(G_RB(op))); // mov [param0],rb
+ UML_MOV(block, MEM(&ppc->param1), IMM(0)); // mov [param1],0
+ UML_CALLC(block, ppccom_execute_tlbl, ppc); // callc ppccom_execute_tlbl,ppc
+ return TRUE;
+
+ case 0x3f2: /* TLBLI */
+ assert(ppc->cap & PPCCAP_603_MMU);
+ UML_MOV(block, MEM(&ppc->param0), R32(G_RB(op))); // mov [param0],rb
+ UML_MOV(block, MEM(&ppc->param1), IMM(1)); // mov [param1],1
+ UML_CALLC(block, ppccom_execute_tlbl, ppc); // callc ppccom_execute_tlbl,ppc
+ return TRUE;
+
+ case 0x013: /* MFCR */
+ UML_MOV(block, R32(G_RD(op)), CR32); // mov rd,cr
+ return TRUE;
+
+ case 0x053: /* MFMSR */
+ UML_MOV(block, R32(G_RD(op)), MSR32); // mov rd,msr
+ return TRUE;
+
+ 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))
+ UML_MOV(block, R32(G_RD(op)), SPR32(spr)); // mov rd,spr
+ else if (spr == SPROEA_PVR)
+ UML_MOV(block, R32(G_RD(op)), IMM(ppc->flavor)); // mov rd,flavor
+ else
+ {
+ generate_update_cycles(block, compiler, IMM(desc->pc), TRUE); // <update cycles>
+ UML_MOV(block, MEM(&ppc->param0), IMM(spr)); // mov [param0],spr
+ UML_CALLC(block, ppccom_execute_mfspr, ppc); // callc ppccom_execute_mfspr,ppc
+ UML_MOV(block, R32(G_RD(op)), MEM(&ppc->param1)); // mov rd,[param1]
+ }
+ return TRUE;
+ }
+
+ case 0x253: /* MFSR */
+ UML_MOV(block, R32(G_RD(op)), SR32(G_SR(op))); // mov rd,sr
+ return TRUE;
+
+ case 0x293: /* MFSRIN */
+ UML_SHR(block, IREG(0), R32(G_RB(op)), IMM(28)); // shr i0,G_RB,28
+ UML_LOAD(block, R32(G_RD(op)), &ppc->sr[0], IREG(0), DWORD); // load rd,sr,i0,dword
+ return TRUE;
+
+ case 0x173: /* MFTB */
+ {
+ UINT32 tbr = compute_spr(G_SPR(op));
+ if (tbr != SPRVEA_TBL_R && tbr != SPRVEA_TBU_R)
+ return FALSE;
+ generate_update_cycles(block, compiler, IMM(desc->pc), TRUE); // <update cycles>
+ UML_MOV(block, MEM(&ppc->param0), IMM(tbr)); // mov [param0],tbr
+ UML_CALLC(block, ppccom_execute_mftb, ppc); // callc ppccom_execute_mftb,ppc
+ UML_MOV(block, R32(G_RD(op)), MEM(&ppc->param1)); // mov rd,[param1]
+ return TRUE;
+ }
+
+ 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
+ return TRUE;
+
+ case 0x092: /* MTMSR */
+ if (ppc->cap & PPCCAP_603_MMU)
+ UML_XOR(block, IREG(0), MSR32, R32(G_RS(op))); // xor i0,msr32,rs
+ UML_MOV(block, MSR32, R32(G_RS(op))); // mov msr,rs
+ if (ppc->cap & PPCCAP_603_MMU)
+ {
+ UML_TEST(block, IREG(0), IMM(MSR603_TGPR)); // test i0,tgpr
+ UML_CALLHc(block, IF_NZ, ppc->impstate->swap_tgpr); // callh swap_tgpr,nz
+ }
+ generate_update_mode(block); // <update mode>
+ return TRUE;
+
+ 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))
+ UML_MOV(block, SPR32(spr), R32(G_RS(op))); // mov spr,rs
+ else if (spr == SPROEA_PVR)
+ ; // read only
+ else
+ {
+ generate_update_cycles(block, compiler, IMM(desc->pc), TRUE); // <update cycles>
+ UML_MOV(block, MEM(&ppc->param0), IMM(spr)); // mov [param0],spr
+ UML_MOV(block, MEM(&ppc->param1), R32(G_RS(op))); // mov [param1],rs
+ UML_CALLC(block, ppccom_execute_mtspr, ppc); // callc ppccom_execute_mtspr,ppc
+ compiler->checkints = TRUE;
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ }
+ return TRUE;
+ }
+
+ case 0x0d2: /* MTSR */
+ UML_MOV(block, SR32(G_SR(op)), R32(G_RS(op))); // mov sr[G_SR],rs
+ UML_CALLC(block, ppccom_tlb_flush, ppc); // callc ppccom_tlb_flush,ppc
+ return TRUE;
+
+ case 0x0f2: /* MTSRIN */
+ UML_SHR(block, IREG(0), R32(G_RB(op)), IMM(28)); // shr i0,G_RB,28
+ UML_STORE(block, &ppc->sr[0], IREG(0), R32(G_RS(op)), DWORD); // store sr,i0,rs,dword
+ UML_CALLC(block, ppccom_tlb_flush, ppc); // callc ppccom_tlb_flush,ppc
+ 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_AND(block, SPR32(SPR_XER), SPR32(SPR_XER), IMM(~0xf0000000)); // and [xer],[xer],~0xf0000000
+ return TRUE;
+
+ case 0x106: /* ICBT */
+ case 0x1c6: /* DCCCI */
+ case 0x3c6: /* ICCCI */
+ assert(ppc->cap & PPCCAP_4XX);
+ /* effective no-nop */
+ return TRUE;
+
+ case 0x1e6: /* DCREAD */
+ case 0x3e6: /* ICREAD */
+ assert(ppc->cap & PPCCAP_4XX);
+ UML_MOV(block, R32(G_RT(op)), IMM(0)); // mov rt,0
+ return TRUE;
+
+ case 0x143: /* MFDCR */
+ {
+ UINT32 spr = compute_spr(G_SPR(op));
+ assert(ppc->cap & PPCCAP_4XX);
+ generate_update_cycles(block, compiler, IMM(desc->pc), TRUE); // <update cycles>
+ UML_MOV(block, MEM(&ppc->param0), IMM(spr)); // mov [param0],spr
+ UML_CALLC(block, ppccom_execute_mfdcr, ppc); // callc ppccom_execute_mfdcr,ppc
+ UML_MOV(block, R32(G_RD(op)), MEM(&ppc->param1)); // mov rd,[param1]
+ return TRUE;
+ }
+
+ case 0x1c3: /* MTDCR */
+ {
+ UINT32 spr = compute_spr(G_SPR(op));
+ assert(ppc->cap & PPCCAP_4XX);
+ generate_update_cycles(block, compiler, IMM(desc->pc), TRUE); // <update cycles>
+ UML_MOV(block, MEM(&ppc->param0), IMM(spr)); // mov [param0],spr
+ UML_MOV(block, MEM(&ppc->param1), R32(G_RS(op))); // mov [param1],rs
+ UML_CALLC(block, ppccom_execute_mtdcr, ppc); // callc ppccom_execute_mtdcr,ppc
+ compiler->checkints = TRUE;
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+ }
+
+ case 0x083: /* WRTEE */
+ assert(ppc->cap & PPCCAP_4XX);
+ UML_ROLINS(block, MSR32, R32(G_RS(op)), IMM(0), IMM(MSR_EE)); // rolins msr,rs,0,MSR_EE
+ compiler->checkints = TRUE;
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ return TRUE;
+
+ case 0x0a3: /* WRTEEI */
+ assert(ppc->cap & PPCCAP_4XX);
+ if (op & MSR_EE)
+ {
+ UML_OR(block, MSR32, MSR32, IMM(MSR_EE)); // or msr,msr,MSR_EE
+ compiler->checkints = TRUE;
+ generate_update_cycles(block, compiler, IMM(desc->pc + 4), TRUE); // <update cycles>
+ }
+ else
+ UML_AND(block, MSR32, MSR32, IMM(~MSR_EE)); // and msr,msr,~MSR_EE
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ generate_instruction_3b - compile opcodes in
+ the 0x3b group
+-------------------------------------------------*/
+
+static int generate_instruction_3b(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = *desc->opptr.l;
+ UINT32 opswitch = (op >> 1) & 0x1f;
+
+ switch (opswitch)
+ {
+ case 0x15: /* FADDSx */
+ UML_FDADD(block, FREG(0), F64(G_RA(op)), F64(G_RB(op))); // fdadd f0,ra,rb
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x14: /* FSUBSx */
+ UML_FDSUB(block, FREG(0), F64(G_RA(op)), F64(G_RB(op))); // fdsub f0,ra,rb
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x19: /* FMULSx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_RB(op))); // fdmul f0,ra,rb
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x12: /* FDIVSx */
+ UML_FDDIV(block, FREG(0), F64(G_RA(op)), F64(G_RB(op))); // fddiv f0,ra,rb
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x16: /* FSQRTSx */
+ UML_FDSQRT(block, FREG(0), F64(G_RB(op))); // fdsqrt f0,rb
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x18: /* FRESx */
+ UML_FSFRFLT(block, FREG(0), F64(G_RB(op)), QWORD); // fsfrlt f0,rb,qword
+ UML_FSRECIP(block, FREG(0), FREG(0)); // fsrecip f0,f0
+ UML_FDFRFLT(block, F64(G_RD(op)), FREG(0), DWORD); // fdfrflt rd,f0,dword
+ return TRUE;
+
+ case 0x1d: /* FMADDSx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, FREG(0), FREG(0), F64(G_RB(op))); // fdadd f0,f0,rb
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x1c: /* FMSUBSx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, FREG(0), FREG(0), F64(G_RB(op))); // fdsub f0,f0,rb
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x1f: /* FNMADDSx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, FREG(0), FREG(0), F64(G_RB(op))); // fdadd f0,f0,rb
+ UML_FDNEG(block, FREG(0), FREG(0)); // fdneg f0,f0
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+
+ case 0x1e: /* FNMSUBSx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, FREG(0), F64(G_RB(op)), FREG(0)); // fdsub f0,rb,f0
+ UML_FDRNDS(block, F64(G_RD(op)), FREG(0)); // fdrnds rd,f0
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+/*-------------------------------------------------
+ generate_instruction_3f - compile opcodes in
+ the 0x3f group
+-------------------------------------------------*/
+
+static int generate_instruction_3f(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc)
+{
+ UINT32 op = *desc->opptr.l;
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ if (opswitch & 0x10)
+ {
+ opswitch &= 0x1f;
+ switch (opswitch)
+ {
+ case 0x15: /* FADDx */
+ UML_FDADD(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_RB(op))); // fdadd rd,ra,rb
+ return TRUE;
+
+ case 0x14: /* FSUBx */
+ UML_FDSUB(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_RB(op))); // fdsub rd,ra,rb
+ return TRUE;
+
+ case 0x19: /* FMULx */
+ UML_FDMUL(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_RB(op))); // fdmul rd,ra,rb
+ return TRUE;
+
+ case 0x12: /* FDIVx */
+ UML_FDDIV(block, F64(G_RD(op)), F64(G_RA(op)), F64(G_RB(op))); // fddiv rd,ra,rb
+ return TRUE;
+
+ case 0x16: /* FSQRTx */
+ UML_FDSQRT(block, F64(G_RD(op)), F64(G_RB(op))); // fdsqrt rd,rb
+ return TRUE;
+
+ case 0x1a: /* FRSQRTEx */
+ UML_FDRSQRT(block, F64(G_RD(op)), F64(G_RB(op))); // fdrsqrt rd,rb
+ return TRUE;
+
+ case 0x17: /* FSELx */
+ UML_FDCMP(block, F64(G_RA(op)), MEM(&ppc->impstate->fp0)); // fdcmp f0,ra,[fp0]
+ UML_FDMOVc(block, IF_AE, F64(G_RD(op)), F64(G_REGC(op))); // fdmov rd,rc,AE
+ UML_FDMOVc(block, IF_B, F64(G_RD(op)), F64(G_RB(op))); // fdmov rd,rb,B
+ return TRUE;
+
+ case 0x1d: /* FMADDx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, F64(G_RD(op)), FREG(0), F64(G_RB(op))); // fdadd rd,f0,rb
+ return TRUE;
+
+ case 0x1f: /* FNMADDx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDADD(block, FREG(0), FREG(0), F64(G_RB(op))); // fdadd f0,f0,rb
+ UML_FDNEG(block, F64(G_RD(op)), FREG(0)); // fdneg rd,f0
+ return TRUE;
+
+ case 0x1c: /* FMSUBx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, F64(G_RD(op)), FREG(0), F64(G_RB(op))); // fdsub rd,f0,rb
+ return TRUE;
+
+ case 0x1e: /* FNMSUBx */
+ UML_FDMUL(block, FREG(0), F64(G_RA(op)), F64(G_REGC(op))); // fdmul f0,ra,rc
+ UML_FDSUB(block, F64(G_RD(op)), F64(G_RB(op)), FREG(0)); // fdsub rd,rb,f0
+ return TRUE;
+ }
+ }
+ else
+ {
+ switch (opswitch)
+ {
+ case 0x32e: /* FCTIDx - 64-bit only */
+ case 0x32f: /* FCTIDZx - 64-bit only */
+ case 0x34e: /* FCFIDx - 64-bit only */
+ return FALSE;
+
+ case 0x000: /* FCMPU */
+ 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]
+ return TRUE;
+
+ case 0x00c: /* FRSPx */
+ UML_FDRNDS(block, F64(G_RD(op)), F64(G_RB(op))); // fdrnds rd,rb
+ return TRUE;
+
+ case 0x00e: /* FCTIWx */
+ UML_FDTOINT(block, IREG(0), F64(G_RB(op)), DWORD, DEFAULT); // fdtoint i0,rb,dword,default
+ UML_DAND(block, MEM(&ppc->impstate->tempdata), IREG(0), IMM(0xffffffff)); // dand i0,i0,0xffffffff
+ UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata)); // fdmovr rd,i0
+ return TRUE;
+
+ case 0x00f: /* FCTIWZx */
+ UML_FDTOINT(block, IREG(0), F64(G_RB(op)), DWORD, TRUNC); // fdtoint i0,rb,dword,default
+ UML_DAND(block, MEM(&ppc->impstate->tempdata), IREG(0), IMM(0xffffffff)); // dand i0,i0,0xffffffff
+ UML_FDMOV(block, F64(G_RD(op)), MEM(&ppc->impstate->tempdata)); // fdmovr rd,i0
+ return TRUE;
+
+ case 0x028: /* FNEGx */
+ UML_FDNEG(block, F64(G_RD(op)), F64(G_RB(op))); // fdneg rd,rb
+ return TRUE;
+
+ case 0x048: /* FMRx */
+ UML_FDMOV(block, F64(G_RD(op)), F64(G_RB(op))); // fdmov rd,rb
+ return TRUE;
+
+ case 0x088: /* FNABSx */
+ UML_FDABS(block, FREG(0), F64(G_RB(op))); // fdabs f0,rb
+ UML_FDNEG(block, F64(G_RD(op)), FREG(0)); // fdneg rd,f0
+ return TRUE;
+
+ case 0x108: /* FABSx */
+ UML_FDABS(block, F64(G_RD(op)), F64(G_RB(op))); // fdabs rd,rb
+ return TRUE;
+
+ case 0x046: /* MTFSB0x */
+ UML_AND(block, FPSCR32, FPSCR32, IMM(~(0x80000000 >> G_CRBD(op)))); // and fpscr32,fpscr32,~(0x80000000 >> G_CRBD)
+ return TRUE;
+
+ case 0x026: /* MTFSB1x */
+ UML_OR(block, FPSCR32, FPSCR32, IMM(0x80000000 >> G_CRBD(op))); // or fpscr32,fpscr32,(0x80000000 >> G_CRBD)
+ 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_AND(block, FPSCR32, FPSCR32, IMM(~CRMASK(G_CRFS(op)))); // and fpscr,fpscr,~crmask[crfs]
+ return TRUE;
+
+ case 0x247: /* MFFSx */
+ UML_MOV(block, R32(G_RD(op)), FPSCR32); // mov rd,fpscr
+ return TRUE;
+
+ case 0x2c7: /* MTFSFx */
+ UML_ROLINS(block, FPSCR32, R32(G_RB(op)), IMM(0), IMM(compute_crf_mask(G_FM(op))));
+ // rolins fpscr,rb,0,crf_mask
+ return TRUE;
+
+ case 0x086: /* MTFSFIx */
+ UML_ROLINS(block, FPSCR32, R32(G_IMM(op)), IMM(28 - 4 * G_CRFD(op)), IMM(CRMASK(G_CRFD(op))));
+ // rolins fpscr,rb,0,crf_mask
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+
+
+/***************************************************************************
+ CODE LOGGING HELPERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ log_add_disasm_comment - add a comment
+ including disassembly of a PowerPC instruction
+-------------------------------------------------*/
+
+static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op)
+{
+#if (LOG_UML)
+ char buffer[100];
+ ppc_dasm_one(buffer, pc, op);
+ UML_COMMENT(block, "%08X: %s", pc, buffer); // comment
+#endif
+}
+
+
+/*-------------------------------------------------
+ log_desc_flags_to_string - generate a string
+ representing the instruction description
+ flags
+-------------------------------------------------*/
+
+static const char *log_desc_flags_to_string(UINT32 flags)
+{
+ static char tempbuf[30];
+ char *dest = tempbuf;
+
+ /* branches */
+ if (flags & OPFLAG_IS_UNCONDITIONAL_BRANCH)
+ *dest++ = 'U';
+ else if (flags & OPFLAG_IS_CONDITIONAL_BRANCH)
+ *dest++ = 'C';
+ else
+ *dest++ = '.';
+
+ /* intrablock branches */
+ *dest++ = (flags & OPFLAG_INTRABLOCK_BRANCH) ? 'i' : '.';
+
+ /* branch targets */
+ *dest++ = (flags & OPFLAG_IS_BRANCH_TARGET) ? 'B' : '.';
+
+ /* delay slots */
+ *dest++ = (flags & OPFLAG_IN_DELAY_SLOT) ? 'D' : '.';
+
+ /* exceptions */
+ if (flags & OPFLAG_WILL_CAUSE_EXCEPTION)
+ *dest++ = 'E';
+ else if (flags & OPFLAG_CAN_CAUSE_EXCEPTION)
+ *dest++ = 'e';
+ else
+ *dest++ = '.';
+
+ /* read/write */
+ if (flags & OPFLAG_READS_MEMORY)
+ *dest++ = 'R';
+ else if (flags & OPFLAG_WRITES_MEMORY)
+ *dest++ = 'W';
+ else
+ *dest++ = '.';
+
+ /* TLB validation */
+ *dest++ = (flags & OPFLAG_VALIDATE_TLB) ? 'V' : '.';
+
+ /* TLB modification */
+ *dest++ = (flags & OPFLAG_MODIFIES_TRANSLATION) ? 'T' : '.';
+
+ /* redispatch */
+ *dest++ = (flags & OPFLAG_REDISPATCH) ? 'R' : '.';
+ return tempbuf;
+}
+
+
+/*-------------------------------------------------
+ log_register_list - log a list of GPR registers
+-------------------------------------------------*/
+
+static void log_register_list(drcuml_state *drcuml, const char *string, UINT64 gprmask, UINT64 fprmask)
+{
+ int count = 0;
+ int regnum;
+
+ /* skip if nothing */
+ if ((gprmask & ~1) == 0 && fprmask == 0)
+ return;
+
+ drcuml_log_printf(drcuml, "[%s:", string);
+
+ for (regnum = 0; regnum < 32; regnum++)
+ if (gprmask & ((UINT64)1 << regnum))
+ drcuml_log_printf(drcuml, "%sr%d", (count++ == 0) ? "" : ",", regnum);
+ for (regnum = 0; regnum < 8; regnum++)
+ if (gprmask & ((UINT64)1 << (32 + regnum)))
+ drcuml_log_printf(drcuml, "%scr%d", (count++ == 0) ? "" : ",", regnum);
+ if (gprmask & ((UINT64)1 << 40))
+ drcuml_log_printf(drcuml, "%sxer", (count++ == 0) ? "" : ",");
+ if (gprmask & ((UINT64)1 << 41))
+ drcuml_log_printf(drcuml, "%sctr", (count++ == 0) ? "" : ",");
+ if (gprmask & ((UINT64)1 << 42))
+ drcuml_log_printf(drcuml, "%slr", (count++ == 0) ? "" : ",");
+
+ for (regnum = 0; regnum < 32; regnum++)
+ if (fprmask & ((UINT64)1 << regnum))
+ drcuml_log_printf(drcuml, "%sfpr%d", (count++ == 0) ? "" : ",", regnum);
+ if (fprmask & ((UINT64)1 << 32))
+ drcuml_log_printf(drcuml, "%sfpscr", (count++ == 0) ? "" : ",");
+ drcuml_log_printf(drcuml, "] ");
+}
+
+
+/*-------------------------------------------------
+ log_opcode_desc - log a list of descriptions
+-------------------------------------------------*/
+
+static void log_opcode_desc(drcuml_state *drcuml, const opcode_desc *desclist, int indent)
+{
+ /* open the file, creating it if necessary */
+ if (indent == 0)
+ drcuml_log_printf(drcuml, "\nDescriptor list @ %08X\n", desclist->pc);
+
+ /* output each descriptor */
+ for ( ; desclist != NULL; desclist = desclist->next)
+ {
+ char buffer[100];
+
+ /* disassemle the current instruction and output it to the log */
+#if (LOG_UML || LOG_NATIVE)
+ if (desclist->flags & OPFLAG_VIRTUAL_NOOP)
+ strcpy(buffer, "<virtual nop>");
+ else
+ ppc_dasm_one(buffer, desclist->pc, *desclist->opptr.l);
+#else
+ strcpy(buffer, "???");
+#endif
+ drcuml_log_printf(drcuml, "%08X [%08X] t:%08X f:%s: %-30s", desclist->pc, desclist->physpc, desclist->targetpc, log_desc_flags_to_string(desclist->flags), buffer);
+
+ /* output register states */
+ log_register_list(drcuml, "use", desclist->gpr.used, desclist->fpr.used);
+ log_register_list(drcuml, "mod", desclist->gpr.modified, desclist->fpr.modified);
+ log_register_list(drcuml, "lrd", desclist->gpr.liveread, desclist->fpr.liveread);
+ log_register_list(drcuml, "lwr", desclist->gpr.livewrite, desclist->fpr.livewrite);
+ drcuml_log_printf(drcuml, "\n");
+
+ /* if we have a delay slot, output it recursively */
+ if (desclist->delay != NULL)
+ log_opcode_desc(drcuml, desclist->delay, indent + 1);
+
+ /* at the end of a sequence add a dividing line */
+ if (desclist->flags & OPFLAG_END_SEQUENCE)
+ drcuml_log_printf(drcuml, "-----\n");
+ }
+}
+
+
+
+/***************************************************************************
+ PPC 4XX VARIANTS
+***************************************************************************/
+
+#if (HAS_PPC403GA || HAS_PPC403GCX)
+
+/*-------------------------------------------------
+ ppcdrc4xx_get_info - PowerPC 4XX-specific
+ information getter
+-------------------------------------------------*/
+
+static void ppcdrc4xx_get_info(UINT32 state, cpuinfo *info)
+{
+ ppcdrc_get_info(state, info);
+ ppc4xx_get_info(ppc, state, info);
+}
+
+
+/*-------------------------------------------------
+ ppcdrc4xx_set_info - PowerPC 4XX-specific
+ information setter
+-------------------------------------------------*/
+
+static void ppcdrc4xx_set_info(UINT32 state, cpuinfo *info)
+{
+ ppcdrc_set_info(state, info);
+ ppc4xx_set_info(ppc, state, info);
+}
+
+#endif
+
+
+#if (HAS_PPC403GA)
+
+/*-------------------------------------------------
+ ppc403ga_init - PowerPC 403GA-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc403ga_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_403GA, PPCCAP_4XX, 1, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc403ga_get_info - PowerPC 403GA-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc403ga_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc403ga_init; break;
+ case CPUINFO_PTR_SET_INFO: info->setinfo = ppcdrc4xx_set_info; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 403GA"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc4xx_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+#if (HAS_PPC403GCX)
+
+/*-------------------------------------------------
+ ppc403gcx_init - PowerPC 403GCX-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc403gcx_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_403GCX, PPCCAP_4XX, 1, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc403gcx_get_info - PowerPC 403GCX-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc403gcx_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc403gcx_init; break;
+ case CPUINFO_PTR_SET_INFO: info->setinfo = ppcdrc4xx_set_info; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 403GCX"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc4xx_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+
+/***************************************************************************
+ PPC 6XX VARIANTS
+***************************************************************************/
+
+#if (HAS_PPC601)
+
+/*-------------------------------------------------
+ ppc601_init - PowerPC 601-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc601_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_601, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED, 0/* no TB */, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc601_get_info - PowerPC 601-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc601_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc601_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 601"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+#if (HAS_PPC602)
+
+/*-------------------------------------------------
+ ppc602_init - PowerPC 602-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc602_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_602, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED, 1/* unknown */, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc602_get_info - PowerPC 602-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc602_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc602_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 602"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+#if (HAS_PPC603)
+
+/*-------------------------------------------------
+ ppc603_init - PowerPC 603-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc603_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_603, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_603_MMU, 4, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc603_get_info - PowerPC 603-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc603_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc603_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 603"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+#if (HAS_PPC603E)
+
+/*-------------------------------------------------
+ ppc603e_init - PowerPC 603e-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc603e_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_603E, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_603_MMU, 4, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc603e_get_info - PowerPC 603e-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc603e_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc603e_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 603e"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+#if (HAS_PPC603R)
+
+/*-------------------------------------------------
+ ppc603r_init - PowerPC 603r-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc603r_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_603R, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED | PPCCAP_603_MMU, 4, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc603r_get_info - PowerPC 603r-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc603r_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc603r_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 603R"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+#if (HAS_PPC604)
+
+/*-------------------------------------------------
+ ppc604_init - PowerPC 604-specific
+ initialization
+-------------------------------------------------*/
+
+static void ppc604_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_604, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED, 4, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ ppc604_get_info - PowerPC 604-specific
+ information getter
+-------------------------------------------------*/
+
+void ppc604_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = ppc604_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC 604"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+
+/***************************************************************************
+ PPC 6XX VARIANTS
+***************************************************************************/
+
+#if (HAS_MPC8240)
+
+/*-------------------------------------------------
+ mpc8240_init - PowerPC MPC8240-specific
+ initialization
+-------------------------------------------------*/
+
+static void mpc8240_init(int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ ppcdrc_init(PPC_MODEL_MPC8240, PPCCAP_OEA | PPCCAP_VEA | PPCCAP_FPU | PPCCAP_MISALIGNED, 4/* unknown */, clock, config, irqcallback);
+}
+
+
+/*-------------------------------------------------
+ mpc8240_get_info - PowerPC MPC8240-specific
+ information getter
+-------------------------------------------------*/
+
+void mpc8240_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_INIT: info->init = mpc8240_init; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "PowerPC MPC8240"); break;
+
+ /* --- everything else is handled generically --- */
+ default: ppcdrc_get_info(state, info); break;
+ }
+}
+
+#endif
+
+
+
+/***************************************************************************
+ DISASSEMBLERS
+***************************************************************************/
+
+#if !defined(MAME_DEBUG) && (LOG_UML || LOG_NATIVE)
+#include "ppc_dasm.c"
+#endif
diff --git a/src/emu/cpu/powerpc/ppcdrco.c b/src/emu/cpu/powerpc/ppcdrco.c
deleted file mode 100644
index 398228e53b6..00000000000
--- a/src/emu/cpu/powerpc/ppcdrco.c
+++ /dev/null
@@ -1,2485 +0,0 @@
-/*
- PowerPC 4xx/6xx Dynamic Recompiler for x86
-
- Written by Ville Linde
-*/
-
-#include "debugger.h"
-#include "ppc.h"
-#include "cpu/x86drc.h"
-
-
-#define PPC_DRC
-#define LOG_CODE (0)
-
-#define CACHE_SIZE (16 * 1024 * 1024)
-#define MAX_INSTRUCTIONS 512
-
-
-#if (HAS_PPC603)
-static void ppcdrc603_init(int index, int clock, const void *_config, int (*irqcallback)(int));
-static void ppcdrc603_exit(void);
-#endif
-#if (HAS_PPC601 || HAS_PPC603 || HAS_MPC8240 || HAS_PPC604)
-static void ppcdrc603_reset(void);
-static int ppcdrc603_execute(int cycles);
-static void ppcdrc603_set_irq_line(int irqline, int state);
-#endif
-#if (HAS_PPC602)
-static void ppcdrc602_init(int index, int clock, const void *_config, int (*irqcallback)(int));
-static void ppcdrc602_exit(void);
-static void ppcdrc602_reset(void);
-static int ppcdrc602_execute(int cycles);
-static void ppcdrc602_set_irq_line(int irqline, int state);
-#endif
-#if (HAS_PPC403)
-static UINT8 ppc403_spu_r(UINT32 a);
-static void ppc403_spu_w(UINT32 a, UINT8 d);
-static void ppcdrc403_init(int index, int clock, const void *_config, int (*irqcallback)(int));
-static void ppcdrc403_exit(void);
-static void ppcdrc403_reset(void);
-static int ppcdrc403_execute(int cycles);
-static void ppcdrc403_set_irq_line(int irqline, int state);
-#endif
-
-static void ppcdrc_init(void);
-static void ppcdrc_reset(drc_core *drc);
-static void ppcdrc_recompile(drc_core *drc);
-static void ppcdrc_entrygen(drc_core *drc);
-
-#define RD ((op >> 21) & 0x1F)
-#define RT ((op >> 21) & 0x1f)
-#define RS ((op >> 21) & 0x1f)
-#define RA ((op >> 16) & 0x1f)
-#define RB ((op >> 11) & 0x1f)
-#define RC ((op >> 6) & 0x1f)
-
-#define MB ((op >> 6) & 0x1f)
-#define ME ((op >> 1) & 0x1f)
-#define SH ((op >> 11) & 0x1f)
-#define BO ((op >> 21) & 0x1f)
-#define BI ((op >> 16) & 0x1f)
-#define CRFD ((op >> 23) & 0x7)
-#define CRFA ((op >> 18) & 0x7)
-#define FXM ((op >> 12) & 0xff)
-#define SPR (((op >> 16) & 0x1f) | ((op >> 6) & 0x3e0))
-
-#define SIMM16 (INT32)(INT16)(op & 0xffff)
-#define UIMM16 (UINT32)(op & 0xffff)
-
-#define RCBIT (op & 0x1)
-#define OEBIT (op & 0x400)
-#define AABIT (op & 0x2)
-#define LKBIT (op & 0x1)
-
-#define REG(x) (ppc.r[x])
-#define LR (ppc.lr)
-#define CTR (ppc.ctr)
-#define XER (ppc.xer)
-#define CR(x) (ppc.cr[x])
-#define MSR (ppc.msr)
-#define SRR0 (ppc.srr0)
-#define SRR1 (ppc.srr1)
-#define SRR2 (ppc.srr2)
-#define SRR3 (ppc.srr3)
-#define EVPR (ppc.evpr)
-#define EXIER (ppc.exier)
-#define EXISR (ppc.exisr)
-#define DEC (ppc.dec)
-
-
-// Stuff added for the 6xx
-#define FPR(x) (ppc.fpr[x])
-#define FM ((op >> 17) & 0xFF)
-#define SPRF (((op >> 6) & 0x3E0) | ((op >> 16) & 0x1F))
-
-
-#define CHECK_SUPERVISOR() \
- if((ppc.msr & 0x4000) != 0){ \
- }
-
-#define CHECK_FPU_AVAILABLE() \
- if((ppc.msr & 0x2000) == 0){ \
- }
-
-#if (HAS_PPC601||HAS_PPC602||HAS_PPC603||HAS_PPC604||HAS_MPC8240)
-static UINT32 ppc_field_xlat[256];
-#endif
-
-
-
-#define FPSCR_FX 0x80000000
-#define FPSCR_FEX 0x40000000
-#define FPSCR_VX 0x20000000
-#define FPSCR_OX 0x10000000
-#define FPSCR_UX 0x08000000
-#define FPSCR_ZX 0x04000000
-#define FPSCR_XX 0x02000000
-
-
-
-#define BITMASK_0(n) (UINT32)(((UINT64)1 << n) - 1)
-#define CRBIT(x) ((ppc.cr[x / 4] & (1 << (3 - (x % 4)))) ? 1 : 0)
-#define _BIT(n) (1 << (n))
-#define GET_ROTATE_MASK(mb,me) (ppc_rotate_mask[mb][me])
-#define ADD_CA(r,a,b) ((UINT32)r < (UINT32)a)
-#define SUB_CA(r,a,b) (!((UINT32)a < (UINT32)b))
-#define ADD_OV(r,a,b) ((~((a) ^ (b)) & ((a) ^ (r))) & 0x80000000)
-#define SUB_OV(r,a,b) (( ((a) ^ (b)) & ((a) ^ (r))) & 0x80000000)
-
-#define XER_SO 0x80000000
-#define XER_OV 0x40000000
-#define XER_CA 0x20000000
-
-#define MSR_AP 0x00800000 /* Access privilege state (PPC602) */
-#define MSR_SA 0x00400000 /* Supervisor access mode (PPC602) */
-#define MSR_POW 0x00040000 /* Power Management Enable */
-#define MSR_WE 0x00040000
-#define MSR_CE 0x00020000
-#define MSR_ILE 0x00010000 /* Interrupt Little Endian Mode */
-#define MSR_EE 0x00008000 /* External Interrupt Enable */
-#define MSR_PR 0x00004000 /* Problem State */
-#define MSR_FP 0x00002000 /* Floating Point Available */
-#define MSR_ME 0x00001000 /* Machine Check Enable */
-#define MSR_FE0 0x00000800
-#define MSR_SE 0x00000400 /* Single Step Trace Enable */
-#define MSR_BE 0x00000200 /* Branch Trace Enable */
-#define MSR_DE 0x00000200
-#define MSR_FE1 0x00000100
-#define MSR_IP 0x00000040 /* Interrupt Prefix */
-#define MSR_IR 0x00000020 /* Instruction Relocate */
-#define MSR_DR 0x00000010 /* Data Relocate */
-#define MSR_PE 0x00000008
-#define MSR_PX 0x00000004
-#define MSR_RI 0x00000002 /* Recoverable Interrupt Enable */
-#define MSR_LE 0x00000001
-
-#define TSR_ENW 0x80000000
-#define TSR_WIS 0x40000000
-
-#define BYTE_REVERSE16(x) ((((x) >> 8) & 0xff) | (((x) << 8) & 0xff00))
-#define BYTE_REVERSE32(x) ((((x) >> 24) & 0xff) | (((x) >> 8) & 0xff00) | (((x) << 8) & 0xff0000) | (((x) << 24) & 0xff000000))
-
-typedef struct {
- UINT32 cr;
- UINT32 da;
- UINT32 sa;
- UINT32 ct;
- UINT32 cc;
-} DMA_REGS;
-
-typedef struct {
- UINT8 spls;
- UINT8 sphs;
- UINT16 brd;
- UINT8 spctl;
- UINT8 sprc;
- UINT8 sptc;
- UINT8 sprb;
- UINT8 sptb;
- emu_timer *rx_timer;
- emu_timer *tx_timer;
-} SPU_REGS;
-
-typedef union {
- UINT64 id;
- double fd;
-} FPR;
-
-typedef union {
- UINT32 i;
- float f;
-} FPR32;
-
-typedef struct {
- UINT32 u;
- UINT32 l;
-} BATENT;
-
-
-typedef struct {
- UINT32 r[32];
- UINT32 pc;
- UINT32 npc;
-
- UINT32 lr;
- UINT32 ctr;
- UINT32 xer;
- UINT32 msr;
- UINT8 cr[8];
- UINT32 pvr;
- UINT32 srr0;
- UINT32 srr1;
- UINT32 srr2;
- UINT32 srr3;
- UINT32 hid0;
- UINT32 hid1;
- UINT32 hid2;
- UINT32 sdr1;
- UINT32 sprg[4];
-
- UINT32 dsisr;
- UINT32 dar;
- UINT32 ear;
- UINT32 dmiss;
- UINT32 dcmp;
- UINT32 hash1;
- UINT32 hash2;
- UINT32 imiss;
- UINT32 icmp;
- UINT32 rpa;
-
- BATENT ibat[4];
- BATENT dbat[4];
-
- UINT32 evpr;
- UINT32 exier;
- UINT32 exisr;
- UINT32 bear;
- UINT32 besr;
- UINT32 iocr;
- UINT32 br[8];
- UINT32 iabr;
- UINT32 esr;
- UINT32 iccr;
- UINT32 dccr;
- UINT32 pit;
- UINT32 tsr;
- UINT32 tcr;
- UINT32 dbsr;
- UINT32 sgr;
- UINT32 pid;
- UINT32 pbl1, pbl2, pbu1, pbu2;
- UINT32 fit_bit;
- UINT32 fit_int_enable;
- UINT32 wdt_bit;
- UINT32 wdt_int_enable;
- UINT32 dac1, dac2;
- UINT32 iac1, iac2;
-
- SPU_REGS spu;
- DMA_REGS dma[4];
- UINT32 dmasr;
-
- int reserved;
- UINT32 reserved_address;
-
- int exception_pending;
-
- UINT64 tb; /* 56-bit timebase register */
-
- int (*irq_callback)(int irqline);
- drc_core *drc;
- UINT32 drcoptions;
-
- x86code * invoke_exception_handler;
- x86code * generate_interrupt_exception;
- x86code * generate_syscall_exception;
- x86code * generate_decrementer_exception;
- x86code * generate_trap_exception;
- x86code * generate_dsi_exception;
- x86code * generate_isi_exception;
- x86code * generate_fit_exception;
-
- // PowerPC 60x specific registers */
- UINT32 dec, dec_frac;
- UINT32 fpscr;
-
- FPR fpr[32];
- UINT32 sr[16];
-
- int is603;
- int is602;
-
- /* PowerPC 602 specific registers */
- UINT32 lt;
- UINT32 sp;
- UINT32 ibr;
- UINT32 esasrr;
- UINT32 sebr;
- UINT32 ser;
-
- /* PowerPC function pointers for memory accesses/exceptions */
- UINT8 (*read8)(offs_t address);
- UINT16 (*read16)(offs_t address);
- UINT32 (*read32)(offs_t address);
- UINT64 (*read64)(offs_t address);
- void (*write8)(offs_t address, UINT8 data);
- void (*write16)(offs_t address, UINT16 data);
- void (*write32)(offs_t address, UINT32 data);
- void (*write64)(offs_t address, UINT64 data);
- UINT16 (*read16_unaligned)(offs_t address);
- UINT32 (*read32_unaligned)(offs_t address);
- UINT64 (*read64_unaligned)(offs_t address);
- void (*write16_unaligned)(offs_t address, UINT16 data);
- void (*write32_unaligned)(offs_t address, UINT32 data);
- void (*write64_unaligned)(offs_t address, UINT64 data);
-
- /* saved ESP when entering entry point */
- UINT32 host_esp;
-
- UINT32 (* optable19[1024])(drc_core *, UINT32);
- UINT32 (* optable31[1024])(drc_core *, UINT32);
- UINT32 (* optable59[1024])(drc_core *, UINT32);
- UINT32 (* optable63[1024])(drc_core *, UINT32);
- UINT32 (* optable[64])(drc_core *, UINT32);
-} PPC_REGS;
-
-
-
-typedef struct {
- int code;
- int subcode;
- UINT32 (* handler)(drc_core *, UINT32);
-} PPC_OPCODE;
-
-
-/* code logging info */
-typedef struct _code_log_entry code_log_entry;
-struct _code_log_entry
-{
- UINT32 pc;
- UINT32 op;
- void * base;
-};
-
-
-
-static int ppc_icount;
-static int ppc_tb_base_icount;
-static int ppc_dec_base_icount;
-static int ppc_dec_trigger_cycle;
-static int bus_freq_multiplier = 1;
-static int ppc_fit_trigger_cycle;
-static PPC_REGS ppc;
-static UINT32 ppc_rotate_mask[32][32];
-
-#define ROPCODE(pc) cpu_readop32(pc)
-#define ROPCODE64(pc) cpu_readop64(DWORD_XOR_BE(pc))
-
-INLINE void SET_CR0(INT32 rd)
-{
- if( rd < 0 ) {
- CR(0) = 0x8;
- } else if( rd > 0 ) {
- CR(0) = 0x4;
- } else {
- CR(0) = 0x2;
- }
-
- if( XER & XER_SO )
- CR(0) |= 0x1;
-}
-
-INLINE void SET_CR1(void)
-{
- CR(1) = (ppc.fpscr >> 28) & 0xf;
-}
-
-INLINE void SET_ADD_OV(UINT32 rd, UINT32 ra, UINT32 rb)
-{
- if( ADD_OV(rd, ra, rb) )
- XER |= XER_SO | XER_OV;
- else
- XER &= ~XER_OV;
-}
-
-INLINE void SET_SUB_OV(UINT32 rd, UINT32 ra, UINT32 rb)
-{
- if( SUB_OV(rd, ra, rb) )
- XER |= XER_SO | XER_OV;
- else
- XER &= ~XER_OV;
-}
-
-INLINE void SET_ADD_CA(UINT32 rd, UINT32 ra, UINT32 rb)
-{
- if( ADD_CA(rd, ra, rb) )
- XER |= XER_CA;
- else
- XER &= ~XER_CA;
-}
-
-INLINE void SET_SUB_CA(UINT32 rd, UINT32 ra, UINT32 rb)
-{
- if( SUB_CA(rd, ra, rb) )
- XER |= XER_CA;
- else
- XER &= ~XER_CA;
-}
-
-INLINE UINT32 check_condition_code(UINT32 bo, UINT32 bi)
-{
- UINT32 ctr_ok;
- UINT32 condition_ok;
- UINT32 bo0 = (bo & 0x10) ? 1 : 0;
- UINT32 bo1 = (bo & 0x08) ? 1 : 0;
- UINT32 bo2 = (bo & 0x04) ? 1 : 0;
- UINT32 bo3 = (bo & 0x02) ? 1 : 0;
-
- if( bo2 == 0 )
- --CTR;
-
- ctr_ok = bo2 | ((CTR != 0) ^ bo3);
- condition_ok = bo0 | (CRBIT(bi) ^ (~bo1 & 0x1));
-
- return ctr_ok && condition_ok;
-}
-
-INLINE UINT64 ppc_read_timebase(void)
-{
- int cycles = ppc_tb_base_icount - ppc_icount;
-
- if (ppc.is603 || ppc.is602)
- {
- // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
- return ppc.tb + (cycles / 4);
- }
- else
- {
- // timebase is incremented once every core cycle on PPC403
- return ppc.tb + cycles;
- }
-}
-
-INLINE void ppc_write_timebase_l(UINT32 tbl)
-{
- ppc_tb_base_icount = ppc_icount;
-
- ppc.tb &= ~0xffffffff;
- ppc.tb |= tbl;
-}
-
-INLINE void ppc_write_timebase_h(UINT32 tbh)
-{
- ppc_tb_base_icount = ppc_icount;
-
- ppc.tb &= 0xffffffff;
- ppc.tb |= (UINT64)(tbh) << 32;
-}
-
-INLINE UINT32 read_decrementer(void)
-{
- int cycles = ppc_dec_base_icount - ppc_icount;
-
- // decrementer is decremented once every four bus clock cycles, so adjust the cycles accordingly
- return DEC - (cycles / (bus_freq_multiplier * 2));
-}
-
-INLINE void write_decrementer(UINT32 value)
-{
- ppc_dec_base_icount = ppc_icount + (ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2);
-
- DEC = value;
-
- // check if decrementer exception occurs during execution
- if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
- {
- ppc_dec_trigger_cycle = ppc_icount - DEC;
- }
- else
- {
- ppc_dec_trigger_cycle = 0x7fffffff;
- }
-}
-
-/*********************************************************************/
-
-INLINE void ppc_exception(int exception_type)
-{
- void *exception_code = NULL;
- void (*invoke_exception_handler)(void *handler);
-
- switch(exception_type)
- {
- case EXCEPTION_DECREMENTER:
- exception_code = ppc.generate_decrementer_exception;
- break;
- case EXCEPTION_DSI:
- exception_code = ppc.generate_dsi_exception;
- break;
- case EXCEPTION_ISI:
- exception_code = ppc.generate_isi_exception;
- break;
- default:
- fatalerror("Unknown exception %d", exception_type);
- break;
- }
-
- memcpy(&invoke_exception_handler, &ppc.invoke_exception_handler, sizeof(invoke_exception_handler));
- invoke_exception_handler(exception_code);
-}
-
-/*********************************************************************/
-
-INLINE void ppc_set_spr(int spr, UINT32 value)
-{
- switch (spr)
- {
- case SPR_LR: LR = value; return;
- case SPR_CTR: CTR = value; return;
- case SPR_XER: XER = value; return;
- case SPR_SRR0: ppc.srr0 = value; return;
- case SPR_SRR1: ppc.srr1 = value; return;
- case SPR_SPRG0: ppc.sprg[0] = value; return;
- case SPR_SPRG1: ppc.sprg[1] = value; return;
- case SPR_SPRG2: ppc.sprg[2] = value; return;
- case SPR_SPRG3: ppc.sprg[3] = value; return;
- case SPR_PVR: return;
- }
-
-#if (HAS_PPC603 || HAS_PPC602 || HAS_PPC601 || HAS_PPC604)
- if(ppc.is603 || ppc.is602) {
- switch(spr)
- {
- case SPR603E_DEC:
- if((value & 0x80000000) && !(DEC & 0x80000000))
- {
- /* trigger interrupt */
- if( MSR & MSR_EE )
- ppc_exception(EXCEPTION_DECREMENTER);
- }
- write_decrementer(value);
- return;
-
- case SPR603E_TBL_W:
- case SPR603E_TBL_R: // special 603e case
- ppc_write_timebase_l(value);
- return;
-
- case SPR603E_TBU_R:
- case SPR603E_TBU_W: // special 603e case
- ppc_write_timebase_h(value);
- return;
-
- case SPR603E_HID0:
- ppc.hid0 = value;
- return;
-
- case SPR603E_HID1:
- ppc.hid1 = value;
- return;
-
- case SPR603E_HID2:
- ppc.hid1 = value;
- return;
-
- case SPR603E_DSISR: ppc.dsisr = value; return;
- case SPR603E_DAR: ppc.dar = value; return;
- case SPR603E_EAR: ppc.ear = value; return;
- case SPR603E_DMISS: ppc.dmiss = value; return;
- case SPR603E_DCMP: ppc.dcmp = value; return;
- case SPR603E_HASH1: ppc.hash1 = value; return;
- case SPR603E_HASH2: ppc.hash2 = value; return;
- case SPR603E_IMISS: ppc.imiss = value; return;
- case SPR603E_ICMP: ppc.icmp = value; return;
- case SPR603E_RPA: ppc.rpa = value; return;
-
- case SPR603E_IBAT0L: ppc.ibat[0].l = value; return;
- case SPR603E_IBAT0U: ppc.ibat[0].u = value; return;
- case SPR603E_IBAT1L: ppc.ibat[1].l = value; return;
- case SPR603E_IBAT1U: ppc.ibat[1].u = value; return;
- case SPR603E_IBAT2L: ppc.ibat[2].l = value; return;
- case SPR603E_IBAT2U: ppc.ibat[2].u = value; return;
- case SPR603E_IBAT3L: ppc.ibat[3].l = value; return;
- case SPR603E_IBAT3U: ppc.ibat[3].u = value; return;
- case SPR603E_DBAT0L: ppc.dbat[0].l = value; return;
- case SPR603E_DBAT0U: ppc.dbat[0].u = value; return;
- case SPR603E_DBAT1L: ppc.dbat[1].l = value; return;
- case SPR603E_DBAT1U: ppc.dbat[1].u = value; return;
- case SPR603E_DBAT2L: ppc.dbat[2].l = value; return;
- case SPR603E_DBAT2U: ppc.dbat[2].u = value; return;
- case SPR603E_DBAT3L: ppc.dbat[3].l = value; return;
- case SPR603E_DBAT3U: ppc.dbat[3].u = value; return;
-
- case SPR603E_SDR1:
- ppc.sdr1 = value;
- return;
-
- case SPR603E_IABR: ppc.iabr = value; return;
- }
- }
-#endif
-
-#if (HAS_PPC602)
- if (ppc.is602) {
- switch(spr)
- {
- case SPR602_LT: ppc.lt = value; return;
- case SPR602_IBR: ppc.ibr = value; return;
- case SPR602_SP: ppc.sp = value; return;
- case SPR602_SEBR: ppc.sebr = value; return;
- case SPR602_SER: ppc.ser = value; return;
- case SPR602_TCR: ppc.tcr = value; return;
- }
- }
-#endif
-
-#if (HAS_PPC403)
- if (!ppc.is603 && !ppc.is602) {
- switch(spr)
- {
- case SPR403_TBHI: ppc_write_timebase_h(value); return;
- case SPR403_TBLO: ppc_write_timebase_l(value); return;
-
- case SPR403_TSR:
- ppc.tsr &= ~value; // 1 clears, 0 does nothing
- return;
-
- case SPR403_TCR:
- switch((value >> 24) & 0x3)
- {
- case 0: ppc.fit_bit = 1 << 8; break;
- case 1: ppc.fit_bit = 1 << 12; break;
- case 2: ppc.fit_bit = 1 << 16; break;
- case 3: ppc.fit_bit = 1 << 20; break;
- }
- switch((value >> 30) & 0x3)
- {
- case 0: ppc.wdt_bit = 1 << 16; break;
- case 1: ppc.wdt_bit = 1 << 20; break;
- case 2: ppc.wdt_bit = 1 << 24; break;
- case 3: ppc.wdt_bit = 1 << 28; break;
- }
- ppc.fit_int_enable = (value >> 23) & 0x1;
- ppc.wdt_int_enable = (value >> 27) & 0x1;
- ppc.tcr = value;
-
- if (!ppc.fit_int_enable)
- {
- ppc.exception_pending &= ~0x4;
- }
- return;
-
- case SPR403_ESR: ppc.esr = value; return;
- case SPR403_ICCR: ppc.iccr = value; return;
- case SPR403_DCCR: ppc.dccr = value; return;
- case SPR403_EVPR: EVPR = value & 0xffff0000; return;
- case SPR403_PIT: ppc.pit = value; return;
- case SPR403_SGR: ppc.sgr = value; return;
- case SPR403_DBSR: ppc.dbsr = value; return;
- case SPR403_DCWR: return;
- case SPR403_PID: ppc.pid = value; return;
- case SPR403_PBL1: ppc.pbl1 = value; return;
- case SPR403_PBU1: ppc.pbu1 = value; return;
- case SPR403_PBL2: ppc.pbl2 = value; return;
- case SPR403_PBU2: ppc.pbu2 = value; return;
- case SPR403_SRR2: ppc.srr2 = value; return;
- case SPR403_SRR3: ppc.srr3 = value; return;
- case SPR403_DAC1: ppc.dac1 = value; return;
- case SPR403_DAC2: ppc.dac2 = value; return;
- case SPR403_IAC1: ppc.iac1 = value; return;
- case SPR403_IAC2: ppc.iac2 = value; return;
- }
- }
-#endif
-
- fatalerror("ppc: set_spr: unknown spr %d (%03X) !", spr, spr);
-}
-
-INLINE UINT32 ppc_get_spr(int spr)
-{
- switch(spr)
- {
- case SPR_LR: return LR;
- case SPR_CTR: return CTR;
- case SPR_XER: return XER;
- case SPR_SRR0: return ppc.srr0;
- case SPR_SRR1: return ppc.srr1;
- case SPR_SPRG0: return ppc.sprg[0];
- case SPR_SPRG1: return ppc.sprg[1];
- case SPR_SPRG2: return ppc.sprg[2];
- case SPR_SPRG3: return ppc.sprg[3];
- case SPR_PVR: return ppc.pvr;
- }
-
-#if (HAS_PPC403)
- if (!ppc.is603 && !ppc.is602)
- {
- switch (spr)
- {
- case SPR403_TBLU:
- case SPR403_TBLO: return (UINT32)(ppc_read_timebase());
- case SPR403_TBHU:
- case SPR403_TBHI: return (UINT32)(ppc_read_timebase() >> 32);
-
- case SPR403_EVPR: return EVPR;
- case SPR403_ESR: return ppc.esr;
- case SPR403_TCR: return ppc.tcr;
- case SPR403_ICCR: return ppc.iccr;
- case SPR403_DCCR: return ppc.dccr;
- case SPR403_PIT: return ppc.pit;
- case SPR403_DBSR: return ppc.dbsr;
- case SPR403_SGR: return ppc.sgr;
- case SPR403_TSR: return ppc.tsr;
- case SPR403_PBL1: return ppc.pbl1;
- case SPR403_PBU1: return ppc.pbu1;
- case SPR403_PBL2: return ppc.pbl2;
- case SPR403_PBU2: return ppc.pbu2;
- case SPR403_SRR2: return ppc.srr2;
- case SPR403_SRR3: return ppc.srr3;
- case SPR403_DAC1: return ppc.dac1;
- case SPR403_DAC2: return ppc.dac2;
- case SPR403_IAC1: return ppc.iac1;
- case SPR403_IAC2: return ppc.iac2;
- }
- }
-#endif
-
-#if (HAS_PPC602)
- if (ppc.is602) {
- switch(spr)
- {
- case SPR602_LT: return ppc.lt;
- case SPR602_IBR: return ppc.ibr;
- case SPR602_ESASRR: return ppc.esasrr;
- case SPR602_SEBR: return ppc.sebr;
- case SPR602_SER: return ppc.ser;
- case SPR602_SP: return ppc.sp;
- case SPR602_TCR: return ppc.tcr;
- }
- }
-#endif
-
-#if (HAS_PPC603 || HAS_PPC602 || HAS_PPC601 || HAS_PPC604)
- if (ppc.is603 || ppc.is602)
- {
- switch (spr)
- {
- case SPR603E_TBL_R:
- fatalerror("ppc: get_spr: TBL_R ");
- break;
-
- case SPR603E_TBU_R:
- fatalerror("ppc: get_spr: TBU_R ");
- break;
-
- case SPR603E_TBL_W: return (UINT32)(ppc_read_timebase());
- case SPR603E_TBU_W: return (UINT32)(ppc_read_timebase() >> 32);
- case SPR603E_HID0: return ppc.hid0;
- case SPR603E_HID1: return ppc.hid1;
- case SPR603E_HID2: return ppc.hid2;
- case SPR603E_DEC: return read_decrementer();
- case SPR603E_SDR1: return ppc.sdr1;
- case SPR603E_DSISR: return ppc.dsisr;
- case SPR603E_DAR: return ppc.dar;
- case SPR603E_EAR: return ppc.ear;
- case SPR603E_IBAT0L: return ppc.ibat[0].l;
- case SPR603E_IBAT0U: return ppc.ibat[0].u;
- case SPR603E_IBAT1L: return ppc.ibat[1].l;
- case SPR603E_IBAT1U: return ppc.ibat[1].u;
- case SPR603E_IBAT2L: return ppc.ibat[2].l;
- case SPR603E_IBAT2U: return ppc.ibat[2].u;
- case SPR603E_IBAT3L: return ppc.ibat[3].l;
- case SPR603E_IBAT3U: return ppc.ibat[3].u;
- case SPR603E_DBAT0L: return ppc.dbat[0].l;
- case SPR603E_DBAT0U: return ppc.dbat[0].u;
- case SPR603E_DBAT1L: return ppc.dbat[1].l;
- case SPR603E_DBAT1U: return ppc.dbat[1].u;
- case SPR603E_DBAT2L: return ppc.dbat[2].l;
- case SPR603E_DBAT2U: return ppc.dbat[2].u;
- case SPR603E_DBAT3L: return ppc.dbat[3].l;
- case SPR603E_DBAT3U: return ppc.dbat[3].u;
- }
- }
-#endif
-
- fatalerror("ppc: get_spr: unknown spr %d (%03X) !", spr, spr);
- return 0;
-}
-
-static UINT8 ppc_read8_translated(offs_t address);
-static UINT16 ppc_read16_translated(offs_t address);
-static UINT32 ppc_read32_translated(offs_t address);
-static UINT64 ppc_read64_translated(offs_t address);
-static void ppc_write8_translated(offs_t address, UINT8 data);
-static void ppc_write16_translated(offs_t address, UINT16 data);
-static void ppc_write32_translated(offs_t address, UINT32 data);
-static void ppc_write64_translated(offs_t address, UINT64 data);
-
-INLINE void ppc_set_msr(UINT32 value)
-{
- if( value & (MSR_ILE | MSR_LE) )
- fatalerror("ppc: set_msr: little_endian mode not supported !");
-
- MSR = value;
-
- if (ppc.is603 || ppc.is602)
- {
- if (!(MSR & MSR_DR))
- {
- ppc.read8 = program_read_byte_64be;
- ppc.read16 = program_read_word_64be;
- ppc.read32 = program_read_dword_64be;
- ppc.read64 = program_read_qword_64be;
- ppc.write8 = program_write_byte_64be;
- ppc.write16 = program_write_word_64be;
- ppc.write32 = program_write_dword_64be;
- ppc.write64 = program_write_qword_64be;
- }
- else
- {
- ppc.read8 = ppc_read8_translated;
- ppc.read16 = ppc_read16_translated;
- ppc.read32 = ppc_read32_translated;
- ppc.read64 = ppc_read64_translated;
- ppc.write8 = ppc_write8_translated;
- ppc.write16 = ppc_write16_translated;
- ppc.write32 = ppc_write32_translated;
- ppc.write64 = ppc_write64_translated;
- }
- }
-}
-
-INLINE UINT32 ppc_get_msr(void)
-{
- return MSR;
-}
-
-INLINE void ppc_set_cr(UINT32 value)
-{
- CR(0) = (value >> 28) & 0xf;
- CR(1) = (value >> 24) & 0xf;
- CR(2) = (value >> 20) & 0xf;
- CR(3) = (value >> 16) & 0xf;
- CR(4) = (value >> 12) & 0xf;
- CR(5) = (value >> 8) & 0xf;
- CR(6) = (value >> 4) & 0xf;
- CR(7) = (value >> 0) & 0xf;
-}
-
-INLINE UINT32 ppc_get_cr(void)
-{
- return CR(0) << 28 | CR(1) << 24 | CR(2) << 20 | CR(3) << 16 | CR(4) << 12 | CR(5) << 8 | CR(6) << 4 | CR(7);
-}
-
-#ifdef UNUSED_FUNCTION
-static void log_code(drc_core *drc)
-{
-#if LOG_CODE
- FILE *temp;
- temp = fopen("code.bin", "wb");
- fwrite(drc->cache_base, 1, drc->cache_top - drc->cache_base, temp);
- fclose(temp);
-#endif
-}
-#endif
-
-/***********************************************************************/
-
-#include "ppc_mem.c"
-
-#if (HAS_PPC403)
-#include "ppc403.c"
-#endif
-
-#if (HAS_PPC602)
-#include "ppc602.c"
-#endif
-
-/***************************************************************************
- CODE LOGGING
-***************************************************************************/
-
-#if LOG_CODE
-
-static code_log_entry code_log_buffer[MAX_INSTRUCTIONS*2];
-static int code_log_index;
-static FILE *logfile;
-
-
-/*-------------------------------------------------
- open_logfile - open the log file if it is
- not already opened
--------------------------------------------------*/
-
-INLINE int open_logfile(void)
-{
- if (logfile == NULL)
- logfile = fopen("ppcdrc.asm", "w");
- return (logfile != NULL);
-}
-
-
-/*-------------------------------------------------
- code_log_reset - reset the logging index
--------------------------------------------------*/
-
-INLINE void code_log_reset(void)
-{
- code_log_index = 0;
-}
-
-
-/*-------------------------------------------------
- code_log_add_entry - add an entry to the log
--------------------------------------------------*/
-
-INLINE void code_log_add_entry(UINT32 pc, UINT32 op, void *base)
-{
- code_log_buffer[code_log_index].pc = pc;
- code_log_buffer[code_log_index].op = op;
- code_log_buffer[code_log_index].base = base;
- code_log_index++;
-}
-
-
-/*-------------------------------------------------
- code_log - actually log some code
--------------------------------------------------*/
-
-static void code_log(const char *label, x86code *start, x86code *stop)
-{
- extern int i386_dasm_one(char *buffer, UINT32 eip, UINT8 *oprom, int mode);
- offs_t ppc_dasm_one(char *buffer, UINT32 pc, UINT32 op);
- UINT8 *cur = start;
-
- /* open the file, creating it if necessary */
- if (!open_logfile())
- return;
- fprintf(logfile, "\n%s\n", label);
-
- /* loop from the start until the cache top */
- while (cur < stop)
- {
- char buffer[100];
- int bytes;
- int op;
-
- /* skip filler opcodes */
- if (*cur == 0xcc)
- {
- cur++;
- continue;
- }
-
- /* disassemble this instruction */
-#ifdef PTR64
- bytes = i386_dasm_one(buffer, (UINT32)(FPTR)cur, cur, 64) & DASMFLAG_LENGTHMASK;
-#else
- bytes = i386_dasm_one(buffer, (UINT32)cur, cur, 32) & DASMFLAG_LENGTHMASK;
-#endif
-
- /* look for a match in the registered opcodes */
- for (op = 0; op < code_log_index; op++)
- if (code_log_buffer[op].base == (void *)cur)
- break;
-
- /* if no match, just output the current instruction */
- if (op == code_log_index)
- fprintf(logfile, "%p: %s\n", cur, buffer);
-
- /* otherwise, output with the original instruction to the right */
- else
- {
- char buffer2[100];
- ppc_dasm_one(buffer2, code_log_buffer[op].pc, code_log_buffer[op].op);
- fprintf(logfile, "%p: %-50s %08X: %s\n", cur, buffer, code_log_buffer[op].pc, buffer2);
- }
-
- /* advance past this instruction */
- cur += bytes;
- }
-
- /* flush the file */
- fflush(logfile);
-}
-
-#else
-
-#define code_log_reset()
-#define code_log_add_entry(a,b,c)
-#define code_log(a,b,c)
-
-#endif
-
-
-/********************************************************************/
-
-#include "ppc_ops.c"
-#include "drc_ops.c"
-#include "drc_ops.h"
-
-/* Initialization and shutdown */
-
-static void ppc_init(void)
-{
- int i,j;
-
- for( i=0; i < 64; i++ ) {
- ppc.optable[i] = recompile_invalid;
- }
- for( i=0; i < 1024; i++ ) {
- ppc.optable19[i] = recompile_invalid;
- ppc.optable31[i] = recompile_invalid;
- ppc.optable59[i] = recompile_invalid;
- ppc.optable63[i] = recompile_invalid;
- }
-
- /* Fill the opcode tables */
- for( i=0; i < (sizeof(ppcdrc_opcode_common) / sizeof(PPC_OPCODE)); i++ ) {
-
- switch(ppcdrc_opcode_common[i].code)
- {
- case 19:
- ppc.optable19[ppcdrc_opcode_common[i].subcode] = ppcdrc_opcode_common[i].handler;
- break;
-
- case 31:
- ppc.optable31[ppcdrc_opcode_common[i].subcode] = ppcdrc_opcode_common[i].handler;
- break;
-
- case 59:
- case 63:
- break;
-
- default:
- ppc.optable[ppcdrc_opcode_common[i].code] = ppcdrc_opcode_common[i].handler;
- }
-
- }
-
- /* Calculate rotate mask table */
- for( i=0; i < 32; i++ ) {
- for( j=0; j < 32; j++ ) {
- UINT32 mask;
- int mb = i;
- int me = j;
- mask = ((UINT32)0xFFFFFFFF >> mb) ^ ((me >= 31) ? 0 : ((UINT32)0xFFFFFFFF >> (me + 1)));
- if( mb > me )
- mask = ~mask;
-
- ppc_rotate_mask[i][j] = mask;
- }
- }
-}
-
-#if (HAS_PPC403)
-static void ppcdrc403_init(int index, int clock, const void *_config, int (*irqcallback)(int))
-{
- const ppc_config *config = _config;
-
- ppc_init();
- ppcdrc_init();
-
- /* PPC403 specific opcodes */
- ppc.optable31[454] = recompile_dccci;
- ppc.optable31[486] = recompile_dcread;
- ppc.optable31[262] = recompile_icbt;
- ppc.optable31[966] = recompile_iccci;
- ppc.optable31[998] = recompile_icread;
- ppc.optable31[323] = recompile_mfdcr;
- ppc.optable31[451] = recompile_mtdcr;
- ppc.optable31[131] = recompile_wrtee;
- ppc.optable31[163] = recompile_wrteei;
- ppc.optable19[51] = recompile_rfci;
-
- ppc.spu.rx_timer = timer_alloc(ppc403_spu_rx_callback, NULL);
- ppc.spu.tx_timer = timer_alloc(ppc403_spu_tx_callback, NULL);
-
- ppc.is603 = 0;
- ppc.is602 = 0;
-
- ppc.read8 = ppc403_read8;
- ppc.read16 = ppc403_read16;
- ppc.read32 = ppc403_read32;
- ppc.write8 = ppc403_write8;
- ppc.write16 = ppc403_write16;
- ppc.write32 = ppc403_write32;
- ppc.read16_unaligned = ppc403_read16_unaligned;
- ppc.read32_unaligned = ppc403_read32_unaligned;
- ppc.write16_unaligned = ppc403_write16_unaligned;
- ppc.write32_unaligned = ppc403_write32_unaligned;
-
- ppc.irq_callback = irqcallback;
-
- ppc.pvr = config->pvr;
-}
-
-static void ppcdrc403_exit(void)
-{
-#if LOG_CODE
- //if (symfile) fclose(symfile);
-#endif
- ppcdrc_exit();
-}
-
-static void ppcdrc403_reset(void)
-{
- ppc.pc = ppc.npc = 0xfffffffc;
-
- ppc_set_msr(0);
- change_pc(ppc.pc);
-
- /* reset the DRC */
- drc_cache_reset(ppc.drc);
-}
-
-static int ppcdrc403_execute(int cycles)
-{
- /* count cycles and interrupt cycles */
- ppc_icount = cycles;
- ppc_tb_base_icount = cycles;
-
- ppc_fit_trigger_cycle = 0x7fffffff;
-
- if (ppc.fit_int_enable)
- {
- UINT32 tb = (UINT32)ppc.tb;
- UINT32 fit_cycles = 0;
-
- if (ppc.tb & ppc.fit_bit)
- {
- fit_cycles += ppc.fit_bit;
- tb += fit_cycles;
- }
-
- fit_cycles += ppc.fit_bit - (tb & (ppc.fit_bit-1));
-
- ppc_fit_trigger_cycle = ppc_icount - fit_cycles;
- }
-
- drc_execute(ppc.drc);
-
- // update timebase
- ppc.tb += (ppc_tb_base_icount - ppc_icount);
-
- return cycles - ppc_icount;
-}
-
-static void ppcdrc403_set_irq_line(int irqline, int state)
-{
- if (irqline >= INPUT_LINE_IRQ0 && irqline <= INPUT_LINE_IRQ4)
- {
- UINT32 mask = (1 << (4 - irqline));
- if( state == ASSERT_LINE) {
- if (EXIER & mask)
- {
- ppc.exisr |= mask;
- ppc.exception_pending |= 0x1;
-
- if (ppc.irq_callback)
- {
- ppc.irq_callback(irqline);
- }
- }
- }
- // clear line is used to clear the interrupt when the interrupts are level-sensitive
- else if (state == CLEAR_LINE)
- {
- ppc.exisr &= ~mask;
- }
- }
- else if (irqline == PPC403_SPU_RX)
- {
- UINT32 mask = 0x08000000;
- if (state) {
- if( EXIER & mask ) {
- ppc.exisr |= mask;
- ppc.exception_pending |= 0x1;
- }
- }
- }
- else if (irqline == PPC403_SPU_TX)
- {
- UINT32 mask = 0x04000000;
- if (state) {
- if( EXIER & mask ) {
- ppc.exisr |= mask;
- ppc.exception_pending |= 0x1;
- }
- }
- }
- else
- {
- fatalerror("PPC: Unknown IRQ line %d", irqline);
- }
-}
-#endif
-
-#if (HAS_PPC603)
-static void ppcdrc603_init(int index, int clock, const void *_config, int (*irqcallback)(int))
-{
- int pll_config = 0;
- float multiplier;
- const ppc_config *config = _config;
- int i;
-
- ppc_init();
- ppcdrc_init();
-
- ppc.optable[48] = recompile_lfs;
- ppc.optable[49] = recompile_lfsu;
- ppc.optable[50] = recompile_lfd;
- ppc.optable[51] = recompile_lfdu;
- ppc.optable[52] = recompile_stfs;
- ppc.optable[53] = recompile_stfsu;
- ppc.optable[54] = recompile_stfd;
- ppc.optable[55] = recompile_stfdu;
- ppc.optable31[631] = recompile_lfdux;
- ppc.optable31[599] = recompile_lfdx;
- ppc.optable31[567] = recompile_lfsux;
- ppc.optable31[535] = recompile_lfsx;
- ppc.optable31[595] = recompile_mfsr;
- ppc.optable31[659] = recompile_mfsrin;
- ppc.optable31[371] = recompile_mftb;
- ppc.optable31[210] = recompile_mtsr;
- ppc.optable31[242] = recompile_mtsrin;
- ppc.optable31[758] = recompile_dcba;
- ppc.optable31[759] = recompile_stfdux;
- ppc.optable31[727] = recompile_stfdx;
- ppc.optable31[983] = recompile_stfiwx;
- ppc.optable31[695] = recompile_stfsux;
- ppc.optable31[663] = recompile_stfsx;
- ppc.optable31[370] = recompile_tlbia;
- ppc.optable31[306] = recompile_tlbie;
- ppc.optable31[566] = recompile_tlbsync;
- ppc.optable31[310] = recompile_eciwx;
- ppc.optable31[438] = recompile_ecowx;
-
- ppc.optable63[264] = recompile_fabsx;
- ppc.optable63[21] = recompile_faddx;
- ppc.optable63[32] = recompile_fcmpo;
- ppc.optable63[0] = recompile_fcmpu;
- ppc.optable63[14] = recompile_fctiwx;
- ppc.optable63[15] = recompile_fctiwzx;
- ppc.optable63[18] = recompile_fdivx;
- ppc.optable63[72] = recompile_fmrx;
- ppc.optable63[136] = recompile_fnabsx;
- ppc.optable63[40] = recompile_fnegx;
- ppc.optable63[12] = recompile_frspx;
- ppc.optable63[26] = recompile_frsqrtex;
- ppc.optable63[22] = recompile_fsqrtx;
- ppc.optable63[20] = recompile_fsubx;
- ppc.optable63[583] = recompile_mffsx;
- ppc.optable63[70] = recompile_mtfsb0x;
- ppc.optable63[38] = recompile_mtfsb1x;
- ppc.optable63[711] = recompile_mtfsfx;
- ppc.optable63[134] = recompile_mtfsfix;
- ppc.optable63[64] = recompile_mcrfs;
-
- ppc.optable59[21] = recompile_faddsx;
- ppc.optable59[18] = recompile_fdivsx;
- ppc.optable59[24] = recompile_fresx;
- ppc.optable59[22] = recompile_fsqrtsx;
- ppc.optable59[20] = recompile_fsubsx;
-
- for(i = 0; i < 32; i++)
- {
- ppc.optable63[i * 32 | 29] = recompile_fmaddx;
- ppc.optable63[i * 32 | 28] = recompile_fmsubx;
- ppc.optable63[i * 32 | 25] = recompile_fmulx;
- ppc.optable63[i * 32 | 31] = recompile_fnmaddx;
- ppc.optable63[i * 32 | 30] = recompile_fnmsubx;
- ppc.optable63[i * 32 | 23] = recompile_fselx;
-
- ppc.optable59[i * 32 | 29] = recompile_fmaddsx;
- ppc.optable59[i * 32 | 28] = recompile_fmsubsx;
- ppc.optable59[i * 32 | 25] = recompile_fmulsx;
- ppc.optable59[i * 32 | 31] = recompile_fnmaddsx;
- ppc.optable59[i * 32 | 30] = recompile_fnmsubsx;
- }
-
-#if (HAS_PPC602 || HAS_MPC8240)
- ppc.optable31[978] = recompile_tlbld;
-#endif /* (HAS_PPC602 || HAS_MPC8240) */
-
- for(i = 0; i < 256; i++)
- {
- ppc_field_xlat[i] =
- ((i & 0x80) ? 0xF0000000 : 0) |
- ((i & 0x40) ? 0x0F000000 : 0) |
- ((i & 0x20) ? 0x00F00000 : 0) |
- ((i & 0x10) ? 0x000F0000 : 0) |
- ((i & 0x08) ? 0x0000F000 : 0) |
- ((i & 0x04) ? 0x00000F00 : 0) |
- ((i & 0x02) ? 0x000000F0 : 0) |
- ((i & 0x01) ? 0x0000000F : 0);
- }
-
- ppc.is603 = 1;
-
- ppc.read8 = program_read_byte_64be;
- ppc.read16 = program_read_word_64be;
- ppc.read32 = program_read_dword_64be;
- ppc.read64 = program_read_qword_64be;
- ppc.write8 = program_write_byte_64be;
- ppc.write16 = program_write_word_64be;
- ppc.write32 = program_write_dword_64be;
- ppc.write64 = program_write_qword_64be;
- ppc.read16_unaligned = ppc_read16_unaligned;
- ppc.read32_unaligned = ppc_read32_unaligned;
- ppc.read64_unaligned = ppc_read64_unaligned;
- ppc.write16_unaligned = ppc_write16_unaligned;
- ppc.write32_unaligned = ppc_write32_unaligned;
- ppc.write64_unaligned = ppc_write64_unaligned;
-
- ppc.irq_callback = irqcallback;
-
- ppc.pvr = config->pvr;
-
- multiplier = (float)((config->bus_frequency_multiplier >> 4) & 0xf) +
- (float)(config->bus_frequency_multiplier & 0xf) / 10.0f;
- bus_freq_multiplier = (int)(multiplier * 2);
-
- switch(config->pvr)
- {
- case PPC_MODEL_603E: pll_config = mpc603e_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
- case PPC_MODEL_603EV: pll_config = mpc603ev_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
- case PPC_MODEL_603R: pll_config = mpc603r_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
- default: break;
- }
-
- if (pll_config == -1)
- {
- fatalerror("PPC: Invalid bus/multiplier combination (bus frequency = %d, multiplier = %1.1f)", config->bus_frequency, multiplier);
- }
-
- ppc.hid1 = pll_config << 28;
-}
-
-static void ppcdrc603_exit(void)
-{
-#if LOG_CODE
- //if (symfile) fclose(symfile);
-#endif
- ppcdrc_exit();
-}
-#endif
-
-#if (HAS_PPC601 || HAS_PPC603 || HAS_MPC8240 || HAS_PPC604)
-static void ppcdrc603_reset(void)
-{
- ppc.pc = ppc.npc = 0xfff00100;
-
- ppc_set_msr(0x40);
- change_pc(ppc.pc);
-
- /* reset the DRC */
- drc_cache_reset(ppc.drc);
-}
-
-static int ppcdrc603_execute(int cycles)
-{
- /* count cycles and interrupt cycles */
- ppc_icount = cycles;
- ppc_tb_base_icount = cycles;
- ppc_dec_base_icount = cycles + ppc.dec_frac;
-
- // check if decrementer exception occurs during execution
- if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
- {
- ppc_dec_trigger_cycle = ppc_icount - DEC;
- }
- else
- {
- ppc_dec_trigger_cycle = 0x7fffffff;
- }
-
- drc_execute(ppc.drc);
-
- // update timebase
- // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
- ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
-
- // update decrementer
- ppc.dec_frac = ((ppc_dec_base_icount - ppc_icount) % (bus_freq_multiplier * 2));
- DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
-
- return cycles - ppc_icount;
-}
-
-static void ppcdrc603_set_irq_line(int irqline, int state)
-{
- if( state ) {
- ppc.exception_pending |= 0x1;
- if (ppc.irq_callback)
- {
- ppc.irq_callback(irqline);
- }
- }
-}
-#endif
-
-#if (HAS_PPC602)
-static void ppcdrc602_init(int index, int clock, const void *_config, int (*irqcallback)(int))
-{
- float multiplier;
- const ppc_config *config = _config;
- int i;
-
- ppc_init();
- ppcdrc_init();
-
- ppc.optable[48] = recompile_lfs;
- ppc.optable[49] = recompile_lfsu;
- ppc.optable[50] = recompile_lfd;
- ppc.optable[51] = recompile_lfdu;
- ppc.optable[52] = recompile_stfs;
- ppc.optable[53] = recompile_stfsu;
- ppc.optable[54] = recompile_stfd;
- ppc.optable[55] = recompile_stfdu;
- ppc.optable31[631] = recompile_lfdux;
- ppc.optable31[599] = recompile_lfdx;
- ppc.optable31[567] = recompile_lfsux;
- ppc.optable31[535] = recompile_lfsx;
- ppc.optable31[595] = recompile_mfsr;
- ppc.optable31[659] = recompile_mfsrin;
- ppc.optable31[371] = recompile_mftb;
- ppc.optable31[210] = recompile_mtsr;
- ppc.optable31[242] = recompile_mtsrin;
- ppc.optable31[758] = recompile_dcba;
- ppc.optable31[759] = recompile_stfdux;
- ppc.optable31[727] = recompile_stfdx;
- ppc.optable31[983] = recompile_stfiwx;
- ppc.optable31[695] = recompile_stfsux;
- ppc.optable31[663] = recompile_stfsx;
- ppc.optable31[370] = recompile_tlbia;
- ppc.optable31[306] = recompile_tlbie;
- ppc.optable31[566] = recompile_tlbsync;
- ppc.optable31[310] = recompile_eciwx;
- ppc.optable31[438] = recompile_ecowx;
-
- ppc.optable63[264] = recompile_fabsx;
- ppc.optable63[21] = recompile_faddx;
- ppc.optable63[32] = recompile_fcmpo;
- ppc.optable63[0] = recompile_fcmpu;
- ppc.optable63[14] = recompile_fctiwx;
- ppc.optable63[15] = recompile_fctiwzx;
- ppc.optable63[18] = recompile_fdivx;
- ppc.optable63[72] = recompile_fmrx;
- ppc.optable63[136] = recompile_fnabsx;
- ppc.optable63[40] = recompile_fnegx;
- ppc.optable63[12] = recompile_frspx;
- ppc.optable63[26] = recompile_frsqrtex;
- ppc.optable63[22] = recompile_fsqrtx;
- ppc.optable63[20] = recompile_fsubx;
- ppc.optable63[583] = recompile_mffsx;
- ppc.optable63[70] = recompile_mtfsb0x;
- ppc.optable63[38] = recompile_mtfsb1x;
- ppc.optable63[711] = recompile_mtfsfx;
- ppc.optable63[134] = recompile_mtfsfix;
- ppc.optable63[64] = recompile_mcrfs;
-
- ppc.optable59[21] = recompile_faddsx;
- ppc.optable59[18] = recompile_fdivsx;
- ppc.optable59[24] = recompile_fresx;
- ppc.optable59[22] = recompile_fsqrtsx;
- ppc.optable59[20] = recompile_fsubsx;
-
- for(i = 0; i < 32; i++)
- {
- ppc.optable63[i * 32 | 29] = recompile_fmaddx;
- ppc.optable63[i * 32 | 28] = recompile_fmsubx;
- ppc.optable63[i * 32 | 25] = recompile_fmulx;
- ppc.optable63[i * 32 | 31] = recompile_fnmaddx;
- ppc.optable63[i * 32 | 30] = recompile_fnmsubx;
- ppc.optable63[i * 32 | 23] = recompile_fselx;
-
- ppc.optable59[i * 32 | 29] = recompile_fmaddsx;
- ppc.optable59[i * 32 | 28] = recompile_fmsubsx;
- ppc.optable59[i * 32 | 25] = recompile_fmulsx;
- ppc.optable59[i * 32 | 31] = recompile_fnmaddsx;
- ppc.optable59[i * 32 | 30] = recompile_fnmsubsx;
- }
-
- for(i = 0; i < 256; i++)
- {
- ppc_field_xlat[i] =
- ((i & 0x80) ? 0xF0000000 : 0) |
- ((i & 0x40) ? 0x0F000000 : 0) |
- ((i & 0x20) ? 0x00F00000 : 0) |
- ((i & 0x10) ? 0x000F0000 : 0) |
- ((i & 0x08) ? 0x0000F000 : 0) |
- ((i & 0x04) ? 0x00000F00 : 0) |
- ((i & 0x02) ? 0x000000F0 : 0) |
- ((i & 0x01) ? 0x0000000F : 0);
- }
-
- // PPC602 specific opcodes
- ppc.optable31[596] = recompile_esa;
- ppc.optable31[628] = recompile_dsa;
- ppc.optable31[1010] = recompile_tlbli;
- ppc.optable31[978] = recompile_tlbld;
-
- ppc.is603 = 0;
- ppc.is602 = 1;
-
- ppc.read8 = program_read_byte_64be;
- ppc.read16 = program_read_word_64be;
- ppc.read32 = program_read_dword_64be;
- ppc.read64 = program_read_qword_64be;
- ppc.write8 = program_write_byte_64be;
- ppc.write16 = program_write_word_64be;
- ppc.write32 = program_write_dword_64be;
- ppc.write64 = program_write_qword_64be;
- ppc.read16_unaligned = ppc_read16_unaligned;
- ppc.read32_unaligned = ppc_read32_unaligned;
- ppc.read64_unaligned = ppc_read64_unaligned;
- ppc.write16_unaligned = ppc_write16_unaligned;
- ppc.write32_unaligned = ppc_write32_unaligned;
- ppc.write64_unaligned = ppc_write64_unaligned;
-
- ppc.irq_callback = irqcallback;
-
- ppc.pvr = config->pvr;
-
- multiplier = (float)((config->bus_frequency_multiplier >> 4) & 0xf) +
- (float)(config->bus_frequency_multiplier & 0xf) / 10.0f;
- bus_freq_multiplier = (int)(multiplier * 2);
-}
-
-static void ppcdrc602_exit(void)
-{
-#if LOG_CODE
- //if (symfile) fclose(symfile);
-#endif
- ppcdrc_exit();
-}
-
-static void ppcdrc602_reset(void)
-{
- ppc.pc = ppc.npc = 0xfff00100;
-
- ppc_set_msr(0x40);
- change_pc(ppc.pc);
-
- ppc.hid0 = 1;
-
- /* reset the DRC */
- drc_cache_reset(ppc.drc);
-}
-
-static int ppcdrc602_execute(int cycles)
-{
- /* count cycles and interrupt cycles */
- ppc_icount = cycles;
- ppc_tb_base_icount = cycles;
- ppc_dec_base_icount = cycles;
-
- // check if decrementer exception occurs during execution
- if ((UINT32)(DEC - ppc_icount) > (UINT32)(DEC))
- {
- ppc_dec_trigger_cycle = ppc_icount - DEC;
- }
- else
- {
- ppc_dec_trigger_cycle = 0x7fffffff;
- }
-
- drc_execute(ppc.drc);
-
- // update timebase
- // timebase is incremented once every four core clock cycles, so adjust the cycles accordingly
- ppc.tb += ((ppc_tb_base_icount - ppc_icount) / 4);
-
- // update decrementer
- DEC -= ((ppc_dec_base_icount - ppc_icount) / (bus_freq_multiplier * 2));
-
- return cycles - ppc_icount;
-}
-
-static void ppcdrc602_set_irq_line(int irqline, int state)
-{
- if( state ) {
- ppc.exception_pending |= 0x1;
- if (ppc.irq_callback)
- {
- ppc.irq_callback(irqline);
- }
- }
-}
-#endif
-
-#if (HAS_MPC8240)
-static void mpc8240drc_init(int index, int clock, const void *_config, int (*irqcallback)(int))
-{
- float multiplier;
- const ppc_config *config = _config;
- int i;
-
- ppc_init();
- ppcdrc_init();
-
- ppc.optable[48] = recompile_lfs;
- ppc.optable[49] = recompile_lfsu;
- ppc.optable[50] = recompile_lfd;
- ppc.optable[51] = recompile_lfdu;
- ppc.optable[52] = recompile_stfs;
- ppc.optable[53] = recompile_stfsu;
- ppc.optable[54] = recompile_stfd;
- ppc.optable[55] = recompile_stfdu;
- ppc.optable31[631] = recompile_lfdux;
- ppc.optable31[599] = recompile_lfdx;
- ppc.optable31[567] = recompile_lfsux;
- ppc.optable31[535] = recompile_lfsx;
- ppc.optable31[595] = recompile_mfsr;
- ppc.optable31[659] = recompile_mfsrin;
- ppc.optable31[371] = recompile_mftb;
- ppc.optable31[210] = recompile_mtsr;
- ppc.optable31[242] = recompile_mtsrin;
- ppc.optable31[758] = recompile_dcba;
- ppc.optable31[759] = recompile_stfdux;
- ppc.optable31[727] = recompile_stfdx;
- ppc.optable31[983] = recompile_stfiwx;
- ppc.optable31[695] = recompile_stfsux;
- ppc.optable31[663] = recompile_stfsx;
- ppc.optable31[370] = recompile_tlbia;
- ppc.optable31[306] = recompile_tlbie;
- ppc.optable31[566] = recompile_tlbsync;
- ppc.optable31[310] = recompile_eciwx;
- ppc.optable31[438] = recompile_ecowx;
-
- ppc.optable63[264] = recompile_fabsx;
- ppc.optable63[21] = recompile_faddx;
- ppc.optable63[32] = recompile_fcmpo;
- ppc.optable63[0] = recompile_fcmpu;
- ppc.optable63[14] = recompile_fctiwx;
- ppc.optable63[15] = recompile_fctiwzx;
- ppc.optable63[18] = recompile_fdivx;
- ppc.optable63[72] = recompile_fmrx;
- ppc.optable63[136] = recompile_fnabsx;
- ppc.optable63[40] = recompile_fnegx;
- ppc.optable63[12] = recompile_frspx;
- ppc.optable63[26] = recompile_frsqrtex;
- ppc.optable63[22] = recompile_fsqrtx;
- ppc.optable63[20] = recompile_fsubx;
- ppc.optable63[583] = recompile_mffsx;
- ppc.optable63[70] = recompile_mtfsb0x;
- ppc.optable63[38] = recompile_mtfsb1x;
- ppc.optable63[711] = recompile_mtfsfx;
- ppc.optable63[134] = recompile_mtfsfix;
- ppc.optable63[64] = recompile_mcrfs;
-
- ppc.optable59[21] = recompile_faddsx;
- ppc.optable59[18] = recompile_fdivsx;
- ppc.optable59[24] = recompile_fresx;
- ppc.optable59[22] = recompile_fsqrtsx;
- ppc.optable59[20] = recompile_fsubsx;
-
- for(i = 0; i < 32; i++)
- {
- ppc.optable63[i * 32 | 29] = recompile_fmaddx;
- ppc.optable63[i * 32 | 28] = recompile_fmsubx;
- ppc.optable63[i * 32 | 25] = recompile_fmulx;
- ppc.optable63[i * 32 | 31] = recompile_fnmaddx;
- ppc.optable63[i * 32 | 30] = recompile_fnmsubx;
- ppc.optable63[i * 32 | 23] = recompile_fselx;
-
- ppc.optable59[i * 32 | 29] = recompile_fmaddsx;
- ppc.optable59[i * 32 | 28] = recompile_fmsubsx;
- ppc.optable59[i * 32 | 25] = recompile_fmulsx;
- ppc.optable59[i * 32 | 31] = recompile_fnmaddsx;
- ppc.optable59[i * 32 | 30] = recompile_fnmsubsx;
- }
-
- for(i = 0; i < 256; i++)
- {
- ppc_field_xlat[i] =
- ((i & 0x80) ? 0xF0000000 : 0) |
- ((i & 0x40) ? 0x0F000000 : 0) |
- ((i & 0x20) ? 0x00F00000 : 0) |
- ((i & 0x10) ? 0x000F0000 : 0) |
- ((i & 0x08) ? 0x0000F000 : 0) |
- ((i & 0x04) ? 0x00000F00 : 0) |
- ((i & 0x02) ? 0x000000F0 : 0) |
- ((i & 0x01) ? 0x0000000F : 0);
- }
-
- // MPC8240 specific opcodes
- ppc.optable31[978] = recompile_tlbld;
- ppc.optable31[1010] = recompile_tlbli;
-
- ppc.is603 = 1;
-
- ppc.read8 = program_read_byte_64be;
- ppc.read16 = program_read_word_64be;
- ppc.read32 = program_read_dword_64be;
- ppc.read64 = program_read_qword_64be;
- ppc.write8 = program_write_byte_64be;
- ppc.write16 = program_write_word_64be;
- ppc.write32 = program_write_dword_64be;
- ppc.write64 = program_write_qword_64be;
- ppc.read16_unaligned = ppc_read16_unaligned;
- ppc.read32_unaligned = ppc_read32_unaligned;
- ppc.read64_unaligned = ppc_read64_unaligned;
- ppc.write16_unaligned = ppc_write16_unaligned;
- ppc.write32_unaligned = ppc_write32_unaligned;
- ppc.write64_unaligned = ppc_write64_unaligned;
-
- ppc.irq_callback = irqcallback;
-
- ppc.pvr = config->pvr;
-
- multiplier = (float)((config->bus_frequency_multiplier >> 4) & 0xf) +
- (float)(config->bus_frequency_multiplier & 0xf) / 10.0f;
- bus_freq_multiplier = (int)(multiplier * 2);
-}
-
-static void mpc8240drc_exit(void)
-{
- ppcdrc_exit();
-}
-#endif
-
-
-#if (HAS_PPC601)
-static void ppc601drc_init(int index, int clock, const void *_config, int (*irqcallback)(int))
-{
- int pll_config = 0;
- float multiplier;
- const ppc_config *config = _config;
- int i;
-
- ppc_init();
- ppcdrc_init();
-
- ppc.optable[48] = recompile_lfs;
- ppc.optable[49] = recompile_lfsu;
- ppc.optable[50] = recompile_lfd;
- ppc.optable[51] = recompile_lfdu;
- ppc.optable[52] = recompile_stfs;
- ppc.optable[53] = recompile_stfsu;
- ppc.optable[54] = recompile_stfd;
- ppc.optable[55] = recompile_stfdu;
- ppc.optable31[631] = recompile_lfdux;
- ppc.optable31[599] = recompile_lfdx;
- ppc.optable31[567] = recompile_lfsux;
- ppc.optable31[535] = recompile_lfsx;
- ppc.optable31[595] = recompile_mfsr;
- ppc.optable31[659] = recompile_mfsrin;
- ppc.optable31[371] = recompile_mftb;
- ppc.optable31[210] = recompile_mtsr;
- ppc.optable31[242] = recompile_mtsrin;
- ppc.optable31[758] = recompile_dcba;
- ppc.optable31[759] = recompile_stfdux;
- ppc.optable31[727] = recompile_stfdx;
- ppc.optable31[983] = recompile_stfiwx;
- ppc.optable31[695] = recompile_stfsux;
- ppc.optable31[663] = recompile_stfsx;
- ppc.optable31[370] = recompile_tlbia;
- ppc.optable31[306] = recompile_tlbie;
- ppc.optable31[566] = recompile_tlbsync;
- ppc.optable31[310] = recompile_eciwx;
- ppc.optable31[438] = recompile_ecowx;
-
- ppc.optable63[264] = recompile_fabsx;
- ppc.optable63[21] = recompile_faddx;
- ppc.optable63[32] = recompile_fcmpo;
- ppc.optable63[0] = recompile_fcmpu;
- ppc.optable63[14] = recompile_fctiwx;
- ppc.optable63[15] = recompile_fctiwzx;
- ppc.optable63[18] = recompile_fdivx;
- ppc.optable63[72] = recompile_fmrx;
- ppc.optable63[136] = recompile_fnabsx;
- ppc.optable63[40] = recompile_fnegx;
- ppc.optable63[12] = recompile_frspx;
- ppc.optable63[26] = recompile_frsqrtex;
- ppc.optable63[22] = recompile_fsqrtx;
- ppc.optable63[20] = recompile_fsubx;
- ppc.optable63[583] = recompile_mffsx;
- ppc.optable63[70] = recompile_mtfsb0x;
- ppc.optable63[38] = recompile_mtfsb1x;
- ppc.optable63[711] = recompile_mtfsfx;
- ppc.optable63[134] = recompile_mtfsfix;
- ppc.optable63[64] = recompile_mcrfs;
-
- ppc.optable59[21] = recompile_faddsx;
- ppc.optable59[18] = recompile_fdivsx;
- ppc.optable59[24] = recompile_fresx;
- ppc.optable59[22] = recompile_fsqrtsx;
- ppc.optable59[20] = recompile_fsubsx;
-
- for(i = 0; i < 32; i++)
- {
- ppc.optable63[i * 32 | 29] = recompile_fmaddx;
- ppc.optable63[i * 32 | 28] = recompile_fmsubx;
- ppc.optable63[i * 32 | 25] = recompile_fmulx;
- ppc.optable63[i * 32 | 31] = recompile_fnmaddx;
- ppc.optable63[i * 32 | 30] = recompile_fnmsubx;
- ppc.optable63[i * 32 | 23] = recompile_fselx;
-
- ppc.optable59[i * 32 | 29] = recompile_fmaddsx;
- ppc.optable59[i * 32 | 28] = recompile_fmsubsx;
- ppc.optable59[i * 32 | 25] = recompile_fmulsx;
- ppc.optable59[i * 32 | 31] = recompile_fnmaddsx;
- ppc.optable59[i * 32 | 30] = recompile_fnmsubsx;
- }
-
- for(i = 0; i < 256; i++)
- {
- ppc_field_xlat[i] =
- ((i & 0x80) ? 0xF0000000 : 0) |
- ((i & 0x40) ? 0x0F000000 : 0) |
- ((i & 0x20) ? 0x00F00000 : 0) |
- ((i & 0x10) ? 0x000F0000 : 0) |
- ((i & 0x08) ? 0x0000F000 : 0) |
- ((i & 0x04) ? 0x00000F00 : 0) |
- ((i & 0x02) ? 0x000000F0 : 0) |
- ((i & 0x01) ? 0x0000000F : 0);
- }
-
- ppc.is603 = 1;
-
- ppc.read8 = program_read_byte_64be;
- ppc.read16 = program_read_word_64be;
- ppc.read32 = program_read_dword_64be;
- ppc.read64 = program_read_qword_64be;
- ppc.write8 = program_write_byte_64be;
- ppc.write16 = program_write_word_64be;
- ppc.write32 = program_write_dword_64be;
- ppc.write64 = program_write_qword_64be;
- ppc.read16_unaligned = ppc_read16_unaligned;
- ppc.read32_unaligned = ppc_read32_unaligned;
- ppc.read64_unaligned = ppc_read64_unaligned;
- ppc.write16_unaligned = ppc_write16_unaligned;
- ppc.write32_unaligned = ppc_write32_unaligned;
- ppc.write64_unaligned = ppc_write64_unaligned;
-
- ppc.irq_callback = irqcallback;
-
- ppc.pvr = config->pvr;
-
- multiplier = (float)((config->bus_frequency_multiplier >> 4) & 0xf) +
- (float)(config->bus_frequency_multiplier & 0xf) / 10.0f;
- bus_freq_multiplier = (int)(multiplier * 2);
-
- switch(config->pvr)
- {
- case PPC_MODEL_603E: pll_config = mpc603e_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
- case PPC_MODEL_603EV: pll_config = mpc603ev_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
- case PPC_MODEL_603R: pll_config = mpc603r_pll_config[bus_freq_multiplier-1][config->bus_frequency]; break;
- default: break;
- }
-
- if (pll_config == -1)
- {
- fatalerror("PPC: Invalid bus/multiplier combination (bus frequency = %d, multiplier = %1.1f)", config->bus_frequency, multiplier);
- }
-
- ppc.hid1 = pll_config << 28;
-}
-
-static void ppc601drc_exit(void)
-{
-#if LOG_CODE
- //if (symfile) fclose(symfile);
-#endif
- ppcdrc_exit();
-}
-#endif
-
-
-#if (HAS_PPC604)
-static void ppc604drc_init(int index, int clock, const void *_config, int (*irqcallback)(int))
-{
- float multiplier;
- const ppc_config *config = _config;
- int i;
-
- ppc_init();
- ppcdrc_init();
-
- ppc.optable[48] = recompile_lfs;
- ppc.optable[49] = recompile_lfsu;
- ppc.optable[50] = recompile_lfd;
- ppc.optable[51] = recompile_lfdu;
- ppc.optable[52] = recompile_stfs;
- ppc.optable[53] = recompile_stfsu;
- ppc.optable[54] = recompile_stfd;
- ppc.optable[55] = recompile_stfdu;
- ppc.optable31[631] = recompile_lfdux;
- ppc.optable31[599] = recompile_lfdx;
- ppc.optable31[567] = recompile_lfsux;
- ppc.optable31[535] = recompile_lfsx;
- ppc.optable31[595] = recompile_mfsr;
- ppc.optable31[659] = recompile_mfsrin;
- ppc.optable31[371] = recompile_mftb;
- ppc.optable31[210] = recompile_mtsr;
- ppc.optable31[242] = recompile_mtsrin;
- ppc.optable31[758] = recompile_dcba;
- ppc.optable31[759] = recompile_stfdux;
- ppc.optable31[727] = recompile_stfdx;
- ppc.optable31[983] = recompile_stfiwx;
- ppc.optable31[695] = recompile_stfsux;
- ppc.optable31[663] = recompile_stfsx;
- ppc.optable31[370] = recompile_tlbia;
- ppc.optable31[306] = recompile_tlbie;
- ppc.optable31[566] = recompile_tlbsync;
- ppc.optable31[310] = recompile_eciwx;
- ppc.optable31[438] = recompile_ecowx;
-
- ppc.optable63[264] = recompile_fabsx;
- ppc.optable63[21] = recompile_faddx;
- ppc.optable63[32] = recompile_fcmpo;
- ppc.optable63[0] = recompile_fcmpu;
- ppc.optable63[14] = recompile_fctiwx;
- ppc.optable63[15] = recompile_fctiwzx;
- ppc.optable63[18] = recompile_fdivx;
- ppc.optable63[72] = recompile_fmrx;
- ppc.optable63[136] = recompile_fnabsx;
- ppc.optable63[40] = recompile_fnegx;
- ppc.optable63[12] = recompile_frspx;
- ppc.optable63[26] = recompile_frsqrtex;
- ppc.optable63[22] = recompile_fsqrtx;
- ppc.optable63[20] = recompile_fsubx;
- ppc.optable63[583] = recompile_mffsx;
- ppc.optable63[70] = recompile_mtfsb0x;
- ppc.optable63[38] = recompile_mtfsb1x;
- ppc.optable63[711] = recompile_mtfsfx;
- ppc.optable63[134] = recompile_mtfsfix;
- ppc.optable63[64] = recompile_mcrfs;
-
- ppc.optable59[21] = recompile_faddsx;
- ppc.optable59[18] = recompile_fdivsx;
- ppc.optable59[24] = recompile_fresx;
- ppc.optable59[22] = recompile_fsqrtsx;
- ppc.optable59[20] = recompile_fsubsx;
-
- for(i = 0; i < 32; i++)
- {
- ppc.optable63[i * 32 | 29] = recompile_fmaddx;
- ppc.optable63[i * 32 | 28] = recompile_fmsubx;
- ppc.optable63[i * 32 | 25] = recompile_fmulx;
- ppc.optable63[i * 32 | 31] = recompile_fnmaddx;
- ppc.optable63[i * 32 | 30] = recompile_fnmsubx;
- ppc.optable63[i * 32 | 23] = recompile_fselx;
-
- ppc.optable59[i * 32 | 29] = recompile_fmaddsx;
- ppc.optable59[i * 32 | 28] = recompile_fmsubsx;
- ppc.optable59[i * 32 | 25] = recompile_fmulsx;
- ppc.optable59[i * 32 | 31] = recompile_fnmaddsx;
- ppc.optable59[i * 32 | 30] = recompile_fnmsubsx;
- }
-
- ppc.optable31[978] = recompile_tlbld;
-
- for(i = 0; i < 256; i++)
- {
- ppc_field_xlat[i] =
- ((i & 0x80) ? 0xF0000000 : 0) |
- ((i & 0x40) ? 0x0F000000 : 0) |
- ((i & 0x20) ? 0x00F00000 : 0) |
- ((i & 0x10) ? 0x000F0000 : 0) |
- ((i & 0x08) ? 0x0000F000 : 0) |
- ((i & 0x04) ? 0x00000F00 : 0) |
- ((i & 0x02) ? 0x000000F0 : 0) |
- ((i & 0x01) ? 0x0000000F : 0);
- }
-
- ppc.is603 = 1;
-
- ppc.read8 = program_read_byte_64be;
- ppc.read16 = program_read_word_64be;
- ppc.read32 = program_read_dword_64be;
- ppc.read64 = program_read_qword_64be;
- ppc.write8 = program_write_byte_64be;
- ppc.write16 = program_write_word_64be;
- ppc.write32 = program_write_dword_64be;
- ppc.write64 = program_write_qword_64be;
- ppc.read16_unaligned = ppc_read16_unaligned;
- ppc.read32_unaligned = ppc_read32_unaligned;
- ppc.read64_unaligned = ppc_read64_unaligned;
- ppc.write16_unaligned = ppc_write16_unaligned;
- ppc.write32_unaligned = ppc_write32_unaligned;
- ppc.write64_unaligned = ppc_write64_unaligned;
-
- ppc.irq_callback = irqcallback;
-
- ppc.pvr = config->pvr;
-
- multiplier = (float)((config->bus_frequency_multiplier >> 4) & 0xf) +
- (float)(config->bus_frequency_multiplier & 0xf) / 10.0f;
- bus_freq_multiplier = (int)(multiplier * 2);
-}
-
-static void ppc604drc_exit(void)
-{
-#if LOG_CODE
- //if (symfile) fclose(symfile);
-#endif
- ppcdrc_exit();
-}
-#endif
-
-
-static void ppc_get_context(void *dst)
-{
- /* copy the context */
- if (dst)
- *(PPC_REGS *)dst = ppc;
-}
-
-
-static void ppc_set_context(void *src)
-{
- /* copy the context */
- if (src)
- ppc = *(PPC_REGS *)src;
-
- change_pc(ppc.pc);
-}
-
-
-/**************************************************************************
- * Generic set_info
- **************************************************************************/
-
-static void ppc_set_info(UINT32 state, cpuinfo *info)
-{
- switch (state)
- {
- case CPUINFO_INT_PC:
- case CPUINFO_INT_REGISTER + PPC_PC: ppc.pc = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_MSR: ppc_set_msr(info->i); break;
- case CPUINFO_INT_REGISTER + PPC_CR: ppc_set_cr(info->i); break;
- case CPUINFO_INT_REGISTER + PPC_LR: LR = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_CTR: CTR = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_XER: XER = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_SRR0: SRR0 = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_SRR1: SRR1 = info->i; break;
-
- case CPUINFO_INT_REGISTER + PPC_R0: ppc.r[0] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R1: ppc.r[1] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R2: ppc.r[2] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R3: ppc.r[3] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R4: ppc.r[4] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R5: ppc.r[5] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R6: ppc.r[6] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R7: ppc.r[7] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R8: ppc.r[8] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R9: ppc.r[9] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R10: ppc.r[10] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R11: ppc.r[11] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R12: ppc.r[12] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R13: ppc.r[13] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R14: ppc.r[14] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R15: ppc.r[15] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R16: ppc.r[16] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R17: ppc.r[17] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R18: ppc.r[18] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R19: ppc.r[19] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R20: ppc.r[20] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R21: ppc.r[21] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R22: ppc.r[22] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R23: ppc.r[23] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R24: ppc.r[24] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R25: ppc.r[25] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R26: ppc.r[26] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R27: ppc.r[27] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R28: ppc.r[28] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R29: ppc.r[29] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R30: ppc.r[30] = info->i; break;
- case CPUINFO_INT_REGISTER + PPC_R31: ppc.r[31] = info->i; break;
-
- case CPUINFO_INT_PPC_DRC_OPTIONS: ppc.drcoptions = info->i; break;
- }
-}
-
-static void ppc_get_info(UINT32 state, cpuinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ppc); break;
- case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
- case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
- case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
- case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
- case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
- case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
- case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
- case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
- case CPUINFO_INT_MAX_CYCLES: info->i = 40; break;
-
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
- case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
- case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
- case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
-
- case CPUINFO_INT_INPUT_STATE: info->i = CLEAR_LINE; break;
-
- case CPUINFO_INT_PREVIOUSPC: /* not implemented */ break;
-
- case CPUINFO_INT_PC: /* intentional fallthrough */
- case CPUINFO_INT_REGISTER + PPC_PC: info->i = ppc.pc; break;
- case CPUINFO_INT_REGISTER + PPC_MSR: info->i = ppc_get_msr(); break;
- case CPUINFO_INT_REGISTER + PPC_CR: info->i = ppc_get_cr(); break;
- case CPUINFO_INT_REGISTER + PPC_LR: info->i = LR; break;
- case CPUINFO_INT_REGISTER + PPC_CTR: info->i = CTR; break;
- case CPUINFO_INT_REGISTER + PPC_XER: info->i = XER; break;
- case CPUINFO_INT_REGISTER + PPC_SRR0: info->i = SRR0; break;
- case CPUINFO_INT_REGISTER + PPC_SRR1: info->i = SRR1; break;
-
- case CPUINFO_INT_REGISTER + PPC_R0: info->i = ppc.r[0]; break;
- case CPUINFO_INT_REGISTER + PPC_R1: info->i = ppc.r[1]; break;
- case CPUINFO_INT_REGISTER + PPC_R2: info->i = ppc.r[2]; break;
- case CPUINFO_INT_REGISTER + PPC_R3: info->i = ppc.r[3]; break;
- case CPUINFO_INT_REGISTER + PPC_R4: info->i = ppc.r[4]; break;
- case CPUINFO_INT_REGISTER + PPC_R5: info->i = ppc.r[5]; break;
- case CPUINFO_INT_REGISTER + PPC_R6: info->i = ppc.r[6]; break;
- case CPUINFO_INT_REGISTER + PPC_R7: info->i = ppc.r[7]; break;
- case CPUINFO_INT_REGISTER + PPC_R8: info->i = ppc.r[8]; break;
- case CPUINFO_INT_REGISTER + PPC_R9: info->i = ppc.r[9]; break;
- case CPUINFO_INT_REGISTER + PPC_R10: info->i = ppc.r[10]; break;
- case CPUINFO_INT_REGISTER + PPC_R11: info->i = ppc.r[11]; break;
- case CPUINFO_INT_REGISTER + PPC_R12: info->i = ppc.r[12]; break;
- case CPUINFO_INT_REGISTER + PPC_R13: info->i = ppc.r[13]; break;
- case CPUINFO_INT_REGISTER + PPC_R14: info->i = ppc.r[14]; break;
- case CPUINFO_INT_REGISTER + PPC_R15: info->i = ppc.r[15]; break;
- case CPUINFO_INT_REGISTER + PPC_R16: info->i = ppc.r[16]; break;
- case CPUINFO_INT_REGISTER + PPC_R17: info->i = ppc.r[17]; break;
- case CPUINFO_INT_REGISTER + PPC_R18: info->i = ppc.r[18]; break;
- case CPUINFO_INT_REGISTER + PPC_R19: info->i = ppc.r[19]; break;
- case CPUINFO_INT_REGISTER + PPC_R20: info->i = ppc.r[20]; break;
- case CPUINFO_INT_REGISTER + PPC_R21: info->i = ppc.r[21]; break;
- case CPUINFO_INT_REGISTER + PPC_R22: info->i = ppc.r[22]; break;
- case CPUINFO_INT_REGISTER + PPC_R23: info->i = ppc.r[23]; break;
- case CPUINFO_INT_REGISTER + PPC_R24: info->i = ppc.r[24]; break;
- case CPUINFO_INT_REGISTER + PPC_R25: info->i = ppc.r[25]; break;
- case CPUINFO_INT_REGISTER + PPC_R26: info->i = ppc.r[26]; break;
- case CPUINFO_INT_REGISTER + PPC_R27: info->i = ppc.r[27]; break;
- case CPUINFO_INT_REGISTER + PPC_R28: info->i = ppc.r[28]; break;
- case CPUINFO_INT_REGISTER + PPC_R29: info->i = ppc.r[29]; break;
- case CPUINFO_INT_REGISTER + PPC_R30: info->i = ppc.r[30]; break;
- case CPUINFO_INT_REGISTER + PPC_R31: info->i = ppc.r[31]; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_GET_CONTEXT: info->getcontext = ppc_get_context; break;
- case CPUINFO_PTR_SET_CONTEXT: info->setcontext = ppc_set_context; break;
- case CPUINFO_PTR_BURN: info->burn = NULL; break;
-#ifdef ENABLE_DEBUGGER
- case CPUINFO_PTR_DISASSEMBLE: info->disassemble = ppc_dasm; break;
-#endif /* ENABLE_DEBUGGER */
- case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ppc_icount; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case CPUINFO_STR_NAME: strcpy(info->s, "PPC403"); break;
- case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "PowerPC"); break;
- case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.0"); break;
- case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
- case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break;
-
- case CPUINFO_STR_FLAGS: strcpy(info->s, " "); break;
-
- 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_get_msr()); break;
- case CPUINFO_STR_REGISTER + PPC_CR: sprintf(info->s, "CR: %08X", ppc_get_cr()); break;
- case CPUINFO_STR_REGISTER + PPC_LR: sprintf(info->s, "LR: %08X", LR); break;
- case CPUINFO_STR_REGISTER + PPC_CTR: sprintf(info->s, "CTR: %08X", CTR); break;
- case CPUINFO_STR_REGISTER + PPC_XER: sprintf(info->s, "XER: %08X", XER); break;
- case CPUINFO_STR_REGISTER + PPC_SRR0: sprintf(info->s, "SRR0: %08X", SRR0); break;
- case CPUINFO_STR_REGISTER + PPC_SRR1: sprintf(info->s, "SRR1: %08X", SRR1); break;
-
- case CPUINFO_STR_REGISTER + PPC_R0: sprintf(info->s, "R0: %08X", ppc.r[0]); break;
- case CPUINFO_STR_REGISTER + PPC_R1: sprintf(info->s, "R1: %08X", ppc.r[1]); break;
- case CPUINFO_STR_REGISTER + PPC_R2: sprintf(info->s, "R2: %08X", ppc.r[2]); break;
- case CPUINFO_STR_REGISTER + PPC_R3: sprintf(info->s, "R3: %08X", ppc.r[3]); break;
- case CPUINFO_STR_REGISTER + PPC_R4: sprintf(info->s, "R4: %08X", ppc.r[4]); break;
- case CPUINFO_STR_REGISTER + PPC_R5: sprintf(info->s, "R5: %08X", ppc.r[5]); break;
- case CPUINFO_STR_REGISTER + PPC_R6: sprintf(info->s, "R6: %08X", ppc.r[6]); break;
- case CPUINFO_STR_REGISTER + PPC_R7: sprintf(info->s, "R7: %08X", ppc.r[7]); break;
- case CPUINFO_STR_REGISTER + PPC_R8: sprintf(info->s, "R8: %08X", ppc.r[8]); break;
- case CPUINFO_STR_REGISTER + PPC_R9: sprintf(info->s, "R9: %08X", ppc.r[9]); break;
- case CPUINFO_STR_REGISTER + PPC_R10: sprintf(info->s, "R10: %08X", ppc.r[10]); break;
- case CPUINFO_STR_REGISTER + PPC_R11: sprintf(info->s, "R11: %08X", ppc.r[11]); break;
- case CPUINFO_STR_REGISTER + PPC_R12: sprintf(info->s, "R12: %08X", ppc.r[12]); break;
- case CPUINFO_STR_REGISTER + PPC_R13: sprintf(info->s, "R13: %08X", ppc.r[13]); break;
- case CPUINFO_STR_REGISTER + PPC_R14: sprintf(info->s, "R14: %08X", ppc.r[14]); break;
- case CPUINFO_STR_REGISTER + PPC_R15: sprintf(info->s, "R15: %08X", ppc.r[15]); break;
- case CPUINFO_STR_REGISTER + PPC_R16: sprintf(info->s, "R16: %08X", ppc.r[16]); break;
- case CPUINFO_STR_REGISTER + PPC_R17: sprintf(info->s, "R17: %08X", ppc.r[17]); break;
- case CPUINFO_STR_REGISTER + PPC_R18: sprintf(info->s, "R18: %08X", ppc.r[18]); break;
- case CPUINFO_STR_REGISTER + PPC_R19: sprintf(info->s, "R19: %08X", ppc.r[19]); break;
- case CPUINFO_STR_REGISTER + PPC_R20: sprintf(info->s, "R20: %08X", ppc.r[20]); break;
- case CPUINFO_STR_REGISTER + PPC_R21: sprintf(info->s, "R21: %08X", ppc.r[21]); break;
- case CPUINFO_STR_REGISTER + PPC_R22: sprintf(info->s, "R22: %08X", ppc.r[22]); break;
- case CPUINFO_STR_REGISTER + PPC_R23: sprintf(info->s, "R23: %08X", ppc.r[23]); break;
- case CPUINFO_STR_REGISTER + PPC_R24: sprintf(info->s, "R24: %08X", ppc.r[24]); break;
- case CPUINFO_STR_REGISTER + PPC_R25: sprintf(info->s, "R25: %08X", ppc.r[25]); break;
- case CPUINFO_STR_REGISTER + PPC_R26: sprintf(info->s, "R26: %08X", ppc.r[26]); break;
- case CPUINFO_STR_REGISTER + PPC_R27: sprintf(info->s, "R27: %08X", ppc.r[27]); break;
- case CPUINFO_STR_REGISTER + PPC_R28: sprintf(info->s, "R28: %08X", ppc.r[28]); break;
- case CPUINFO_STR_REGISTER + PPC_R29: sprintf(info->s, "R29: %08X", ppc.r[29]); break;
- case CPUINFO_STR_REGISTER + PPC_R30: sprintf(info->s, "R30: %08X", ppc.r[30]); break;
- case CPUINFO_STR_REGISTER + PPC_R31: sprintf(info->s, "R31: %08X", ppc.r[31]); break;
- }
-}
-
-
-
-/* PowerPC 403 */
-#if (HAS_PPC403)
-static void ppc403_set_info(UINT32 state, cpuinfo *info)
-{
- if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
- {
- ppcdrc403_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
- return;
- }
- switch(state)
- {
- default: ppc_set_info(state, info); break;
- }
-}
-
-void ppc403_get_info(UINT32 state, cpuinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_INPUT_LINES: info->i = 7; break;
- case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_SET_INFO: info->setinfo = ppc403_set_info; break;
- case CPUINFO_PTR_INIT: info->init = ppcdrc403_init; break;
- case CPUINFO_PTR_RESET: info->reset = ppcdrc403_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = ppcdrc403_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = ppcdrc403_execute; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case CPUINFO_STR_NAME: strcpy(info->s, "PPC403"); break;
-
- default: ppc_get_info(state, info); break;
- }
-}
-#endif
-
-/* PowerPC 603 */
-#if (HAS_PPC603)
-static void ppc603_set_info(UINT32 state, cpuinfo *info)
-{
- if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
- {
- ppcdrc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
- return;
- }
- switch(state)
- {
- case CPUINFO_INT_REGISTER + PPC_DEC: write_decrementer(info->i); break;
- default: ppc_set_info(state, info); break;
- }
-}
-
-void ppc603_get_info(UINT32 state, cpuinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
- case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
- case CPUINFO_INT_REGISTER + PPC_DEC: info->i = read_decrementer(); break;
-
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
- case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
- case CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 17; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_SET_INFO: info->setinfo = ppc603_set_info; break;
- case CPUINFO_PTR_INIT: info->init = ppcdrc603_init; break;
- case CPUINFO_PTR_RESET: info->reset = ppcdrc603_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = ppcdrc603_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = ppcdrc603_execute; break;
- case CPUINFO_PTR_READ: info->read = ppc_read; break;
- case CPUINFO_PTR_WRITE: info->write = ppc_write; break;
- case CPUINFO_PTR_READOP: info->readop = ppc_readop; break;
- case CPUINFO_PTR_TRANSLATE: info->translate = ppc_translate_address_cb; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case CPUINFO_STR_NAME: strcpy(info->s, "PPC603"); break;
- case CPUINFO_STR_REGISTER + PPC_DEC: sprintf(info->s, "DEC: %08X", read_decrementer()); break;
-
- default: ppc_get_info(state, info); break;
- }
-}
-#endif
-
-/* PowerPC 602 */
-#if (HAS_PPC602)
-static void ppc602_set_info(UINT32 state, cpuinfo *info)
-{
- if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
- {
- ppcdrc602_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
- return;
- }
- switch(state)
- {
- default: ppc_set_info(state, info); break;
- }
-}
-
-void ppc602_get_info(UINT32 state, cpuinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
- case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
-
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
- case CPUINFO_INT_LOGADDR_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
- case CPUINFO_INT_PAGE_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 17; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_SET_INFO: info->setinfo = ppc602_set_info; break;
- case CPUINFO_PTR_INIT: info->init = ppcdrc602_init; break;
- case CPUINFO_PTR_RESET: info->reset = ppcdrc602_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = ppcdrc602_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = ppcdrc602_execute; break;
- case CPUINFO_PTR_READ: info->read = ppc_read; break;
- case CPUINFO_PTR_WRITE: info->write = ppc_write; break;
- case CPUINFO_PTR_READOP: info->readop = ppc_readop; break;
- case CPUINFO_PTR_TRANSLATE: info->translate = ppc_translate_address_cb; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case CPUINFO_STR_NAME: strcpy(info->s, "PPC602"); break;
-
- default: ppc_get_info(state, info); break;
- }
-}
-#endif
-
-/* Motorola MPC8240 */
-
-#if (HAS_MPC8240)
-static void mpc8240_set_info(UINT32 state, cpuinfo *info)
-{
- if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
- {
- ppcdrc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
- return;
- }
- switch(state)
- {
- default: ppc_set_info(state, info); break;
- }
-}
-
-void mpc8240_get_info(UINT32 state, cpuinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
- case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
-
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_SET_INFO: info->setinfo = mpc8240_set_info; break;
- case CPUINFO_PTR_INIT: info->init = mpc8240drc_init; break;
- case CPUINFO_PTR_RESET: info->reset = ppcdrc603_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = mpc8240drc_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = ppcdrc603_execute; break;
- case CPUINFO_PTR_READ: info->read = ppc_read; break;
- case CPUINFO_PTR_WRITE: info->write = ppc_write; break;
- case CPUINFO_PTR_READOP: info->readop = ppc_readop; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case CPUINFO_STR_NAME: strcpy(info->s, "MPC8240"); break;
-
- default: ppc_get_info(state, info); break;
- }
-}
-#endif
-
-
-/* PPC601 */
-
-#if (HAS_PPC601)
-static void ppc601_set_info(UINT32 state, cpuinfo *info)
-{
- if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
- {
- ppcdrc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
- return;
- }
- switch(state)
- {
- default: ppc_set_info(state, info); break;
- }
-}
-
-void ppc601_get_info(UINT32 state, cpuinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
- case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
-
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_SET_INFO: info->setinfo = ppc601_set_info; break;
- case CPUINFO_PTR_INIT: info->init = ppc601drc_init; break;
- case CPUINFO_PTR_RESET: info->reset = ppcdrc603_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = ppc601drc_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = ppcdrc603_execute; break;
- case CPUINFO_PTR_READ: info->read = ppc_read; break;
- case CPUINFO_PTR_WRITE: info->write = ppc_write; break;
- case CPUINFO_PTR_READOP: info->readop = ppc_readop; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case CPUINFO_STR_NAME: strcpy(info->s, "PPC601"); break;
-
- default: ppc_get_info(state, info); break;
- }
-}
-#endif
-
-/* PPC604 */
-
-#if (HAS_PPC604)
-static void ppc604_set_info(UINT32 state, cpuinfo *info)
-{
- if (state >= CPUINFO_INT_INPUT_STATE && state <= CPUINFO_INT_INPUT_STATE + 5)
- {
- ppcdrc603_set_irq_line(state-CPUINFO_INT_INPUT_STATE, info->i);
- return;
- }
- switch(state)
- {
- default: ppc_set_info(state, info); break;
- }
-}
-
-void ppc604_get_info(UINT32 state, cpuinfo *info)
-{
- switch(state)
- {
- /* --- the following bits of info are returned as 64-bit signed integers --- */
- case CPUINFO_INT_INPUT_LINES: info->i = 5; break;
- case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
-
- case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 64; break;
- case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
-
- /* --- the following bits of info are returned as pointers to data or functions --- */
- case CPUINFO_PTR_SET_INFO: info->setinfo = ppc604_set_info; break;
- case CPUINFO_PTR_INIT: info->init = ppc604drc_init; break;
- case CPUINFO_PTR_RESET: info->reset = ppcdrc603_reset; break;
- case CPUINFO_PTR_EXIT: info->exit = ppc604drc_exit; break;
- case CPUINFO_PTR_EXECUTE: info->execute = ppcdrc603_execute; break;
- case CPUINFO_PTR_READ: info->read = ppc_read; break;
- case CPUINFO_PTR_WRITE: info->write = ppc_write; break;
- case CPUINFO_PTR_READOP: info->readop = ppc_readop; break;
-
- /* --- the following bits of info are returned as NULL-terminated strings --- */
- case CPUINFO_STR_NAME: strcpy(info->s, "PPC604"); break;
-
- default: ppc_get_info(state, info); break;
- }
-}
-#endif
diff --git a/src/emu/cpu/powerpc/ppcfe.c b/src/emu/cpu/powerpc/ppcfe.c
new file mode 100644
index 00000000000..f232793e0d1
--- /dev/null
+++ b/src/emu/cpu/powerpc/ppcfe.c
@@ -0,0 +1,942 @@
+/***************************************************************************
+
+ ppcfe.c
+
+ Front-end for PowerPC recompiler
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#include <stddef.h>
+#include "cpuintrf.h"
+#include "ppcfe.h"
+#include "ppccom.h"
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+static int describe_instruction_13(powerpc_state *ppc, UINT32 op, opcode_desc *desc);
+static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *desc);
+static int describe_instruction_3b(powerpc_state *ppc, UINT32 op, opcode_desc *desc);
+static int describe_instruction_3f(powerpc_state *ppc, UINT32 op, opcode_desc *desc);
+
+
+
+/***************************************************************************
+ INSTRUCTION PARSERS
+***************************************************************************/
+
+/*-------------------------------------------------
+ ppcfe_describe - build a description
+ of a single instruction
+-------------------------------------------------*/
+
+int ppcfe_describe(void *param, opcode_desc *desc)
+{
+ powerpc_state *ppc = param;
+ UINT32 op = *desc->opptr.l;
+ UINT32 opswitch = op >> 26;
+
+ /* all instructions are 4 bytes and default to a single cycle each */
+ desc->length = 4;
+ desc->cycles = 1;
+
+ /* parse the instruction */
+ switch (opswitch)
+ {
+ case 0x02: /* TDI - 64-bit only */
+ case 0x1e: /* 0x1e group - 64-bit only */
+ case 0x3a: /* 0x3a group - 64-bit only */
+ case 0x3e: /* 0x3e group - 64-bit only */
+ return FALSE;
+
+ case 0x03: /* TWI */
+ desc->gpr.used |= REGFLAG_R(G_RA(op));
+ desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x07: /* MULLI */
+ desc->gpr.used |= REGFLAG_R(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ return TRUE;
+
+ case 0x0e: /* ADDI */
+ case 0x0f: /* ADDIS */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ return TRUE;
+
+ case 0x0a: /* CMPLI */
+ case 0x0b: /* CMPI */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(G_CRFD(op));
+ return TRUE;
+
+ case 0x08: /* SUBFIC */
+ case 0x0c: /* ADDIC */
+ desc->gpr.used |= REGFLAG_R(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op)) | REGFLAG_XER;
+ return TRUE;
+
+ case 0x0d: /* ADDIC. */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_R(G_RT(op)) | REGFLAG_CR(0) | REGFLAG_XER;
+ return TRUE;
+
+ case 0x10: /* BCx */
+ desc->gpr.used |= REGFLAG_CR(G_BI(op) / 4);
+ if (op & M_LK) desc->gpr.modified |= REGFLAG_LR;
+ if (!(G_BO(op) & 4))
+ {
+ desc->gpr.used |= REGFLAG_CTR;
+ desc->gpr.modified |= REGFLAG_CTR;
+ }
+ if ((G_BO(op) & 0x14) == 0x14)
+ desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc->targetpc = (INT16)(G_BD(op) << 2) + ((op & M_AA) ? 0 : desc->pc);
+ return TRUE;
+
+ case 0x11: /* SC */
+ if (!(ppc->cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return FALSE;
+ desc->flags |= OPFLAG_WILL_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x12: /* Bx */
+ if (op & M_LK) desc->gpr.modified |= REGFLAG_LR;
+ desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ desc->targetpc = ((INT32)(G_LI(op) << 8) >> 6) + ((op & M_AA) ? 0 : desc->pc);
+ return TRUE;
+
+ case 0x13: /* 0x13 group */
+ return describe_instruction_13(ppc, op, desc);
+
+ case 0x14: /* RLWIMIx */
+ desc->gpr.used |= REGFLAG_R(G_RS(op)) | REGFLAG_R(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(0);
+ }
+ return TRUE;
+
+ case 0x15: /* RLWINMx */
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(0);
+ }
+ return TRUE;
+
+ case 0x17: /* RLWNMx */
+ desc->gpr.used |= REGFLAG_R(G_RS(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(0);
+ }
+ return TRUE;
+
+ case 0x18: /* ORI */
+ case 0x19: /* ORIS */
+ case 0x1a: /* XORI */
+ case 0x1b: /* XORIS */
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ return TRUE;
+
+ case 0x1c: /* ANDI. */
+ case 0x1d: /* ANDIS. */
+ desc->gpr.used |= REGFLAG_R(G_RS(op)) | REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_R(G_RA(op)) | REGFLAG_CR(0);
+ return TRUE;
+
+ case 0x1f: /* 0x1f group */
+ return describe_instruction_1f(ppc, op, desc);
+
+ case 0x20: /* LWZ */
+ case 0x22: /* LBZ */
+ case 0x28: /* LHZ */
+ case 0x2a: /* LHA */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x21: /* LWZU */
+ case 0x23: /* LBZU */
+ case 0x29: /* LHZU */
+ case 0x2b: /* LHAU */
+ if (G_RA(op) == 0)
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op)) | REGFLAG_R(G_RA(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x24: /* STW */
+ case 0x26: /* STB */
+ case 0x2c: /* STH */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x25: /* STWU */
+ case 0x27: /* STBU */
+ case 0x2d: /* STHU */
+ if (G_RA(op) == 0)
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RS(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x2e: /* LMW */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op));
+ desc->gpr.modified |= ((REGFLAG_R(31) << 1) - 1) & ~(REGFLAG_R(G_RD(op)) - 1);
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x2f: /* STMW */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | (((REGFLAG_R(31) << 1) - 1) & ~(REGFLAG_R(G_RS(op)) - 1));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x30: /* LFS */
+ case 0x32: /* LFD */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x31: /* LFSU */
+ case 0x33: /* LFDU */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x34: /* STFS */
+ case 0x36: /* STFD */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op));
+ desc->fpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x35: /* STFSU */
+ case 0x37: /* STFDU */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ desc->fpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x3b: /* 0x3b group */
+ return describe_instruction_3b(ppc, op, desc);
+
+ case 0x3f: /* 0x3f group */
+ return describe_instruction_3f(ppc, op, desc);
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_13 - build a
+ description of a single instruction in the
+ 0x13 group
+-------------------------------------------------*/
+
+static int describe_instruction_13(powerpc_state *ppc, UINT32 op, opcode_desc *desc)
+{
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ switch (opswitch)
+ {
+ case 0x000: /* MTCRF */
+ desc->gpr.used |= REGFLAG_CR(G_CRFS(op));
+ desc->gpr.modified |= REGFLAG_CR(G_CRFD(op));
+ return TRUE;
+
+ case 0x010: /* BCLRx */
+ desc->gpr.used |= REGFLAG_CR(G_BI(op) / 4) | REGFLAG_LR;
+ if (op & M_LK) desc->gpr.modified |= REGFLAG_LR;
+ if (!(G_BO(op) & 4))
+ {
+ desc->gpr.used |= REGFLAG_CTR;
+ desc->gpr.modified |= REGFLAG_CTR;
+ }
+ if ((G_BO(op) & 0x14) == 0x14)
+ desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc->targetpc = BRANCH_TARGET_DYNAMIC;
+ return TRUE;
+
+ case 0x021: /* CRNOR */
+ case 0x081: /* CRANDC */
+ case 0x0c1: /* CRXOR */
+ case 0x0e1: /* CRNAND */
+ case 0x101: /* CRAND */
+ case 0x121: /* CREQV */
+ case 0x1a1: /* CRORC */
+ case 0x1c1: /* CROR */
+ desc->gpr.used |= REGFLAG_CR(G_CRBA(op) / 4) | REGFLAG_CR(G_CRBB(op) / 4);
+ desc->gpr.modified |= REGFLAG_CR(G_CRBD(op) / 4);
+ return TRUE;
+
+ case 0x032: /* RFI */
+ if (!(ppc->cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return FALSE;
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION;
+ desc->targetpc = BRANCH_TARGET_DYNAMIC;
+ return TRUE;
+
+ case 0x033: /* RFCI */
+ if (!(ppc->cap & PPCCAP_4XX))
+ return FALSE;
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CHANGE_MODES | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_CAN_CAUSE_EXCEPTION;
+ desc->targetpc = BRANCH_TARGET_DYNAMIC;
+ return TRUE;
+
+ case 0x096: /* ISYNC */
+ if (!(ppc->cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return FALSE;
+ return TRUE;
+
+ case 0x210: /* BCCTRx */
+ desc->gpr.used |= REGFLAG_CR(G_BI(op) / 4) | REGFLAG_CTR;
+ if (op & M_LK) desc->gpr.modified |= REGFLAG_LR;
+ if ((G_BO(op) & 0x14) == 0x14)
+ desc->flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
+ else
+ desc->flags |= OPFLAG_IS_CONDITIONAL_BRANCH;
+ desc->targetpc = BRANCH_TARGET_DYNAMIC;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_1f - build a
+ description of a single instruction in the
+ 0x1f group
+-------------------------------------------------*/
+
+static int describe_instruction_1f(powerpc_state *ppc, UINT32 op, opcode_desc *desc)
+{
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ switch (opswitch)
+ {
+ case 0x009: /* MULHDUx - 64-bit only */
+ case 0x015: /* LDX - 64-bit only */
+ case 0x01b: /* SLDx - 64-bit only */
+ case 0x035: /* LDUX - 64-bit only */
+ case 0x03a: /* CNTLZDx - 64-bit only */
+ case 0x044: /* TD - 64-bit only */
+ case 0x049: /* MULHDx - 64-bit only */
+ case 0x054: /* LDARX - 64-bit only */
+ case 0x095: /* STDX - 64-bit only */
+ case 0x0b5: /* STDUX - 64-bit only */
+ case 0x0d6: /* STDCX. - 64-bit only */
+ case 0x0e9: /* MULLD - 64-bit only */
+ case 0x2e9: /* MULLDO - 64-bit only */
+ case 0x155: /* LWAX - 64-bit only */
+ case 0x175: /* LWAUX - 64-bit only */
+ case 0x33a: /* SRADIx - 64-bit only */
+ case 0x33b: /* SRADIx - 64-bit only */
+ case 0x1b2: /* SLBIE - 64-bit only */
+ case 0x1c9: /* DIVDUx - 64-bit only */
+ case 0x3c9: /* DIVDUOx - 64-bit only */
+ case 0x1e9: /* DIVDx - 64-bit only */
+ case 0x3e9: /* DIVDOx - 64-bit only */
+ case 0x1f2: /* SLBIA - 64-bit only */
+ case 0x21b: /* SRDx - 64-bit only */
+ case 0x31a: /* SRADx - 64-bit only */
+ case 0x3da: /* EXTSW - 64-bit only */
+ return FALSE;
+
+ case 0x000: /* CMP */
+ case 0x020: /* CMPL */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op)) | REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(G_CRFD(op));
+ return TRUE;
+
+ case 0x004: /* TW */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->flags |= OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x008: /* SUBFCx */
+ case 0x00a: /* ADDCx */
+ case 0x00b: /* MULHWUx */
+ case 0x028: /* SUBFx */
+ case 0x04b: /* MULHWx */
+ case 0x088: /* SUBFEx */
+ case 0x08a: /* ADDEx */
+ case 0x0c8: /* SUBFZEx */
+ case 0x0ca: /* ADDZEx */
+ case 0x0e8: /* SUBFMEx */
+ case 0x0ea: /* ADDMEx */
+ case 0x0eb: /* MULLWx */
+ case 0x10a: /* ADDx */
+ case 0x1cb: /* DIVWUx */
+ case 0x1eb: /* DIVWx */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(0);
+ }
+ return TRUE;
+
+ case 0x208: /* SUBFCOx */
+ case 0x20a: /* ADDCOx */
+ case 0x228: /* SUBFOx */
+ case 0x288: /* SUBFEOx */
+ case 0x28a: /* ADDEOx */
+ case 0x2c8: /* SUBFZEOx */
+ case 0x2ca: /* ADDZEOx */
+ case 0x2e8: /* SUBFMEOx */
+ case 0x2ea: /* ADDMEOx */
+ case 0x2eb: /* MULLWOx */
+ case 0x30a: /* ADDOx */
+ case 0x3cb: /* DIVWUOx */
+ case 0x3eb: /* DIVWOx */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op)) | REGFLAG_XER;
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(0);
+ }
+ return TRUE;
+
+ case 0x013: /* MFCR */
+ desc->gpr.used |= ((REGFLAG_CR(7) << 1) - 1) & ~(REGFLAG_CR(0) - 1);
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ return TRUE;
+
+ case 0x136: /* ECIWX */
+ if (!(ppc->cap & PPCCAP_VEA))
+ return FALSE;
+ case 0x014: /* LWARX */
+ case 0x017: /* LWZX */
+ case 0x057: /* LBZX */
+ case 0x117: /* LHZX */
+ case 0x157: /* LHAX */
+ case 0x216: /* LWBRX */
+ case 0x316: /* LHBRX */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x018: /* SLWx */
+ case 0x01c: /* ANDx */
+ case 0x03c: /* ANDCx */
+ case 0x07c: /* NORx */
+ case 0x11c: /* EQVx */
+ case 0x13c: /* XORx */
+ case 0x19c: /* ORCx */
+ case 0x1bc: /* ORx */
+ case 0x1dc: /* NANDx */
+ case 0x218: /* SRWx */
+ case 0x318: /* SRAWx */
+ desc->gpr.used |= REGFLAG_RZ(G_RS(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ return TRUE;
+
+ case 0x01a: /* CNTLZWx */
+ case 0x39a: /* EXTSHx */
+ case 0x3ba: /* EXTSBx */
+ desc->gpr.used |= REGFLAG_RZ(G_RS(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ return TRUE;
+
+ case 0x036: /* DCBST */
+ case 0x056: /* DCBF */
+ case 0x0f6: /* DCBTST */
+ case 0x116: /* DCBT */
+ case 0x2f6: /* DCBA */
+ case 0x3d6: /* ICBI */
+ if (!(ppc->cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ return TRUE;
+
+ case 0x1d6: /* DCBI */
+ if (!(ppc->cap & (PPCCAP_OEA | PPCCAP_4XX)))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x037: /* LWZUX */
+ case 0x077: /* LBZUX */
+ case 0x137: /* LHZUX */
+ case 0x177: /* LHAUX */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op)) | REGFLAG_R(G_RA(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x153: /* MFSPR */
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ if (G_SPR(op) & 0x200)
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x053: /* MFMSR */
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return TRUE;
+
+ case 0x253: /* MFSR */
+ case 0x293: /* MFSRIN */
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x173: /* MFTB */
+ if (!(ppc->cap & PPCCAP_VEA))
+ return FALSE;
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ return TRUE;
+
+ case 0x068: /* NEGx */
+ desc->gpr.used |= REGFLAG_R(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(0);
+ }
+ return TRUE;
+
+ case 0x268: /* NEGOx */
+ desc->gpr.used |= REGFLAG_R(G_RA(op));
+ desc->gpr.modified |= REGFLAG_R(G_RD(op)) | REGFLAG_XER;
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(0);
+ }
+ return TRUE;
+
+ case 0x090: /* MTCRF */
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ if (G_CRM(op) & 0x01) desc->gpr.modified |= REGFLAG_CR(0);
+ if (G_CRM(op) & 0x02) desc->gpr.modified |= REGFLAG_CR(1);
+ if (G_CRM(op) & 0x04) desc->gpr.modified |= REGFLAG_CR(2);
+ if (G_CRM(op) & 0x08) desc->gpr.modified |= REGFLAG_CR(3);
+ if (G_CRM(op) & 0x10) desc->gpr.modified |= REGFLAG_CR(4);
+ if (G_CRM(op) & 0x20) desc->gpr.modified |= REGFLAG_CR(5);
+ if (G_CRM(op) & 0x40) desc->gpr.modified |= REGFLAG_CR(6);
+ if (G_CRM(op) & 0x80) desc->gpr.modified |= REGFLAG_CR(7);
+ return TRUE;
+
+ case 0x092: /* MTMSR */
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_CHANGE_MODES | OPFLAG_END_SEQUENCE;
+ return TRUE;
+
+ case 0x0d2: /* MTSR */
+ if (!(ppc->cap & PPCCAP_OEA))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x1d3: /* MTSPR */
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ if (G_SPR(op) & 0x200)
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x1b6: /* ECOWX */
+ if (!(ppc->cap & PPCCAP_VEA))
+ return FALSE;
+ case 0x096: /* STWCX. */
+ case 0x097: /* STWX */
+ case 0x0d7: /* STBX */
+ case 0x197: /* STHX */
+ case 0x296: /* STWBRX */
+ case 0x396: /* STHBRX */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op)) | REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x0b7: /* STWUX */
+ case 0x0f7: /* STBUX */
+ case 0x1b7: /* STHUX */
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op)) | REGFLAG_R(G_RS(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x0f2: /* MTSRIN */
+ if (!(ppc->cap & PPCCAP_OEA))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RS(op)) | REGFLAG_R(G_RB(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x132: /* TLBIE */
+ if (!(ppc->cap & PPCCAP_OEA))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RB(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x172: /* TLBIA */
+ if (!(ppc->cap & PPCCAP_OEA) || (ppc->cap & PPCCAP_603_MMU))
+ return FALSE;
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x3d2: /* TLBLD */
+ case 0x3f2: /* TLBLI */
+ if (!(ppc->cap & PPCCAP_603_MMU))
+ return FALSE;
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x200: /* MCRXR */
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(G_CRFD(op));
+ return TRUE;
+
+ case 0x215: /* LSWX */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op)) | REGFLAG_XER;
+ desc->gpr.modified |= ((REGFLAG_R(31) << 1) - 1) & ~(REGFLAG_R(0) - 1);
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x217: /* LFSX */
+ case 0x257: /* LFDX */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x236: /* TLBSYNC */
+ if (!(ppc->cap & PPCCAP_OEA))
+ return FALSE;
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x256: /* SYNC */
+ return TRUE;
+
+ case 0x356: /* EIEIO */
+ if (!(ppc->cap & PPCCAP_VEA))
+ return FALSE;
+ return TRUE;
+
+ case 0x237: /* LFSUX */
+ case 0x277: /* LFDUX */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x255: /* LSWI */
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= ((REGFLAG_R(31) << 1) - 1) & ~(REGFLAG_R(0) - 1);
+ desc->flags |= OPFLAG_READS_MEMORY;
+ return TRUE;
+
+ case 0x295: /* STSWX */
+ case 0x2d5: /* STSWI */
+ desc->gpr.used |= (((REGFLAG_R(31) << 1) - 1) & ~(REGFLAG_R(0) - 1)) | REGFLAG_XER;
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x297: /* STFSX */
+ case 0x2d7: /* STFDX */
+ case 0x3d7: /* STFIWX */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->fpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x2b7: /* STFSUX */
+ case 0x2f7: /* STFDUX */
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_RZ(G_RA(op));
+ desc->fpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x338: /* SRAWIx */
+ desc->gpr.used |= REGFLAG_RZ(G_RS(op));
+ desc->gpr.modified |= REGFLAG_R(G_RA(op));
+ return TRUE;
+
+ case 0x3f6: /* DCBZ */
+ if (!(ppc->cap & (PPCCAP_VEA | PPCCAP_4XX)))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->flags |= OPFLAG_WRITES_MEMORY;
+ return TRUE;
+
+ case 0x106: /* ICBT */
+ case 0x1c6: /* DCCCI */
+ case 0x3c6: /* ICCCI */
+ if (!(ppc->cap & PPCCAP_4XX))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x1e6: /* DCREAD */
+ case 0x3e6: /* ICREAD */
+ if (!(ppc->cap & PPCCAP_4XX))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_RZ(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_R(G_RT(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x143: /* MFDCR */
+ if (!(ppc->cap & PPCCAP_4XX))
+ return FALSE;
+ desc->gpr.modified |= REGFLAG_R(G_RD(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION;
+ return TRUE;
+
+ case 0x1c3: /* MTDCR */
+ if (!(ppc->cap & PPCCAP_4XX))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_PRIVILEGED | OPFLAG_CAN_CAUSE_EXCEPTION | OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return TRUE;
+
+ case 0x083: /* WRTEE */
+ if (!(ppc->cap & PPCCAP_4XX))
+ return FALSE;
+ desc->gpr.used |= REGFLAG_R(G_RS(op));
+ desc->flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return TRUE;
+
+ case 0x0a3: /* WRTEEI */
+ if (!(ppc->cap & PPCCAP_4XX))
+ return FALSE;
+ if (op & MSR_EE)
+ desc->flags |= OPFLAG_CAN_EXPOSE_EXTERNAL_INT;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_3b - build a
+ description of a single instruction in the
+ 0x3b group
+-------------------------------------------------*/
+
+static int describe_instruction_3b(powerpc_state *ppc, UINT32 op, opcode_desc *desc)
+{
+ UINT32 opswitch = (op >> 1) & 0x1f;
+
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+
+ switch (opswitch)
+ {
+ case 0x12: /* FDIVSx */
+ case 0x14: /* FSUBSx */
+ case 0x15: /* FADDSx */
+ case 0x19: /* FMULSx */
+ desc->fpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(1);
+ }
+ return TRUE;
+
+ case 0x16: /* FSQRTSx */
+ case 0x18: /* FRESx */
+ desc->fpr.used |= REGFLAG_R(G_RB(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(1);
+ }
+ return TRUE;
+
+ case 0x1c: /* FMSUBSx */
+ case 0x1d: /* FMADDSx */
+ case 0x1e: /* FNMSUBSx */
+ case 0x1f: /* FNMADDSx */
+ desc->fpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op)) | REGFLAG_R(G_REGC(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(1);
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+/*-------------------------------------------------
+ describe_instruction_3f - build a
+ description of a single instruction in the
+ 0x3f group
+-------------------------------------------------*/
+
+static int describe_instruction_3f(powerpc_state *ppc, UINT32 op, opcode_desc *desc)
+{
+ UINT32 opswitch = (op >> 1) & 0x3ff;
+
+ if (!(ppc->cap & PPCCAP_FPU))
+ return FALSE;
+
+ if (opswitch & 0x10)
+ {
+ opswitch &= 0x1f;
+ switch (opswitch)
+ {
+ case 0x12: /* FDIVx */
+ case 0x14: /* FSUBx */
+ case 0x15: /* FADDx */
+ case 0x19: /* FMULx */
+ desc->fpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(1);
+ }
+ return TRUE;
+
+ case 0x16: /* FSQRTx */
+ case 0x1a: /* FSQRTEx */
+ desc->fpr.used |= REGFLAG_R(G_RB(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(1);
+ }
+ return TRUE;
+
+ case 0x17: /* FSELx */
+ case 0x1c: /* FMSUBx */
+ case 0x1d: /* FMADDx */
+ case 0x1e: /* FNMSUBx */
+ case 0x1f: /* FNMADDx */
+ desc->fpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op)) | REGFLAG_R(G_REGC(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(1);
+ }
+ return TRUE;
+ }
+ }
+ else
+ {
+ switch (opswitch)
+ {
+ case 0x32e: /* FCTIDx - 64-bit only */
+ case 0x32f: /* FCTIDZx - 64-bit only */
+ case 0x34e: /* FCFIDx - 64-bit only */
+ return FALSE;
+
+ case 0x000: /* FCMPU */
+ case 0x020: /* FCMPO */
+ desc->gpr.used |= REGFLAG_XER;
+ desc->fpr.used |= REGFLAG_R(G_RA(op)) | REGFLAG_R(G_RB(op));
+ desc->gpr.modified |= REGFLAG_CR(G_CRFD(op));
+ return TRUE;
+
+ case 0x00c: /* FRSPx */
+ case 0x00e: /* FCTIWx */
+ case 0x00f: /* FCTIWZx */
+ case 0x028: /* FNEGx */
+ case 0x048: /* FMRx */
+ case 0x088: /* FNABSx */
+ case 0x108: /* FABSx */
+ desc->fpr.used |= REGFLAG_R(G_RB(op));
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ if (op & M_RC)
+ {
+ desc->gpr.used |= REGFLAG_XER;
+ desc->gpr.modified |= REGFLAG_CR(1);
+ }
+ return TRUE;
+
+ case 0x026: /* MTFSB1x */
+ case 0x046: /* MTFSB0x */
+ desc->fpr.modified |= REGFLAG_FPSCR;
+ return TRUE;
+
+ case 0x040: /* MCRFS */
+ desc->fpr.used |= REGFLAG_FPSCR;
+ desc->gpr.modified |= REGFLAG_CR(G_CRFD(op));
+ return TRUE;
+
+ case 0x086: /* MTFSFIx */
+ desc->fpr.modified |= REGFLAG_FPSCR;
+ return TRUE;
+
+ case 0x247: /* MFFSx */
+ desc->fpr.used |= REGFLAG_FPSCR;
+ desc->fpr.modified |= REGFLAG_R(G_RD(op));
+ return TRUE;
+
+ case 0x2c7: /* MTFSFx */
+ desc->fpr.used |= REGFLAG_R(G_RB(op));
+ desc->fpr.modified |= REGFLAG_FPSCR;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
diff --git a/src/emu/cpu/powerpc/ppcfe.h b/src/emu/cpu/powerpc/ppcfe.h
new file mode 100644
index 00000000000..7c96d22f64f
--- /dev/null
+++ b/src/emu/cpu/powerpc/ppcfe.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+
+ ppcfe.h
+
+ Front-end for PowerPC recompiler
+
+ Copyright Aaron Giles
+ Released for general non-commercial use under the MAME license
+ Visit http://mamedev.org for licensing and usage restrictions.
+
+***************************************************************************/
+
+#ifndef __PPCFE_H__
+#define __PPCFE_H__
+
+#include "cpu/drcfe.h"
+
+
+/***************************************************************************
+ CONSTANTS
+***************************************************************************/
+
+/* register flags */
+#define REGFLAG_R(n) ((UINT64)1 << (n))
+#define REGFLAG_RZ(n) (((n) == 0) ? 0 : REGFLAG_R(n))
+#define REGFLAG_CR(n) REGFLAG_R(32 + (n))
+#define REGFLAG_XER REGFLAG_R(40)
+#define REGFLAG_CTR REGFLAG_R(41)
+#define REGFLAG_LR REGFLAG_R(42)
+#define REGFLAG_FPSCR REGFLAG_R(32)
+
+
+
+/***************************************************************************
+ FUNCTION PROTOTYPES
+***************************************************************************/
+
+int ppcfe_describe(void *param, opcode_desc *desc);
+
+#endif
diff --git a/src/emu/cpu/x64drc.c b/src/emu/cpu/x64drc.c
deleted file mode 100644
index 266edce7fba..00000000000
--- a/src/emu/cpu/x64drc.c
+++ /dev/null
@@ -1,633 +0,0 @@
-/***************************************************************************
-
- x64drc.c
-
- x64 Dynamic recompiler support routines.
-
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
-****************************************************************************
-
- Windows x64 conventions:
-
- Register Status Use
- -------- ------ ---
- RAX Volatile Return value register
- RCX Volatile First integer argument
- RDX Volatile Second integer argument
- R8 Volatile Third integer argument
- R9 Volatile Fourth integer argument
- R10:R11 Volatile Must be preserved as needed by caller; used in syscall/sysret instructions
- R12:R15 Nonvolatile Must be preserved by callee
- RDI Nonvolatile Must be preserved by callee
- RSI Nonvolatile Must be preserved by callee
- RBX Nonvolatile Must be preserved by callee
- RBP Nonvolatile May be used as a frame pointer; must be preserved by callee
- RSP Nonvolatile Stack pointer
-
- XMM0 Volatile First FP argument
- XMM1 Volatile Second FP argument
- XMM2 Volatile Third FP argument
- XMM3 Volatile Fourth FP argument
- XMM4:XMM5 Volatile Must be preserved as needed by caller
- XMM6:XMM15 Nonvolatile Must be preserved as needed by callee.
-
-
- Linux/MacOS x64 conventions:
-
- Register Status Use
- -------- ------ ---
- RAX Volatile Return value register
- RDI Volatile First integer argument
- RSI Volatile Second integer argument
- RDX Volatile Third integer argument
- RCX Volatile Fourth integer argument
- R8 Volatile Fifth integer argument
- R9 Volatile Sixth integer argument
- R10:R11 Volatile Must be preserved as needed by caller
- R12:R15 Nonvolatile Must be preserved by callee
- RBX Nonvolatile Must be preserved by callee
- RBP Nonvolatile Must be preserved by callee
- RSP Nonvolatile Stack pointer
-
- XMM0 Volatile First FP argument
- XMM1 Volatile Second FP argument
- XMM2 Volatile Third FP argument
- XMM3 Volatile Fourth FP argument
- XMM4 Volatile Fifth FP argument
- XMM5 Volatile Sixth FP argument
- XMM6:XMM15 Volatile Must be preserved as needed by caller.
-
-***************************************************************************/
-
-#include "cpuintrf.h"
-#include "x64drc.h"
-#include "debugger.h"
-
-#ifdef ENABLE_DEBUGGER
-#include "deprecat.h"
-#endif
-
-
-
-/***************************************************************************
- MACROS
-***************************************************************************/
-
-#define MXCSR_VALUE(x) (0x1fc0 | ((x) << 14))
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-static void append_entry_point(drc_core *drc);
-static void append_exit_point(drc_core *drc);
-static void recompile_code(drc_core *drc);
-static void append_recompile(drc_core *drc);
-static void append_flush(drc_core *drc);
-
-
-
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
-
-/*-------------------------------------------------
- allocate_l2_table - allocate an L2 table
- if necessary
--------------------------------------------------*/
-
-INLINE void allocate_l2_table(drc_core *drc, UINT32 l1index)
-{
- if (drc->lookup_l1[l1index] == drc->lookup_l2_recompile)
- {
- /* create a new copy of the recompile table */
- drc->lookup_l1[l1index] = drc_alloc(drc, sizeof(*drc->lookup_l2_recompile) << drc->l2bits);
- memcpy(drc->lookup_l1[l1index], drc->lookup_l2_recompile, sizeof(*drc->lookup_l2_recompile) << drc->l2bits);
- }
-}
-
-
-/***************************************************************************
- EXTERNAL INTERFACES
-***************************************************************************/
-
-/*-------------------------------------------------
- drc_init - initialize the DRC core
--------------------------------------------------*/
-
-drc_core *drc_init(UINT8 cpunum, drc_config *config)
-{
- int address_bits = config->address_bits;
- int effective_address_bits = address_bits - config->lsbs_to_ignore;
- drc_core *drc;
- int i;
-
- /* the drc structure lives at the start of the cache */
- drc = (drc_core *)config->cache_base;
- memset(drc, 0, sizeof(*drc));
-
- /* copy in relevant data from the config */
- drc->baseptr = config->baseptr;
- drc->pcptr = config->pcptr;
- drc->cb_reset = config->cb_reset;
- drc->cb_recompile = config->cb_recompile;
- drc->cb_entrygen = config->cb_entrygen;
- drc->mxcsr_curr = MXCSR_VALUE(FPRND_NEAR);
-
- /* configure cache */
- drc->cache_base = (UINT8 *)config->cache_base + sizeof(*drc);
- drc->cache_size = config->cache_size - sizeof(*drc);
- drc->cache_end = drc->cache_base + drc->cache_size;
- drc->cache_danger = drc->cache_end - 65536;
-
- /* compute shifts and masks */
- drc->l1bits = effective_address_bits / 2;
- drc->l2bits = effective_address_bits - drc->l1bits;
- drc->l1shift = config->lsbs_to_ignore + drc->l2bits;
- drc->l2mask = ((1 << drc->l2bits) - 1) << config->lsbs_to_ignore;
- drc->l2scale = sizeof(x86code *) >> config->lsbs_to_ignore;
-
- /* configure the MXCSR states */
- for (i = 0; i < 4; i++)
- drc->mxcsr_values[i] = MXCSR_VALUE(i);
-
- /* allocate lookup tables out of the cache */
- drc->lookup_l1 = drc_alloc(drc, sizeof(*drc->lookup_l1) << drc->l1bits);
- drc->lookup_l2_recompile = drc_alloc(drc, sizeof(*drc->lookup_l2_recompile) << drc->l2bits);
- if (drc->lookup_l1 == NULL || drc->lookup_l2_recompile == NULL)
- goto error;
- memset(drc->lookup_l1, 0, sizeof(*drc->lookup_l1) << drc->l1bits);
- memset(drc->lookup_l2_recompile, 0, sizeof(*drc->lookup_l2_recompile) << drc->l2bits);
-
- /* allocate the sequence and tentative lists */
- drc->sequence_count_max = config->max_instructions * 2;
- drc->sequence_list = malloc(drc->sequence_count_max * sizeof(*drc->sequence_list));
- if (drc->sequence_list == NULL)
- goto error;
-
- drc->tentative_count_max = config->max_instructions * 2;
- drc->tentative_list = malloc(drc->tentative_count_max * sizeof(*drc->tentative_list));
- if (drc->tentative_list == NULL)
- goto error;
-
- /* get pointers to external C functions */
-#ifdef ENABLE_DEBUGGER
- drc->mame_debug_hook = (x86code *)mame_debug_hook;
-#endif
- drc->recompile_code = (x86code *)recompile_code;
- drc->drc_cache_reset = (x86code *)drc_cache_reset;
- return drc;
-
-error:
- if (drc != NULL)
- drc_exit(drc);
- return NULL;
-}
-
-
-/*-------------------------------------------------
- drc_alloc - allocate memory from the top of
- the DRC cache
--------------------------------------------------*/
-
-void *drc_alloc(drc_core *drc, size_t amount)
-{
- /* if we don't have enough space, reset the cache */
- if (drc->cache_top >= drc->cache_danger - amount)
- drc_cache_reset(drc);
-
- /* if we still don't have enough space, fail */
- if (drc->cache_top >= drc->cache_danger - amount)
- return NULL;
-
- /* adjust the end and danger values downward */
- drc->cache_end -= amount;
- drc->cache_danger -= amount;
- return drc->cache_end;
-}
-
-
-/*-------------------------------------------------
- drc_cache_reset - reset the DRC cache
--------------------------------------------------*/
-
-void drc_cache_reset(drc_core *drc)
-{
- int i;
-
- /* reset the cache and add the basics */
- drc->cache_top = drc->cache_base;
-
- /* append the core entry points to the fresh cache */
- drc->entry_point = (void (*)(void *))(FPTR)drc->cache_top;
- append_entry_point(drc);
- drc->exit_point = drc->cache_top;
- append_exit_point(drc);
- drc->recompile = drc->cache_top;
- append_recompile(drc);
- drc->dispatch = drc->cache_top;
- drc_append_dispatcher(drc);
- drc->flush = drc->cache_top;
- append_flush(drc);
-
- /* populate the recompile table */
- for (i = 0; i < (1 << drc->l2bits); i++)
- drc->lookup_l2_recompile[i] = drc->recompile;
-
- /* reset all the l1 tables */
- for (i = 0; i < (1 << drc->l1bits); i++)
- {
- /* point NULL entries to the generic recompile table */
- if (drc->lookup_l1[i] == NULL)
- drc->lookup_l1[i] = drc->lookup_l2_recompile;
-
- /* reset allocated tables to point all entries back to the recompiler */
- else if (drc->lookup_l1[i] != drc->lookup_l2_recompile)
- memcpy(drc->lookup_l1[i], drc->lookup_l2_recompile, sizeof(*drc->lookup_l2_recompile) << drc->l2bits);
- }
-
- /* call back to the host */
- if (drc->cb_reset != NULL)
- (*drc->cb_reset)(drc);
-}
-
-
-/*-------------------------------------------------
- drc_execute - execute generated code
--------------------------------------------------*/
-
-void drc_execute(drc_core *drc)
-{
- (*drc->entry_point)(drc->baseptr);
-}
-
-
-/*-------------------------------------------------
- drc_exit - release resources allocated by
- the DRC core
--------------------------------------------------*/
-
-void drc_exit(drc_core *drc)
-{
- /* free the lists */
- if (drc->sequence_list != NULL)
- free(drc->sequence_list);
- if (drc->tentative_list != NULL)
- free(drc->tentative_list);
-}
-
-
-/*-------------------------------------------------
- drc_begin_sequence - begin code generation
- for a particular PC
--------------------------------------------------*/
-
-void drc_begin_sequence(drc_core *drc, UINT32 pc)
-{
- /* reset the sequence and tentative counts */
- drc->sequence_count = 0;
- drc->tentative_count = 0;
-}
-
-
-/*-------------------------------------------------
- drc_add_entry_point - add a new external
- entry point for a given PC
--------------------------------------------------*/
-
-int drc_add_entry_point(drc_core *drc, UINT32 pc, int override)
-{
- UINT32 l1index = pc >> drc->l1shift;
- UINT32 l2index = ((pc & drc->l2mask) * drc->l2scale) / sizeof(x86code *);
- int was_occupied;
-
- /* allocate memory if necessary */
- allocate_l2_table(drc, l1index);
-
- /* in case anybody was jumping directly to this code entry, replace
- the code with a jmp to the new code */
- was_occupied = (drc->lookup_l1[l1index][l2index] != drc->recompile);
- if (was_occupied && override)
- {
- x86code *dest = drc->lookup_l1[l1index][l2index];
- emit_jmp(&dest, drc->cache_top);
- }
-
- /* note the current location for this instruction */
- if (!was_occupied || override)
- drc->lookup_l1[l1index][l2index] = drc->cache_top;
- return was_occupied;
-}
-
-
-/*------------------------------------------------------------------
- drc_end_sequence
-------------------------------------------------------------------*/
-
-void drc_end_sequence(drc_core *drc)
-{
- int i, j;
-
- /* fix up any internal links */
- for (i = 0; i < drc->tentative_count; i++)
- {
- for (j = 0; j < drc->sequence_count; j++)
- if (drc->tentative_list[i].pc == drc->sequence_list[j].pc)
- {
- x86code *dest = drc->tentative_list[i].target;
- emit_jmp(&dest, drc->sequence_list[j].target);
- while (dest < drc->tentative_list[i].end)
- emit_int_3(&dest);
- break;
- }
- }
-}
-
-
-/*------------------------------------------------------------------
- drc_register_code_at_cache_top
-------------------------------------------------------------------*/
-
-void drc_register_code_at_cache_top(drc_core *drc, UINT32 pc)
-{
- pc_ptr_pair *pair = &drc->sequence_list[drc->sequence_count++];
- assert_always(drc->sequence_count <= drc->sequence_count_max, "drc_register_code_at_cache_top: too many instructions!");
-
- pair->target = drc->cache_top;
- pair->pc = pc;
-}
-
-
-/*------------------------------------------------------------------
- drc_get_code_at_pc
-------------------------------------------------------------------*/
-
-x86code *drc_get_code_at_pc(drc_core *drc, UINT32 pc)
-{
- UINT32 l1index = pc >> drc->l1shift;
- UINT32 l2index = ((pc & drc->l2mask) * drc->l2scale) / sizeof(x86code *);
- x86code *codeptr = drc->lookup_l1[l1index][l2index];
- return (codeptr != drc->recompile) ? codeptr : NULL;
-}
-
-
-/*------------------------------------------------------------------
- drc_invalidate_code_range
-------------------------------------------------------------------*/
-
-void drc_invalidate_code_range(drc_core *drc, UINT32 startpc, UINT32 endpc)
-{
- UINT32 startl1index = startpc >> drc->l1shift;
- UINT32 startl2index = ((startpc & drc->l2mask) * drc->l2scale) / sizeof(x86code *);
- UINT32 endl1index = endpc >> drc->l1shift;
- UINT32 endl2index = ((endpc & drc->l2mask) * drc->l2scale) / sizeof(x86code *);
- UINT32 curl1;
-
- /* iterate over l1 bunches */
- for (curl1 = startl1index; curl1 <= endl1index; curl1++)
- {
- x86code **l2table = drc->lookup_l1[curl1];
- UINT32 l2start, l2end, curl2;
-
- /* if this is already empty, skip it */
- if (l2table == drc->lookup_l2_recompile)
- continue;
-
- /* determine start/stop for this range */
- l2start = (curl1 == startl1index) ? startl2index : 0;
- l2end = (curl1 == endl1index) ? endl2index : ((1 << drc->l2bits) - 1);
-
- /* invalidate any code entries here */
- for (curl2 = l2start; curl2 <= l2end; curl2++)
- if (l2table[curl2] != drc->recompile)
- {
- /* overwrite code there with a jump to the recompiler in case we ever get there */
- x86code *dest = l2table[curl2];
-// emit_int_3(&dest);
- emit_jmp(&dest, drc->recompile);
- l2table[curl2] = drc->recompile;
- }
- }
-}
-
-
-/*------------------------------------------------------------------
- drc_append_call_debugger
-------------------------------------------------------------------*/
-
-void drc_append_call_debugger(drc_core *drc)
-{
-#ifdef ENABLE_DEBUGGER
- if (Machine->debug_mode)
- emit_call_m64(DRCTOP, MDRC(&drc->mame_debug_hook)); // call mame_debug_hook
-#endif
-}
-
-
-/*------------------------------------------------------------------
- drc_append_dispatcher
-------------------------------------------------------------------*/
-
-void drc_append_dispatcher(drc_core *drc)
-{
- /* target PC is in P1 on entry; we must keep P1 intact in case we jump to the recompile callback */
- emit_mov_r32_r32(DRCTOP, REG_P2, REG_P1); // mov p2,p1
- emit_mov_r32_r32(DRCTOP, REG_EAX, REG_P1); // mov eax,p1
- emit_shr_r32_imm(DRCTOP, REG_P2, drc->l1shift); // shr p2,l1shift
- emit_mov_r64_m64(DRCTOP, REG_P2, MDRCISD(drc->lookup_l1, REG_P2, 8, 0)); // mov p2,[rbp+p2*8+l1lookup]
- emit_and_r32_imm(DRCTOP, REG_EAX, drc->l2mask); // and eax,l2mask
- emit_jmp_m64(DRCTOP, MBISD(REG_P2, REG_EAX, drc->l2scale, 0)); // jmp [p2 + eax*l2scale]
-}
-
-
-/*------------------------------------------------------------------
- drc_append_fixed_dispatcher
-------------------------------------------------------------------*/
-
-void drc_append_fixed_dispatcher(drc_core *drc, UINT32 pc, int loadpc)
-{
- UINT32 l1index = pc >> drc->l1shift;
- UINT32 l2index = ((pc & drc->l2mask) * drc->l2scale) / sizeof(x86code *);
-
- /* make sure we have an L2 table for this entry */
- allocate_l2_table(drc, l1index);
-
- /* emit a jump through the table entry */
- if (loadpc)
- emit_mov_r32_imm(DRCTOP, REG_P1, pc); // mov p1,pc
- emit_jmp_m64(DRCTOP, MDRC(&drc->lookup_l1[l1index][l2index])); // jmp [lookup[l1index][l2index]]
-}
-
-
-/*------------------------------------------------------------------
- drc_append_tentative_fixed_dispatcher
-------------------------------------------------------------------*/
-
-void drc_append_tentative_fixed_dispatcher(drc_core *drc, UINT32 newpc, int loadpc)
-{
- pc_ptr_pair *pair = &drc->tentative_list[drc->tentative_count++];
- assert_always(drc->tentative_count <= drc->tentative_count_max, "drc_append_tentative_fixed_dispatcher: too many tentative branches!");
-
- pair->target = drc->cache_top;
- pair->pc = newpc;
- drc_append_fixed_dispatcher(drc, newpc, loadpc);
- pair->end = drc->cache_top;
-}
-
-
-/*------------------------------------------------------------------
- drc_append_set_sse_rounding
-------------------------------------------------------------------*/
-
-void drc_append_set_sse_rounding(drc_core *drc, UINT8 regindex)
-{
- emit_ldmxcsr_m32(DRCTOP, MDRCISD(&drc->mxcsr_values[0], regindex, 4, 0)); // ldmxcsr [mxcsr_values + reg*4]
- emit_stmxcsr_m32(DRCTOP, MDRC(&drc->mxcsr_curr)); // stmxcsr [mxcsr_curr]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_append_set_temp_sse_rounding
-------------------------------------------------------------------*/
-
-void drc_append_set_temp_sse_rounding(drc_core *drc, UINT8 rounding)
-{
- emit_ldmxcsr_m32(DRCTOP, MDRC(&drc->mxcsr_values[rounding])); // ldmxcsr mxcsr_values[rounding]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_append_restore_sse_rounding
-------------------------------------------------------------------*/
-
-void drc_append_restore_sse_rounding(drc_core *drc)
-{
- emit_ldmxcsr_m32(DRCTOP, MDRC(&drc->mxcsr_curr)); // ldmxcsr [mxcsr_curr]
-}
-
-
-
-/***************************************************************************
- INTERNAL CODEGEN
-***************************************************************************/
-
-/*------------------------------------------------------------------
- append_entry_point
-------------------------------------------------------------------*/
-
-static void append_entry_point(drc_core *drc)
-{
- int pushbytes = 8 * (6 + (REG_NV5 != REG_NONE) + (REG_NV6 != REG_NONE));
-
- /* save non-volatile registers */
- emit_push_r64(DRCTOP, REG_DRC); // push drc
- emit_push_r64(DRCTOP, REG_NV0); // push nv0
- emit_push_r64(DRCTOP, REG_NV1); // push nv1
- emit_push_r64(DRCTOP, REG_NV2); // push nv2
- emit_push_r64(DRCTOP, REG_NV3); // push nv3
- emit_push_r64(DRCTOP, REG_NV4); // push nv4
- if (REG_NV5 != REG_NONE) emit_push_r64(DRCTOP, REG_NV5); // push nv5
- if (REG_NV6 != REG_NONE) emit_push_r64(DRCTOP, REG_NV6); // push nv6
-
- /* stack frame:
- 0x40/0x48 bytes of scratch space/alignment
- 0x20 bytes for register parameter spilling in Windows ABI
- */
- emit_sub_r64_imm(DRCTOP, REG_RSP, 0x68 + (pushbytes % 16)); // sub rsp,0x68/0x70
-
- /* parameter 1 is the baseptr; copy to RBP */
- emit_mov_r64_r64(DRCTOP, REG_DRC, REG_P1); // mov rbp,p1
-
- /* update the MXCSR register */
- emit_stmxcsr_m32(DRCTOP, MDRC(&drc->mxcsr_save)); // stmxcsr [mxcsr_save]
- emit_ldmxcsr_m32(DRCTOP, MDRC(&drc->mxcsr_curr)); // ldmxcsr [mxcsr_curr]
-
- /* continue performing entry generation duties */
- if (drc->cb_entrygen != NULL)
- (*drc->cb_entrygen)(drc); // additional entry point duties
-
- /* reload the PC into P1 and dispatch */
- emit_mov_r32_m32(DRCTOP, REG_P1, MDRC(drc->pcptr)); // mov p1,[pc]
- drc_append_dispatcher(drc); // dispatch
-}
-
-
-/*------------------------------------------------------------------
- append_exit_point
-------------------------------------------------------------------*/
-
-static void append_exit_point(drc_core *drc)
-{
- int pushbytes = 8 * (6 + (REG_NV5 != REG_NONE) + (REG_NV6 != REG_NONE));
-
- /* on exit, P1 must contain the final PC */
- emit_mov_m32_r32(DRCTOP, MDRC(drc->pcptr), REG_P1); // mov [pc],p1
-
- /* restore the MXCSR state */
- emit_ldmxcsr_m32(DRCTOP, MDRC(&drc->mxcsr_save)); // ldmxcsr [mxcsr_save]
-
- /* add 0x18 to RSP to get us back to the original stack pointer */
- emit_add_r64_imm(DRCTOP, REG_RSP, 0x68 + (pushbytes % 16)); // add rsp,0x68/0x70
-
- /* save non-volatile registers */
- if (REG_NV6 != REG_NONE) emit_pop_r64(DRCTOP, REG_NV6); // pop nv6
- if (REG_NV5 != REG_NONE) emit_pop_r64(DRCTOP, REG_NV5); // pop nv5
- emit_pop_r64(DRCTOP, REG_NV4); // pop nv4
- emit_pop_r64(DRCTOP, REG_NV3); // pop nv3
- emit_pop_r64(DRCTOP, REG_NV2); // pop nv2
- emit_pop_r64(DRCTOP, REG_NV1); // pop nv1
- emit_pop_r64(DRCTOP, REG_NV0); // pop nv0
- emit_pop_r64(DRCTOP, REG_DRC); // pop drc
- emit_ret(DRCTOP); // ret
-}
-
-
-/*------------------------------------------------------------------
- recompile_code
-------------------------------------------------------------------*/
-
-static void recompile_code(drc_core *drc)
-{
- /* if we're above the danger line, flush the cache before recompiling */
- if (drc->cache_top >= drc->cache_danger)
- drc_cache_reset(drc);
-
- /* call the recompile callback */
- (*drc->cb_recompile)(drc);
-}
-
-
-/*------------------------------------------------------------------
- append_recompile
-------------------------------------------------------------------*/
-
-static void append_recompile(drc_core *drc)
-{
- /* on entry, P1 must contain the PC that needs recompilation */
- emit_mov_m32_r32(DRCTOP, MDRC(drc->pcptr), REG_P1); // mov [pc],p1
- emit_lea_r64_m64(DRCTOP, REG_P1, MDRC(drc)); // lea p1,drc
- emit_call_m64(DRCTOP, MDRC(&drc->recompile_code)); // call recompile_code
- emit_mov_r32_m32(DRCTOP, REG_P1, MDRC(drc->pcptr)); // mov p1,[pc]
- drc_append_dispatcher(drc); // dispatch
-}
-
-
-/*------------------------------------------------------------------
- append_flush
-------------------------------------------------------------------*/
-
-static void append_flush(drc_core *drc)
-{
- /* on entry, P1 must contain the PC that needs recompilation */
- emit_mov_m32_r32(DRCTOP, MDRC(drc->pcptr), REG_P1); // mov [pc],p1
- emit_lea_r64_m64(DRCTOP, REG_P1, MDRC(drc)); // lea p1,drc
- emit_call_m64(DRCTOP, MDRC(&drc->drc_cache_reset)); // call drc_cache_reset
- emit_mov_r32_m32(DRCTOP, REG_P1, MDRC(drc->pcptr)); // mov p1,[pc]
- drc_append_dispatcher(drc); // dispatch
-}
diff --git a/src/emu/cpu/x64drc.h b/src/emu/cpu/x64drc.h
deleted file mode 100644
index 7a949949f60..00000000000
--- a/src/emu/cpu/x64drc.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/***************************************************************************
-
- x64drc.h
-
- x64 Dynamic recompiler support routines.
-
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
-***************************************************************************/
-
-#pragma once
-
-#ifndef __X64DRC_H__
-#define __X64DRC_H__
-
-#include "cpuintrf.h"
-#include "x86emit.h"
-
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-/* ABI-specific configuration */
-#define REG_DRC REG_RBP /* pointer to DRC base */
-
-#ifdef X64_WINDOWS_ABI
-
-#define REG_P1 REG_RCX /* 1st function parameter */
-#define REG_P2 REG_RDX /* 2nd function parameter */
-#define REG_P3 REG_R8 /* 3rd function parameter */
-#define REG_P4 REG_R9 /* 4th function parameter */
-#define REG_V5 REG_R10 /* volatile register 5 */
-#define REG_V6 REG_R11 /* volatile register 6 */
-
-#define NUM_NVREG 7 /* number of non-volatile registers */
-#define REG_NV0 REG_RBX /* non-volatile reg 0 */
-#define REG_NV1 REG_RDI /* non-volatile reg 1 */
-#define REG_NV2 REG_RSI /* non-volatile reg 2 */
-#define REG_NV3 REG_R12 /* non-volatile reg 3 */
-#define REG_NV4 REG_R13 /* non-volatile reg 4 */
-#define REG_NV5 REG_R14 /* non-volatile reg 5 */
-#define REG_NV6 REG_R15 /* non-volatile reg 6 */
-
-#else
-
-#define REG_P1 REG_RDI /* 1st function parameter */
-#define REG_P2 REG_RSI /* 2nd function parameter */
-#define REG_P3 REG_RDX /* 3rd function parameter */
-#define REG_P4 REG_RCX /* 4th function parameter */
-#define REG_V5 REG_R10 /* volatile register 5 */
-#define REG_V6 REG_R11 /* volatile register 6 */
-
-#define NUM_NVREG 5 /* number of non-volatile registers */
-#define REG_NV0 REG_RBX /* non-volatile reg 0 */
-#define REG_NV1 REG_R12 /* non-volatile reg 1 */
-#define REG_NV2 REG_R13 /* non-volatile reg 2 */
-#define REG_NV3 REG_R14 /* non-volatile reg 3 */
-#define REG_NV4 REG_R15 /* non-volatile reg 4 */
-#define REG_NV5 REG_NONE /* non-volatile reg 5 */
-#define REG_NV6 REG_NONE /* non-volatile reg 6 */
-
-#endif
-
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* PC and pointer pair */
-typedef struct _pc_ptr_pair pc_ptr_pair;
-struct _pc_ptr_pair
-{
- UINT32 pc;
- x86code * target;
- x86code * end;
-};
-
-
-/* core interface structure for the drc common code */
-typedef struct _drc_core drc_core;
-struct _drc_core
-{
- /* cache parameters */
- x86code * cache_base; /* base pointer to the compiler cache */
- x86code * cache_top; /* current top of cache */
- x86code * cache_danger; /* high water mark for the end */
- x86code * cache_end; /* end of cache memory */
- size_t cache_size; /* cache allocated size */
-
- /* hash table lookups */
- x86code *** lookup_l1; /* level 1 lookup */
- x86code ** lookup_l2_recompile; /* level 2 lookup populated with recompile pointers */
- UINT8 l1bits; /* number of bits in level 1 lookup */
- UINT8 l2bits; /* number of bits in level 2 lookup */
- UINT8 l1shift; /* shift to go from PC to level 1 lookup */
- UINT32 l2mask; /* mask to go from PC to level 2 lookup */
- UINT8 l2scale; /* scale to get from masked PC value to final level 2 lookup */
-
- /* entry point for calling from C code */
- void (*entry_point)(void *); /* pointer to asm entry point */
-
- /* base pointer for memory accesses */
- void * baseptr; /* pointer to base; all cache must be accessible from here */
-
- /* internal subroutines generated in the cache */
- x86code * exit_point; /* exit out of the DRC engine */
- x86code * recompile; /* pointer to recompile jump point */
- x86code * dispatch; /* pointer to dispatch jump point */
- x86code * flush; /* pointer to flush jump point */
-
- /* pointers to external C code */
- x86code * mame_debug_hook; /* pointer to mame_debug_hook function */
- x86code * recompile_code; /* pointer to recompile_code function */
- x86code * drc_cache_reset; /* pointer to drc_cache_reset function */
-
- /* pointers to the PC */
- UINT32 * pcptr; /* pointer to where the PC is stored */
-
- /* save areas for the MXCSR register */
- UINT32 mxcsr_curr; /* current SSE control word */
- UINT32 mxcsr_save; /* saved SSE control word */
- UINT32 mxcsr_values[4]; /* array of values for different modes */
-
- /* internal lists of sequences and tentative branches */
- pc_ptr_pair * sequence_list; /* PC/pointer sets for the current instruction sequence */
- UINT32 sequence_count; /* number of instructions in the current sequence */
- UINT32 sequence_count_max; /* max number of instructions in the current sequence */
- pc_ptr_pair * tentative_list; /* PC/pointer sets for tentative branches */
- UINT32 tentative_count; /* number of tentative branches */
- UINT32 tentative_count_max; /* max number of tentative branches */
-
- /* CPU-specific callbacks */
- void (*cb_reset)(struct _drc_core *drc); /* callback when the cache is reset */
- void (*cb_recompile)(struct _drc_core *drc); /* callback when code needs to be recompiled */
- void (*cb_entrygen)(struct _drc_core *drc); /* callback before generating the dispatcher on entry */
-};
-
-
-/* configuration structure for the drc common code */
-typedef struct _drc_config drc_config;
-struct _drc_config
-{
- void * cache_base; /* base of cache */
- UINT32 cache_size; /* size of cache */
- UINT32 max_instructions; /* maximum instructions per sequence */
- UINT8 address_bits; /* number of live address bits in the PC */
- UINT8 lsbs_to_ignore; /* number of LSBs to ignore on the PC */
-
- void * baseptr; /* pointer to base; all cache must be accessible from here */
- UINT32 * pcptr; /* pointer to where the PC is stored */
-
- void (*cb_reset)(drc_core *drc); /* callback when the cache is reset */
- void (*cb_recompile)(drc_core *drc); /* callback when code needs to be recompiled */
- void (*cb_entrygen)(drc_core *drc); /* callback before generating the dispatcher on entry */
-};
-
-
-
-/***************************************************************************
- MACROS
-***************************************************************************/
-
-/* use this macro in emit_* instructions to make them shorter */
-#define DRCTOP &drc->cache_top
-
-/* memory references to DRC-relative data */
-#define MDRC(x) MBD(REG_DRC, drcrel32(drc->baseptr, (x)))
-#define MDRCD(x, disp) MBD(REG_DRC, drcrel32(drc->baseptr, (x)) + (disp))
-#define MDRCISD(x, index, scale, disp) MBISD(REG_DRC, (index), (scale), drcrel32(drc->baseptr, (x)) + (disp))
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* init/shutdown */
-drc_core *drc_init(UINT8 cpunum, drc_config *config);
-void *drc_alloc(drc_core *drc, size_t amount);
-void drc_cache_reset(drc_core *drc);
-void drc_execute(drc_core *drc);
-void drc_exit(drc_core *drc);
-
-/* code management */
-void drc_begin_sequence(drc_core *drc, UINT32 pc);
-int drc_add_entry_point(drc_core *drc, UINT32 pc, int override);
-void drc_end_sequence(drc_core *drc);
-void drc_register_code_at_cache_top(drc_core *drc, UINT32 pc);
-x86code *drc_get_code_at_pc(drc_core *drc, UINT32 pc);
-void drc_invalidate_code_range(drc_core *drc, UINT32 startpc, UINT32 endpc);
-
-/* standard appendages */
-void drc_append_dispatcher(drc_core *drc);
-void drc_append_fixed_dispatcher(drc_core *drc, UINT32 newpc, int loadpc);
-void drc_append_tentative_fixed_dispatcher(drc_core *drc, UINT32 newpc, int loadpc);
-void drc_append_call_debugger(drc_core *drc);
-void drc_append_set_sse_rounding(drc_core *drc, UINT8 regindex);
-void drc_append_set_temp_sse_rounding(drc_core *drc, UINT8 rounding);
-void drc_append_restore_sse_rounding(drc_core *drc);
-
-
-
-/***************************************************************************
- INLINE FUNCTIONS
-***************************************************************************/
-
-INLINE INT32 drcrel32(void *base, void *ptr)
-{
- INT64 delta = (UINT8 *)ptr - (UINT8 *)base;
- assert((INT32)delta == delta);
- return (INT32)delta;
-}
-
-INLINE void *drcrelptr(drc_core *drc, INT32 offset)
-{
- return (UINT8 *)drc + offset;
-}
-
-#endif /* __X64DRC_H__ */
diff --git a/src/emu/cpu/x86drc.c b/src/emu/cpu/x86drc.c
deleted file mode 100644
index 03d3aa90f8e..00000000000
--- a/src/emu/cpu/x86drc.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/***************************************************************************
-
- x86drc.c
-
- x86 Dynamic recompiler support routines.
-
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
-***************************************************************************/
-
-#include "debugger.h"
-#include "deprecat.h"
-#include "x86drc.h"
-
-#define LOG_DISPATCHES 0
-#define BREAK_ON_MODIFIED_CODE 0
-
-
-
-
-static const UINT16 fp_control[4] = { 0x023f, 0x063f, 0x0a3f, 0x0e3f };
-static const UINT32 sse_control[4] = { 0x9fc0, 0xbfc0, 0xdfc0, 0xffc0 };
-
-
-static void append_entry_point(drc_core *drc);
-static void append_recompile(drc_core *drc);
-static void append_flush(drc_core *drc);
-static void append_out_of_cycles(drc_core *drc);
-
-#if LOG_DISPATCHES
-static void log_dispatch(drc_core *drc);
-#endif
-
-
-
-/***************************************************************************
- EXTERNAL INTERFACES
-***************************************************************************/
-
-/*-------------------------------------------------
- drc_init - initialize the DRC core
--------------------------------------------------*/
-
-drc_core *drc_init(UINT8 cpunum, drc_config *config)
-{
- int address_bits = config->address_bits;
- int effective_address_bits = address_bits - config->lsbs_to_ignore;
- UINT8 cache_allocated = FALSE;
- drc_core *drc = NULL;
-
- /* allocate memory */
- if (config->cache_base == NULL)
- {
- config->cache_base = osd_alloc_executable(config->cache_size);
- if (config->cache_base == NULL)
- goto error;
- cache_allocated = TRUE;
- }
-
- /* the drc structure lives at the start of the cache */
- drc = (drc_core *)config->cache_base;
- memset(drc, 0, sizeof(*drc));
-
- /* copy in relevant data from the config */
- drc->pcptr = config->pcptr;
- drc->icountptr = config->icountptr;
- drc->esiptr = config->esiptr;
- drc->cb_reset = config->cb_reset;
- drc->cb_recompile = config->cb_recompile;
- drc->cb_entrygen = config->cb_entrygen;
- drc->uses_fp = config->uses_fp;
- drc->uses_sse = config->uses_sse;
- drc->pc_in_memory = config->pc_in_memory;
- drc->icount_in_memory = config->icount_in_memory;
- drc->fpcw_curr = fp_control[0];
- drc->mxcsr_curr = sse_control[0];
-
- /* configure cache */
- drc->cache_base = (UINT8 *)config->cache_base + sizeof(*drc);
- drc->cache_size = config->cache_size - sizeof(*drc);
- drc->cache_end = drc->cache_base + drc->cache_size;
- drc->cache_danger = drc->cache_end - 65536;
- drc->cache_allocated = cache_allocated;
-
- /* compute shifts and masks */
- drc->l1bits = effective_address_bits/2;
- drc->l2bits = effective_address_bits - drc->l1bits;
- drc->l1shift = config->lsbs_to_ignore + drc->l2bits;
- drc->l2mask = ((1 << drc->l2bits) - 1) << config->lsbs_to_ignore;
- drc->l2scale = 4 >> config->lsbs_to_ignore;
-
- /* allocate lookup tables */
- drc->lookup_l1 = malloc(sizeof(*drc->lookup_l1) * (1 << drc->l1bits));
- drc->lookup_l2_recompile = malloc(sizeof(*drc->lookup_l2_recompile) * (1 << drc->l2bits));
- if (drc->lookup_l1 == NULL || drc->lookup_l2_recompile == NULL)
- goto error;
- memset(drc->lookup_l1, 0, sizeof(*drc->lookup_l1) * (1 << drc->l1bits));
- memset(drc->lookup_l2_recompile, 0, sizeof(*drc->lookup_l2_recompile) * (1 << drc->l2bits));
-
- /* allocate the sequence and tentative lists */
- drc->sequence_count_max = config->max_instructions;
- drc->sequence_list = malloc(drc->sequence_count_max * sizeof(*drc->sequence_list));
- if (drc->sequence_list == NULL)
- goto error;
-
- drc->tentative_count_max = config->max_instructions;
- drc->tentative_list = malloc(drc->tentative_count_max * sizeof(*drc->tentative_list));
- if (!drc->tentative_list)
- return NULL;
-
- return drc;
-
-error:
- if (drc != NULL)
- drc_exit(drc);
- return NULL;
-}
-
-
-/*-------------------------------------------------
- drc_alloc - allocate memory from the top of
- the DRC cache
--------------------------------------------------*/
-
-void *drc_alloc(drc_core *drc, size_t amount)
-{
- /* if we don't have enough space, reset the cache */
- if (drc->cache_top >= drc->cache_danger - amount)
- drc_cache_reset(drc);
-
- /* if we still don't have enough space, fail */
- if (drc->cache_top >= drc->cache_danger - amount)
- return NULL;
-
- /* adjust the end and danger values downward */
- drc->cache_end -= amount;
- drc->cache_danger -= amount;
- return drc->cache_end;
-}
-
-
-/*-------------------------------------------------
- drc_cache_reset - reset the DRC cache
--------------------------------------------------*/
-
-void drc_cache_reset(drc_core *drc)
-{
- int i;
-
- /* reset the cache and add the basics */
- drc->cache_top = drc->cache_base;
-
- /* append the core entry points to the fresh cache */
- drc->entry_point = (void (*)(void))(UINT32)drc->cache_top;
- append_entry_point(drc);
- drc->out_of_cycles = drc->cache_top;
- append_out_of_cycles(drc);
-
- /* append an INT 3 before the recompile so that BREAK_ON_MODIFIED_CODE works */
- emit_int_3(DRCTOP);
- drc->recompile = drc->cache_top;
- append_recompile(drc);
- drc->dispatch = drc->cache_top;
- drc_append_dispatcher(drc);
- drc->flush = drc->cache_top;
- append_flush(drc);
-
- /* populate the recompile table */
- for (i = 0; i < (1 << drc->l2bits); i++)
- drc->lookup_l2_recompile[i] = drc->recompile;
-
- /* reset all the l1 tables */
- for (i = 0; i < (1 << drc->l1bits); i++)
- {
- /* point NULL entries to the generic recompile table */
- if (drc->lookup_l1[i] == NULL)
- drc->lookup_l1[i] = drc->lookup_l2_recompile;
-
- /* reset allocated tables to point all entries back to the recompiler */
- else if (drc->lookup_l1[i] != drc->lookup_l2_recompile)
- memcpy(drc->lookup_l1[i], drc->lookup_l2_recompile, sizeof(*drc->lookup_l2_recompile) * (1 << drc->l2bits));
- }
-
- /* call back to the host */
- if (drc->cb_reset)
- (*drc->cb_reset)(drc);
-}
-
-
-/*------------------------------------------------------------------
- drc_execute
-------------------------------------------------------------------*/
-
-void drc_execute(drc_core *drc)
-{
- (*drc->entry_point)();
-}
-
-
-/*------------------------------------------------------------------
- drc_exit
-------------------------------------------------------------------*/
-
-void drc_exit(drc_core *drc)
-{
- int i;
-
- /* free all the l2 tables allocated */
- for (i = 0; i < (1 << drc->l1bits); i++)
- if (drc->lookup_l1[i] != drc->lookup_l2_recompile)
- free(drc->lookup_l1[i]);
-
- /* free the l1 table */
- if (drc->lookup_l1)
- free(drc->lookup_l1);
-
- /* free the default l2 table */
- if (drc->lookup_l2_recompile)
- free(drc->lookup_l2_recompile);
-
- /* free the lists */
- if (drc->sequence_list)
- free(drc->sequence_list);
- if (drc->tentative_list)
- free(drc->tentative_list);
-
- /* and the drc itself */
- if (drc->cache_allocated)
- osd_free_executable(drc, drc->cache_size + sizeof(*drc));
-}
-
-
-/*------------------------------------------------------------------
- drc_begin_sequence
-------------------------------------------------------------------*/
-
-void drc_begin_sequence(drc_core *drc, UINT32 pc)
-{
- UINT32 l1index = pc >> drc->l1shift;
- UINT32 l2index = ((pc & drc->l2mask) * drc->l2scale) / 4;
-
- /* reset the sequence and tentative counts */
- drc->sequence_count = 0;
- drc->tentative_count = 0;
-
- /* allocate memory if necessary */
- if (drc->lookup_l1[l1index] == drc->lookup_l2_recompile)
- {
- /* create a new copy of the recompile table */
- drc->lookup_l1[l1index] = malloc_or_die(sizeof(*drc->lookup_l2_recompile) * (1 << drc->l2bits));
-
- memcpy(drc->lookup_l1[l1index], drc->lookup_l2_recompile, sizeof(*drc->lookup_l2_recompile) * (1 << drc->l2bits));
- }
-
- /* nuke any previous link to this instruction */
- if (drc->lookup_l1[l1index][l2index] != drc->recompile)
- {
- UINT8 *cache_save = drc->cache_top;
- drc->cache_top = drc->lookup_l1[l1index][l2index];
- emit_jmp(DRCTOP, drc->dispatch);
- drc->cache_top = cache_save;
- }
-
- /* note the current location for this instruction */
- drc->lookup_l1[l1index][l2index] = drc->cache_top;
-}
-
-
-/*------------------------------------------------------------------
- drc_end_sequence
-------------------------------------------------------------------*/
-
-void drc_end_sequence(drc_core *drc)
-{
- int i, j;
-
- /* fix up any internal links */
- for (i = 0; i < drc->tentative_count; i++)
- for (j = 0; j < drc->sequence_count; j++)
- if (drc->tentative_list[i].pc == drc->sequence_list[j].pc)
- {
- UINT8 *cache_save = drc->cache_top;
- drc->cache_top = drc->tentative_list[i].target;
- emit_jmp(DRCTOP, drc->sequence_list[j].target);
- drc->cache_top = cache_save;
- break;
- }
-}
-
-
-/*------------------------------------------------------------------
- drc_register_code_at_cache_top
-------------------------------------------------------------------*/
-
-void drc_register_code_at_cache_top(drc_core *drc, UINT32 pc)
-{
- pc_ptr_pair *pair = &drc->sequence_list[drc->sequence_count++];
- assert_always(drc->sequence_count <= drc->sequence_count_max, "drc_register_code_at_cache_top: too many instructions!");
-
- pair->target = drc->cache_top;
- pair->pc = pc;
-}
-
-
-/*------------------------------------------------------------------
- drc_get_code_at_pc
-------------------------------------------------------------------*/
-
-void *drc_get_code_at_pc(drc_core *drc, UINT32 pc)
-{
- UINT32 l1index = pc >> drc->l1shift;
- UINT32 l2index = ((pc & drc->l2mask) * drc->l2scale) / 4;
- return (drc->lookup_l1[l1index][l2index] != drc->recompile) ? drc->lookup_l1[l1index][l2index] : NULL;
-}
-
-
-/*------------------------------------------------------------------
- drc_append_verify_code
-------------------------------------------------------------------*/
-
-void drc_append_verify_code(drc_core *drc, void *code, UINT8 length)
-{
-#if BREAK_ON_MODIFIED_CODE
- x86code *recompile = drc->recompile - 1;
-#else
- x86code *recompile = drc->recompile;
-#endif
-
- if (length > 8)
- {
- UINT32 *codeptr = code, sum = 0;
- void *target;
- int i;
-
- for (i = 0; i < length / 4; i++)
- {
- sum = (sum >> 1) | (sum << 31);
- sum += *codeptr++;
- }
-
- emit_xor_r32_r32(DRCTOP, REG_EAX, REG_EAX); // xor eax,eax
- emit_mov_r32_imm(DRCTOP, REG_EBX, (FPTR)code); // mov ebx,code
- emit_mov_r32_imm(DRCTOP, REG_ECX, length / 4); // mov ecx,length / 4
- target = drc->cache_top; // target:
- emit_ror_r32_imm(DRCTOP, REG_EAX, 1); // ror eax,1
- emit_add_r32_m32(DRCTOP, REG_EAX, MBD(REG_EBX, 0)); // add eax,[ebx]
- emit_sub_r32_imm(DRCTOP, REG_ECX, 1); // sub ecx,1
- emit_lea_r32_m32(DRCTOP, REG_EBX, MBD(REG_EBX, 4)); // lea ebx,[ebx+4]
- emit_jcc(DRCTOP, COND_NZ, target); // jnz target
- emit_cmp_r32_imm(DRCTOP, REG_EAX, sum); // cmp eax,sum
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- }
- else if (length >= 12)
- {
- emit_cmp_m32_imm(DRCTOP, MABS(code), *(UINT32 *)code); // cmp [pc],opcode
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- emit_cmp_m32_imm(DRCTOP, MABS((UINT8 *)code + 4), ((UINT32 *)code)[1]); // cmp [pc+4],opcode+4
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- emit_cmp_m32_imm(DRCTOP, MABS((UINT8 *)code + 8), ((UINT32 *)code)[2]); // cmp [pc+8],opcode+8
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- }
- else if (length >= 8)
- {
- emit_cmp_m32_imm(DRCTOP, MABS(code), *(UINT32 *)code); // cmp [pc],opcode
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- emit_cmp_m32_imm(DRCTOP, MABS((UINT8 *)code + 4), ((UINT32 *)code)[1]); // cmp [pc+4],opcode+4
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- }
- else if (length >= 4)
- {
- emit_cmp_m32_imm(DRCTOP, MABS(code), *(UINT32 *)code); // cmp [pc],opcode
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- }
- else if (length >= 2)
- {
- emit_cmp_m16_imm(DRCTOP, MABS(code), *(UINT16 *)code); // cmp [pc],opcode
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- }
- else
- {
- emit_cmp_m8_imm(DRCTOP, MABS(code), *(UINT8 *)code); // cmp [pc],opcode
- emit_jcc(DRCTOP, COND_NE, recompile); // jne recompile
- }
-}
-
-
-/*------------------------------------------------------------------
- drc_append_call_debugger
-------------------------------------------------------------------*/
-
-void drc_append_call_debugger(drc_core *drc)
-{
-#ifdef ENABLE_DEBUGGER
- if (Machine->debug_mode)
- {
- emit_link link;
- emit_cmp_m32_imm(DRCTOP, MABS(&Machine->debug_mode), 0); // cmp [Machine->debug_mode],0
- emit_jcc_short_link(DRCTOP, COND_E, &link); // je skip
- emit_sub_r32_imm(DRCTOP, REG_ESP, 12); // align stack
- drc_append_save_call_restore(drc, (x86code *)mame_debug_hook, 12); // save volatiles
- resolve_link(DRCTOP, &link);
- }
-#endif
-}
-
-
-/*------------------------------------------------------------------
- drc_append_save_volatiles
-------------------------------------------------------------------*/
-
-void drc_append_save_volatiles(drc_core *drc)
-{
- if (drc->icountptr && !drc->icount_in_memory)
- emit_mov_m32_r32(DRCTOP, MABS(drc->icountptr), REG_EBP);
- if (drc->pcptr && !drc->pc_in_memory)
- emit_mov_m32_r32(DRCTOP, MABS(drc->pcptr), REG_EDI);
- if (drc->esiptr)
- emit_mov_m32_r32(DRCTOP, MABS(drc->esiptr), REG_ESI);
-}
-
-
-/*------------------------------------------------------------------
- drc_append_restore_volatiles
-------------------------------------------------------------------*/
-
-void drc_append_restore_volatiles(drc_core *drc)
-{
- if (drc->icountptr && !drc->icount_in_memory)
- emit_mov_r32_m32(DRCTOP, REG_EBP, MABS(drc->icountptr));
- if (drc->pcptr && !drc->pc_in_memory)
- emit_mov_r32_m32(DRCTOP, REG_EDI, MABS(drc->pcptr));
- if (drc->esiptr)
- emit_mov_r32_m32(DRCTOP, REG_ESI, MABS(drc->esiptr));
-}
-
-
-/*------------------------------------------------------------------
- drc_append_save_call_restore
-------------------------------------------------------------------*/
-
-void drc_append_save_call_restore(drc_core *drc, x86code *target, UINT32 stackadj)
-{
- drc_append_save_volatiles(drc); // save volatiles
- emit_call(DRCTOP, target); // call target
- drc_append_restore_volatiles(drc); // restore volatiles
- if (stackadj)
- emit_add_r32_imm(DRCTOP, REG_ESP, stackadj); // adjust stack
-}
-
-
-/*------------------------------------------------------------------
- drc_append_standard_epilogue
-------------------------------------------------------------------*/
-
-void drc_append_standard_epilogue(drc_core *drc, INT32 cycles, INT32 pcdelta, int allow_exit)
-{
- if (pcdelta != 0 && drc->pc_in_memory)
- emit_add_m32_imm(DRCTOP, MABS(drc->pcptr), pcdelta); // add [pc],pcdelta
- if (cycles != 0)
- {
- if (drc->icount_in_memory)
- emit_sub_m32_imm(DRCTOP, MABS(drc->icountptr), cycles); // sub [icount],cycles
- else
- emit_sub_r32_imm(DRCTOP, REG_EBP, cycles); // sub ebp,cycles
- }
- if (pcdelta != 0 && !drc->pc_in_memory)
- emit_lea_r32_m32(DRCTOP, REG_EDI, MBD(REG_EDI, pcdelta)); // lea edi,[edi+pcdelta]
- if (allow_exit && cycles != 0)
- emit_jcc(DRCTOP, COND_S, drc->out_of_cycles); // js out_of_cycles
-}
-
-
-/*------------------------------------------------------------------
- drc_append_dispatcher
-------------------------------------------------------------------*/
-
-void drc_append_dispatcher(drc_core *drc)
-{
-#if LOG_DISPATCHES
- emit_sub_r32_imm(DRCTOP, REG_ESP, 8); // align stack
- emit_push_imm(DRCTOP, drc); // push drc
- drc_append_save_call_restore(drc, (x86code *)log_dispatch, 12); // call log_dispatch
-#endif
- if (drc->pc_in_memory)
- emit_mov_r32_m32(DRCTOP, REG_EDI, MABS(drc->pcptr)); // mov edi,[pc]
- emit_mov_r32_r32(DRCTOP, REG_EAX, REG_EDI); // mov eax,edi
- emit_shr_r32_imm(DRCTOP, REG_EAX, drc->l1shift); // shr eax,l1shift
- emit_mov_r32_r32(DRCTOP, REG_EDX, REG_EDI); // mov edx,edi
- emit_mov_r32_m32(DRCTOP, REG_EAX, MISD(REG_EAX, 4, (FPTR)drc->lookup_l1)); // mov eax,[eax*4 + l1lookup]
- emit_and_r32_imm(DRCTOP, REG_EDX, drc->l2mask); // and edx,l2mask
- emit_jmp_m32(DRCTOP, MBISD(REG_EAX, REG_EDX, drc->l2scale, 0)); // jmp [eax+edx*l2scale]
-}
-
-
-/*------------------------------------------------------------------
- drc_append_fixed_dispatcher
-------------------------------------------------------------------*/
-
-void drc_append_fixed_dispatcher(drc_core *drc, UINT32 newpc)
-{
- x86code **base = drc->lookup_l1[newpc >> drc->l1shift];
- if (base == drc->lookup_l2_recompile)
- {
- emit_mov_r32_m32(DRCTOP, REG_EAX, MABS(&drc->lookup_l1[newpc >> drc->l1shift]));
- // mov eax,[(newpc >> l1shift)*4 + l1lookup]
- emit_jmp_m32(DRCTOP, MBD(REG_EAX, (newpc & drc->l2mask) * drc->l2scale));
- // jmp [eax+(newpc & l2mask)*l2scale]
- }
- else
- emit_jmp_m32(DRCTOP, MABS((UINT8 *)base + (newpc & drc->l2mask) * drc->l2scale));
- // jmp [eax+(newpc & l2mask)*l2scale]
-}
-
-
-/*------------------------------------------------------------------
- drc_append_tentative_fixed_dispatcher
-------------------------------------------------------------------*/
-
-void drc_append_tentative_fixed_dispatcher(drc_core *drc, UINT32 newpc)
-{
- pc_ptr_pair *pair = &drc->tentative_list[drc->tentative_count++];
- assert_always(drc->tentative_count <= drc->tentative_count_max, "drc_append_tentative_fixed_dispatcher: too many tentative branches!");
-
- pair->target = drc->cache_top;
- pair->pc = newpc;
- drc_append_fixed_dispatcher(drc, newpc);
-}
-
-
-/*------------------------------------------------------------------
- drc_append_set_fp_rounding
-------------------------------------------------------------------*/
-
-void drc_append_set_fp_rounding(drc_core *drc, UINT8 regindex)
-{
- emit_fldcw_m16(DRCTOP, MISD(regindex, 2, (INT32)&fp_control[0])); // fldcw [fp_control + reg*2]
- emit_fstcw_m16(DRCTOP, MABS(&drc->fpcw_curr)); // fnstcw [fpcw_curr]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_append_set_temp_fp_rounding
-------------------------------------------------------------------*/
-
-void drc_append_set_temp_fp_rounding(drc_core *drc, UINT8 rounding)
-{
- emit_fldcw_m16(DRCTOP, MABS(&fp_control[rounding])); // fldcw [fp_control]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_append_restore_fp_rounding
-------------------------------------------------------------------*/
-
-void drc_append_restore_fp_rounding(drc_core *drc)
-{
- emit_fldcw_m16(DRCTOP, MABS(&drc->fpcw_curr)); // fldcw [fpcw_curr]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_append_set_sse_rounding
-------------------------------------------------------------------*/
-
-void drc_append_set_sse_rounding(drc_core *drc, UINT8 regindex)
-{
- emit_ldmxcsr_m32(DRCTOP, MISD(regindex, 4, (INT32)&sse_control[0])); // ldmxcsr [sse_control + reg*2]
- emit_stmxcsr_m32(DRCTOP, MABS(&drc->mxcsr_curr)); // stmxcsr [mxcsr_curr]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_append_set_temp_sse_rounding
-------------------------------------------------------------------*/
-
-void drc_append_set_temp_sse_rounding(drc_core *drc, UINT8 rounding)
-{
- emit_ldmxcsr_m32(DRCTOP, MABS(&sse_control[rounding])); // ldmxcsr [sse_control]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_append_restore_sse_rounding
-------------------------------------------------------------------*/
-
-void drc_append_restore_sse_rounding(drc_core *drc)
-{
- emit_ldmxcsr_m32(DRCTOP, MABS(&drc->mxcsr_curr)); // ldmxcsr [mxcsr_curr]
-}
-
-
-
-/*------------------------------------------------------------------
- drc_dasm
-
- An attempt to make a disassembler for DRC code; currently limited
- by the functionality of DasmI386
-------------------------------------------------------------------*/
-
-void drc_dasm(FILE *f, const void *begin, const void *end)
-{
- extern int i386_dasm_one(char *buffer, UINT32 eip, UINT8 *oprom, int mode);
-
- char buffer[256];
- const UINT8 *begin_ptr = (const UINT8 *) begin;
- const UINT8 *end_ptr = (const UINT8 *) end;
- UINT32 pc = (UINT32) begin;
- int length;
-
- while(begin_ptr < end_ptr)
- {
-#if defined(ENABLE_DEBUGGER) && HAS_I386
- length = i386_dasm_one(buffer, pc, (UINT8 *) begin_ptr, 32) & DASMFLAG_LENGTHMASK;
-#else
- sprintf(buffer, "%02X", *begin_ptr);
- length = 1;
-#endif
-
- fprintf(f, "%08X:\t%s\n", (unsigned) pc, buffer);
- begin_ptr += length;
- pc += length;
- }
-}
-
-
-
-
-/***************************************************************************
- INTERNAL CODEGEN
-***************************************************************************/
-
-/*------------------------------------------------------------------
- append_entry_point
-------------------------------------------------------------------*/
-
-static void append_entry_point(drc_core *drc)
-{
- emit_pushad(DRCTOP); // pushad
- if (drc->uses_fp)
- {
- emit_fstcw_m16(DRCTOP, MABS(&drc->fpcw_save)); // fstcw [fpcw_save]
- emit_fldcw_m16(DRCTOP, MABS(&drc->fpcw_curr)); // fldcw [fpcw_curr]
- }
- if (drc->uses_sse)
- {
- emit_stmxcsr_m32(DRCTOP, MABS(&drc->mxcsr_save)); // stmxcsr [mxcsr_save]
- emit_ldmxcsr_m32(DRCTOP, MABS(&drc->mxcsr_curr)); // ldmxcsr [mxcsr_curr]
- }
- drc_append_restore_volatiles(drc); // load volatiles
- if (drc->cb_entrygen)
- (*drc->cb_entrygen)(drc); // additional entry point duties
- drc_append_dispatcher(drc); // dispatch
-}
-
-
-/*------------------------------------------------------------------
- recompile_code
-------------------------------------------------------------------*/
-
-static void recompile_code(drc_core *drc)
-{
- if (drc->cache_top >= drc->cache_danger)
- drc_cache_reset(drc);
- (*drc->cb_recompile)(drc);
-}
-
-
-/*------------------------------------------------------------------
- append_recompile
-------------------------------------------------------------------*/
-
-static void append_recompile(drc_core *drc)
-{
- emit_sub_r32_imm(DRCTOP, REG_ESP, 8); // align stack
- emit_push_imm(DRCTOP, (FPTR)drc); // push drc
- drc_append_save_call_restore(drc, (x86code *)recompile_code, 12); // call recompile_code
- drc_append_dispatcher(drc); // dispatch
-}
-
-
-/*------------------------------------------------------------------
- append_flush
-------------------------------------------------------------------*/
-
-static void append_flush(drc_core *drc)
-{
- emit_sub_r32_imm(DRCTOP, REG_ESP, 8); // align stack
- emit_push_imm(DRCTOP, (FPTR)drc); // push drc
- drc_append_save_call_restore(drc, (x86code *)drc_cache_reset, 12); // call drc_cache_reset
- drc_append_dispatcher(drc); // dispatch
-}
-
-
-/*------------------------------------------------------------------
- append_out_of_cycles
-------------------------------------------------------------------*/
-
-static void append_out_of_cycles(drc_core *drc)
-{
- drc_append_save_volatiles(drc); // save volatiles
- if (drc->uses_fp)
- {
- emit_fclex(DRCTOP); // fnclex
- emit_fldcw_m16(DRCTOP, MABS(&drc->fpcw_save)); // fldcw [fpcw_save]
- }
- if (drc->uses_sse)
- emit_ldmxcsr_m32(DRCTOP, MABS(&drc->mxcsr_save)); // ldmxcsr [mxcsr_save]
- emit_popad(DRCTOP); // popad
- emit_ret(DRCTOP); // ret
-}
-
-
-
-/*------------------------------------------------------------------
- drc_x86_get_features()
-------------------------------------------------------------------*/
-UINT32 drc_x86_get_features(void)
-{
- UINT32 features = 0;
-#ifdef _MSC_VER
- __asm
- {
- mov eax, 1
- xor ebx, ebx
- xor ecx, ecx
- xor edx, edx
- __asm _emit 0Fh __asm _emit 0A2h // cpuid
- mov features, edx
- }
-#else /* !_MSC_VER */
- __asm__
- (
- "pushl %%ebx ; "
- "movl $1,%%eax ; "
- "xorl %%ebx,%%ebx ; "
- "xorl %%ecx,%%ecx ; "
- "xorl %%edx,%%edx ; "
- "cpuid ; "
- "movl %%edx,%0 ; "
- "popl %%ebx ; "
- : "=&a" (features) /* result has to go in eax */
- : /* no inputs */
- : "%ecx", "%edx" /* clobbers ebx, ecx and edx */
- );
-#endif /* MSC_VER */
- return features;
-}
-
-
-
-/*------------------------------------------------------------------
- log_dispatch
-------------------------------------------------------------------*/
-
-#if LOG_DISPATCHES
-static void log_dispatch(drc_core *drc)
-{
- if (input_code_pressed(KEYCODE_D))
- logerror("Disp:%08X\n", *drc->pcptr);
-}
-#endif
diff --git a/src/emu/cpu/x86drc.h b/src/emu/cpu/x86drc.h
deleted file mode 100644
index b0b670fee65..00000000000
--- a/src/emu/cpu/x86drc.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/***************************************************************************
-
- x86drc.h
-
- x86 Dynamic recompiler support routines.
-
- Copyright Nicola Salmoria and the MAME Team.
- Visit http://mamedev.org for licensing and usage restrictions.
-
-***************************************************************************/
-
-#pragma once
-
-#ifndef __X86DRC_H__
-#define __X86DRC_H__
-
-#include "cpuintrf.h"
-#include "x86emit.h"
-
-
-/***************************************************************************
- TYPE DEFINITIONS
-***************************************************************************/
-
-/* PC and pointer pair */
-typedef struct _pc_ptr_pair pc_ptr_pair;
-struct _pc_ptr_pair
-{
- UINT32 pc;
- x86code * target;
-};
-
-
-/* core interface structure for the drc common code */
-typedef struct _drc_core drc_core;
-struct _drc_core
-{
- UINT8 * cache_base; /* base pointer to the compiler cache */
- UINT8 * cache_top; /* current top of cache */
- UINT8 * cache_danger; /* high water mark for the end */
- UINT8 * cache_end; /* end of cache memory */
- size_t cache_size; /* cache allocated size */
- UINT8 cache_allocated; /* did the DRC core allocate the cache? */
-
- x86code *** lookup_l1; /* level 1 lookup */
- x86code ** lookup_l2_recompile; /* level 2 lookup populated with recompile pointers */
- UINT8 l1bits; /* number of bits in level 1 lookup */
- UINT8 l2bits; /* number of bits in level 2 lookup */
- UINT8 l1shift; /* shift to go from PC to level 1 lookup */
- UINT32 l2mask; /* mask to go from PC to level 2 lookup */
- UINT8 l2scale; /* scale to get from masked PC value to final level 2 lookup */
-
- void (*entry_point)(void); /* pointer to asm entry point */
- x86code * out_of_cycles; /* pointer to out of cycles jump point */
- x86code * recompile; /* pointer to recompile jump point */
- x86code * dispatch; /* pointer to dispatch jump point */
- x86code * flush; /* pointer to flush jump point */
-
- UINT32 * pcptr; /* pointer to where the PC is stored */
- UINT32 * icountptr; /* pointer to where the icount is stored */
- UINT32 * esiptr; /* pointer to where the volatile data in ESI is stored */
- UINT8 pc_in_memory; /* true if the PC is stored in memory */
- UINT8 icount_in_memory; /* true if the icount is stored in memory */
-
- UINT8 uses_fp; /* true if we need the FP unit */
- UINT8 uses_sse; /* true if we need the SSE unit */
- UINT16 fpcw_curr; /* current FPU control word */
- UINT32 mxcsr_curr; /* current SSE control word */
- UINT16 fpcw_save; /* saved FPU control word */
- UINT32 mxcsr_save; /* saved SSE control word */
-
- pc_ptr_pair *sequence_list; /* PC/pointer sets for the current instruction sequence */
- UINT32 sequence_count; /* number of instructions in the current sequence */
- UINT32 sequence_count_max; /* max number of instructions in the current sequence */
- pc_ptr_pair *tentative_list; /* PC/pointer sets for tentative branches */
- UINT32 tentative_count; /* number of tentative branches */
- UINT32 tentative_count_max; /* max number of tentative branches */
-
- void (*cb_reset)(struct _drc_core *drc); /* callback when the cache is reset */
- void (*cb_recompile)(struct _drc_core *drc); /* callback when code needs to be recompiled */
- void (*cb_entrygen)(struct _drc_core *drc); /* callback before generating the dispatcher on entry */
-};
-
-
-/* configuration structure for the drc common code */
-typedef struct _drc_config drc_config;
-struct _drc_config
-{
- UINT8 * cache_base; /* base pointer to the compiler cache */
- UINT32 cache_size; /* size of cache to allocate */
- UINT32 max_instructions; /* maximum instructions per sequence */
- UINT8 address_bits; /* number of live address bits in the PC */
- UINT8 lsbs_to_ignore; /* number of LSBs to ignore on the PC */
- UINT8 uses_fp; /* true if we need the FP unit */
- UINT8 uses_sse; /* true if we need the SSE unit */
- UINT8 pc_in_memory; /* true if the PC is stored in memory */
- UINT8 icount_in_memory; /* true if the icount is stored in memory */
-
- UINT32 * pcptr; /* pointer to where the PC is stored */
- UINT32 * icountptr; /* pointer to where the icount is stored */
- UINT32 * esiptr; /* pointer to where the volatile data in ESI is stored */
-
- void (*cb_reset)(drc_core *drc); /* callback when the cache is reset */
- void (*cb_recompile)(drc_core *drc); /* callback when code needs to be recompiled */
- void (*cb_entrygen)(drc_core *drc); /* callback before generating the dispatcher on entry */
-};
-
-
-/* structure to hold link data to be filled in later */
-typedef struct _link_info link_info;
-struct _link_info
-{
- UINT8 size;
- UINT8 * target;
-};
-
-
-
-/***************************************************************************
- MACROS
-***************************************************************************/
-
-/* use this macro in emit_* instructions to make them shorter */
-#define DRCTOP &drc->cache_top
-
-
-
-/***************************************************************************
- HELPER MACROS
-***************************************************************************/
-
-/* useful macros for accessing hi/lo portions of 64-bit values */
-#define LO(x) (&(((UINT32 *)(UINT32)(x))[0]))
-#define HI(x) (&(((UINT32 *)(UINT32)(x))[1]))
-
-
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-/* features */
-#define CPUID_FEATURES_MMX (1 << 23)
-#define CPUID_FEATURES_SSE (1 << 26)
-#define CPUID_FEATURES_SSE2 (1 << 25)
-#define CPUID_FEATURES_CMOV (1 << 15)
-#define CPUID_FEATURES_TSC (1 << 4)
-
-
-
-/***************************************************************************
- FUNCTION PROTOTYPES
-***************************************************************************/
-
-/* init/shutdown */
-drc_core *drc_init(UINT8 cpunum, drc_config *config);
-void *drc_alloc(drc_core *drc, size_t amount);
-void drc_cache_reset(drc_core *drc);
-void drc_execute(drc_core *drc);
-void drc_exit(drc_core *drc);
-
-/* code management */
-void drc_begin_sequence(drc_core *drc, UINT32 pc);
-void drc_end_sequence(drc_core *drc);
-void drc_register_code_at_cache_top(drc_core *drc, UINT32 pc);
-void *drc_get_code_at_pc(drc_core *drc, UINT32 pc);
-
-/* standard appendages */
-void drc_append_dispatcher(drc_core *drc);
-void drc_append_fixed_dispatcher(drc_core *drc, UINT32 newpc);
-void drc_append_tentative_fixed_dispatcher(drc_core *drc, UINT32 newpc);
-void drc_append_call_debugger(drc_core *drc);
-void drc_append_standard_epilogue(drc_core *drc, INT32 cycles, INT32 pcdelta, int allow_exit);
-void drc_append_save_volatiles(drc_core *drc);
-void drc_append_restore_volatiles(drc_core *drc);
-void drc_append_save_call_restore(drc_core *drc, x86code *target, UINT32 stackadj);
-void drc_append_verify_code(drc_core *drc, void *code, UINT8 length);
-
-void drc_append_set_fp_rounding(drc_core *drc, UINT8 regindex);
-void drc_append_set_temp_fp_rounding(drc_core *drc, UINT8 rounding);
-void drc_append_restore_fp_rounding(drc_core *drc);
-
-void drc_append_set_sse_rounding(drc_core *drc, UINT8 regindex);
-void drc_append_set_temp_sse_rounding(drc_core *drc, UINT8 rounding);
-void drc_append_restore_sse_rounding(drc_core *drc);
-
-/* disassembling drc code */
-void drc_dasm(FILE *f, const void *begin, const void *end);
-
-/* x86 CPU features */
-UINT32 drc_x86_get_features(void);
-
-
-#endif /* __X86DRC_H__ */
diff --git a/src/emu/cpuexec.h b/src/emu/cpuexec.h
index fe7a64f8964..dbc608f391e 100644
--- a/src/emu/cpuexec.h
+++ b/src/emu/cpuexec.h
@@ -200,10 +200,13 @@ enum _cpu_type
CPU_V810,
CPU_M37702,
CPU_M37710,
- CPU_PPC403,
+ CPU_PPC403GA,
+ CPU_PPC403GCX,
CPU_PPC601,
CPU_PPC602,
CPU_PPC603,
+ CPU_PPC603E,
+ CPU_PPC603R,
CPU_PPC604,
CPU_MPC8240,
CPU_SE3208,
diff --git a/src/emu/cpuintrf.c b/src/emu/cpuintrf.c
index 6eb80089ed6..dd5094db184 100644
--- a/src/emu/cpuintrf.c
+++ b/src/emu/cpuintrf.c
@@ -172,10 +172,13 @@ void h8_3044_get_info(UINT32 state, cpuinfo *info);
void v810_get_info(UINT32 state, cpuinfo *info);
void m37702_get_info(UINT32 state, cpuinfo *info);
void m37710_get_info(UINT32 state, cpuinfo *info);
-void ppc403_get_info(UINT32 state, cpuinfo *info);
+void ppc403ga_get_info(UINT32 state, cpuinfo *info);
+void ppc403gcx_get_info(UINT32 state, cpuinfo *info);
void ppc601_get_info(UINT32 state, cpuinfo *info);
void ppc602_get_info(UINT32 state, cpuinfo *info);
void ppc603_get_info(UINT32 state, cpuinfo *info);
+void ppc603e_get_info(UINT32 state, cpuinfo *info);
+void ppc603r_get_info(UINT32 state, cpuinfo *info);
void ppc604_get_info(UINT32 state, cpuinfo *info);
void mpc8240_get_info(UINT32 state, cpuinfo *info);
void SE3208_get_info(UINT32 state, cpuinfo *info);
@@ -709,8 +712,11 @@ static const struct
#if (HAS_M37710)
{ CPU_M37710, m37710_get_info },
#endif
-#if (HAS_PPC403)
- { CPU_PPC403, ppc403_get_info },
+#if (HAS_PPC403GA)
+ { CPU_PPC403GA, ppc403ga_get_info },
+#endif
+#if (HAS_PPC403GCX)
+ { CPU_PPC403GCX, ppc403gcx_get_info },
#endif
#if (HAS_PPC601)
{ CPU_PPC601, ppc601_get_info },
@@ -721,6 +727,12 @@ static const struct
#if (HAS_PPC603)
{ CPU_PPC603, ppc603_get_info },
#endif
+#if (HAS_PPC603E)
+ { CPU_PPC603E, ppc603e_get_info },
+#endif
+#if (HAS_PPC603R)
+ { CPU_PPC603R, ppc603r_get_info },
+#endif
#if (HAS_PPC604)
{ CPU_PPC604, ppc604_get_info },
#endif
diff --git a/src/emu/memory.c b/src/emu/memory.c
index 2eb23638e5a..efb2d615d7a 100644
--- a/src/emu/memory.c
+++ b/src/emu/memory.c
@@ -3164,7 +3164,7 @@ static WRITE32_HANDLER( stub_write8_from_32 )
while (subunits-- != 0)
{
int shift = *subshift++;
- if ((UINT8)(mem_mask >> shift) != 0xff)
+ if ((UINT8)(mem_mask >> shift) != 0)
(*handler->subhandler.write.mhandler8)(handler->subobject, offset, data >> shift);
offset++;
}
diff --git a/src/mame/drivers/firebeat.c b/src/mame/drivers/firebeat.c
index 468d23ae0ce..026a9e648f9 100644
--- a/src/mame/drivers/firebeat.c
+++ b/src/mame/drivers/firebeat.c
@@ -1985,16 +1985,10 @@ static MACHINE_RESET( firebeat )
cdda_set_cdrom(0, cd);
}
-static const ppc_config firebeat_ppc_cfg =
-{
- PPC_MODEL_403GCX
-};
-
static MACHINE_DRIVER_START(firebeat)
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 66000000)
- MDRV_CPU_CONFIG(firebeat_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GCX, 66000000)
MDRV_CPU_PROGRAM_MAP(firebeat_map, 0)
MDRV_CPU_VBLANK_INT("main", firebeat_interrupt)
@@ -2032,8 +2026,7 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START(firebeat2)
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 66000000)
- MDRV_CPU_CONFIG(firebeat_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GCX, 66000000)
MDRV_CPU_PROGRAM_MAP(firebeat_map, 0)
MDRV_CPU_VBLANK_INT("left", firebeat_interrupt)
@@ -2232,9 +2225,7 @@ static void security_w(UINT8 data)
{
int r = ibutton_w(data);
if (r >= 0)
- {
- ppc403_spu_rx(r & 0xff);
- }
+ cpunum_set_info_int(0, CPUINFO_INT_PPC_RX_DATA, r & 0xff);
}
/*****************************************************************************/
@@ -2269,7 +2260,7 @@ static void init_firebeat(running_machine *machine)
cur_cab_data = cab_data;
- ppc403_install_spu_tx_handler(security_w);
+ cpunum_set_info_fct(0, CPUINFO_PTR_SPU_TX_HANDLER, (genf *)security_w);
set_ibutton(rom);
diff --git a/src/mame/drivers/gticlub.c b/src/mame/drivers/gticlub.c
index b7c9b5c27cc..7203af4b0ce 100644
--- a/src/mame/drivers/gticlub.c
+++ b/src/mame/drivers/gticlub.c
@@ -366,9 +366,9 @@ static WRITE32_HANDLER( sysreg_w )
}
/* Konami K056230 (LANC) */
-static UINT8 K056230_r(int reg)
+READ8_HANDLER( K056230_r )
{
- switch (reg)
+ switch (offset)
{
case 0: // Status register
{
@@ -376,14 +376,19 @@ static UINT8 K056230_r(int reg)
}
}
-// mame_printf_debug("K056230_r: %d at %08X\n", reg, activecpu_get_pc());
+// mame_printf_debug("K056230_r: %d at %08X\n", offset, activecpu_get_pc());
return 0;
}
-static void K056230_w(int reg, UINT8 data)
+TIMER_CALLBACK( network_irq_gen )
{
- switch (reg)
+ cpunum_set_input_line(Machine, 0, INPUT_LINE_IRQ2, ASSERT_LINE);
+}
+
+WRITE8_HANDLER( K056230_w )
+{
+ switch (offset)
{
case 0: // Mode register
{
@@ -396,9 +401,12 @@ static void K056230_w(int reg, UINT8 data)
// Thunder Hurricane breaks otherwise...
if (mame_stricmp(Machine->gamedrv->name, "thunderh") != 0)
{
- cpunum_set_input_line(Machine, 0, INPUT_LINE_IRQ2, ASSERT_LINE);
+// timer_set(ATTOTIME_IN_MSEC(1), NULL, 0, network_irq_gen);
+// cpunum_set_input_line(Machine, 0, INPUT_LINE_IRQ2, ASSERT_LINE);
}
}
+ else
+ cpunum_set_input_line(Machine, 0, INPUT_LINE_IRQ2, CLEAR_LINE);
break;
}
case 2: // Sub ID register
@@ -406,54 +414,7 @@ static void K056230_w(int reg, UINT8 data)
break;
}
}
-// mame_printf_debug("K056230_w: %d, %02X at %08X\n", reg, data, activecpu_get_pc());
-}
-
-READ32_HANDLER( lanc_r )
-{
- UINT32 r = 0;
- int reg = offset * 4;
-
- if (ACCESSING_BITS_24_31)
- {
- r |= K056230_r(reg+0) << 24;
- }
- if (ACCESSING_BITS_16_23)
- {
- r |= K056230_r(reg+1) << 16;
- }
- if (ACCESSING_BITS_8_15)
- {
- r |= K056230_r(reg+2) << 8;
- }
- if (ACCESSING_BITS_0_7)
- {
- r |= K056230_r(reg+3) << 0;
- }
-
- return r;
-}
-
-WRITE32_HANDLER( lanc_w )
-{
- int reg = offset * 4;
-
- if (ACCESSING_BITS_24_31)
- {
- K056230_w(reg+0, (data >> 24) & 0xff);
- }
- if (ACCESSING_BITS_16_23)
- {
- K056230_w(reg+1, (data >> 16) & 0xff);
- }
- if (ACCESSING_BITS_8_15)
- {
- K056230_w(reg+2, (data >> 8) & 0xff);
- }
- if (ACCESSING_BITS_0_7)
- {
- K056230_w(reg+3, (data >> 0) & 0xff);
- }
+// mame_printf_debug("K056230_w: %d, %02X at %08X\n", offset, data, activecpu_get_pc());
}
static UINT32 lanc_ram[0x2000/4];
@@ -482,7 +443,7 @@ static ADDRESS_MAP_START( gticlub_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x78080000, 0x7808000f) AM_MIRROR(0x80000000) AM_READWRITE(K001006_1_r, K001006_1_w)
AM_RANGE(0x780c0000, 0x780c0003) AM_MIRROR(0x80000000) AM_READWRITE(cgboard_dsp_comm_r_ppc, cgboard_dsp_comm_w_ppc)
AM_RANGE(0x7e000000, 0x7e003fff) AM_MIRROR(0x80000000) AM_READWRITE(sysreg_r, sysreg_w)
- AM_RANGE(0x7e008000, 0x7e009fff) AM_MIRROR(0x80000000) AM_READWRITE(lanc_r, lanc_w)
+ AM_RANGE(0x7e008000, 0x7e009fff) AM_MIRROR(0x80000000) AM_READWRITE8(K056230_r, K056230_w, 0xffffffff)
AM_RANGE(0x7e00a000, 0x7e00bfff) AM_MIRROR(0x80000000) AM_READWRITE(lanc_ram_r, lanc_ram_w)
AM_RANGE(0x7e00c000, 0x7e00c007) AM_MIRROR(0x80000000) AM_WRITE(K056800_host_w)
AM_RANGE(0x7e00c000, 0x7e00c007) AM_MIRROR(0x80000000) AM_READ(K056800_host_r) // Hang Pilot
@@ -747,11 +708,6 @@ static INTERRUPT_GEN( gticlub_vblank )
}
-static const ppc_config gticlub_ppc_cfg =
-{
- PPC_MODEL_403GA
-};
-
static const sharc_config sharc_cfg =
{
BOOT_MODE_EPROM
@@ -770,8 +726,7 @@ static MACHINE_RESET( gticlub )
static MACHINE_DRIVER_START( gticlub )
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 64000000/2) /* PowerPC 403GA 32MHz */
- MDRV_CPU_CONFIG(gticlub_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GA, 64000000/2) /* PowerPC 403GA 32MHz */
MDRV_CPU_PROGRAM_MAP(gticlub_map, 0)
MDRV_CPU_VBLANK_INT("main", gticlub_vblank)
@@ -816,8 +771,7 @@ static MACHINE_RESET( hangplt )
static MACHINE_DRIVER_START( hangplt )
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 64000000/2) /* PowerPC 403GA 32MHz */
- MDRV_CPU_CONFIG(gticlub_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GA, 64000000/2) /* PowerPC 403GA 32MHz */
MDRV_CPU_PROGRAM_MAP(gticlub_map, 0)
MDRV_CPU_ADD(M68000, 64000000/4) /* 16MHz */
@@ -1043,7 +997,7 @@ static DRIVER_INIT(slrasslt)
DRIVER_INIT_CALL(gticlub);
// enable self-modifying code checks
- cpunum_set_info_int(0, CPUINFO_INT_PPC_DRC_OPTIONS, PPCDRC_OPTIONS_CHECK_SELFMOD_CODE);
+ cpunum_set_info_int(0, CPUINFO_INT_PPC_DRC_OPTIONS, PPCDRC_STRICT_VERIFY);
}
/*************************************************************************/
diff --git a/src/mame/drivers/hornet.c b/src/mame/drivers/hornet.c
index 4ca6c4ce5d9..6feaaf2d6ac 100644
--- a/src/mame/drivers/hornet.c
+++ b/src/mame/drivers/hornet.c
@@ -683,71 +683,52 @@ static VIDEO_UPDATE( hornet_2board )
}
/*****************************************************************************/
+static UINT32 *workram;
-static READ32_HANDLER( sysreg_r )
+static READ8_HANDLER( sysreg_r )
{
- UINT32 r = 0;
- if (offset == 0)
- {
- if (ACCESSING_BITS_24_31)
- {
- //printf("read sysreg 0\n");
- r |= input_port_read_indexed(machine, 0) << 24;
- }
- if (ACCESSING_BITS_16_23)
- {
- r |= input_port_read_indexed(machine, 1) << 16;
- }
- if (ACCESSING_BITS_8_15)
- {
- r |= input_port_read_indexed(machine, 2) << 8;
- }
- if (ACCESSING_BITS_0_7)
- {
- r |= 0xf7;
- }
- }
- else if (offset == 1)
+ UINT8 r = 0;
+
+ switch (offset)
{
- if (ACCESSING_BITS_24_31)
- {
- r |= input_port_read_indexed(machine, 3) << 24;
- }
+ case 0:
+ case 1:
+ case 2:
+ r = input_port_read_indexed(machine, offset);
+ break;
+
+ case 3:
+ r = 0xf7;
+ break;
+
+ case 4:
+ r = input_port_read_indexed(machine, 3);
+ break;
}
return r;
}
-static WRITE32_HANDLER( sysreg_w )
+static WRITE8_HANDLER( sysreg_w )
{
- if( offset == 0 ) {
- if (ACCESSING_BITS_24_31)
- {
- led_reg0 = (data >> 24) & 0xff;
- }
- if (ACCESSING_BITS_16_23)
- {
- led_reg1 = (data >> 16) & 0xff;
- }
- return;
- }
- if( offset == 1 )
+ switch (offset)
{
- if (ACCESSING_BITS_24_31)
- {
- }
- if (ACCESSING_BITS_0_7)
- {
+ case 0:
+ led_reg0 = data;
+ break;
+
+ case 1:
+ led_reg1 = data;
+ break;
+
+ case 7:
if (data & 0x80) /* CG Board 1 IRQ Ack */
- {
cpunum_set_input_line(machine, 0, INPUT_LINE_IRQ1, CLEAR_LINE);
- }
+
if (data & 0x40) /* CG Board 0 IRQ Ack */
- {
cpunum_set_input_line(machine, 0, INPUT_LINE_IRQ0, CLEAR_LINE);
- }
+
set_cgboard_id((data >> 4) & 0x3);
- }
- return;
+ break;
}
}
@@ -778,14 +759,14 @@ static READ32_HANDLER( comm0_unk_r )
/*****************************************************************************/
static ADDRESS_MAP_START( hornet_map, ADDRESS_SPACE_PROGRAM, 32 )
- AM_RANGE(0x00000000, 0x003fffff) AM_MIRROR(0x80000000) AM_RAM /* Work RAM */
+ AM_RANGE(0x00000000, 0x003fffff) AM_MIRROR(0x80000000) AM_RAM AM_BASE(&workram) /* Work RAM */
AM_RANGE(0x74000000, 0x740000ff) AM_MIRROR(0x80000000) AM_READWRITE(K037122_reg_r, K037122_reg_w)
AM_RANGE(0x74020000, 0x7403ffff) AM_MIRROR(0x80000000) AM_READWRITE(K037122_sram_r, K037122_sram_w)
AM_RANGE(0x74040000, 0x7407ffff) AM_MIRROR(0x80000000) AM_READWRITE(K037122_char_r, K037122_char_w)
AM_RANGE(0x78000000, 0x7800ffff) AM_MIRROR(0x80000000) AM_READWRITE(cgboard_dsp_shared_r_ppc, cgboard_dsp_shared_w_ppc)
AM_RANGE(0x780c0000, 0x780c0003) AM_MIRROR(0x80000000) AM_READWRITE(cgboard_dsp_comm_r_ppc, cgboard_dsp_comm_w_ppc)
- AM_RANGE(0x7d000000, 0x7d00ffff) AM_MIRROR(0x80000000) AM_READ(sysreg_r)
- AM_RANGE(0x7d010000, 0x7d01ffff) AM_MIRROR(0x80000000) AM_WRITE(sysreg_w)
+ AM_RANGE(0x7d000000, 0x7d00ffff) AM_MIRROR(0x80000000) AM_READ8(sysreg_r, 0xffffffff)
+ AM_RANGE(0x7d010000, 0x7d01ffff) AM_MIRROR(0x80000000) AM_WRITE8(sysreg_w, 0xffffffff)
AM_RANGE(0x7d020000, 0x7d021fff) AM_MIRROR(0x80000000) AM_READWRITE(timekeeper_0_32be_r, timekeeper_0_32be_w) /* M48T58Y RTC/NVRAM */
AM_RANGE(0x7d030000, 0x7d030007) AM_MIRROR(0x80000000) AM_READWRITE(K056800_host_r, K056800_host_w)
AM_RANGE(0x7d042000, 0x7d043fff) AM_MIRROR(0x80000000) AM_RAM /* COMM BOARD 0 */
@@ -963,11 +944,6 @@ static const struct RF5C400interface rf5c400_interface =
REGION_SOUND1
};
-static const ppc_config hornet_ppc_cfg =
-{
- PPC_MODEL_403GA
-};
-
static sharc_config sharc_cfg =
{
BOOT_MODE_EPROM
@@ -983,6 +959,19 @@ static sharc_config sharc_cfg =
*/
+static MACHINE_START( hornet )
+{
+ /* set conservative DRC options */
+ cpunum_set_info_int(0, CPUINFO_INT_PPC_DRC_OPTIONS, PPCDRC_COMPATIBLE_OPTIONS);
+
+ /* configure fast RAM regions for DRC */
+ cpunum_set_info_int(0, CPUINFO_INT_PPC_FASTRAM_SELECT, 0);
+ cpunum_set_info_int(0, CPUINFO_INT_PPC_FASTRAM_START, 0x80000000);
+ cpunum_set_info_int(0, CPUINFO_INT_PPC_FASTRAM_END, 0x803fffff);
+ cpunum_set_info_ptr(0, CPUINFO_PTR_PPC_FASTRAM_BASE, workram);
+ cpunum_set_info_int(0, CPUINFO_INT_PPC_FASTRAM_READONLY, 0);
+}
+
static MACHINE_RESET( hornet )
{
if (memory_region(REGION_USER3))
@@ -996,8 +985,7 @@ static MACHINE_RESET( hornet )
static MACHINE_DRIVER_START( hornet )
/* basic machine hardware */
- MDRV_CPU_ADD_TAG("main", PPC403, 64000000/2) /* PowerPC 403GA 32MHz */
- MDRV_CPU_CONFIG(hornet_ppc_cfg)
+ MDRV_CPU_ADD_TAG("main", PPC403GA, 64000000/2) /* PowerPC 403GA 32MHz */
MDRV_CPU_PROGRAM_MAP(hornet_map, 0)
MDRV_CPU_ADD(M68000, 64000000/4) /* 16MHz */
@@ -1009,6 +997,7 @@ static MACHINE_DRIVER_START( hornet )
MDRV_INTERLEAVE(100)
+ MDRV_MACHINE_START( hornet )
MDRV_MACHINE_RESET( hornet )
MDRV_NVRAM_HANDLER( timekeeper_0 )
@@ -1079,25 +1068,34 @@ MACHINE_DRIVER_END
/*****************************************************************************/
+static void jamma_jvs_cmd_exec(void);
+
static UINT8 jvs_rdata[1024];
static UINT8 jvs_sdata[1024];
static int jvs_rdata_ptr = 0;
static int jvs_sdata_ptr = 0;
+static int jvs_rdata_count = 0;
-static UINT8 jamma_jvs_r(void)
+static int jamma_jvs_r(UINT8 *data)
{
- UINT8 r;
- r = jvs_rdata[jvs_rdata_ptr];
- jvs_rdata_ptr++;
-
- return r;
+ if (jvs_rdata_ptr < jvs_rdata_count)
+ {
+ *data = jvs_rdata[jvs_rdata_ptr++];
+ return TRUE;
+ }
+ return FALSE;
}
static void jamma_jvs_w(UINT8 data)
{
+ if (jvs_sdata_ptr == 0 && data != 0xe0)
+ return;
jvs_sdata[jvs_sdata_ptr] = data;
jvs_sdata_ptr++;
+
+ if (jvs_sdata_ptr >= 3 && jvs_sdata_ptr >= 3 + jvs_sdata[2])
+ jamma_jvs_cmd_exec();
}
static int jvs_encode_data(UINT8 *in, UINT8 *out, int length)
@@ -1160,13 +1158,7 @@ static void jamma_jvs_cmd_exec(void)
sync = jvs_sdata[0];
node = jvs_sdata[1];
byte_num = jvs_sdata[2];
-
- if (sync != 0xe0)
- {
- printf("jamma_jvs_cmd_exec: SYNC byte not found! (%02X)\n", sync);
- return;
- }
-
+
length = jvs_decode_data(&jvs_sdata[3], data, byte_num-1);
/*
@@ -1231,6 +1223,7 @@ static void jamma_jvs_cmd_exec(void)
// write sum
jvs_rdata[3+length] = (UINT8)(sum-1);
+ jvs_rdata_count = length + 4;
jvs_rdata_ptr = 0;
jvs_sdata_ptr = 0;
}
@@ -1238,30 +1231,6 @@ static void jamma_jvs_cmd_exec(void)
/*****************************************************************************/
-static UINT8 jamma_rdata[1024];
-static void jamma_r(int length)
-{
- int i;
-// printf("jamma_r %d\n", length);
- for (i=0; i < length; i++)
- {
- jamma_rdata[i] = jamma_jvs_r();
- }
-}
-
-static UINT8 jamma_wdata[1024];
-static void jamma_w(int length)
-{
- int i;
-// printf("jamma_w %d\n", length);
- for (i=0; i < length; i++)
- {
- jamma_jvs_w(jamma_wdata[i]);
- }
-
- jamma_jvs_cmd_exec();
-}
-
static void sound_irq_callback(running_machine *machine, int irq)
{
if (irq == 0)
@@ -1283,8 +1252,8 @@ static void init_hornet(running_machine *machine)
timekeeper_init(0, TIMEKEEPER_M48T58, backup_ram);
- ppc403_install_spu_tx_dma_handler(jamma_w, jamma_wdata);
- ppc403_install_spu_rx_dma_handler(jamma_r, jamma_rdata);
+ cpunum_set_info_fct(0, CPUINFO_PTR_SPU_TX_HANDLER, (genf *)jamma_jvs_w);
+ cpunum_set_info_fct(0, CPUINFO_PTR_SPU_RX_HANDLER, (genf *)jamma_jvs_r);
}
static void init_hornet_2board(running_machine *machine)
@@ -1301,8 +1270,8 @@ static void init_hornet_2board(running_machine *machine)
timekeeper_init(0, TIMEKEEPER_M48T58, backup_ram);
- ppc403_install_spu_tx_dma_handler(jamma_w, jamma_wdata);
- ppc403_install_spu_rx_dma_handler(jamma_r, jamma_rdata);
+ cpunum_set_info_fct(0, CPUINFO_PTR_SPU_TX_HANDLER, (genf *)jamma_jvs_w);
+ cpunum_set_info_fct(0, CPUINFO_PTR_SPU_RX_HANDLER, (genf *)jamma_jvs_r);
}
static DRIVER_INIT(gradius4)
diff --git a/src/mame/drivers/konamim2.c b/src/mame/drivers/konamim2.c
index faae530985e..250d506e764 100644
--- a/src/mame/drivers/konamim2.c
+++ b/src/mame/drivers/konamim2.c
@@ -1110,11 +1110,9 @@ static INPUT_PORTS_START( m2 )
INPUT_PORTS_END
-static const ppc_config ppc602_config =
+static const powerpc_config ppc602_config =
{
- PPC_MODEL_602,
- 0x20, /* Multiplier 2, Bus = 33MHz, Core = 66MHz */
- BUS_FREQUENCY_33MHZ
+ 33000000 /* Multiplier 2, Bus = 33MHz, Core = 66MHz */
};
static INTERRUPT_GEN(m2)
diff --git a/src/mame/drivers/model3.c b/src/mame/drivers/model3.c
index f5dd28a07d3..7aab404c588 100644
--- a/src/mame/drivers/model3.c
+++ b/src/mame/drivers/model3.c
@@ -365,8 +365,10 @@ ALL VROM ROMs are 16M MASK
#include "machine/53c810.h"
#include "sound/scsp.h"
-static int model3_irq_enable;
-int model3_irq_state;
+static UINT8 irq_enable;
+static UINT8 irq_state;
+static UINT8 scsi_irq_state;
+
int model3_step;
UINT32 *model3_vrom;
@@ -412,6 +414,25 @@ static void real3d_dma_callback(UINT32 src, UINT32 dst, int length, int byteswap
static UINT16 *model3_soundram;
+
+static void update_irq_state(running_machine *machine)
+{
+ if ((irq_enable & irq_state) || scsi_irq_state)
+ cpunum_set_input_line(machine, 0, PPC_IRQ, ASSERT_LINE);
+ else
+ cpunum_set_input_line(machine, 0, PPC_IRQ, CLEAR_LINE);
+}
+
+void model3_set_irq_line(running_machine *machine, UINT8 bit, int state)
+{
+ if (state != CLEAR_LINE)
+ irq_state |= bit;
+ else
+ irq_state &= ~bit;
+ update_irq_state(machine);
+}
+
+
#define BYTE_REVERSE32(x) (((x >> 24) & 0xff) | \
((x >> 8) & 0xff00) | \
((x << 8) & 0xff0000) | \
@@ -789,15 +810,9 @@ static UINT32 scsi_fetch(UINT32 dsp)
static void scsi_irq_callback(running_machine *machine, int state)
{
- if (state)
- {
- model3_irq_state |= model3_irq_enable & ~0x60; /* FIXME: enable only SCSI interrupt */
- cpunum_set_input_line(machine, 0, INPUT_LINE_IRQ1, ASSERT_LINE);
- }
- else
- {
- cpunum_set_input_line(machine, 0, INPUT_LINE_IRQ1, CLEAR_LINE);
- }
+ scsi_irq_state = state;
+// model3_irq_state |= irq_enable & ~0x60; /* FIXME: enable only SCSI interrupt */
+ update_irq_state(machine);
}
/*****************************************************************************/
@@ -1244,12 +1259,12 @@ static READ64_HANDLER( model3_sys_r )
}
else if (ACCESSING_BITS_24_31)
{
- return (model3_irq_enable<<24);
+ return (irq_enable<<24);
}
else logerror("m3_sys: Unk sys_r @ 0x10: mask = %x\n", (UINT32)mem_mask);
break;
case 0x18/8:
- return (UINT64)model3_irq_state<<56 | 0xff000000;
+ return (UINT64)irq_state<<56 | 0xff000000;
break;
}
@@ -1264,7 +1279,7 @@ static WRITE64_HANDLER( model3_sys_w )
case 0x10/8:
if (ACCESSING_BITS_24_31)
{
- model3_irq_enable = (data>>24)&0xff;
+ irq_enable = (data>>24)&0xff;
}
else logerror("m3_sys: unknown mask on IRQen write\n");
break;
@@ -1328,7 +1343,7 @@ static READ64_HANDLER(model3_sound_r)
static WRITE64_HANDLER(model3_sound_w)
{
- model3_irq_state &= ~0x40;
+ model3_set_irq_line(machine, 0x40, CLEAR_LINE);
// serial configuration writes
if ((mem_mask == U64(0xff00000000000000)) && (offset == 0))
@@ -1598,8 +1613,8 @@ static INPUT_PORTS_START( scud )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* View Button 2 */
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) /* View Button 3 */
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) /* View Button 4 */
- PORT_BIT( 0x50, IP_ACTIVE_LOW, IPT_BUTTON5 ) /* Shift 1 */
- PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_BUTTON6 ) /* Shift 2 */
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON5 ) /* Shift 1 */
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON6 ) /* Shift 2 */
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON7 ) /* Shift 3 */
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON8 ) /* Shift 4 */
@@ -1692,8 +1707,8 @@ static INPUT_PORTS_START( daytona2 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* View Button 2 */
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON3 ) /* View Button 3 */
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON4 ) /* View Button 4 */
- PORT_BIT( 0x50, IP_ACTIVE_LOW, IPT_BUTTON5 ) /* Shift 1 */
- PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_BUTTON6 ) /* Shift 2 */
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON5 ) /* Shift 1 */
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON6 ) /* Shift 2 */
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON7 ) /* Shift 3 */
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON8 ) /* Shift 4 */
@@ -1743,8 +1758,8 @@ static INPUT_PORTS_START( eca )
PORT_START
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* View Change */
PORT_BIT( 0x0e, IP_ACTIVE_LOW, IPT_UNUSED )
- PORT_BIT( 0x50, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* Shift Up */
- PORT_BIT( 0x60, IP_ACTIVE_LOW, IPT_BUTTON3 ) /* Shift Down */
+ PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* Shift Up */
+ PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON3 ) /* Shift Down */
PORT_START
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
@@ -4043,52 +4058,48 @@ static const struct SCSPinterface scsp2_interface =
/* IRQs */
/*
- 0x80: Unused ?
+ 0x80: Unknown (no clearing logic in scud)
0x40: SCSP
- 0x20: Unused ?
+ 0x20: Unknown (no clearing logic in scud)
0x10: Network
- 0x08: V-blank end ?
- 0x04: ???
- 0x02: V-blank start
- 0x01: Unused ?
+ 0x08: Video (unknown -- has callback hook in scud)
+ 0x04: Video (unknown -- has callback hook in scud)
+ 0x02: Video (VBLANK start?)
+ 0x01: Video (unused?)
*/
static int model3_vblank = 0;
static INTERRUPT_GEN(model3_interrupt)
{
if (model3_vblank == 0) {
- model3_irq_state = 0x42;
+ model3_set_irq_line(machine, 0x42, ASSERT_LINE);
} else {
- model3_irq_state = 0x0d;
+ model3_set_irq_line(machine, 0x0d, ASSERT_LINE);
}
- cpunum_set_input_line(machine, 0, INPUT_LINE_IRQ1, ASSERT_LINE);
model3_vblank++;
model3_vblank &= 1;
}
-static const ppc_config model3_10 =
+static const powerpc_config model3_10 =
{
- PPC_MODEL_603E, /* 603e, Stretch, 1.3 */
- 0x10, /* Multiplier 1, Bus = 66MHz, Core = 66MHz */
- BUS_FREQUENCY_66MHZ
+ /* 603e, Stretch, 1.3 */
+ 66000000 /* Multiplier 1, Bus = 66MHz, Core = 66MHz */
};
-static const ppc_config model3_15 =
+static const powerpc_config model3_15 =
{
- PPC_MODEL_603E, /* 603e, Stretch, 1.3 */
- 0x15, /* Multiplier 1.5, Bus = 66MHz, Core = 100MHz */
- BUS_FREQUENCY_66MHZ
+ /* 603e, Stretch, 1.3 */
+ 66000000 /* Multiplier 1.5, Bus = 66MHz, Core = 100MHz */
};
-static const ppc_config model3_2x =
+static const powerpc_config model3_2x =
{
- PPC_MODEL_603R, /* 603e-PID7t, Goldeneye, 2.1 */
- 0x25, /* Multiplier 2.5, Bus = 66MHz, Core = 166MHz */
- BUS_FREQUENCY_66MHZ
+ /* 603e-PID7t, Goldeneye, 2.1 */
+ 66000000 /* Multiplier 2.5, Bus = 66MHz, Core = 166MHz */
};
static MACHINE_DRIVER_START( model3_10 )
- MDRV_CPU_ADD(PPC603, 66000000)
+ MDRV_CPU_ADD(PPC603E, 66000000)
MDRV_CPU_CONFIG(model3_10)
MDRV_CPU_PROGRAM_MAP(model3_mem, 0)
MDRV_CPU_VBLANK_INT_HACK(model3_interrupt,2)
@@ -4128,7 +4139,7 @@ static MACHINE_DRIVER_START( model3_10 )
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( model3_15 )
- MDRV_CPU_ADD(PPC603, 100000000)
+ MDRV_CPU_ADD(PPC603E, 100000000)
MDRV_CPU_CONFIG(model3_15)
MDRV_CPU_PROGRAM_MAP(model3_mem, 0)
MDRV_CPU_VBLANK_INT_HACK(model3_interrupt,2)
@@ -4166,7 +4177,7 @@ static MACHINE_DRIVER_START( model3_15 )
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( model3_20 )
- MDRV_CPU_ADD(PPC603, 166000000)
+ MDRV_CPU_ADD(PPC603R, 166000000)
MDRV_CPU_CONFIG(model3_2x)
MDRV_CPU_PROGRAM_MAP(model3_mem, 0)
MDRV_CPU_VBLANK_INT_HACK(model3_interrupt,2)
@@ -4203,7 +4214,7 @@ static MACHINE_DRIVER_START( model3_20 )
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( model3_21 )
- MDRV_CPU_ADD(PPC603, 166000000)
+ MDRV_CPU_ADD(PPC603R, 166000000)
MDRV_CPU_CONFIG(model3_2x)
MDRV_CPU_PROGRAM_MAP(model3_mem, 0)
MDRV_CPU_VBLANK_INT_HACK(model3_interrupt,2)
diff --git a/src/mame/drivers/nwk-tr.c b/src/mame/drivers/nwk-tr.c
index 4926f6819c7..ea45b373d18 100644
--- a/src/mame/drivers/nwk-tr.c
+++ b/src/mame/drivers/nwk-tr.c
@@ -881,11 +881,6 @@ static const struct RF5C400interface rf5c400_interface =
REGION_SOUND1
};
-static const ppc_config nwktr_ppc_cfg =
-{
- PPC_MODEL_403GA
-};
-
static const sharc_config sharc_cfg =
{
BOOT_MODE_EPROM
@@ -899,8 +894,7 @@ static MACHINE_RESET( nwktr )
static MACHINE_DRIVER_START( nwktr )
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 64000000/2) /* PowerPC 403GA 32MHz */
- MDRV_CPU_CONFIG(nwktr_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GA, 64000000/2) /* PowerPC 403GA 32MHz */
MDRV_CPU_PROGRAM_MAP(nwktr_map, 0)
MDRV_CPU_ADD(M68000, 64000000/4) /* 16MHz */
@@ -938,30 +932,6 @@ MACHINE_DRIVER_END
/*****************************************************************************/
-static UINT8 jamma_rdata[1024];
-static void jamma_r(int length)
-{
- int i;
- //printf("jamma_r %d\n", length);
- for (i=0; i < length; i++)
- {
- jamma_rdata[i] = 0;
- }
-}
-
-static UINT8 jamma_wdata[1024];
-static void jamma_w(int length)
-{
- int i;
- //printf("jamma_w %d\n", length);
- for (i=0; i < length; i++)
- {
- //jamma_jvs_w(jamma_wdata[i]);
- }
-
- //jamma_jvs_cmd_exec();
-}
-
static void sound_irq_callback(running_machine *machine, int irq)
{
if (irq == 0)
@@ -981,8 +951,8 @@ static DRIVER_INIT( nwktr )
K056800_init(sound_irq_callback);
K033906_init();
- ppc403_install_spu_tx_dma_handler(jamma_w, jamma_wdata);
- ppc403_install_spu_rx_dma_handler(jamma_r, jamma_rdata);
+// cpunum_set_info_fct(0, CPUINFO_PTR_SPU_TX_HANDLER, (genf *)jamma_jvs_w);
+// cpunum_set_info_fct(0, CPUINFO_PTR_SPU_RX_HANDLER, (genf *)jamma_jvs_r);
adc1213x_init(0, adc12138_input_callback);
}
diff --git a/src/mame/drivers/ultrsprt.c b/src/mame/drivers/ultrsprt.c
index 0d74092b3f2..016cd522ee2 100644
--- a/src/mame/drivers/ultrsprt.c
+++ b/src/mame/drivers/ultrsprt.c
@@ -207,11 +207,6 @@ static NVRAM_HANDLER(ultrsprt)
eeprom_handler(file, read_or_write);
}
-static const ppc_config ultrsprt_ppc_cfg =
-{
- PPC_MODEL_403GA
-};
-
static const struct K054539interface k054539_interface =
{
REGION_SOUND1
@@ -225,8 +220,7 @@ static INTERRUPT_GEN( ultrsprt_vblank )
static MACHINE_DRIVER_START( ultrsprt )
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 25000000) /* PowerPC 403GA 25MHz */
- MDRV_CPU_CONFIG(ultrsprt_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GA, 25000000) /* PowerPC 403GA 25MHz */
MDRV_CPU_PROGRAM_MAP(ultrsprt_map, 0)
MDRV_CPU_VBLANK_INT("main", ultrsprt_vblank)
diff --git a/src/mame/drivers/viper.c b/src/mame/drivers/viper.c
index 27fee538f0f..99d82c41266 100644
--- a/src/mame/drivers/viper.c
+++ b/src/mame/drivers/viper.c
@@ -611,11 +611,9 @@ ADDRESS_MAP_END
-static const ppc_config viper_ppc_cfg =
+static const powerpc_config viper_ppc_cfg =
{
- PPC_MODEL_MPC8240,
- 0x30,
- BUS_FREQUENCY_66MHZ
+ 66000000
};
static INTERRUPT_GEN(viper_vblank)
diff --git a/src/mame/drivers/zr107.c b/src/mame/drivers/zr107.c
index a4a9cd4a47f..7ccc3f30823 100644
--- a/src/mame/drivers/zr107.c
+++ b/src/mame/drivers/zr107.c
@@ -56,8 +56,8 @@ static UINT8 led_reg0 = 0x7f, led_reg1 = 0x7f;
// defined in drivers/gticlub.c
-extern READ32_HANDLER(lanc_r);
-extern WRITE32_HANDLER(lanc_w);
+extern READ8_HANDLER(K056230_r);
+extern WRITE8_HANDLER(K056230_w);
extern READ32_HANDLER(lanc_ram_r);
extern WRITE32_HANDLER(lanc_ram_w);
@@ -312,7 +312,7 @@ static ADDRESS_MAP_START( zr107_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x78040000, 0x7804000f) AM_MIRROR(0x80000000) AM_READWRITE(K001006_0_r, K001006_0_w)
AM_RANGE(0x780c0000, 0x780c0007) AM_MIRROR(0x80000000) AM_READWRITE(cgboard_dsp_comm_r_ppc, cgboard_dsp_comm_w_ppc)
AM_RANGE(0x7e000000, 0x7e003fff) AM_MIRROR(0x80000000) AM_READWRITE(sysreg_r, sysreg_w)
- AM_RANGE(0x7e008000, 0x7e009fff) AM_MIRROR(0x80000000) AM_READWRITE(lanc_r, lanc_w) /* LANC registers */
+ AM_RANGE(0x7e008000, 0x7e009fff) AM_MIRROR(0x80000000) AM_READWRITE8(K056230_r, K056230_w, 0xffffffff) /* LANC registers */
AM_RANGE(0x7e00a000, 0x7e00bfff) AM_MIRROR(0x80000000) AM_READWRITE(lanc_ram_r, lanc_ram_w) /* LANC Buffer RAM (27E) */
AM_RANGE(0x7e00c000, 0x7e00c007) AM_MIRROR(0x80000000) AM_WRITE(K056800_host_w)
AM_RANGE(0x7e00c008, 0x7e00c00f) AM_MIRROR(0x80000000) AM_READ(K056800_host_r)
@@ -340,7 +340,7 @@ static ADDRESS_MAP_START( jetwave_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x78080000, 0x7808000f) AM_MIRROR(0x80000000) AM_READWRITE(K001006_1_r, K001006_1_w)
AM_RANGE(0x780c0000, 0x780c0007) AM_MIRROR(0x80000000) AM_READWRITE(cgboard_dsp_comm_r_ppc, cgboard_dsp_comm_w_ppc)
AM_RANGE(0x7e000000, 0x7e003fff) AM_MIRROR(0x80000000) AM_READWRITE(sysreg_r, sysreg_w)
- AM_RANGE(0x7e008000, 0x7e009fff) AM_MIRROR(0x80000000) AM_READWRITE(lanc_r, lanc_w) /* LANC registers */
+ AM_RANGE(0x7e008000, 0x7e009fff) AM_MIRROR(0x80000000) AM_READWRITE8(K056230_r, K056230_w, 0xffffffff) /* LANC registers */
AM_RANGE(0x7e00a000, 0x7e00bfff) AM_MIRROR(0x80000000) AM_READWRITE(lanc_ram_r, lanc_ram_w) /* LANC Buffer RAM (27E) */
AM_RANGE(0x7e00c000, 0x7e00c007) AM_MIRROR(0x80000000) AM_WRITE(K056800_host_w)
AM_RANGE(0x7e00c008, 0x7e00c00f) AM_MIRROR(0x80000000) AM_READ(K056800_host_r)
@@ -541,11 +541,6 @@ static INPUT_PORTS_START( jetwave )
INPUT_PORTS_END
-static const ppc_config zr107_ppc_cfg =
-{
- PPC_MODEL_403GA
-};
-
static sharc_config sharc_cfg =
{
BOOT_MODE_EPROM
@@ -570,8 +565,7 @@ static MACHINE_RESET( zr107 )
static MACHINE_DRIVER_START( zr107 )
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 64000000/2) /* PowerPC 403GA 32MHz */
- MDRV_CPU_CONFIG(zr107_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GA, 64000000/2) /* PowerPC 403GA 32MHz */
MDRV_CPU_PROGRAM_MAP(zr107_map, 0)
MDRV_CPU_VBLANK_INT("main", zr107_vblank)
@@ -615,8 +609,7 @@ MACHINE_DRIVER_END
static MACHINE_DRIVER_START( jetwave )
/* basic machine hardware */
- MDRV_CPU_ADD(PPC403, 64000000/2) /* PowerPC 403GA 32MHz */
- MDRV_CPU_CONFIG(zr107_ppc_cfg)
+ MDRV_CPU_ADD(PPC403GA, 64000000/2) /* PowerPC 403GA 32MHz */
MDRV_CPU_PROGRAM_MAP(jetwave_map, 0)
MDRV_CPU_VBLANK_INT("main", zr107_vblank)
diff --git a/src/mame/mame.mak b/src/mame/mame.mak
index fb3e4f7e934..a8d38ef8e71 100644
--- a/src/mame/mame.mak
+++ b/src/mame/mame.mak
@@ -168,10 +168,13 @@ CPUS += H83002
CPUS += V810
CPUS += M37702
CPUS += M37710
-CPUS += PPC403
+CPUS += PPC403GA
+CPUS += PPC403GCX
CPUS += PPC601
CPUS += PPC602
CPUS += PPC603
+CPUS += PPC603E
+CPUS += PPC603R
CPUS += MPC8240
CPUS += SE3208
CPUS += MC68HC11
diff --git a/src/mame/video/konamiic.c b/src/mame/video/konamiic.c
index aea429466e4..8e1383ad759 100644
--- a/src/mame/video/konamiic.c
+++ b/src/mame/video/konamiic.c
@@ -5367,18 +5367,18 @@ static int K056832_rom_half;
// locally cached values
static int K056832_LayerAssociatedWithPage[K056832_PAGE_COUNT];
-static int K056832_LayerOffset[4][2];
-static int K056832_LSRAMPage[4][2];
-static INT32 K056832_X[4]; // 0..3 left
-static INT32 K056832_Y[4]; // 0..3 top
-static INT32 K056832_W[4]; // 0..3 width -> 1..4 pages
-static INT32 K056832_H[4]; // 0..3 height -> 1..4 pages
-static INT32 K056832_dx[4]; // scroll
-static INT32 K056832_dy[4]; // scroll
+static int K056832_LayerOffset[8][2];
+static int K056832_LSRAMPage[8][2];
+static INT32 K056832_X[8]; // 0..3 left
+static INT32 K056832_Y[8]; // 0..3 top
+static INT32 K056832_W[8]; // 0..3 width -> 1..4 pages
+static INT32 K056832_H[8]; // 0..3 height -> 1..4 pages
+static INT32 K056832_dx[8]; // scroll
+static INT32 K056832_dy[8]; // scroll
static UINT32 K056832_LineDirty[K056832_PAGE_COUNT][8];
static UINT8 K056832_AllLinesDirty[K056832_PAGE_COUNT];
static UINT8 K056832_PageTileMode[K056832_PAGE_COUNT];
-static UINT8 K056832_LayerTileMode[4];
+static UINT8 K056832_LayerTileMode[8];
static int K056832_DefaultLayerAssociation;
static int K056832_LayerAssociation;
static int K056832_ActiveLayer;
diff --git a/src/mame/video/model3.c b/src/mame/video/model3.c
index ecae1198906..301956649b0 100644
--- a/src/mame/video/model3.c
+++ b/src/mame/video/model3.c
@@ -75,7 +75,8 @@ static void draw_viewport(int pri, UINT32 address);
/*****************************************************************************/
-extern int model3_irq_state;
+/* in drivers/model3.c */
+void model3_set_irq_line(running_machine *machine, UINT8 bit, int state);
extern int model3_step;
@@ -476,7 +477,7 @@ WRITE64_HANDLER(model3_vid_reg_w)
{
case 0x00/8: logerror("vid_reg0: %08X%08X\n", (UINT32)(data>>32),(UINT32)(data)); vid_reg0 = data; break;
case 0x08/8: break; /* ??? */
- case 0x10/8: model3_irq_state &= ~(data >> 56); break; /* VBL IRQ Ack */
+ case 0x10/8: model3_set_irq_line(machine, (data >> 56) & 0x0f, CLEAR_LINE); break; /* VBL IRQ Ack */
case 0x20/8: model3_layer_enable = (data >> 52); break;