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:
Aaron Giles 2008-06-05 08:34:13 +00:00
parent 8ea2d9e334
commit ed6ad8b4f9
43 changed files with 10455 additions and 9541 deletions

10
.gitattributes vendored
View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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)
{

View File

@ -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)

View File

@ -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 */

View File

@ -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);
}

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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__ */

View File

@ -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 {

View File

@ -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:

View File

@ -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

File diff suppressed because it is too large Load Diff

View 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

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
View 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;
}

View 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

View File

@ -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
}

View File

@ -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__ */

View File

@ -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

View File

@ -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__ */

View File

@ -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,

View File

@ -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

View File

@ -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++;
}

View File

@ -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);

View File

@ -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);
}
/*************************************************************************/

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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);
}

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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;