mirror of
https://github.com/holub/mame
synced 2025-10-04 16:34:53 +03:00
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]
This commit is contained in:
parent
8ea2d9e334
commit
ed6ad8b4f9
10
.gitattributes
vendored
10
.gitattributes
vendored
@ -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
|
||||
|
8
makefile
8
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
|
||||
|
@ -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 \
|
||||
$(CPUOBJ)/powerpc/ppcdrc.o: $(CPUSRC)/powerpc/ppcdrc.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 \
|
||||
$(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)
|
||||
|
||||
|
||||
|
@ -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 (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_WRITE || opcode == DRCUML_OP_WRITEM || opcode == DRCUML_OP_FWRITE)
|
||||
psize[0] = psize[1] = 4;
|
||||
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];
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2U, 4, 0): /* LOAD2U dst,base,index */
|
||||
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_LOAD2S, 4, 0): /* LOAD2S dst,base,index */
|
||||
PARAM0 = inst[1].pint16[PARAM2];
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD4U, 4, 0): /* LOAD4U dst,base,index */
|
||||
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_STORE1, 4, 0): /* STORE1 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_LOADS4, 4, 0): /* LOADS dst,base,index,DWORD */
|
||||
PARAM0 = inst[1].pint32[PARAM2];
|
||||
break;
|
||||
|
||||
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);
|
||||
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_READ1S, 4, 0): /* READ1S dst,space,src1 */
|
||||
PARAM0 = (INT8)(*active_address_space[PARAM1].accessors->read_byte)(PARAM2);
|
||||
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_READ2U, 4, 0): /* READ2U dst,space,src1 */
|
||||
PARAM0 = (UINT16)(*active_address_space[PARAM1].accessors->read_word)(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_READ2S, 4, 0): /* READ2S dst,space,src1 */
|
||||
PARAM0 = (INT16)(*active_address_space[PARAM1].accessors->read_word)(PARAM2);
|
||||
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_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_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_READ4U, 4, 0): /* READ4U dst,space,src1 */
|
||||
PARAM0 = (UINT32)(*active_address_space[PARAM1].accessors->read_dword)(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_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_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_WRITE1, 4, 0): /* WRITE1 space,dst,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_byte)(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_WRITE2, 4, 0): /* WRITE2 space,dst,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_word)(PARAM1, PARAM2);
|
||||
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_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_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_WRITE4, 4, 0): /* WRITE4 space,dst,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_dword)(PARAM1, PARAM2);
|
||||
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);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(DRCUML_OP_FLAGS, 4, 0): /* FLAGS dst,mask,table */
|
||||
PARAM0 = (PARAM0 & ~PARAM1) | (inst[2].puint32[flags & 0x1f] & PARAM1);
|
||||
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];
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD2U, 8, 0): /* DLOAD2U dst,base,index */
|
||||
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_LOAD2S, 8, 0): /* DLOAD2S dst,base,index */
|
||||
DPARAM0 = inst[1].pint16[PARAM2];
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD4U, 8, 0): /* DLOAD4U dst,base,index */
|
||||
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_LOAD4S, 8, 0): /* DLOAD4S dst,base,index */
|
||||
DPARAM0 = inst[1].pint32[PARAM2];
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(DRCUML_OP_LOAD8U, 8, 0): /* DLOAD8U dst,base,index */
|
||||
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_STORE1, 8, 0): /* DSTORE1 dst,base,index */
|
||||
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_LOADS2, 8, 0): /* DLOADS dst,base,index,WORD */
|
||||
DPARAM0 = inst[1].pint16[PARAM2];
|
||||
break;
|
||||
|
||||
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): /* 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);
|
||||
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_READ1S, 8, 0): /* DREAD1S dst,space,src1 */
|
||||
DPARAM0 = (INT8)(*active_address_space[PARAM1].accessors->read_byte)(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_READ2U, 8, 0): /* DREAD2U dst,space,src1 */
|
||||
DPARAM0 = (UINT16)(*active_address_space[PARAM1].accessors->read_word)(PARAM2);
|
||||
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_READ2S, 8, 0): /* DREAD2S dst,space,src1 */
|
||||
DPARAM0 = (INT16)(*active_address_space[PARAM1].accessors->read_word)(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_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_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_READ4U, 8, 0): /* DREAD4U dst,space,src1 */
|
||||
DPARAM0 = (UINT32)(*active_address_space[PARAM1].accessors->read_dword)(PARAM2);
|
||||
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_READ4S, 8, 0): /* DREAD4S dst,space,src1 */
|
||||
DPARAM0 = (INT32)(*active_address_space[PARAM1].accessors->read_dword)(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_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_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_READ8U, 8, 0): /* DREAD8U dst,space,src1 */
|
||||
DPARAM0 = (UINT64)(*active_address_space[PARAM1].accessors->read_qword)(PARAM2);
|
||||
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_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_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_WRITE1, 8, 0): /* DWRITE1 space,dst,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_byte)(PARAM1, 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_WRITE2, 8, 0): /* DWRITE2 space,dst,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_word)(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_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_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_WRITE4, 8, 0): /* DWRITE4 space,dst,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_dword)(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_WRIT4M, 8, 0): /* DWRIT4M space,dst,mask,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_dword_masked)(PARAM1, DPARAM3, DPARAM2);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(DRCUML_OP_WRITE8, 8, 0): /* DWRITE8 space,dst,src1 */
|
||||
(*active_address_space[PARAM0].accessors->write_qword)(PARAM1, 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;
|
||||
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_ZEXT2, 8, 0): /* DZEXT2 dst,src */
|
||||
DPARAM0 = (UINT16)PARAM1;
|
||||
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;
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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 */
|
||||
|
@ -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 } },
|
||||
@ -447,6 +415,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);
|
||||
}
|
||||
|
@ -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_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_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_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_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_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_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_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_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_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)
|
||||
|
@ -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;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
@ -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 */
|
||||
/***************************************************************************
|
||||
REGISTER ENUMERATION
|
||||
***************************************************************************/
|
||||
|
||||
#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
|
||||
};
|
||||
|
||||
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;
|
||||
#define PPC_MAX_FASTRAM 4
|
||||
#define PPC_MAX_HOTSPOTS 16
|
||||
|
||||
// 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 },
|
||||
};
|
||||
|
||||
#define PPCDRC_OPTIONS_CHECK_SELFMOD_CODE 0x1
|
||||
|
||||
enum
|
||||
{
|
||||
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 */
|
||||
};
|
||||
|
||||
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);
|
||||
/***************************************************************************
|
||||
INTERRUPT CONSTANTS
|
||||
***************************************************************************/
|
||||
|
||||
#define PPC403_SPU_RX 5
|
||||
#define PPC403_SPU_TX 6
|
||||
#define PPC403_CRITICAL_IRQ 7
|
||||
#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
|
||||
{
|
||||
UINT32 bus_frequency;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/***************************************************************************
|
||||
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__ */
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
/* 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;
|
||||
|
||||
/*
|
||||
* Some PowerPC implementations may implement MFTB and MFSPR identically,
|
||||
* therefore TBR registers are also decoded here
|
||||
*/
|
||||
/* VEA SPR register indexes */
|
||||
case SPRVEA_TBL_R: strcat(dest, "tbl"); break;
|
||||
case SPRVEA_TBU_R: strcat(dest, "tbu"); break;
|
||||
|
||||
case 268: strcat(dest, "tbl"); break;
|
||||
case 269: 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/EC603e-specific registers
|
||||
*/
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
/* 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, "bt");
|
||||
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;
|
||||
@ -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:
|
||||
|
@ -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;
|
||||
|
||||
|
1792
src/emu/cpu/powerpc/ppccom.c
Normal file
1792
src/emu/cpu/powerpc/ppccom.c
Normal file
File diff suppressed because it is too large
Load Diff
611
src/emu/cpu/powerpc/ppccom.h
Normal file
611
src/emu/cpu/powerpc/ppccom.h
Normal file
@ -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
|
4337
src/emu/cpu/powerpc/ppcdrc.c
Normal file
4337
src/emu/cpu/powerpc/ppcdrc.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
942
src/emu/cpu/powerpc/ppcfe.c
Normal file
942
src/emu/cpu/powerpc/ppcfe.c
Normal file
@ -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;
|
||||
}
|
40
src/emu/cpu/powerpc/ppcfe.h
Normal file
40
src/emu/cpu/powerpc/ppcfe.h
Normal file
@ -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
|
@ -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
|
||||
}
|
@ -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__ */
|
@ -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
|
@ -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__ */
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
@ -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)
|
||||
UINT8 r = 0;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user