Virtual Combat driver improvements. [Jason Eckhardt, Andrew Gardner]

* Graphics decoded, video improved, inputs mapped.

Intel i860 CPU core added. [Jason Eckhardt]


(The CPU core doesn't have accurate cycle counts for each opcode yet, but it'll have them soon.  I believe that is the main culprit behind the sync of the two i860s and the 68k being outta' whack.  You can still see the i860s do their thing and rasterize a voxel? groundplane and some simple polygon bad guys).
This commit is contained in:
Andrew Gardner 2009-01-15 04:40:57 +00:00
parent f4392d4c6f
commit 6ea9ca0589
8 changed files with 6341 additions and 172 deletions

2
.gitattributes vendored
View File

@ -162,6 +162,8 @@ src/emu/cpu/i86/table86.h svneol=native#text/plain
src/emu/cpu/i860/i860.c svneol=native#text/plain
src/emu/cpu/i860/i860.h svneol=native#text/plain
src/emu/cpu/i860/i860dasm.c svneol=native#text/plain
src/emu/cpu/i860/i860dec.c svneol=native#text/plain
src/emu/cpu/i860/i860dis.c svneol=native#text/plain
src/emu/cpu/i960/i960.c svneol=native#text/plain
src/emu/cpu/i960/i960.h svneol=native#text/plain
src/emu/cpu/i960/i960dis.c svneol=native#text/plain

View File

@ -744,12 +744,12 @@ CPUDEFS += -DHAS_I860=$(if $(filter I860,$(CPUS)),1,0)
ifneq ($(filter I860,$(CPUS)),)
OBJDIRS += $(CPUOBJ)/i860
CPUOBJS += $(CPUOBJ)/i860/i860.o
DBGOBJS += $(CPUOBJ)/i860/i860dasm.o
DBGOBJS += $(CPUOBJ)/i860/i860dis.o
endif
$(CPUOBJ)/i860/i860.o: $(CPUSRC)/i860/i860.c \
$(CPUSRC)/i860/i860.h
$(CPUOBJ)/i860/i860.o: $(CPUSRC)/i860/i860.c \
$(CPUSRC)/i860/i860.h \
$(CPUSRC)/i860/i860dec.c
#-------------------------------------------------
# Intel i960

View File

@ -1,91 +1,285 @@
/***************************************************************************
i860.c
Interface file for the Intel i860 emulator.
Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
Released for general non-commercial use under the MAME license
with the additional requirement that you are free to use and
redistribute this code in modified or unmodified form, provided
you list me in the credits.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
/*
TODO: Separate out i860XR and i860XP (make different types, etc).
Hook IRQ lines into MAME core (they're custom functions atm).
*/
#include "debugger.h"
#include "i860.h"
/**************************************************************************
* The core struct
**************************************************************************/
typedef struct _i860_state_t i860_state_t;
struct _i860_state_t
{
const device_config *device;
const address_space *program;
UINT32 pc;
UINT32 ppc;
int icount;
};
/**************************************************************************
* Functions specified by GET_INFO
**************************************************************************/
static CPU_INIT( i860 )
{
i860_state_t *i860 = device->token;
i860->device = device;
i860->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
i860_state_t *cpustate = device->token;
cpustate->device = device;
cpustate->program = memory_find_address_space(device, ADDRESS_SPACE_PROGRAM);
reset_i860(cpustate);
i860_set_pin(cpustate, DEC_PIN_BUS_HOLD, 0);
i860_set_pin(cpustate, DEC_PIN_RESET, 0);
cpustate->single_stepping = 0;
state_save_register_device_item_array(device, 0, cpustate->iregs);
state_save_register_device_item_array(device, 0, cpustate->cregs);
state_save_register_device_item_array(device, 0, cpustate->frg);
state_save_register_device_item(device, 0, cpustate->pc);
}
static CPU_RESET( i860 )
{
logerror("i860 reset\n");
i860_state_t *cpustate = device->token;
reset_i860(cpustate);
}
static CPU_EXECUTE( i860 )
/***************************************************************************
* Disassembler hook
***************************************************************************/
static CPU_DISASSEMBLE( i860 )
{
/* Just a disassembler ATM */
return cycles;
extern unsigned disasm_i860(char*, unsigned, UINT32);
/* Hard-coded little endian for now. */
return disasm_i860(buffer, pc, (oprom[0] << 0) |
(oprom[1] << 8) |
(oprom[2] << 16) |
(oprom[3] << 24));
}
extern CPU_DISASSEMBLE( i860 );
/**************************************************************************
* The actual decode and execute code.
**************************************************************************/
#include "i860dec.c"
/**************************************************************************
* Generic set_info/get_info
**************************************************************************/
#define CPU_SET_INFO_F(fnum) cpustate->frg[0+(4*fnum)] = (info->i & 0x000000ff); \
cpustate->frg[1+(4*fnum)] = (info->i & 0x0000ff00) >> 8; \
cpustate->frg[2+(4*fnum)] = (info->i & 0x00ff0000) >> 16; \
cpustate->frg[3+(4*fnum)] = (info->i & 0xff000000) >> 24;
static CPU_SET_INFO( i860 )
{
i860_state_t *i860 = device->token;
i860_state_t *cpustate = device->token;
switch(state)
{
/* Interfacing */
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + I860_PC: i860->pc = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_PC: cpustate->pc = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_FIR: cpustate->cregs[CR_FIR] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_PSR: cpustate->cregs[CR_PSR] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_DIRBASE: cpustate->cregs[CR_DIRBASE] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_DB: cpustate->cregs[CR_DB] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_FSR: cpustate->cregs[CR_FSR] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_EPSR: cpustate->cregs[CR_EPSR] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R0: cpustate->iregs[0] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R1: cpustate->iregs[1] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R2: cpustate->iregs[2] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R3: cpustate->iregs[3] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R4: cpustate->iregs[4] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R5: cpustate->iregs[5] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R6: cpustate->iregs[6] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R7: cpustate->iregs[7] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R8: cpustate->iregs[8] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R9: cpustate->iregs[9] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R10: cpustate->iregs[10] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R11: cpustate->iregs[11] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R12: cpustate->iregs[12] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R13: cpustate->iregs[13] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R14: cpustate->iregs[14] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R15: cpustate->iregs[15] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R16: cpustate->iregs[16] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R17: cpustate->iregs[17] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R18: cpustate->iregs[18] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R19: cpustate->iregs[19] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R20: cpustate->iregs[20] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R21: cpustate->iregs[21] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R22: cpustate->iregs[22] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R23: cpustate->iregs[23] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R24: cpustate->iregs[24] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R25: cpustate->iregs[25] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R26: cpustate->iregs[26] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R27: cpustate->iregs[27] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R28: cpustate->iregs[28] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R29: cpustate->iregs[29] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R30: cpustate->iregs[30] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_R31: cpustate->iregs[31] = info->i & 0xffffffff; break;
case CPUINFO_INT_REGISTER + I860_F0: CPU_SET_INFO_F(0); break;
case CPUINFO_INT_REGISTER + I860_F1: CPU_SET_INFO_F(1); break;
case CPUINFO_INT_REGISTER + I860_F2: CPU_SET_INFO_F(2); break;
case CPUINFO_INT_REGISTER + I860_F3: CPU_SET_INFO_F(3); break;
case CPUINFO_INT_REGISTER + I860_F4: CPU_SET_INFO_F(4); break;
case CPUINFO_INT_REGISTER + I860_F5: CPU_SET_INFO_F(5); break;
case CPUINFO_INT_REGISTER + I860_F6: CPU_SET_INFO_F(6); break;
case CPUINFO_INT_REGISTER + I860_F7: CPU_SET_INFO_F(7); break;
case CPUINFO_INT_REGISTER + I860_F8: CPU_SET_INFO_F(8); break;
case CPUINFO_INT_REGISTER + I860_F9: CPU_SET_INFO_F(9); break;
case CPUINFO_INT_REGISTER + I860_F10: CPU_SET_INFO_F(10); break;
case CPUINFO_INT_REGISTER + I860_F11: CPU_SET_INFO_F(11); break;
case CPUINFO_INT_REGISTER + I860_F12: CPU_SET_INFO_F(12); break;
case CPUINFO_INT_REGISTER + I860_F13: CPU_SET_INFO_F(13); break;
case CPUINFO_INT_REGISTER + I860_F14: CPU_SET_INFO_F(14); break;
case CPUINFO_INT_REGISTER + I860_F15: CPU_SET_INFO_F(15); break;
case CPUINFO_INT_REGISTER + I860_F16: CPU_SET_INFO_F(16); break;
case CPUINFO_INT_REGISTER + I860_F17: CPU_SET_INFO_F(17); break;
case CPUINFO_INT_REGISTER + I860_F18: CPU_SET_INFO_F(18); break;
case CPUINFO_INT_REGISTER + I860_F19: CPU_SET_INFO_F(19); break;
case CPUINFO_INT_REGISTER + I860_F20: CPU_SET_INFO_F(20); break;
case CPUINFO_INT_REGISTER + I860_F21: CPU_SET_INFO_F(21); break;
case CPUINFO_INT_REGISTER + I860_F22: CPU_SET_INFO_F(22); break;
case CPUINFO_INT_REGISTER + I860_F23: CPU_SET_INFO_F(23); break;
case CPUINFO_INT_REGISTER + I860_F24: CPU_SET_INFO_F(24); break;
case CPUINFO_INT_REGISTER + I860_F25: CPU_SET_INFO_F(25); break;
case CPUINFO_INT_REGISTER + I860_F26: CPU_SET_INFO_F(26); break;
case CPUINFO_INT_REGISTER + I860_F27: CPU_SET_INFO_F(27); break;
case CPUINFO_INT_REGISTER + I860_F28: CPU_SET_INFO_F(28); break;
case CPUINFO_INT_REGISTER + I860_F29: CPU_SET_INFO_F(29); break;
case CPUINFO_INT_REGISTER + I860_F30: CPU_SET_INFO_F(30); break;
case CPUINFO_INT_REGISTER + I860_F31: CPU_SET_INFO_F(31); break;
}
}
#define CPU_GET_INFO_INT_F(fnum) (info->i = cpustate->frg[0+(4*fnum)] | \
cpustate->frg[1+(4*fnum)] << 8 | \
cpustate->frg[2+(4*fnum)] << 16 | \
cpustate->frg[3+(4*fnum)] << 24)
#define CPU_GET_INFO_STR_F(fnum) (sprintf(info->s, "F%d : %08x", fnum, cpustate->frg[0+(4*fnum)] | \
cpustate->frg[1+(4*fnum)] << 8 | \
cpustate->frg[2+(4*fnum)] << 16 | \
cpustate->frg[3+(4*fnum)] << 24))
CPU_GET_INFO( i860 )
{
i860_state_t *i860 = (device != NULL) ? device->token : NULL;
i860_state_t *cpustate = (device != NULL) ? device->token : NULL;
switch (state)
{
// --- the following bits of info are returned as 64-bit signed integers ---
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i860_state_t); break;
case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x00000000; break;
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 8; break;
/* --- the following bits of info are returned as 64-bit signed integers --- */
case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(i860_state_t); break;
case CPUINFO_INT_INPUT_LINES: info->i = 0; break;
case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0x00000000; break;
case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_LITTLE; break;
case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 4; break;
case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
case CPUINFO_INT_MAX_CYCLES: info->i = 8; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 32; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH_PROGRAM: info->i = 64; break;
case CPUINFO_INT_ADDRBUS_WIDTH_PROGRAM: info->i = 32; break;
case CPUINFO_INT_ADDRBUS_SHIFT_PROGRAM: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH_DATA: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT_DATA: info->i = 0; break;
case CPUINFO_INT_DATABUS_WIDTH_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_WIDTH_IO: info->i = 0; break;
case CPUINFO_INT_ADDRBUS_SHIFT_IO: info->i = 0; break;
// --- the following bits of info are returned as pointers to data or functions ---
case CPUINFO_INT_PC:
case CPUINFO_INT_REGISTER + I860_PC: info->i = cpustate->pc; break;
case CPUINFO_INT_PREVIOUSPC: info->i = cpustate->ppc; break;
case CPUINFO_INT_REGISTER + I860_FIR: info->i = cpustate->cregs[CR_FIR]; break;
case CPUINFO_INT_REGISTER + I860_PSR: info->i = cpustate->cregs[CR_PSR]; break;
case CPUINFO_INT_REGISTER + I860_DIRBASE: info->i = cpustate->cregs[CR_DIRBASE]; break;
case CPUINFO_INT_REGISTER + I860_DB: info->i = cpustate->cregs[CR_DB]; break;
case CPUINFO_INT_REGISTER + I860_FSR: info->i = cpustate->cregs[CR_FSR]; break;
case CPUINFO_INT_REGISTER + I860_EPSR: info->i = cpustate->cregs[CR_EPSR]; break;
case CPUINFO_INT_REGISTER + I860_R0: info->i = cpustate->iregs[0]; break;
case CPUINFO_INT_REGISTER + I860_R1: info->i = cpustate->iregs[1]; break;
case CPUINFO_INT_REGISTER + I860_R2: info->i = cpustate->iregs[2]; break;
case CPUINFO_INT_REGISTER + I860_R3: info->i = cpustate->iregs[3]; break;
case CPUINFO_INT_REGISTER + I860_R4: info->i = cpustate->iregs[4]; break;
case CPUINFO_INT_REGISTER + I860_R5: info->i = cpustate->iregs[5]; break;
case CPUINFO_INT_REGISTER + I860_R6: info->i = cpustate->iregs[6]; break;
case CPUINFO_INT_REGISTER + I860_R7: info->i = cpustate->iregs[7]; break;
case CPUINFO_INT_REGISTER + I860_R8: info->i = cpustate->iregs[8]; break;
case CPUINFO_INT_REGISTER + I860_R9: info->i = cpustate->iregs[9]; break;
case CPUINFO_INT_REGISTER + I860_R10: info->i = cpustate->iregs[10]; break;
case CPUINFO_INT_REGISTER + I860_R11: info->i = cpustate->iregs[11]; break;
case CPUINFO_INT_REGISTER + I860_R12: info->i = cpustate->iregs[12]; break;
case CPUINFO_INT_REGISTER + I860_R13: info->i = cpustate->iregs[13]; break;
case CPUINFO_INT_REGISTER + I860_R14: info->i = cpustate->iregs[14]; break;
case CPUINFO_INT_REGISTER + I860_R15: info->i = cpustate->iregs[15]; break;
case CPUINFO_INT_REGISTER + I860_R16: info->i = cpustate->iregs[16]; break;
case CPUINFO_INT_REGISTER + I860_R17: info->i = cpustate->iregs[17]; break;
case CPUINFO_INT_REGISTER + I860_R18: info->i = cpustate->iregs[18]; break;
case CPUINFO_INT_REGISTER + I860_R19: info->i = cpustate->iregs[19]; break;
case CPUINFO_INT_REGISTER + I860_R20: info->i = cpustate->iregs[20]; break;
case CPUINFO_INT_REGISTER + I860_R21: info->i = cpustate->iregs[21]; break;
case CPUINFO_INT_REGISTER + I860_R22: info->i = cpustate->iregs[22]; break;
case CPUINFO_INT_REGISTER + I860_R23: info->i = cpustate->iregs[23]; break;
case CPUINFO_INT_REGISTER + I860_R24: info->i = cpustate->iregs[24]; break;
case CPUINFO_INT_REGISTER + I860_R25: info->i = cpustate->iregs[25]; break;
case CPUINFO_INT_REGISTER + I860_R26: info->i = cpustate->iregs[26]; break;
case CPUINFO_INT_REGISTER + I860_R27: info->i = cpustate->iregs[27]; break;
case CPUINFO_INT_REGISTER + I860_R28: info->i = cpustate->iregs[28]; break;
case CPUINFO_INT_REGISTER + I860_R29: info->i = cpustate->iregs[29]; break;
case CPUINFO_INT_REGISTER + I860_R30: info->i = cpustate->iregs[30]; break;
case CPUINFO_INT_REGISTER + I860_R31: info->i = cpustate->iregs[31]; break;
case CPUINFO_INT_REGISTER + I860_F0: CPU_GET_INFO_INT_F(0); break;
case CPUINFO_INT_REGISTER + I860_F1: CPU_GET_INFO_INT_F(1); break;
case CPUINFO_INT_REGISTER + I860_F2: CPU_GET_INFO_INT_F(2); break;
case CPUINFO_INT_REGISTER + I860_F3: CPU_GET_INFO_INT_F(3); break;
case CPUINFO_INT_REGISTER + I860_F4: CPU_GET_INFO_INT_F(4); break;
case CPUINFO_INT_REGISTER + I860_F5: CPU_GET_INFO_INT_F(5); break;
case CPUINFO_INT_REGISTER + I860_F6: CPU_GET_INFO_INT_F(6); break;
case CPUINFO_INT_REGISTER + I860_F7: CPU_GET_INFO_INT_F(7); break;
case CPUINFO_INT_REGISTER + I860_F8: CPU_GET_INFO_INT_F(8); break;
case CPUINFO_INT_REGISTER + I860_F9: CPU_GET_INFO_INT_F(9); break;
case CPUINFO_INT_REGISTER + I860_F10: CPU_GET_INFO_INT_F(10); break;
case CPUINFO_INT_REGISTER + I860_F11: CPU_GET_INFO_INT_F(11); break;
case CPUINFO_INT_REGISTER + I860_F12: CPU_GET_INFO_INT_F(12); break;
case CPUINFO_INT_REGISTER + I860_F13: CPU_GET_INFO_INT_F(13); break;
case CPUINFO_INT_REGISTER + I860_F14: CPU_GET_INFO_INT_F(14); break;
case CPUINFO_INT_REGISTER + I860_F15: CPU_GET_INFO_INT_F(15); break;
case CPUINFO_INT_REGISTER + I860_F16: CPU_GET_INFO_INT_F(16); break;
case CPUINFO_INT_REGISTER + I860_F17: CPU_GET_INFO_INT_F(17); break;
case CPUINFO_INT_REGISTER + I860_F18: CPU_GET_INFO_INT_F(18); break;
case CPUINFO_INT_REGISTER + I860_F19: CPU_GET_INFO_INT_F(19); break;
case CPUINFO_INT_REGISTER + I860_F20: CPU_GET_INFO_INT_F(20); break;
case CPUINFO_INT_REGISTER + I860_F21: CPU_GET_INFO_INT_F(21); break;
case CPUINFO_INT_REGISTER + I860_F22: CPU_GET_INFO_INT_F(22); break;
case CPUINFO_INT_REGISTER + I860_F23: CPU_GET_INFO_INT_F(23); break;
case CPUINFO_INT_REGISTER + I860_F24: CPU_GET_INFO_INT_F(24); break;
case CPUINFO_INT_REGISTER + I860_F25: CPU_GET_INFO_INT_F(25); break;
case CPUINFO_INT_REGISTER + I860_F26: CPU_GET_INFO_INT_F(26); break;
case CPUINFO_INT_REGISTER + I860_F27: CPU_GET_INFO_INT_F(27); break;
case CPUINFO_INT_REGISTER + I860_F28: CPU_GET_INFO_INT_F(28); break;
case CPUINFO_INT_REGISTER + I860_F29: CPU_GET_INFO_INT_F(29); break;
case CPUINFO_INT_REGISTER + I860_F30: CPU_GET_INFO_INT_F(30); break;
case CPUINFO_INT_REGISTER + I860_F31: CPU_GET_INFO_INT_F(31); break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(i860); break;
case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(i860); break;
case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(i860); break;
@ -98,16 +292,90 @@ CPU_GET_INFO( i860 )
case CPUINFO_FCT_READ: info->read = NULL; break;
case CPUINFO_FCT_WRITE: info->write = NULL; break;
case CPUINFO_FCT_READOP: info->readop = NULL; break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &i860->icount; break;
case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
// --- the following bits of info are returned as NULL-terminated strings ---
case CPUINFO_STR_NAME: strcpy(info->s, "i860"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Intel"); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case CPUINFO_STR_NAME: strcpy(info->s, "i860XR"); break;
case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Intel i860"); break;
case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "0.1"); break;
case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Jason Eckhardt and Andrew Gardner"); break;
case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Jason Eckhardt"); break;
case CPUINFO_INT_PC: info->i = i860->pc; break;
case CPUINFO_INT_PREVIOUSPC: info->i = i860->ppc; break;
case CPUINFO_STR_FLAGS:
strcpy(info->s, ""); break;
case CPUINFO_STR_REGISTER + I860_PC: sprintf(info->s, "PC : %08x", cpustate->pc); break;
case CPUINFO_STR_REGISTER + I860_FIR: sprintf(info->s, "FIR : %08x", cpustate->cregs[CR_FIR]); break;
case CPUINFO_STR_REGISTER + I860_PSR: sprintf(info->s, "PSR : %08x", cpustate->cregs[CR_PSR]); break;
case CPUINFO_STR_REGISTER + I860_DIRBASE: sprintf(info->s, "DIRBASE : %08x", cpustate->cregs[CR_DIRBASE]);break;
case CPUINFO_STR_REGISTER + I860_DB: sprintf(info->s, "DB : %08x", cpustate->cregs[CR_DB]); break;
case CPUINFO_STR_REGISTER + I860_FSR: sprintf(info->s, "FSR : %08x", cpustate->cregs[CR_FSR]); break;
case CPUINFO_STR_REGISTER + I860_EPSR: sprintf(info->s, "EPSR : %08x", cpustate->cregs[CR_EPSR]); break;
case CPUINFO_STR_REGISTER + I860_R0: sprintf(info->s, "R0 : %08x", cpustate->iregs[0]); break;
case CPUINFO_STR_REGISTER + I860_R1: sprintf(info->s, "R1 : %08x", cpustate->iregs[1]); break;
case CPUINFO_STR_REGISTER + I860_R2: sprintf(info->s, "R2 : %08x", cpustate->iregs[2]); break;
case CPUINFO_STR_REGISTER + I860_R3: sprintf(info->s, "R3 : %08x", cpustate->iregs[3]); break;
case CPUINFO_STR_REGISTER + I860_R4: sprintf(info->s, "R4 : %08x", cpustate->iregs[4]); break;
case CPUINFO_STR_REGISTER + I860_R5: sprintf(info->s, "R5 : %08x", cpustate->iregs[5]); break;
case CPUINFO_STR_REGISTER + I860_R6: sprintf(info->s, "R6 : %08x", cpustate->iregs[6]); break;
case CPUINFO_STR_REGISTER + I860_R7: sprintf(info->s, "R7 : %08x", cpustate->iregs[7]); break;
case CPUINFO_STR_REGISTER + I860_R8: sprintf(info->s, "R8 : %08x", cpustate->iregs[8]); break;
case CPUINFO_STR_REGISTER + I860_R9: sprintf(info->s, "R9 : %08x", cpustate->iregs[9]); break;
case CPUINFO_STR_REGISTER + I860_R10: sprintf(info->s, "R10 : %08x", cpustate->iregs[10]); break;
case CPUINFO_STR_REGISTER + I860_R11: sprintf(info->s, "R11 : %08x", cpustate->iregs[11]); break;
case CPUINFO_STR_REGISTER + I860_R12: sprintf(info->s, "R12 : %08x", cpustate->iregs[12]); break;
case CPUINFO_STR_REGISTER + I860_R13: sprintf(info->s, "R13 : %08x", cpustate->iregs[13]); break;
case CPUINFO_STR_REGISTER + I860_R14: sprintf(info->s, "R14 : %08x", cpustate->iregs[14]); break;
case CPUINFO_STR_REGISTER + I860_R15: sprintf(info->s, "R15 : %08x", cpustate->iregs[15]); break;
case CPUINFO_STR_REGISTER + I860_R16: sprintf(info->s, "R16 : %08x", cpustate->iregs[16]); break;
case CPUINFO_STR_REGISTER + I860_R17: sprintf(info->s, "R17 : %08x", cpustate->iregs[17]); break;
case CPUINFO_STR_REGISTER + I860_R18: sprintf(info->s, "R18 : %08x", cpustate->iregs[18]); break;
case CPUINFO_STR_REGISTER + I860_R19: sprintf(info->s, "R19 : %08x", cpustate->iregs[19]); break;
case CPUINFO_STR_REGISTER + I860_R20: sprintf(info->s, "R20 : %08x", cpustate->iregs[20]); break;
case CPUINFO_STR_REGISTER + I860_R21: sprintf(info->s, "R21 : %08x", cpustate->iregs[21]); break;
case CPUINFO_STR_REGISTER + I860_R22: sprintf(info->s, "R22 : %08x", cpustate->iregs[22]); break;
case CPUINFO_STR_REGISTER + I860_R23: sprintf(info->s, "R23 : %08x", cpustate->iregs[23]); break;
case CPUINFO_STR_REGISTER + I860_R24: sprintf(info->s, "R24 : %08x", cpustate->iregs[24]); break;
case CPUINFO_STR_REGISTER + I860_R25: sprintf(info->s, "R25 : %08x", cpustate->iregs[25]); break;
case CPUINFO_STR_REGISTER + I860_R26: sprintf(info->s, "R26 : %08x", cpustate->iregs[26]); break;
case CPUINFO_STR_REGISTER + I860_R27: sprintf(info->s, "R27 : %08x", cpustate->iregs[27]); break;
case CPUINFO_STR_REGISTER + I860_R28: sprintf(info->s, "R28 : %08x", cpustate->iregs[28]); break;
case CPUINFO_STR_REGISTER + I860_R29: sprintf(info->s, "R29 : %08x", cpustate->iregs[29]); break;
case CPUINFO_STR_REGISTER + I860_R30: sprintf(info->s, "R30 : %08x", cpustate->iregs[30]); break;
case CPUINFO_STR_REGISTER + I860_R31: sprintf(info->s, "R31 : %08x", cpustate->iregs[31]); break;
case CPUINFO_STR_REGISTER + I860_F0: CPU_GET_INFO_STR_F(0); break;
case CPUINFO_STR_REGISTER + I860_F1: CPU_GET_INFO_STR_F(1); break;
case CPUINFO_STR_REGISTER + I860_F2: CPU_GET_INFO_STR_F(2); break;
case CPUINFO_STR_REGISTER + I860_F3: CPU_GET_INFO_STR_F(3); break;
case CPUINFO_STR_REGISTER + I860_F4: CPU_GET_INFO_STR_F(4); break;
case CPUINFO_STR_REGISTER + I860_F5: CPU_GET_INFO_STR_F(5); break;
case CPUINFO_STR_REGISTER + I860_F6: CPU_GET_INFO_STR_F(6); break;
case CPUINFO_STR_REGISTER + I860_F7: CPU_GET_INFO_STR_F(7); break;
case CPUINFO_STR_REGISTER + I860_F8: CPU_GET_INFO_STR_F(8); break;
case CPUINFO_STR_REGISTER + I860_F9: CPU_GET_INFO_STR_F(9); break;
case CPUINFO_STR_REGISTER + I860_F10: CPU_GET_INFO_STR_F(10); break;
case CPUINFO_STR_REGISTER + I860_F11: CPU_GET_INFO_STR_F(11); break;
case CPUINFO_STR_REGISTER + I860_F12: CPU_GET_INFO_STR_F(12); break;
case CPUINFO_STR_REGISTER + I860_F13: CPU_GET_INFO_STR_F(13); break;
case CPUINFO_STR_REGISTER + I860_F14: CPU_GET_INFO_STR_F(14); break;
case CPUINFO_STR_REGISTER + I860_F15: CPU_GET_INFO_STR_F(15); break;
case CPUINFO_STR_REGISTER + I860_F16: CPU_GET_INFO_STR_F(16); break;
case CPUINFO_STR_REGISTER + I860_F17: CPU_GET_INFO_STR_F(17); break;
case CPUINFO_STR_REGISTER + I860_F18: CPU_GET_INFO_STR_F(18); break;
case CPUINFO_STR_REGISTER + I860_F19: CPU_GET_INFO_STR_F(19); break;
case CPUINFO_STR_REGISTER + I860_F20: CPU_GET_INFO_STR_F(20); break;
case CPUINFO_STR_REGISTER + I860_F21: CPU_GET_INFO_STR_F(21); break;
case CPUINFO_STR_REGISTER + I860_F22: CPU_GET_INFO_STR_F(22); break;
case CPUINFO_STR_REGISTER + I860_F23: CPU_GET_INFO_STR_F(23); break;
case CPUINFO_STR_REGISTER + I860_F24: CPU_GET_INFO_STR_F(24); break;
case CPUINFO_STR_REGISTER + I860_F25: CPU_GET_INFO_STR_F(25); break;
case CPUINFO_STR_REGISTER + I860_F26: CPU_GET_INFO_STR_F(26); break;
case CPUINFO_STR_REGISTER + I860_F27: CPU_GET_INFO_STR_F(27); break;
case CPUINFO_STR_REGISTER + I860_F28: CPU_GET_INFO_STR_F(28); break;
case CPUINFO_STR_REGISTER + I860_F29: CPU_GET_INFO_STR_F(29); break;
case CPUINFO_STR_REGISTER + I860_F30: CPU_GET_INFO_STR_F(30); break;
case CPUINFO_STR_REGISTER + I860_F31: CPU_GET_INFO_STR_F(31); break;
}
}

View File

@ -1,3 +1,18 @@
/***************************************************************************
i860.h
Interface file for the Intel i860 emulator.
Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
Released for general non-commercial use under the MAME license
with the additional requirement that you are free to use and
redistribute this code in modified or unmodified form, provided
you list me in the credits.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#pragma once
#ifndef __I860_H__
@ -5,13 +20,199 @@
#include "cpuintrf.h"
/***************************************************************************
REGISTER ENUMERATION
***************************************************************************/
enum
{
I860_PC = 0
I860_PC = 1,
I860_FIR,
I860_PSR,
I860_DIRBASE,
I860_DB,
I860_FSR,
I860_EPSR,
I860_R0, I860_R1, I860_R2, I860_R3, I860_R4, I860_R5, I860_R6, I860_R7, I860_R8, I860_R9,
I860_R10, I860_R11, I860_R12, I860_R13, I860_R14, I860_R15, I860_R16, I860_R17, I860_R18, I860_R19,
I860_R20, I860_R21, I860_R22, I860_R23, I860_R24, I860_R25, I860_R26, I860_R27, I860_R28, I860_R29,
I860_R30, I860_R31,
I860_F0, I860_F1, I860_F2, I860_F3, I860_F4, I860_F5, I860_F6, I860_F7, I860_F8, I860_F9,
I860_F10, I860_F11, I860_F12, I860_F13, I860_F14, I860_F15, I860_F16, I860_F17, I860_F18, I860_F19,
I860_F20, I860_F21, I860_F22, I860_F23, I860_F24, I860_F25, I860_F26, I860_F27, I860_F28, I860_F29,
I860_F30, I860_F31,
};
/* Needed for MAME */
CPU_GET_INFO( i860 );
#define CPU_I860 CPU_GET_INFO_NAME( i860 )
/***************************************************************************
STRUCTURES & TYPEDEFS
***************************************************************************/
/* i860 state. */
typedef struct {
/* Integer registers (32 x 32-bits). */
UINT32 iregs[32];
/* Floating point registers (32 x 32-bits, 16 x 64 bits, or 8 x 128 bits).
When referenced as pairs or quads, the higher numbered registers
are the upper bits. E.g., double precision f0 is f1:f0. */
UINT8 frg[32 * 4];
/* Control registers (6 x 32-bits). */
UINT32 cregs[6];
/* Program counter (1 x 32-bits). Reset starts at pc=0xffffff00. */
UINT32 pc;
/* Special registers (4 x 64-bits). */
union
{
float s;
double d;
} KR, KI, T;
UINT64 merge;
/* The adder pipeline, always 3 stages. */
struct
{
/* The stage contents. */
union {
float s;
double d;
} val;
/* The stage status bits. */
struct {
/* Adder result precision (1 = dbl, 0 = sgl). */
char arp;
} stat;
} A[3];
/* The multiplier pipeline. 3 stages for single precision, 2 stages
for double precision, and confusing for mixed precision. */
struct {
/* The stage contents. */
union {
float s;
double d;
} val;
/* The stage status bits. */
struct {
/* Multiplier result precision (1 = dbl, 0 = sgl). */
char mrp;
} stat;
} M[3];
/* The load pipeline, always 3 stages. */
struct {
/* The stage contents. */
union {
float s;
double d;
} val;
/* The stage status bits. */
struct {
/* Load result precision (1 = dbl, 0 = sgl). */
char lrp;
} stat;
} L[3];
/* The graphics/integer pipeline, always 1 stage. */
struct {
/* The stage contents. */
union {
float s;
double d;
} val;
/* The stage status bits. */
struct {
/* Integer/graphics result precision (1 = dbl, 0 = sgl). */
char irp;
} stat;
} G;
/* Pins. */
int pin_bus_hold;
int pin_reset;
/*
* Other emulator state.
*/
int exiting_readmem;
int exiting_ifetch;
/* Indicate a control-flow instruction, so we know the PC is updated. */
int pc_updated;
/* Indicate an instruction just generated a trap, so we know the PC
needs to go to the trap address. */
int pending_trap;
/* This is 1 if the next fir load gets the trap address, otherwise
it is 0 to get the ld.c address. This is set to 1 only when a
non-reset trap occurs. */
int fir_gets_trap_addr;
/* Single stepping flag for internal use. */
int single_stepping;
/*
* MAME-specific stuff.
*/
const device_config *device;
const address_space *program;
UINT32 ppc;
int icount;
} i860_state_t;
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/* This is the external interface for asserting an external interrupt
to the i860. */
extern void i860_gen_interrupt(i860_state_t*);
/* This is the external interface for asserting/deasserting a pin on
the i860. */
extern void i860_set_pin(i860_state_t*, int, int);
/* Hard or soft reset. */
extern void reset_i860(i860_state_t*);
/* i860 pins. */
enum {
DEC_PIN_BUS_HOLD, /* Bus HOLD pin. */
DEC_PIN_RESET /* System reset pin. */
};
/* TODO: THESE WILL BE REPLACED BY MAME FUNCTIONS
#define BYTE_REV32(t) \
do { \
(t) = ((UINT32)(t) >> 16) | ((UINT32)(t) << 16); \
(t) = (((UINT32)(t) >> 8) & 0x00ff00ff) | (((UINT32)(t) << 8) & 0xff00ff00); \
} while (0);
#define BYTE_REV16(t) \
do { \
(t) = (((UINT16)(t) >> 8) & 0x00ff) | (((UINT16)(t) << 8) & 0xff00); \
} while (0);
#endif
*/
#endif /* __I860_H__ */

4722
src/emu/cpu/i860/i860dec.c Normal file

File diff suppressed because it is too large Load Diff

694
src/emu/cpu/i860/i860dis.c Normal file
View File

@ -0,0 +1,694 @@
/***************************************************************************
i860dis.c
Disassembler for the Intel i860 emulator.
Copyright (C) 1995-present Jason Eckhardt (jle@rice.edu)
Released for general non-commercial use under the MAME license
with the additional requirement that you are free to use and
redistribute this code in modified or unmodified form, provided
you list me in the credits.
Visit http://mamedev.org for licensing and usage restrictions.
***************************************************************************/
#include "i860.h"
#include <string.h>
/* Macros for accessing register fields in instruction word. */
#define get_isrc1(bits) (((bits) >> 11) & 0x1f)
#define get_isrc2(bits) (((bits) >> 21) & 0x1f)
#define get_idest(bits) (((bits) >> 16) & 0x1f)
#define get_fsrc1(bits) (((bits) >> 11) & 0x1f)
#define get_fsrc2(bits) (((bits) >> 21) & 0x1f)
#define get_fdest(bits) (((bits) >> 16) & 0x1f)
#define get_creg(bits) (((bits) >> 21) & 0x7)
/* Macros for accessing immediate fields. */
/* 16-bit immediate. */
#define get_imm16(insn) ((insn) & 0xffff)
/* Control register names. */
static const char *const cr2str[] =
{"fir", "psr", "dirbase", "db", "fsr", "epsr", "!", "!"};
/* Sign extend N-bit number. */
static INT32 sign_ext(UINT32 x, int n)
{
INT32 t;
t = x >> (n - 1);
t = ((-t) << n) | x;
return t;
}
/* Basic integer 3-address register format:
* mnemonic %rs1,%rs2,%rd */
static void int_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
/* Possibly prefix shrd with 'd.' */
if (((insn & 0xfc000000) == 0xb0000000) && (insn & 0x200))
sprintf(buf, "d.%s\t%%r%d,%%r%d,%%r%d", mnemonic,
get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
else
sprintf(buf, "%s\t%%r%d,%%r%d,%%r%d", mnemonic,
get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
}
/* Basic integer 3-address imm16 format:
* mnemonic #imm16,%rs2,%rd */
static void int_i2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
/* Sign extend the 16-bit immediate.
Print as hex for the bitwise operations. */
int upper_6bits = (insn >> 26) & 0x3f;
if (upper_6bits >= 0x30 && upper_6bits <= 0x3f)
sprintf(buf, "%s\t0x%04x,%%r%d,%%r%d", mnemonic,
(UINT32)(get_imm16 (insn)), get_isrc2 (insn), get_idest (insn));
else
sprintf(buf, "%s\t%d,%%r%d,%%r%d", mnemonic,
sign_ext(get_imm16 (insn), 16), get_isrc2 (insn), get_idest (insn));
}
/* Integer (mixed) 2-address isrc1ni,fdest. */
static void int_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
sprintf(buf, "%s\t%%r%d,%%f%d", mnemonic, get_isrc1 (insn), get_fdest (insn));
}
/* Integer (mixed) 2-address csrc2,idest. */
static void int_cd(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
sprintf(buf, "%s\t%%%s,%%r%d", mnemonic, cr2str[get_creg (insn)], get_idest (insn));
}
/* Integer (mixed) 2-address isrc1,csrc2. */
static void int_1c(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
sprintf(buf, "%s\t%%r%d,%%%s", mnemonic, get_isrc1(insn), cr2str[get_creg (insn)]);
}
/* Integer 1-address register format:
* mnemonic %rs1 */
static void int_1(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
sprintf(buf, "%s\t%%r%d", mnemonic, get_isrc1 (insn));
}
/* Integer no-address register format:
* mnemonic */
static void int_0(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
sprintf(buf, "%s", mnemonic);
}
/* Basic floating-point 3-address register format:
* mnemonic %fs1,%fs2,%fd */
static void flop_12d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
const char *suffix[4] = { "ss", "sd", "ds", "dd" };
const char *prefix_d, *prefix_p;
int s = (insn & 0x180) >> 7;
prefix_p = (insn & 0x400) ? "p" : "";
prefix_d = (insn & 0x200) ? "d." : "";
/* Special case: pf[m]am and pf[m]sm families are always pipelined, so they
do not have a prefix. Also, for the pfmam and pfmsm families, replace
any 'a' in the mnemonic with 'm' and prepend an 'm'. */
if ((insn & 0x7f) < 0x20)
{
int is_pfam = insn & 0x400;
if (!is_pfam)
{
char newname[256];
char *op = mnemonic;
char *np = newname + 1;
newname[0] = 'm';
while (*op)
{
if (*op == 'a')
*np = 'm';
else
*np = *op;
np++;
op++;
}
*np = 0;
mnemonic = newname;
}
prefix_p = "";
}
/* Special case: pfgt/pfle-- R-bit distinguishes the two. */
if ((insn & 0x7f) == 0x34)
{
const char *mn[2] = { "fgt.", "fle." };
int r = (insn & 0x080) >> 7;
int s = (insn & 0x100) ? 3 : 0;
sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mn[r],
suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
}
else
sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
suffix[s], get_fsrc1 (insn), get_fsrc2 (insn), get_fdest (insn));
}
/* Floating-point 2-address register format:
* mnemonic %fs1,%fd */
static void flop_1d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
const char *suffix[4] = { "ss", "sd", "ds", "dd" };
const char *prefix_d, *prefix_p;
int s = (insn & 0x180) >> 7;
prefix_p = (insn & 0x400) ? "p" : "";
prefix_d = (insn & 0x200) ? "d." : "";
sprintf(buf, "%s%s%s%s\t%%f%d,%%f%d", prefix_d, prefix_p, mnemonic,
suffix[s], get_fsrc1 (insn), get_fdest (insn));
}
/* Floating-point 2-address register format:
* mnemonic %fs2,%fd */
static void flop_2d(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
const char *suffix[4] = { "ss", "sd", "ds", "dd" };
const char *prefix_d;
int s = (insn & 0x180) >> 7;
prefix_d = (insn & 0x200) ? "d." : "";
sprintf(buf, "%s%s%s\t%%f%d,%%f%d", prefix_d, mnemonic, suffix[s],
get_fsrc2 (insn), get_fdest (insn));
}
/* Floating-point (mixed) 2-address register format:
* fxfr fsrc1,idest. */
static void flop_fxfr(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
const char *prefix_d = (insn & 0x200) ? "d." : "";
sprintf(buf, "%s%s\t%%f%d,%%r%d", prefix_d, mnemonic, get_fsrc1 (insn),
get_idest (insn));
}
/* Branch with reg,reg,sbroff format:
* mnemonic %rs1,%rs2,sbroff */
static void int_12S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
INT32 rel = (INT32)pc + (sbroff << 2) + 4;
sprintf(buf, "%s\t%%r%d,%%r%d,0x%08x", mnemonic, get_isrc1 (insn),
get_isrc2 (insn), (UINT32)rel);
}
/* Branch with #const5,reg,sbroff format:
* mnemonic #const5,%rs2,sbroff */
static void int_i2S(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
INT32 sbroff = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
INT32 rel = (INT32)pc + (sbroff << 2) + 4;
sprintf(buf, "%s\t%d,%%r%d,0x%08x", mnemonic, ((insn >> 11) & 0x1f),
get_isrc2 (insn), (UINT32)rel);
}
/* Branch with lbroff format:
* mnemonic lbroff */
static void int_L(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
INT32 lbroff = sign_ext ((insn & 0x03ffffff), 26);
INT32 rel = (INT32)pc + (lbroff << 2) + 4;
sprintf(buf, "%s\t0x%08x", mnemonic, (UINT32)rel);
}
/* Integer load.
* ld.{b,s,l} isrc1(isrc2),idest
* ld.{b,s,l} #const(isrc2),idest */
static void int_ldx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
/* Operand size, in bytes. */
int sizes[4] = { 1, 1, 2, 4 };
const char *suffix[4] = { "b", "b", "s", "l" };
UINT32 idx = 0;
/* Bits 28 and 0 determine the operand size. */
idx = ((insn >> 27) & 2) | (insn & 1);
/* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
if (insn & 0x04000000)
{
/* Chop off lower bits of displacement. */
INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
int size = sizes[idx];
immsrc1 &= ~(size - 1);
sprintf(buf, "%s%s\t%d(%%r%d),%%r%d", mnemonic, suffix[idx],
immsrc1, get_isrc2 (insn), get_idest (insn));
}
else
sprintf(buf, "%s%s\t%%r%d(%%r%d),%%r%d", mnemonic, suffix[idx],
get_isrc1 (insn), get_isrc2 (insn), get_idest (insn));
}
/* Integer store: st.b isrc1ni,#const(isrc2) */
static void int_stx(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
/* Operand size, in bytes. */
int sizes[4] = { 1, 1, 2, 4 };
const char *suffix[4] = { "b", "b", "s", "l" };
int idx = 0;
int size;
INT32 immsrc = sign_ext ((((insn >> 5) & 0xf800) | (insn & 0x07ff)), 16);
/* Bits 28 and 0 determine the operand size. */
idx = ((insn >> 27) & 2) | (insn & 1);
/* Chop off lower bits of displacement. */
size = sizes[idx];
immsrc &= ~(size - 1);
sprintf(buf, "%s%s\t%%r%d,%d(%%r%d)", mnemonic, suffix[idx],
get_isrc1 (insn), immsrc, get_isrc2 (insn));
}
/* Disassemble:
* "[p]fld.y isrc1(isrc2),fdest", "[p]fld.y isrc1(isrc2)++,idest",
* "[p]fld.y #const(isrc2),fdest" or "[p]fld.y #const(isrc2)++,idest".
* "fst.y fdest,isrc1(isrc2)", "fst.y fdest,isrc1(isrc2)++",
* "fst.y fdest,#const(isrc2)" or "fst.y fdest,#const(isrc2)++"
* Where y = {l,d,q}. Note, there is no pfld.q, though. */
static void int_fldst(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
INT32 immsrc1 = sign_ext (get_imm16 (insn), 16);
/* Operand size, in bytes. */
int sizes[4] = { 8, 4, 16, 4 };
const char *suffix[4] = { "d", "l", "q", "l" };
int idx = 0;
int size = 0;
int auto_inc = (insn & 1);
const char *auto_suff[2] = { "", "++" };
int piped = (insn & 0x40000000) >> 29;
const char *piped_suff[2] = { "", "p" };
int upper_6bits = (insn >> 26) & 0x3f;
int is_load = (upper_6bits == 8 || upper_6bits == 9 || upper_6bits == 24
|| upper_6bits == 25);
/* Bits 2 and 1 determine the operand size. */
idx = ((insn >> 1) & 3);
size = sizes[idx];
/* There is no pipelined load quad on XR. */
if (piped && size == 16)
{
sprintf (buf, ".long\t%#08x; *", insn);
return;
}
/* There is only a 64-bit pixel store. */
if ((upper_6bits == 15) && size != 8)
{
sprintf (buf, ".long\t%#08x", insn);
return;
}
/* Bit 26 determines the addressing mode (reg+reg or disp+reg). */
if (insn & 0x04000000)
{
/* Chop off lower bits of displacement. */
immsrc1 &= ~(size - 1);
if (is_load)
sprintf(buf, "%s%s%s\t%d(%%r%d)%s,%%f%d", piped_suff[piped], mnemonic,
suffix[idx], immsrc1, get_isrc2 (insn), auto_suff[auto_inc],
get_fdest (insn));
else
sprintf(buf, "%s%s\t%%f%d,%d(%%r%d)%s", mnemonic, suffix[idx],
get_fdest (insn), immsrc1, get_isrc2 (insn), auto_suff[auto_inc]);
}
else
{
if (is_load)
sprintf(buf, "%s%s%s\t%%r%d(%%r%d)%s,%%f%d", piped_suff[piped],
mnemonic, suffix[idx], get_isrc1 (insn), get_isrc2 (insn),
auto_suff[auto_inc], get_fdest (insn));
else
sprintf(buf, "%s%s\t%%f%d,%%r%d(%%r%d)%s", mnemonic, suffix[idx],
get_fdest (insn), get_isrc1 (insn), get_isrc2 (insn),
auto_suff[auto_inc]);
}
}
/* flush #const(isrc2)[++]. */
static void int_flush(char *buf, char *mnemonic, UINT32 pc, UINT32 insn)
{
const char *auto_suff[2] = { "", "++" };
INT32 immsrc = sign_ext (get_imm16 (insn), 16);
immsrc &= ~(16-1);
sprintf(buf, "%s\t%d(%%r%d)%s", mnemonic, immsrc, get_isrc2 (insn),
auto_suff[(insn & 1)]);
}
/* Flags for the decode table. */
enum
{
DEC_MORE = 1, /* More decoding necessary. */
DEC_DECODED = 2 /* Fully decoded, go. */
};
typedef struct
{
/* Disassembly function for this opcode.
Call with buffer, mnemonic, pc, insn. */
void (*insn_dis)(char *, char *, UINT32, UINT32);
/* Flags for this opcode. */
char flags;
/* Mnemonic of this opcode (sometimes partial when more decode is
done in disassembly routines-- e.g., loads and stores). */
const char *mnemonic;
} decode_tbl_t;
/* First-level decode table (i.e., for the 6 primary opcode bits). */
static decode_tbl_t decode_tbl[64] =
{
/* A slight bit of decoding for loads and stores is done in the
execution routines (operand size and addressing mode), which
is why their respective entries are identical. */
{ int_ldx, DEC_DECODED, "ld." }, /* ld.b isrc1(isrc2),idest. */
{ int_ldx, DEC_DECODED, "ld." }, /* ld.b #const(isrc2),idest. */
{ int_1d, DEC_DECODED, "ixfr" }, /* ixfr isrc1ni,fdest. */
{ int_stx, DEC_DECODED, "st." }, /* st.b isrc1ni,#const(isrc2). */
{ int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} isrc1(isrc2),idest. */
{ int_ldx, DEC_DECODED, "ld." }, /* ld.{s,l} #const(isrc2),idest. */
{ 0, 0 , 0 },
{ int_stx, DEC_DECODED, "st." }, /* st.{s,l} isrc1ni,#const(isrc2),idest.*/
{ int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} isrc1(isrc2)[++],fdest. */
{ int_fldst, DEC_DECODED, "fld." }, /* fld.{l,d,q} #const(isrc2)[++],fdest. */
{ int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,isrc1(isrc2)[++] */
{ int_fldst, DEC_DECODED, "fst." }, /* fst.{l,d,q} fdest,#const(isrc2)[++] */
{ int_cd, DEC_DECODED, "ld.c" }, /* ld.c csrc2,idest. */
{ int_flush, DEC_DECODED, "flush" }, /* flush #const(isrc2) (or autoinc). */
{ int_1c, DEC_DECODED, "st.c" }, /* st.c isrc1,csrc2. */
{ int_fldst, DEC_DECODED, "pstd." }, /* pst.d fdest,#const(isrc2)[++]. */
{ int_1, DEC_DECODED, "bri" }, /* bri isrc1ni. */
{ int_12d, DEC_DECODED, "trap" }, /* trap isrc1ni,isrc2,idest. */
{ 0, DEC_MORE, 0 }, /* FP ESCAPE FORMAT, more decode. */
{ 0, DEC_MORE, 0 }, /* CORE ESCAPE FORMAT, more decode. */
{ int_12S, DEC_DECODED, "btne" }, /* btne isrc1,isrc2,sbroff. */
{ int_i2S, DEC_DECODED, "btne" }, /* btne #const,isrc2,sbroff. */
{ int_12S, DEC_DECODED, "bte" }, /* bte isrc1,isrc2,sbroff. */
{ int_i2S, DEC_DECODED, "bte" }, /* bte #const5,isrc2,idest. */
{ int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} isrc1(isrc2)[++],fdest. */
{ int_fldst, DEC_DECODED, "pfld." }, /* pfld.{l,d,q} #const(isrc2)[++],fdest.*/
{ int_L, DEC_DECODED, "br" }, /* br lbroff. */
{ int_L, DEC_DECODED, "call" }, /* call lbroff . */
{ int_L, DEC_DECODED, "bc" }, /* bc lbroff. */
{ int_L, DEC_DECODED, "bc.t" }, /* bc.t lbroff. */
{ int_L, DEC_DECODED, "bnc" }, /* bnc lbroff. */
{ int_L, DEC_DECODED, "bnc.t" }, /* bnc.t lbroff. */
{ int_12d, DEC_DECODED, "addu" }, /* addu isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "addu" }, /* addu #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "subu" }, /* subu isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "subu" }, /* subu #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "adds" }, /* adds isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "adds" }, /* adds #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "subs" }, /* subs isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "subs" }, /* subs #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "shl" }, /* shl isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "shl" }, /* shl #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "shr" }, /* shr isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "shr" }, /* shr #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "shrd" }, /* shrd isrc1ni,isrc2,idest. */
{ int_12S, DEC_DECODED, "bla" }, /* bla isrc1ni,isrc2,sbroff. */
{ int_12d, DEC_DECODED, "shra" }, /* shra isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "shra" }, /* shra #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "and" }, /* and isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "and" }, /* and #const,isrc2,idest. */
{ 0, 0 , 0 },
{ int_i2d, DEC_DECODED, "andh" }, /* andh #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "andnot" }, /* andnot isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "andnot" }, /* andnot #const,isrc2,idest. */
{ 0, 0 , 0 },
{ int_i2d, DEC_DECODED, "andnoth" }, /* andnoth #const,isrc2,idest.*/
{ int_12d, DEC_DECODED, "or" }, /* or isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "or" }, /* or #const,isrc2,idest. */
{ 0, 0 , 0 },
{ int_i2d, DEC_DECODED, "orh" }, /* orh #const,isrc2,idest. */
{ int_12d, DEC_DECODED, "xor" }, /* xor isrc1,isrc2,idest. */
{ int_i2d, DEC_DECODED, "xor" }, /* xor #const,isrc2,idest. */
{ 0, 0 , 0 },
{ int_i2d, DEC_DECODED, "xorh" }, /* xorh #const,isrc2,idest. */
};
/* Second-level decode table (i.e., for the 3 core escape opcode bits). */
static decode_tbl_t core_esc_decode_tbl[8] =
{
{ 0, 0 , 0 },
{ int_0, DEC_DECODED, "lock" }, /* lock. */
{ int_1, DEC_DECODED, "calli" }, /* calli isrc1ni. */
{ 0, 0 , 0 },
{ int_0, DEC_DECODED, "intovr" }, /* intovr. */
{ 0, 0 , 0 },
{ 0, 0 , 0 },
{ int_0, DEC_DECODED, "unlock" }, /* unlock. */
};
/* Second-level decode table (i.e., for the 7 FP extended opcode bits). */
static decode_tbl_t fp_decode_tbl[128] =
{
/* Floating point instructions. The least significant 7 bits are
the (extended) opcode and bits 10:7 are P,D,S,R respectively
([p]ipelined, [d]ual, [s]ource prec., [r]esult prec.).
For some operations, I defer decoding the P,S,R bits to the
emulation routine for them. */
{ flop_12d, DEC_DECODED, "r2p1." }, /* 0x00 pf[m]am */
{ flop_12d, DEC_DECODED, "r2pt." }, /* 0x01 pf[m]am */
{ flop_12d, DEC_DECODED, "r2ap1." }, /* 0x02 pf[m]am */
{ flop_12d, DEC_DECODED, "r2apt." }, /* 0x03 pf[m]am */
{ flop_12d, DEC_DECODED, "i2p1." }, /* 0x04 pf[m]am */
{ flop_12d, DEC_DECODED, "i2pt." }, /* 0x05 pf[m]am */
{ flop_12d, DEC_DECODED, "i2ap1." }, /* 0x06 pf[m]am */
{ flop_12d, DEC_DECODED, "i2apt." }, /* 0x07 pf[m]am */
{ flop_12d, DEC_DECODED, "rat1p2." }, /* 0x08 pf[m]am */
{ flop_12d, DEC_DECODED, "m12apm." }, /* 0x09 pf[m]am */
{ flop_12d, DEC_DECODED, "ra1p2." }, /* 0x0A pf[m]am */
{ flop_12d, DEC_DECODED, "m12ttpa." }, /* 0x0B pf[m]am */
{ flop_12d, DEC_DECODED, "iat1p2." }, /* 0x0C pf[m]am */
{ flop_12d, DEC_DECODED, "m12tpm." }, /* 0x0D pf[m]am */
{ flop_12d, DEC_DECODED, "ia1p2." }, /* 0x0E pf[m]am */
{ flop_12d, DEC_DECODED, "m12tpa." }, /* 0x0F pf[m]am */
{ flop_12d, DEC_DECODED, "r2s1." }, /* 0x10 pf[m]sm */
{ flop_12d, DEC_DECODED, "r2st." }, /* 0x11 pf[m]sm */
{ flop_12d, DEC_DECODED, "r2as1." }, /* 0x12 pf[m]sm */
{ flop_12d, DEC_DECODED, "r2ast." }, /* 0x13 pf[m]sm */
{ flop_12d, DEC_DECODED, "i2s1." }, /* 0x14 pf[m]sm */
{ flop_12d, DEC_DECODED, "i2st." }, /* 0x15 pf[m]sm */
{ flop_12d, DEC_DECODED, "i2as1." }, /* 0x16 pf[m]sm */
{ flop_12d, DEC_DECODED, "i2ast." }, /* 0x17 pf[m]sm */
{ flop_12d, DEC_DECODED, "rat1s2." }, /* 0x18 pf[m]sm */
{ flop_12d, DEC_DECODED, "m12asm." }, /* 0x19 pf[m]sm */
{ flop_12d, DEC_DECODED, "ra1s2." }, /* 0x1A pf[m]sm */
{ flop_12d, DEC_DECODED, "m12ttsa." }, /* 0x1B pf[m]sm */
{ flop_12d, DEC_DECODED, "iat1s2." }, /* 0x1C pf[m]sm */
{ flop_12d, DEC_DECODED, "m12tsm." }, /* 0x1D pf[m]sm */
{ flop_12d, DEC_DECODED, "ia1s2." }, /* 0x1E pf[m]sm */
{ flop_12d, DEC_DECODED, "m12tsa." }, /* 0x1F pf[m]sm */
{ flop_12d, DEC_DECODED, "fmul." }, /* 0x20 [p]fmul */
{ flop_12d, DEC_DECODED, "fmlow." }, /* 0x21 fmlow.dd */
{ flop_2d, DEC_DECODED, "frcp." }, /* 0x22 frcp.{ss,sd,dd} */
{ flop_2d, DEC_DECODED, "frsqr." }, /* 0x23 frsqr.{ss,sd,dd} */
{ flop_12d, DEC_DECODED, "pfmul3.dd" }, /* 0x24 pfmul3.dd */
{ 0, 0 , 0 }, /* 0x25 */
{ 0, 0 , 0 }, /* 0x26 */
{ 0, 0 , 0 }, /* 0x27 */
{ 0, 0 , 0 }, /* 0x28 */
{ 0, 0 , 0 }, /* 0x29 */
{ 0, 0 , 0 }, /* 0x2A */
{ 0, 0 , 0 }, /* 0x2B */
{ 0, 0 , 0 }, /* 0x2C */
{ 0, 0 , 0 }, /* 0x2D */
{ 0, 0 , 0 }, /* 0x2E */
{ 0, 0 , 0 }, /* 0x2F */
{ flop_12d, DEC_DECODED, "fadd." }, /* 0x30, [p]fadd.{ss,sd,dd} */
{ flop_12d, DEC_DECODED, "fsub." }, /* 0x31, [p]fsub.{ss,sd,dd} */
{ flop_1d, DEC_DECODED, "fix." }, /* 0x32, [p]fix.{ss,sd,dd} */
{ flop_1d, DEC_DECODED, "famov." }, /* 0x33, [p]famov.{ss,sd,ds,dd} */
{ flop_12d, DEC_DECODED, "f{gt,le}" }, /* 0x34, pf{gt,le}.{ss,dd} */
{ flop_12d, DEC_DECODED, "feq." }, /* 0x35, pfeq.{ss,dd} */
{ 0, 0 , 0 }, /* 0x36 */
{ 0, 0 , 0 }, /* 0x37 */
{ 0, 0 , 0 }, /* 0x38 */
{ 0, 0 , 0 }, /* 0x39 */
{ flop_1d, DEC_DECODED, "ftrunc." }, /* 0x3A, [p]ftrunc.{ss,sd,dd} */
{ 0, 0 , 0 }, /* 0x3B */
{ 0, 0 , 0 }, /* 0x3C */
{ 0, 0 , 0 }, /* 0x3D */
{ 0, 0 , 0 }, /* 0x3E */
{ 0, 0 , 0 }, /* 0x3F */
{ flop_fxfr, DEC_DECODED, "fxfr" }, /* 0x40, fxfr fsrc1,idest. */
{ 0, 0 , 0 }, /* 0x41 */
{ 0, 0 , 0 }, /* 0x42 */
{ 0, 0 , 0 }, /* 0x43 */
{ 0, 0 , 0 }, /* 0x44 */
{ 0, 0 , 0 }, /* 0x45 */
{ 0, 0 , 0 }, /* 0x46 */
{ 0, 0 , 0 }, /* 0x47 */
{ 0, 0 , 0 }, /* 0x48 */
{ flop_12d, DEC_DECODED, "fiadd." }, /* 0x49, [p]fiadd.{ss,dd} */
{ 0, 0 , 0 }, /* 0x4A */
{ 0, 0 , 0 }, /* 0x4B */
{ 0, 0 , 0 }, /* 0x4C */
{ flop_12d, DEC_DECODED, "fisub." }, /* 0x4D, [p]fisub.{ss,dd} */
{ 0, 0 , 0 }, /* 0x4E */
{ 0, 0 , 0 }, /* 0x4F */
{ flop_12d, DEC_DECODED, "faddp" }, /* 0x50, [p]faddp */
{ flop_12d, DEC_DECODED, "faddz" }, /* 0x51, [p]faddz */
{ 0, 0 , 0 }, /* 0x52 */
{ 0, 0 , 0 }, /* 0x53 */
{ 0, 0 , 0 }, /* 0x54 */
{ 0, 0 , 0 }, /* 0x55 */
{ 0, 0 , 0 }, /* 0x56 */
{ flop_12d, DEC_DECODED, "fzchkl" }, /* 0x57, [p]fzchkl */
{ 0, 0 , 0 }, /* 0x58 */
{ 0, 0 , 0 }, /* 0x59 */
{ flop_1d, DEC_DECODED, "form" }, /* 0x5A, [p]form.dd */
{ 0, 0 , 0 }, /* 0x5B */
{ 0, 0 , 0 }, /* 0x5C */
{ 0, 0 , 0 }, /* 0x5D */
{ 0, 0 , 0 }, /* 0x5E */
{ flop_12d, DEC_DECODED, "fzchks" }, /* 0x5F, [p]fzchks */
{ 0, 0 , 0 }, /* 0x60 */
{ 0, 0 , 0 }, /* 0x61 */
{ 0, 0 , 0 }, /* 0x62 */
{ 0, 0 , 0 }, /* 0x63 */
{ 0, 0 , 0 }, /* 0x64 */
{ 0, 0 , 0 }, /* 0x65 */
{ 0, 0 , 0 }, /* 0x66 */
{ 0, 0 , 0 }, /* 0x67 */
{ 0, 0 , 0 }, /* 0x68 */
{ 0, 0 , 0 }, /* 0x69 */
{ 0, 0 , 0 }, /* 0x6A */
{ 0, 0 , 0 }, /* 0x6B */
{ 0, 0 , 0 }, /* 0x6C */
{ 0, 0 , 0 }, /* 0x6D */
{ 0, 0 , 0 }, /* 0x6E */
{ 0, 0 , 0 }, /* 0x6F */
{ 0, 0 , 0 }, /* 0x70 */
{ 0, 0 , 0 }, /* 0x71 */
{ 0, 0 , 0 }, /* 0x72 */
{ 0, 0 , 0 }, /* 0x73 */
{ 0, 0 , 0 }, /* 0x74 */
{ 0, 0 , 0 }, /* 0x75 */
{ 0, 0 , 0 }, /* 0x76 */
{ 0, 0 , 0 }, /* 0x77 */
{ 0, 0 , 0 }, /* 0x78 */
{ 0, 0 , 0 }, /* 0x79 */
{ 0, 0 , 0 }, /* 0x7A */
{ 0, 0 , 0 }, /* 0x7B */
{ 0, 0 , 0 }, /* 0x7C */
{ 0, 0 , 0 }, /* 0x7D */
{ 0, 0 , 0 }, /* 0x7E */
{ 0, 0 , 0 }, /* 0x7F */
};
/* Replaces tabs with spaces. */
static void i860_dasm_tab_replacer(char* buf, int tab_size)
{
int i = 0;
int tab_count = 0;
char tab_buf[1024];
memset(tab_buf, 0, 1024);
while (i != strlen(buf))
{
if (buf[i] != '\t')
{
tab_buf[tab_count] = buf[i];
tab_count++;
}
else
{
while (tab_count % tab_size != 0)
{
strcat(tab_buf, " ");
tab_count++;
}
}
i++;
}
tab_buf[tab_count] = 0x00;
strcpy(buf, tab_buf);
}
/* Entry point for disassembler. */
unsigned disasm_i860(char *buf, unsigned pc, UINT32 insn)
{
int unrecognized_op = 1;
int upper_6bits = (insn >> 26) & 0x3f;
char flags = decode_tbl[upper_6bits].flags;
if (flags & DEC_DECODED)
{
const char *s = decode_tbl[upper_6bits].mnemonic;
decode_tbl[upper_6bits].insn_dis (buf, (char *)s, pc, insn);
unrecognized_op = 0;
}
else if (flags & DEC_MORE)
{
if (upper_6bits == 0x12)
{
/* FP instruction format handled here. */
char fp_flags = fp_decode_tbl[insn & 0x7f].flags;
const char *s = fp_decode_tbl[insn & 0x7f].mnemonic;
if (fp_flags & DEC_DECODED)
{
fp_decode_tbl[insn & 0x7f].insn_dis (buf, (char *)s, pc, insn);
unrecognized_op = 0;
}
}
else if (upper_6bits == 0x13)
{
/* Core escape instruction format handled here. */
char esc_flags = core_esc_decode_tbl[insn & 0x3].flags;
const char *s = core_esc_decode_tbl[insn & 0x3].mnemonic;
if (esc_flags & DEC_DECODED)
{
core_esc_decode_tbl[insn & 0x3].insn_dis (buf, (char *)s, pc, insn);
unrecognized_op = 0;
}
}
}
if (unrecognized_op)
sprintf (buf, ".long\t%#08x", insn);
/* Replace tabs with spaces */
i860_dasm_tab_replacer(buf, 10);
/* Return number of bytes disassembled. */
/* MAME dasm flags haven't been added yet */
return (4);
}

View File

@ -1,8 +1,8 @@
/*
Virtual Combat hardware games.
Driver by Jason Eckhardt and Andrew Gardner.
Driver by Jason Eckhardt and Andrew Gardner.
----
There are two known games on this hardware. Both are developed by
@ -17,10 +17,10 @@ Shadow Fighters (German) (c) Sega? 1989?
There are two boards to this hardware. The upper, which contains the
graphics ROMs and the i860, and the lower which contains the main
and sound CPUs. Virtual Combat sports two upper boards which presumably
and sound CPUs. Virtual Combat sports two upper boards which
output a different rasterization of the scene for each stereo eye.
UPPER:
UPPER: (Virtual Combat has an identical MIDDLE board also).
Intel I860 XR processor
MB8298-25P-SK RAMS x12 (silkscreen said 62256)
Analog device ADV476KN50E (silkscreen said BT476)
@ -28,7 +28,7 @@ UPPER:
8-way DIP switch
574200D x4
PAL palce24v10 x2 (next to the i860)
Bt476 RAMDAC
Bt476 RAMDAC
LOWER:
Motorola MC68000P12 x2
@ -54,20 +54,50 @@ NOTES : Shadow Fighters appears to have been dumped from an earlier
The data stored in "samples" is simply a series of
Creative Media VOC files concatenated to eachother.
The sound program ("sound") is about 640 bytes long.
The graphics ROMs have had images successfully extracted from
them. Pictures for Shadow Fighters can be found online.
The hardware is said to run at medium resolution.
The SRAM module dump can likely be thrown away for both games.
The PAL that's dumped for Shadow Fighters looks pretty bad.
Websites seem to say Shadow Fighters is a SEGA game, but I
couldn't find a SEGA string anywhere in the ROMs. I also,
however, could not find a VR8 string in the Virtual Combat
ROMs, so who knows... Kyle's name is easily found in both
though :).
TODO : This is a skeleton driver. Nearly everything.
i860XR-25 CPU core!
TODO : This is a partially working driver. Most of the memory maps for
all four CPUs are complete. An Intel i860XR CPU core has now
been incorporated into MAME.
-------- Notes/questions ----------
- Most of the memory maps and input ports are complete now.
For "main", the only I/O locations that seem to be left
mysterious are:
0x600010,
0x60000C: Only written; maybe mc6845? Often accessed
together, and 16 consecutive words of data are
written to 0x60000C, making me think it might be
6845-related. May or may not be important for
reasonable emulation.
0x60001C: Only read; might be a latch of some sort. It is
read each time M0's interrupt service routine syncs
with the i860's to have them update the frame buffer.
Might this be a HW blank bit so things look clean when
the i860's do their updates?
The two other times I see it read are just before
and after one of the pallette setups is done.
0x600018: ? No info yet.
0x704000: (VC only) Likely analog axis for VR headset
0x703000: (VC only) Likely analog axis for VR headset
0x702000: (Shadow only). I think this is another IN port. It
is always read at the same time as the other two
ports.
- Assuming a single framebuffer, as I think we are at the moment,
how are all the CPUs writes to the framebuffer prioritized,
if at all? The zero values written by the 68k side erase
the i860-generated FB data (i.e., zero maps to black in the
pallette). On the other hand, treating the zero values as
transparent doesn't quite look right either. Could just the
i860s each have their own framebuffers? After
all, since each eye of the binocular sees a slightly different
picture, the i860's might just maintain their own. Then maybe
the 68k shares with each of the two, since I think it just
generates a single picture (not sure about that either).
----------------------------------------------
*/
#include <stdio.h>
@ -77,61 +107,266 @@ TODO : This is a skeleton driver. Nearly everything.
#include "video/generic.h"
#include "video/tlc34076.h"
static UINT16* framebuffer;
static UINT16* framebuffer_main;
static UINT16* framebuffer_secondary;
static UINT16* vid_0_shared_RAM;
static UINT16* vid_1_shared_RAM;
static VIDEO_UPDATE( vcombat )
{
int x, y;
int count = 0;
const rgb_t *pens = tlc34076_get_pens();
/* TODO: It looks like the leftmost chunk of the ground should really be on the right side? */
/* But the i860 draws the background correctly, so it may be an original game issue. */
/* There's also some garbage in the upper-left corner. Might be related to this 'wraparound'. */
/* Or maybe it's related to the 68k's alpha? It might come from the 68k side of the house. */
/* Main eye */
for(y = 0; y < 256; y++)
{
for(x = 384; x < 640; x++)
{
UINT32 color;
if (x % 2) color = (framebuffer_main[count] & 0xff00) >> 8;
else color = framebuffer_main[count] & 0x00ff;
/* Vcombat's screen renders 'flopped' - very likely because VR headset displays may reflect off mirrors.
Shadfgtr isn't flopped, so it's not a constant feature of the hardware. */
if(x < video_screen_get_visible_area(screen)->max_x && y < video_screen_get_visible_area(screen)->max_y)
*BITMAP_ADDR32(bitmap, y, x) = pens[color];
if (x % 2) count++;
}
}
/* Early out for shadow fighters */
if (!framebuffer_secondary)
return 0;
/* Secondary eye */
count = 0;
for(y = 0; y < 256; y++)
{
for(x = 0; x < 256; x++)
{
UINT32 color;
if (x % 2) color = (framebuffer_secondary[count] & 0xff00) >> 8;
else color = framebuffer_secondary[count] & 0x00ff;
/* Vcombat's screen renders 'flopped' - very likely because VR headset displays may reflect off mirrors.
Shadfgtr isn't flopped, so it's not a constant feature of the hardware. */
if(x < video_screen_get_visible_area(screen)->max_x && y < video_screen_get_visible_area(screen)->max_y)
*BITMAP_ADDR32(bitmap, y, x) = pens[color];
if (x % 2) count++;
}
}
return 0;
}
/* Maybe there's a blend chip between the 68k and the framebuffer? */
static WRITE16_HANDLER( main_video_write )
{
/* Doesn't seem to make sense for shadow fighters. Maybe some of that factory rework disables this? */
/* Doesn't always seem to work for vcombat either. More testing needed. */
if (data != 0x00000000) {
framebuffer_main[offset] = data;
}
}
static READ16_HANDLER( control_1_r )
{
return (input_port_read(space->machine, "IN0") << 8);
}
static READ16_HANDLER( control_2_r )
{
return (input_port_read(space->machine, "IN1") << 8);
}
static void wiggle_i860_common(int n, UINT16 data, const device_config *device)
{
int bus_hold = (data & 0x03) == 0x03;
int reset = data & 0x10;
assert(n >= 0 && n < 2);
if (!device)
return;
if (bus_hold)
{
fprintf(stderr, "M0 asserting bus HOLD to i860 %s\n", device->tag);
i860_set_pin(device->token, DEC_PIN_BUS_HOLD, 1);
}
else
{
fprintf(stderr, "M0 clearing bus HOLD to i860 %s\n", device->tag);
i860_set_pin(device->token, DEC_PIN_BUS_HOLD, 0);
}
if (reset)
{
fprintf(stderr, "M0 asserting RESET to i860 %s\n", device->tag);
i860_set_pin(device->token, DEC_PIN_RESET, 1);
}
else
i860_set_pin(device->token, DEC_PIN_RESET, 0);
}
static WRITE16_HANDLER( wiggle_i860p0_pins_w )
{
wiggle_i860_common(0, data, cputag_get_cpu(space->machine, "vid_0"));
}
static WRITE16_HANDLER( wiggle_i860p1_pins_w )
{
wiggle_i860_common(1, data, cputag_get_cpu(space->machine, "vid_1"));
}
static READ16_HANDLER( main_irqiack_r )
{
//fprintf(stderr, "M0: irq iack\n");
cpu_set_input_line(cputag_get_cpu(space->machine, "main"), M68K_IRQ_1, CLEAR_LINE);
//cpu_set_input_line(cputag_get_cpu(space->machine, "main"), INPUT_LINE_RESET, CLEAR_LINE);
return 0;
}
static READ16_HANDLER( sound_resetmain_r )
{
//fprintf(stderr, "M1: reset line to M0\n");
//cpu_set_input_line(cputag_get_cpu(space->machine, "main"), INPUT_LINE_RESET, PULSE_LINE);
return 0;
}
static WRITE64_HANDLER( v0_fb_w )
{
/* The frame buffer seems to sit on a 32-bit data bus, while the
i860 uses a 64-bit data bus. Adjust accordingly. */
char *p = (char *)framebuffer_main;
int m = mem_mask;
int o = (offset << 2);
if (m & 0xff000000) {
p[o+3] = (data >> 24) & 0xff;
}
if (m & 0x00ff0000) {
p[o+2] = (data >> 16) & 0xff;
}
if (m & 0x0000ff00) {
p[o+1] = (data >> 8) & 0xff;
}
if (m & 0x000000ff) {
p[o+0] = (data >> 0) & 0xff;
}
}
/* This is just temporary so we can see what each i860 is doing to the
framebuffer. */
static WRITE64_HANDLER( v1_fb_w )
{
/* The frame buffer seems to sit on a 32-bit data bus, while the
i860 uses a 64-bit data bus. Adjust accordingly. */
char *p = (char *)framebuffer_secondary;
int m = mem_mask;
int o = (offset << 2);
if (m & 0xff000000) {
p[o+3] = (data >> 24) & 0xff;
}
if (m & 0x00ff0000) {
p[o+2] = (data >> 16) & 0xff;
}
if (m & 0x0000ff00) {
p[o+1] = (data >> 8) & 0xff;
}
if (m & 0x000000ff) {
p[o+0] = (data >> 0) & 0xff;
}
}
static ADDRESS_MAP_START( main_map, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x0fffff) AM_ROM
AM_RANGE(0x200000, 0x2fffff) AM_RAM
AM_RANGE(0x300000, 0x3fffff) AM_RAM AM_BASE(&framebuffer) AM_SHARE(1)
AM_RANGE(0x300000, 0x30ffff) AM_RAM_WRITE(main_video_write)
AM_RANGE(0x400000, 0x43ffff) AM_RAM AM_BASE(&vid_0_shared_RAM) AM_SHARE(2) /* First i860 shared RAM */
// AM_RANGE(0x440000, 0x440003) i860 #1 com 1
// AM_RANGE(0x480000, 0x480003) i860 #1 com 2
// AM_RANGE(0x4c0000, 0x4c0003) i860 #1 stop/start/reset
AM_RANGE(0x440000, 0x440003) AM_RAM AM_SHARE(6) /* M0->P0 i860 #1 com 1 */
AM_RANGE(0x480000, 0x480003) AM_RAM AM_SHARE(7) /* M0<-P0 i860 #1 com 2 */
AM_RANGE(0x4c0000, 0x4c0003) AM_WRITE(wiggle_i860p0_pins_w) /* i860 #1 stop/start/reset */
AM_RANGE(0x500000, 0x53ffff) AM_RAM AM_BASE(&vid_1_shared_RAM) AM_SHARE(3) /* Second i860 shared RAM */
// AM_RANGE(0x540000, 0x540003) i860 #2 com 1
// AM_RANGE(0x580000, 0x580003) i860 #2 com 2
// AM_RANGE(0x5c0000, 0x5c0003) i860 #2 stop/start/reset
AM_RANGE(0x540000, 0x540003) AM_RAM AM_SHARE(8) /* M0->P1 i860 #2 com 1 */
AM_RANGE(0x580000, 0x580003) AM_RAM AM_SHARE(9) /* M0<-P1 i860 #2 com 2 */
AM_RANGE(0x5c0000, 0x5c0003) AM_WRITE(wiggle_i860p1_pins_w) /* i860 #2 stop/start/reset */
AM_RANGE(0x600000, 0x600001) AM_READ(control_1_r) /* IN0 port */
AM_RANGE(0x600004, 0x600005) AM_RAM AM_SHARE(5) /* M0<-M1 */
AM_RANGE(0x600008, 0x600009) AM_READ(control_2_r) /* IN1 port */
/* AM_RANGE(0x60000c, 0x60000d) See notes at top of driver. */
/* AM_RANGE(0x600010, 0x600011) See notes at top of driver. */
AM_RANGE(0x700000, 0x7007ff) AM_RAM /* TODO: Non-volatile RAM */
AM_RANGE(0x701000, 0x701001) AM_READ(main_irqiack_r)
AM_RANGE(0x705000, 0x705001) AM_RAM AM_SHARE(4) /* M1->M0 */
//AM_RANGE(0x703000, 0x703001) /* Headset rotation axis? */
//AM_RANGE(0x704000, 0x704001) /* Headset rotation axis? */
AM_RANGE(0x706000, 0x70601f) AM_READWRITE(tlc34076_lsb_r, tlc34076_lsb_w)
ADDRESS_MAP_END
/* The first i860 - middle board */
static ADDRESS_MAP_START( vid_0_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x000fffff) AM_RAM AM_SHARE(1) /* Shared framebuffer */
// AM_RANGE(0x20000000, 0x20000003) com 1 (0x440000 in 68k-land)
// AM_RANGE(0x40000000, 0x401fffff) AM_ROM /* 3d data ROMs */
// AM_RANGE(0x80000000, 0x80000003) com 2 (0x480000 in 68k-land)
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(2) /* Shared RAM with main */
static ADDRESS_MAP_START( vid_0_map, ADDRESS_SPACE_PROGRAM, 64 )
AM_RANGE(0x00000000, 0x0001ffff) AM_RAM_WRITE(v0_fb_w) /* Shared framebuffer - half of the bits lost to 32-bit bus */
AM_RANGE(0x20000000, 0x20000007) AM_RAM AM_SHARE(6) /* M0<-P0 com 1 (0x440000 in 68k-land) */
AM_RANGE(0x40000000, 0x401fffff) AM_ROM AM_REGION("gfx", 0)
AM_RANGE(0x80000000, 0x80000007) AM_RAM AM_SHARE(7) /* M0->P0 com 2 (0x480000 in 68k-land) */
AM_RANGE(0xc0000000, 0xc0000fff) AM_NOP /* Dummy D$ flush page. */
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(2) /* Shared RAM with main */
ADDRESS_MAP_END
/* The second i860 - top board */
static ADDRESS_MAP_START( vid_1_map, ADDRESS_SPACE_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x000fffff) AM_RAM AM_SHARE(1) /* Shared framebuffer */
// AM_RANGE(0x20000000, 0x20000003) com 1 (0x540000 in 68k-land)
// AM_RANGE(0x40000000, 0x401fffff) AM_ROM /* 3d data ROMs */
// AM_RANGE(0x80000000, 0x80000003) com 2 (0x580000 in 68k-land)
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(3) /* Shared RAM with main */
static ADDRESS_MAP_START( vid_1_map, ADDRESS_SPACE_PROGRAM, 64 )
AM_RANGE(0x00000000, 0x0001ffff) AM_RAM_WRITE(v1_fb_w) /* Half of the bits lost to 32-bit bus */
AM_RANGE(0x20000000, 0x20000007) AM_RAM AM_SHARE(8) /* M0->P1 com 1 (0x540000 in 68k-land) */
AM_RANGE(0x40000000, 0x401fffff) AM_ROM AM_REGION("gfx", 0)
AM_RANGE(0x80000000, 0x80000007) AM_RAM AM_SHARE(9) /* M0<-P1 com 2 (0x580000 in 68k-land) */
AM_RANGE(0xc0000000, 0xc0000fff) AM_NOP /* Dummy D$ flush page. */
AM_RANGE(0xfffc0000, 0xffffffff) AM_RAM AM_SHARE(3) /* Shared RAM with main */
ADDRESS_MAP_END
/* Sound CPU - temprarily disabled */
//static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 16 )
// AM_RANGE(0x000000, 0x03ffff) AM_ROM
//ADDRESS_MAP_END
/* Sound CPU */
static ADDRESS_MAP_START( sound_map, ADDRESS_SPACE_PROGRAM, 16 )
AM_RANGE(0x000000, 0x03ffff) AM_ROM
AM_RANGE(0x081000, 0x081fff) AM_RAM
AM_RANGE(0x140000, 0x140001) AM_READ(sound_resetmain_r) /* Ping M0's reset line */
AM_RANGE(0x180000, 0x180001) AM_RAM AM_SHARE(4) /* M1<-M0 */
AM_RANGE(0x1C0000, 0x1C0001) AM_RAM AM_SHARE(5) /* M1->M0 */
ADDRESS_MAP_END
static MACHINE_RESET( vcombat )
{
/* Setup the Bt476 VGA RAMDAC palette chip */
tlc34076_reset(6);
i860_set_pin(cputag_get_cpu(machine, "vid_0")->token, DEC_PIN_BUS_HOLD, 1);
i860_set_pin(cputag_get_cpu(machine, "vid_1")->token, DEC_PIN_BUS_HOLD, 1);
}
static MACHINE_RESET( shadfgtr )
{
/* Setup the Bt476 VGA RAMDAC palette chip */
tlc34076_reset(6);
i860_set_pin(cputag_get_cpu(machine, "vid_0")->token, DEC_PIN_BUS_HOLD, 1);
}
static DIRECT_UPDATE_HANDLER( vid_0_direct_handler )
{
if (address >= 0xfffc0000 && address <= 0xffffffff)
@ -152,6 +387,7 @@ static DIRECT_UPDATE_HANDLER( vid_1_direct_handler )
return address;
}
static DRIVER_INIT( vcombat )
{
UINT8 *ROM = memory_region(machine, "main");
@ -160,72 +396,87 @@ static DRIVER_INIT( vcombat )
memory_set_direct_update_handler(cputag_get_address_space(machine, "vid_0", ADDRESS_SPACE_PROGRAM), vid_0_direct_handler);
memory_set_direct_update_handler(cputag_get_address_space(machine, "vid_1", ADDRESS_SPACE_PROGRAM), vid_1_direct_handler);
// Hacks
// pc==4016 : jump 4038 ... There's something strange about how it waits at 402e (interrupts all masked out)
/* Allocate the two framebuffers */
framebuffer_main = auto_malloc(0x10000 * sizeof(UINT16));
framebuffer_secondary = auto_malloc(0x10000 * sizeof(UINT16));
/* pc==4016 : jump 4038 ... There's something strange about how it waits at 402e (interrupts all masked out)
I think what is happening here is that M0 snags the first time
it hits this point based on a counter test just above this
instruction. That counter gets updated just past this instruction.
However, the only way this can be passed is if the M0 CPU is
reset (the IPL=7, but irq 7 is a nop). I am almost sure that M1
reads a latch, which resets M0 (probably to ensure M0 and M1 are
both alive) and gets passed this snag. I tried to hook up a reset
which should work, but asserting the reset line on the m68k doesn't
seem to do anything. Maybe the 68k emulator doesn't respond to
that, or I didn't do it correctly. But I think that is what needs
to be done. But it isn't crucial for emulation. Shadow does not
have this snag. */
ROM[0x4017] = 0x66;
}
// Sound CPU comm bits
// pc==40fa : jump 40fc ... 600004 should be -16
ROM[0x40fb] = 0x67;
// pc==410e : jump 4110 ... 600004 should be 31
ROM[0x410f] = 0x67;
static DRIVER_INIT( shadfgtr )
{
/* Allocate just one framebuffer */
framebuffer_main = auto_malloc(0x10000 * sizeof(UINT16));
framebuffer_secondary = NULL;
// pc==e220 : jump e222 ... 20119a should not be 0. (no interrupts masked)
// TODO: I wonder if this is an input bit that's ticked on vblank or something. The menu selection continually crawls up.
/* The i860 executes out of RAM */
memory_set_direct_update_handler(cputag_get_address_space(machine, "vid_0", ADDRESS_SPACE_PROGRAM), vid_0_direct_handler);
}
static INPUT_PORTS_START( vcombat )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) /* Left button */
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) /* Right button */
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static VIDEO_UPDATE( vcombat )
{
int x, y;
int count = 0;
const rgb_t *pens = tlc34076_get_pens();
static INPUT_PORTS_START( shadfgtr )
PORT_START("IN0")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY /* ? */
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_4WAY /* ? */
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
for(y = 0; y < 480; y++)
{
for(x = 0; x < 256; x++)
{
UINT32 color;
if (x % 2) color = (framebuffer[count] & 0xff00) >> 8;
else color = framebuffer[count] & 0x00ff;
if(x < video_screen_get_visible_area(screen)->max_x && y < video_screen_get_visible_area(screen)->max_y)
*BITMAP_ADDR32(bitmap, y, x) = pens[color];
if (x % 2) count++;
}
}
return 0;
}
// This is just here to show that there is text in the main program ROM. It probably won't really be a useful decode.
static const gfx_layout vcombat_charlayout =
{
8, 8,
0x100000 / 0x80,
8,
{ 0,1,2,3,4,5,6,7 },
{ 0*16, 1*16, 2*16, 3*16, 4*16, 5*16, 6*16, 7*16 },
{ 0*16*8, 1*16*8, 2*16*8, 3*16*8, 4*16*8, 5*16*8, 6*16*8, 7*16*8 },
8 * 0x80
};
static GFXDECODE_START( vcombat )
GFXDECODE_ENTRY( "main", 0, vcombat_charlayout, 0, 256 )
GFXDECODE_END
PORT_START("IN1")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
INPUT_PORTS_END
static MACHINE_DRIVER_START( vcombat )
MDRV_CPU_ADD("main", M68000, XTAL_12MHz)
MDRV_CPU_PROGRAM_MAP(main_map,0)
//MDRV_CPU_VBLANK_INT("main", irq7_line_hold)
MDRV_CPU_VBLANK_INT("main", irq1_line_assert)
/* The middle board i860 */
MDRV_CPU_ADD("vid_0", I860, XTAL_20MHz)
@ -235,14 +486,43 @@ static MACHINE_DRIVER_START( vcombat )
MDRV_CPU_ADD("vid_1", I860, XTAL_20MHz)
MDRV_CPU_PROGRAM_MAP(vid_1_map,0)
/* Sound CPU Disabled for now */
//MDRV_CPU_ADD("sound", M68000, XTAL_12MHz)
//MDRV_CPU_PROGRAM_MAP(sound_map,0)
/* Sound CPU */
MDRV_CPU_ADD("sound", M68000, XTAL_12MHz)
MDRV_CPU_PROGRAM_MAP(sound_map,0)
MDRV_MACHINE_RESET(vcombat)
// Likely will go away
MDRV_GFXDECODE(vcombat)
/* Temporary hack for experimenting with timing. */
#if 0
//MDRV_QUANTUM_TIME(HZ(1200))
MDRV_QUANTUM_PERFECT_CPU("main")
#endif
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(50)
MDRV_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0))
MDRV_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MDRV_SCREEN_SIZE(640, 480)
MDRV_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1)
MDRV_VIDEO_UPDATE(vcombat)
MACHINE_DRIVER_END
static MACHINE_DRIVER_START( shadfgtr )
MDRV_CPU_ADD("main", M68000, XTAL_12MHz)
MDRV_CPU_PROGRAM_MAP(main_map,0)
MDRV_CPU_VBLANK_INT("main", irq1_line_assert)
/* The middle board i860 */
MDRV_CPU_ADD("vid_0", I860, XTAL_20MHz)
MDRV_CPU_PROGRAM_MAP(vid_0_map,0)
/* Sound CPU */
MDRV_CPU_ADD("sound", M68000, XTAL_12MHz)
MDRV_CPU_PROGRAM_MAP(sound_map,0)
MDRV_MACHINE_RESET(shadfgtr)
MDRV_SCREEN_ADD("main", RASTER)
MDRV_SCREEN_REFRESH_RATE(60)
@ -255,6 +535,9 @@ static MACHINE_DRIVER_START( vcombat )
MACHINE_DRIVER_END
/* Perhaps add this to the core romload.h file? */
#define ROM_LOAD64_WORD(name,offset,length,hash) ROMX_LOAD(name, offset, length, hash, ROM_GROUPWORD | ROM_SKIP(6))
ROM_START( vcombat )
ROM_REGION( 0x100000, "main", 0 )
ROM_LOAD16_BYTE( "ep8v2.b49", 0x00000, 0x80000, CRC(98d5a45d) SHA1(099e314f11c93ad6e642ceaa311e2a5b6fd7193c) )
@ -270,15 +553,15 @@ ROM_START( vcombat )
ROM_LOAD16_BYTE( "ep3v2.b40", 0x100000, 0x40000, CRC(8c491526) SHA1(95c6bcbe0adcfffb12fd2b86c9f4ca26aa188bbf) )
ROM_LOAD16_BYTE( "ep5v2.b36", 0x100001, 0x40000, CRC(7592b2eb) SHA1(92a540726306d7adbf207fe86a4c4fa66958f90b) )
ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
ROM_LOAD( "ds1220y.b53", 0x000, 0x800, CRC(b21cfe5f) SHA1(898ace3cd0913ea4b0dc84320219777773ef856f) )
/* These roms are identical on both of the upper boards */
ROM_REGION( 0x200000, "3d", 0 )
ROM_LOAD16_BYTE( "11.u56", 0x000000, 0x80000, CRC(a83094ce) SHA1(c3512375fecdb5e7eb02a4aa140ae4efe0233cb8) )
ROM_LOAD16_BYTE( "9.u54", 0x000001, 0x80000, CRC(a276e18b) SHA1(6d60e519196a4858b82241504592413df498e12f) )
ROM_LOAD16_BYTE( "12.u57", 0x100000, 0x80000, CRC(0cdffd4f) SHA1(65ace78711b3ef6e0ff9a7ad7343b5558e652f6c) )
ROM_LOAD16_BYTE( "10.u55", 0x100001, 0x80000, CRC(8921f20e) SHA1(6e9ca2eaad3e1108ba0e1d7792fd5d0305bec201) )
ROM_REGION( 0x200000, "gfx", 0 )
ROM_LOAD64_WORD( "9.u55", 0x000000, 0x80000, CRC(a276e18b) SHA1(6d60e519196a4858b82241504592413df498e12f) )
ROM_LOAD64_WORD( "10.u57", 0x000002, 0x80000, CRC(8921f20e) SHA1(6e9ca2eaad3e1108ba0e1d7792fd5d0305bec201) )
ROM_LOAD64_WORD( "11.u54", 0x000004, 0x80000, CRC(a83094ce) SHA1(c3512375fecdb5e7eb02a4aa140ae4efe0233cb8) )
ROM_LOAD64_WORD( "12.u56", 0x000006, 0x80000, CRC(0cdffd4f) SHA1(65ace78711b3ef6e0ff9a7ad7343b5558e652f6c) )
ROM_REGION( 0x400, "plds", 0 )
ROM_LOAD( "pal1_w2.u51", 0x000, 0x1f1, CRC(af497420) SHA1(03aa82189d91ae194dd5a6e7b9dbdb7cd473ddb6) )
@ -301,18 +584,17 @@ ROM_START( shadfgtr )
ROM_REGION( 0x800, "user1", 0 ) /* The SRAM module */
ROM_LOAD( "shadfgtr.b53", 0x000, 0x800, CRC(e766a3ab) SHA1(e7696ec08d5c86f64d768480f43edbd19ded162d) )
/* These roms are identical on both of the upper boards */
ROM_REGION( 0x200000, "3d", 0 )
ROM_LOAD16_BYTE( "shadfgtr.u56", 0x000000, 0x80000, CRC(fb76db5a) SHA1(fa546f465df113c13037abed1162bfa6f9b1dc9b) )
ROM_LOAD16_BYTE( "shadfgtr.u54", 0x000001, 0x80000, CRC(c45d68d6) SHA1(a133e4f13d3af18bccf0d060a659d64ac699b159) )
ROM_LOAD16_BYTE( "shadfgtr.u57", 0x100000, 0x80000, CRC(60d701d7) SHA1(936473b5e3b2e9e9e3b50cf977fc5a670a097850) )
ROM_LOAD16_BYTE( "shadfgtr.u55", 0x100001, 0x80000, CRC(e807631d) SHA1(9027ff7dc60b808434dac292c08f0630d3d52186) )
ROM_REGION( 0x200000, "gfx", 0 )
ROM_LOAD64_WORD( "shadfgtr.u55", 0x000000, 0x80000, CRC(e807631d) SHA1(9027ff7dc60b808434dac292c08f0630d3d52186) )
ROM_LOAD64_WORD( "shadfgtr.u57", 0x000002, 0x80000, CRC(60d701d7) SHA1(936473b5e3b2e9e9e3b50cf977fc5a670a097850) )
ROM_LOAD64_WORD( "shadfgtr.u54", 0x000004, 0x80000, CRC(c45d68d6) SHA1(a133e4f13d3af18bccf0d060a659d64ac699b159) )
ROM_LOAD64_WORD( "shadfgtr.u56", 0x000006, 0x80000, CRC(fb76db5a) SHA1(fa546f465df113c13037abed1162bfa6f9b1dc9b) )
ROM_REGION( 0x200, "plds", 0 )
ROM_LOAD( "shadfgtr.u51", 0x000, 0x1f1, CRC(bab58337) SHA1(c4a79c8e53aeadb7f64d49d214b607b5b36f144e) )
/* The second upper-board PAL couldn't be read */
ROM_END
/* YEAR NAME PARENT MACHINE INPUT INIT MONITOR COMPANY FULLNAME FLAGS */
GAME( 1993, vcombat, 0, vcombat, vcombat, vcombat, ROT0, "VR8 Inc.", "Virtual Combat", GAME_NOT_WORKING | GAME_NO_SOUND )
GAME( 1989, shadfgtr, 0, vcombat, vcombat, 0, ROT0, "Sega?", "Shadow Fighters", GAME_NOT_WORKING | GAME_NO_SOUND )
/* YEAR NAME PARENT MACHINE INPUT INIT MONITOR COMPANY FULLNAME FLAGS */
GAME( 1993, vcombat, 0, vcombat, vcombat, vcombat, ORIENTATION_FLIP_X, "VR8 Inc.", "Virtual Combat", GAME_NOT_WORKING | GAME_NO_SOUND )
GAME( 1989, shadfgtr, 0, shadfgtr, shadfgtr, shadfgtr, ROT0, "DUTECH Inc.", "Shadow Fighters", GAME_NOT_WORKING | GAME_NO_SOUND )

View File

@ -8433,7 +8433,7 @@ Other Sun games
DRIVER( blazlaz ) /* (c) 1989 Hudson Soft */
DRIVER( paranoia ) /* (c) 1990 Naxat Soft */
DRIVER( vcombat ) /* (c) 1993 VR8 Inc. */
DRIVER( shadfgtr ) /* (c) 1989 Sega? */
DRIVER( shadfgtr ) /* (c) 1989 DUTECH Inc. */
DRIVER( blackt96 ) /* (c) 1996 D.G.R.M. of Korea */
DRIVER( magictg ) /* (c) 199? Acclaim */
DRIVER( magictga ) /* (c) 199? Acclaim */