summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/53c810.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/machine/53c810.c')
-rw-r--r--src/emu/machine/53c810.c896
1 files changed, 896 insertions, 0 deletions
diff --git a/src/emu/machine/53c810.c b/src/emu/machine/53c810.c
new file mode 100644
index 00000000000..ec8b30fe50e
--- /dev/null
+++ b/src/emu/machine/53c810.c
@@ -0,0 +1,896 @@
+/* LSI Logic LSI53C810A PCI to SCSI I/O Processor */
+
+#include "driver.h"
+#include "53c810.h"
+
+#define DMA_MAX_ICOUNT 512 /* Maximum number of DMA Scripts opcodes to run */
+#define DASM_OPCODES 0
+
+static SCSIInstance *devices[8]; /* SCSI IDs 0-7 */
+static struct LSI53C810interface *intf;
+static UINT8 last_id;
+
+static struct {
+ UINT8 scntl0;
+ UINT8 scntl1;
+ UINT8 scntl2;
+ UINT8 scntl3;
+ UINT8 scid;
+ UINT8 socl;
+ UINT8 istat;
+ UINT8 dstat;
+ UINT8 sstat0;
+ UINT8 sstat1;
+ UINT8 sstat2;
+ UINT8 dien;
+ UINT8 dcntl;
+ UINT8 dmode;
+ UINT32 temp;
+ UINT32 dsa;
+ UINT32 dsp;
+ UINT32 dsps;
+ UINT32 dcmd;
+ UINT8 sien0;
+ UINT8 sien1;
+ UINT8 stime0;
+ UINT8 respid;
+ UINT8 stest1;
+ UINT8 scratch_a[4];
+ UINT8 scratch_b[4];
+ int dma_icount;
+ int halted;
+ int carry;
+ UINT32 (* fetch)(UINT32 dsp);
+ void (* irq_callback)(void);
+ void (* dma_callback)(UINT32, UINT32, int, int);
+} lsi810;
+
+static void (* dma_opcode[256])(void);
+
+
+INLINE UINT32 FETCH(void)
+{
+ UINT32 r = intf->fetch(lsi810.dsp);
+ lsi810.dsp += 4;
+ return r;
+}
+
+#ifdef UNUSED_FUNCTION
+static UINT32 sign_extend24(UINT32 val)
+{
+ if (val & 0x00800000)
+ val |= 0xFF000000;
+ else
+ val &= ~0xFF000000;
+ return val;
+}
+#endif
+
+static void dmaop_invalid(void)
+{
+ fatalerror("LSI53C810: Invalid SCRIPTS DMA opcode %08X at %08X", lsi810.dcmd, lsi810.dsp);
+}
+
+static void dmaop_move_memory(void)
+{
+ UINT32 src = FETCH();
+ UINT32 dst = FETCH();
+ int count;
+
+ count = lsi810.dcmd & 0xffffff;
+ if(intf->dma_callback != NULL) {
+ intf->dma_callback(src, dst, count, 1);
+ }
+}
+
+static void dmaop_interrupt(void)
+{
+ if(lsi810.dcmd & 0x100000) {
+ fatalerror("LSI53C810: INTFLY opcode not implemented");
+ }
+ lsi810.dsps = FETCH();
+
+ lsi810.istat |= 0x1; /* DMA interrupt pending */
+ lsi810.dstat |= 0x4; /* SIR (SCRIPTS Interrupt Instruction Received) */
+
+ if(intf->irq_callback != NULL) {
+ intf->irq_callback();
+ }
+ lsi810.dma_icount = 0;
+ lsi810.halted = 1;
+}
+
+static void dmaop_block_move(void)
+{
+ UINT32 address;
+ UINT32 count;
+ INT32 dsps;
+
+ address = FETCH();
+ count = lsi810.dcmd & 0x00ffffff;
+
+ // normal indirect
+ if (lsi810.dcmd & 0x20000000)
+ address = intf->fetch(address);
+
+ // table indirect
+ if (lsi810.dcmd & 0x10000000)
+ {
+ dsps = (INT32)address&0xffffff;
+ // sign extend
+ if (dsps & 0x00800000)
+ {
+ dsps |= 0xff000000;
+ }
+ logerror("table offset: %x, DSA = %x\n", dsps, lsi810.dsa);
+ dsps += lsi810.dsa;
+
+ logerror("Loading from table at %x\n", dsps);
+ count = lsi810.fetch(dsps);
+ address = lsi810.fetch(dsps+4);
+ }
+
+ logerror("block move: address %x count %x phase %x\n", address, count, (lsi810.dcmd>>24)&7);
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ fatalerror("LSI53C810: dmaop_block_move not implemented in target mode");
+ }
+ else
+ {
+ /* initiator mode */
+ logerror("53c810: block_move not actually implemented\n");
+ }
+}
+
+static void dmaop_select(void)
+{
+ UINT32 operand;
+
+ operand = FETCH();
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ logerror("LSI53C810: reselect ID #%d\n", (lsi810.dcmd >> 16) & 0x07);
+ }
+ else
+ {
+ /* initiator mode */
+ logerror("53c810: SELECT: our ID %d, target ID %d\n", lsi810.scid&7, (lsi810.dcmd>>16)&7);
+
+ lsi810.sstat1 &= ~0x07; // clear current bus phase
+ if (lsi810.dcmd & 0x01000000) // select with ATN
+ {
+ mame_printf_debug("53c810: want select with ATN, setting message phase\n");
+ lsi810.sstat1 |= 0x7; // ATN means we want message in phase
+ }
+ }
+}
+
+static void dmaop_wait_disconnect(void)
+{
+ UINT32 operand;
+
+ operand = FETCH();
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ fatalerror("LSI53C810: dmaop_wait_disconnect not implemented in target mode");
+ }
+ else
+ {
+ /* initiator mode */
+ fatalerror("LSI53C810: dmaop_wait_disconnect not implemented");
+ }
+}
+
+static void dmaop_wait_reselect(void)
+{
+ UINT32 operand;
+
+ operand = FETCH();
+
+ if (lsi810.scntl0 & 0x01)
+ {
+ /* target mode */
+ fatalerror("LSI53C810: dmaop_wait_reselect not implemented in target mode");
+ }
+ else
+ {
+ /* initiator mode */
+ fatalerror("LSI53C810: dmaop_wait_reselect not implemented");
+ }
+}
+
+static void dmaop_set(void)
+{
+ UINT32 operand;
+
+ operand = FETCH();
+
+ /* initiator mode */
+ if (lsi810.dcmd & 0x8)
+ {
+ // set ATN in SOCL
+ lsi810.socl |= 0x08;
+ }
+ if (lsi810.dcmd & 0x40)
+ {
+ // set ACK in SOCL
+ lsi810.socl |= 0x40;
+ }
+ if (lsi810.dcmd & 0x200)
+ {
+ // set target mode
+ lsi810.scntl0 |= 0x01;
+ }
+ if (lsi810.dcmd & 0x400)
+ {
+ // set carry in ALU
+ lsi810.carry = 1;
+ }
+}
+
+static void dmaop_clear(void)
+{
+ UINT32 operand;
+
+ operand = FETCH();
+
+ /* initiator mode */
+ if (lsi810.dcmd & 0x8)
+ {
+ // clear ATN in SOCL
+ lsi810.socl &= ~0x08;
+ }
+ if (lsi810.dcmd & 0x40)
+ {
+ // clear ACK in SOCL
+ lsi810.socl &= ~0x40;
+ }
+ if (lsi810.dcmd & 0x200)
+ {
+ // clear target mode
+ lsi810.scntl0 &= ~0x01;
+ }
+ if (lsi810.dcmd & 0x400)
+ {
+ // clear carry in ALU
+ lsi810.carry = 0;
+ }
+}
+
+static void dmaop_move_from_sfbr(void)
+{
+ fatalerror("LSI53C810: dmaop_move_from_sfbr not implemented in target mode");
+}
+
+static void dmaop_move_to_sfbr(void)
+{
+ fatalerror("LSI53C810: dmaop_move_to_sfbr not implemented");
+}
+
+static void dmaop_read_modify_write(void)
+{
+ fatalerror("LSI53C810: dmaop_read_modify_write not implemented");
+}
+
+static int scripts_compute_branch(void)
+{
+ int dtest, ptest, wanted, passed;
+
+// |jump if true
+// 878b0000 ||compare data
+// 1000 0111 1000 1011 0000 0000 0000 0000
+// | |rel ||wait valid phase
+// | |compare phase
+// |desired phase: message in
+
+ if (lsi810.dcmd & 0x00200000)
+ {
+ fatalerror("LSI53C810: jump with carry test not implemented");
+ }
+
+ if (lsi810.dcmd & 0x00100000)
+ {
+ fatalerror("LSI53C810: jump with interrupt on the fly not implemented");
+ }
+
+ // set desired result to take jump
+ wanted = (lsi810.dcmd & 0x00080000) ? 1 : 0;
+ // default to passing the tests in case they're disabled
+ dtest = ptest = wanted;
+
+ // phase test?
+ if (lsi810.dcmd & 0x00020000)
+ {
+ logerror("53c810: phase test. current: %x. target: %x\n", lsi810.sstat1 & 7, (lsi810.dcmd>>24)&7);
+
+ // do the phases match?
+ if (((lsi810.dcmd>>24)&7) == (lsi810.sstat1 & 7))
+ {
+ ptest = 1;
+ }
+ else
+ {
+ ptest = 0;
+ }
+ }
+
+ // data test?
+ if (lsi810.dcmd & 0x00040000)
+ {
+ logerror("53c810: data test. target: %x [not yet implemented]\n", lsi810.dcmd&0xff);
+}
+
+ // if all conditions go, take the jump
+ passed = 0;
+ if ((ptest == dtest) && (dtest == wanted))
+ {
+ passed = 1;
+ }
+
+ logerror("53c810: phase test %d data test %d wanted %d => pass %d\n", ptest, dtest, wanted, passed);
+
+ return passed;
+}
+
+static UINT32 scripts_get_jump_dest(void)
+{
+ INT32 dsps;
+ UINT32 dest;
+
+ dsps = FETCH();
+
+ /* relative or absolute addressing? */
+ if (lsi810.dcmd & 0x00800000)
+ {
+ // sign-extend the 24-bit value
+ if (dsps & 0x00800000)
+ {
+ dsps |= 0xff000000;
+ }
+
+ logerror("dsps = %x, dsp = %x\n", dsps, lsi810.dsp);
+ dsps += lsi810.dsp;
+}
+
+ dest = (UINT32)dsps;
+
+ logerror("cur DSP %x, dest %x\n", lsi810.dsp, dest);
+
+ return dest;
+}
+
+static void dmaop_jump(void)
+{
+ if (scripts_compute_branch())
+{
+ lsi810.dsp = scripts_get_jump_dest();
+ }
+ else
+ {
+ FETCH(); // skip operand to continue on
+ }
+}
+
+static void dmaop_call(void)
+{
+ if (scripts_compute_branch())
+ {
+ // save return address
+ lsi810.temp = lsi810.dsp;
+
+ // and go
+ lsi810.dsp = scripts_get_jump_dest();
+ }
+ else
+ {
+ FETCH(); // skip operand to continue on
+ }
+}
+
+static void dmaop_return(void)
+{
+ // is this correct? return only happens if the condition is true?
+ if (scripts_compute_branch())
+ {
+ // restore return address
+ lsi810.dsp = lsi810.temp;
+ }
+ else
+ {
+ FETCH(); // skip operand to continue on
+ }
+}
+
+static void dmaop_store(void)
+{
+ fatalerror("LSI53C810: dmaop_store not implemented");
+}
+
+static void dmaop_load(void)
+{
+ fatalerror("LSI53C810: dmaop_load not implemented");
+}
+
+
+
+static void dma_exec(void)
+{
+ lsi810.dma_icount = DMA_MAX_ICOUNT;
+
+ while(lsi810.dma_icount > 0)
+ {
+ int op;
+
+ if (DASM_OPCODES)
+ {
+ char buf[256];
+ lsi53c810_dasm(buf, lsi810.dsp);
+ logerror("0x%08X: %s\n", lsi810.dsp, buf);
+ }
+
+ lsi810.dcmd = FETCH();
+
+ op = (lsi810.dcmd >> 24) & 0xff;
+ dma_opcode[op]();
+
+ lsi810.dma_icount--;
+ }
+}
+
+UINT8 lsi53c810_reg_r(int reg)
+{
+ logerror("53c810: read reg %d:0x%x (PC=%x)\n", reg, reg, activecpu_get_pc());
+ switch(reg)
+ {
+ case 0x00: /* SCNTL0 */
+ return lsi810.scntl0;
+ case 0x01: /* SCNTL1 */
+ return lsi810.scntl1;
+ case 0x02: /* SCNTL2 */
+ return lsi810.scntl2;
+ case 0x03: /* SCNTL3 */
+ return lsi810.scntl3;
+ case 0x04: /* SCID */
+ return lsi810.scid;
+ case 0x09: /* SOCL */
+ return lsi810.socl;
+ case 0x0c: /* DSTAT */
+ return lsi810.dstat;
+ case 0x0d: /* SSTAT0 */
+ return lsi810.sstat0;
+ case 0x0e: /* SSTAT1 */
+ return lsi810.sstat1;
+ case 0x0f: /* SSTAT2 */
+ return lsi810.sstat2;
+ case 0x10: /* DSA [7-0] */
+ return lsi810.dsa & 0xff;
+ case 0x11: /* DSA [15-8] */
+ return (lsi810.dsa >> 8) & 0xff;
+ case 0x12: /* DSA [23-16] */
+ return (lsi810.dsa >> 16) & 0xff;
+ case 0x13: /* DSA [31-24] */
+ return (lsi810.dsa >> 24) & 0xff;
+ case 0x14: /* ISTAT */
+ return lsi810.istat;
+ case 0x2c: /* DSP [7-0] */
+ return lsi810.dsp & 0xff;
+ case 0x2d: /* DSP [15-8] */
+ return (lsi810.dsp >> 8) & 0xff;
+ case 0x2e: /* DSP [23-16] */
+ return (lsi810.dsp >> 16) & 0xff;
+ case 0x2f: /* DSP [31-24] */
+ return (lsi810.dsp >> 24) & 0xff;
+ case 0x34: /* SCRATCH A */
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ return lsi810.scratch_a[reg % 4];
+ case 0x39: /* DIEN */
+ return lsi810.dien;
+ case 0x3b: /* DCNTL */
+ return lsi810.dcntl;
+ case 0x40: /* SIEN0 */
+ return lsi810.sien0;
+ case 0x41: /* SIEN1 */
+ return lsi810.sien1;
+ case 0x48: /* STIME0 */
+ return lsi810.stime0;
+ case 0x4a: /* RESPID */
+ return lsi810.respid;
+ case 0x4d: /* STEST1 */
+ return lsi810.stest1;
+ case 0x5c: /* SCRATCH B */
+ case 0x5d:
+ case 0x5e:
+ case 0x5f:
+ return lsi810.scratch_b[reg % 4];
+
+ default:
+ fatalerror("LSI53C810: reg_r: Unknown reg %02X", reg);
+ }
+
+ return 0;
+}
+
+void lsi53c810_reg_w(int reg, UINT8 value)
+{
+ logerror("53c810: %02x to reg %d:0x%x (PC=%x)\n", value, reg, reg, activecpu_get_pc());
+ switch(reg)
+ {
+ case 0x00: /* SCNTL0 */
+ lsi810.scntl0 = value;
+ break;
+ case 0x01: /* SCNTL1 */
+ lsi810.scntl1 = value;
+ break;
+ case 0x02: /* SCNTL2 */
+ lsi810.scntl2 = value;
+ break;
+ case 0x03: /* SCNTL3 */
+ lsi810.scntl3 = value;
+ break;
+ case 0x04: /* SCID */
+ lsi810.scid = value;
+ break;
+ case 0x09: /* SOCL */
+ lsi810.socl = value;
+ break;
+ case 0x0d: /* SSTAT0 */
+ lsi810.sstat0 = value;
+ break;
+ case 0x0e: /* SSTAT1 */
+ lsi810.sstat1 = value;
+ break;
+ case 0x0f: /* SSTAT2 */
+ lsi810.sstat2 = value;
+ break;
+ case 0x10: /* DSA [7-0] */
+ lsi810.dsa &= 0xffffff00;
+ lsi810.dsa |= value;
+ break;
+ case 0x11: /* DSA [15-8] */
+ lsi810.dsa &= 0xffff00ff;
+ lsi810.dsa |= value << 8;
+ break;
+ case 0x12: /* DSA [23-16] */
+ lsi810.dsa &= 0xff00ffff;
+ lsi810.dsa |= value << 16;
+ break;
+ case 0x13: /* DSA [31-24] */
+ lsi810.dsa &= 0x00ffffff;
+ lsi810.dsa |= value << 24;
+ break;
+ case 0x14: /* ISTAT */
+ lsi810.istat = value;
+ break;
+ case 0x2c: /* DSP [7-0] */
+ lsi810.dsp &= 0xffffff00;
+ lsi810.dsp |= value;
+ break;
+ case 0x2d: /* DSP [15-8] */
+ lsi810.dsp &= 0xffff00ff;
+ lsi810.dsp |= value << 8;
+ break;
+ case 0x2e: /* DSP [23-16] */
+ lsi810.dsp &= 0xff00ffff;
+ lsi810.dsp |= value << 16;
+ break;
+ case 0x2f: /* DSP [31-24] */
+ lsi810.dsp &= 0x00ffffff;
+ lsi810.dsp |= value << 24;
+ lsi810.halted = 0;
+ if((lsi810.dmode & 0x1) == 0 && !lsi810.halted) {
+ dma_exec();
+ }
+ break;
+ case 0x34: /* SCRATCH A */
+ case 0x35:
+ case 0x36:
+ case 0x37:
+ lsi810.scratch_a[reg % 4] = value;
+ break;
+ case 0x38: /* DMODE */
+ lsi810.dmode = value;
+ break;
+ case 0x39: /* DIEN */
+ lsi810.dien = value;
+ break;
+ case 0x3b: /* DCNTL */
+ lsi810.dcntl = value;
+
+ if(lsi810.dcntl & 0x14 && !lsi810.halted) /* single-step & start DMA */
+ {
+ int op;
+ lsi810.dcmd = FETCH();
+ op = (lsi810.dcmd >> 24) & 0xff;
+ dma_opcode[op]();
+
+ lsi810.istat |= 0x3; /* DMA interrupt pending */
+ lsi810.dstat |= 0x8; /* SSI (Single Step Interrupt) */
+ if(intf->irq_callback != NULL) {
+ intf->irq_callback();
+ }
+ }
+ else if(lsi810.dcntl & 0x04 && !lsi810.halted) /* manual start DMA */
+ {
+ dma_exec();
+ }
+ break;
+ case 0x40: /* SIEN0 */
+ lsi810.sien0 = value;
+ break;
+ case 0x41: /* SIEN1 */
+ lsi810.sien1 = value;
+ break;
+ case 0x48: /* STIME0 */
+ lsi810.stime0 = value;
+ break;
+ case 0x4a: /* RESPID */
+ lsi810.respid = value;
+ break;
+ case 0x4d: /* STEST1 */
+ lsi810.stest1 = value;
+ break;
+ case 0x5c: /* SCRATCH B */
+ case 0x5d:
+ case 0x5e:
+ case 0x5f:
+ lsi810.scratch_b[reg % 4] = value;
+ break;
+
+ default:
+ fatalerror("LSI53C810: reg_w: Unknown reg %02X, %02X", reg, value);
+ }
+}
+
+static void add_opcode(UINT8 op, UINT8 mask, void (* handler)(void))
+{
+ int i;
+ for(i=0; i < 256; i++) {
+ if((i & mask) == op) {
+ dma_opcode[i] = handler;
+ }
+ }
+}
+
+extern void lsi53c810_init(struct LSI53C810interface *interface)
+{
+ int i;
+
+ // save interface pointer for later
+ intf = interface;
+
+ memset(&lsi810, 0, sizeof(lsi810));
+ for(i = 0; i < 256; i++)
+ {
+ dma_opcode[i] = dmaop_invalid;
+ }
+
+ add_opcode(0x00, 0xc0, dmaop_block_move);
+ add_opcode(0x40, 0xf8, dmaop_select);
+ add_opcode(0x48, 0xf8, dmaop_wait_disconnect);
+ add_opcode(0x50, 0xf8, dmaop_wait_reselect);
+ add_opcode(0x58, 0xf8, dmaop_set);
+ add_opcode(0x60, 0xf8, dmaop_clear);
+ add_opcode(0x68, 0xf8, dmaop_move_from_sfbr);
+ add_opcode(0x70, 0xf8, dmaop_move_to_sfbr);
+ add_opcode(0x78, 0xf8, dmaop_read_modify_write);
+ add_opcode(0x80, 0xf8, dmaop_jump);
+ add_opcode(0x88, 0xf8, dmaop_call);
+ add_opcode(0x90, 0xf8, dmaop_return);
+ add_opcode(0x98, 0xf8, dmaop_interrupt);
+ add_opcode(0xc0, 0xfe, dmaop_move_memory);
+ add_opcode(0xe0, 0xed, dmaop_store);
+ add_opcode(0xe1, 0xed, dmaop_load);
+
+ memset(devices, 0, sizeof(devices));
+
+ // try to open the devices
+ for (i = 0; i < interface->scsidevs->devs_present; i++)
+ {
+ SCSIAllocInstance( interface->scsidevs->devices[i].scsiClass, &devices[interface->scsidevs->devices[i].scsiID], interface->scsidevs->devices[i].diskID );
+ }
+}
+
+void lsi53c810_read_data(int bytes, UINT8 *pData)
+{
+ if (devices[last_id])
+ {
+ SCSIReadData( devices[last_id], pData, bytes);
+ }
+ else
+ {
+ logerror("lsi53c810: read unknown device SCSI ID %d\n", last_id);
+ }
+}
+
+void lsi53c810_write_data(int bytes, UINT8 *pData)
+{
+ if (devices[last_id])
+ {
+ SCSIWriteData( devices[last_id], pData, bytes );
+ }
+ else
+ {
+ logerror("lsi53c810: write to unknown device SCSI ID %d\n", last_id);
+ }
+}
+
+void *lsi53c810_get_device(int id)
+{
+ void *ret;
+
+ if (devices[id])
+ {
+ logerror("lsi53c810: fetching dev pointer for SCSI ID %d\n", id);
+ SCSIGetDevice( devices[id], &ret );
+
+ return ret;
+ }
+
+ return NULL;
+}
+
+/*************************************
+ *
+ * Disassembler
+ *
+ *************************************/
+
+static UINT32 lsi53c810_dasm_fetch(UINT32 pc)
+{
+ return intf->fetch(pc);
+}
+
+unsigned lsi53c810_dasm(char *buf, UINT32 pc)
+{
+ unsigned result = 0;
+ const char *op_mnemonic = NULL;
+ UINT32 op = lsi53c810_dasm_fetch(pc);
+ UINT32 dest;
+ int i;
+
+ static const char *phases[] =
+ {
+ "DATA_OUT", "DATA_IN", "CMD", "STATUS",
+ "RESERVED_OUT??", "RESERVED_IN??", "MSG_OUT", "MSG_IN"
+ };
+
+ if ((op & 0xF8000000) == 0x40000000)
+ {
+ /* SELECT */
+ dest = lsi53c810_dasm_fetch(pc + 4);
+
+ buf += sprintf(buf, "SELECT%s %d, 0x%08X",
+ (op & 0x01000000) ? " ATN" : "",
+ (op >> 16) & 0x07,
+ dest);
+
+ result = 8;
+ }
+ else if (((op & 0xF8000000) == 0x58000000)
+ | ((op & 0xF8000000) == 0x60000000))
+ {
+ static struct
+ {
+ UINT32 flag;
+ const char *text;
+ } flags[] =
+ {
+ { 0x00000008, "ATN" },
+ { 0x00000040, "ACK" },
+ { 0x00000200, "TARGET" },
+ { 0x00000400, "CARRY" }
+ };
+ int need_cojunction = FALSE;
+
+ /* SET/CLEAR */
+ switch(op & 0xF8000000)
+ {
+ case 0x58000000: op_mnemonic = "SET"; break;
+ case 0x60000000: op_mnemonic = "CLEAR"; break;
+ }
+
+ buf += sprintf(buf, "%s ", op_mnemonic);
+ need_cojunction = FALSE;
+
+ for (i = 0; i < sizeof(flags) / sizeof(flags[0]); i++)
+ {
+ if (op & flags[i].flag)
+ {
+ if (need_cojunction)
+ buf += sprintf(buf, " AND ");
+ else
+ need_cojunction = TRUE;
+ buf += sprintf(buf, "%s", flags[i].text);
+ }
+ }
+ }
+ else if (((op & 0xF8000000) == 0x80000000)
+ | ((op & 0xF8000000) == 0x88000000)
+ | ((op & 0xF8000000) == 0x98000000))
+ {
+ /* JUMP/CALL/INT */
+ switch(op & 0xF8000000)
+ {
+ case 0x80000000: op_mnemonic = "JUMP"; break;
+ case 0x88000000: op_mnemonic = "CALL"; break;
+ case 0x98000000: op_mnemonic = "INT"; break;
+ }
+
+ dest = lsi53c810_dasm_fetch(pc + 4);
+
+ if (op & 0x00800000)
+ {
+ /* relative */
+ if (dest & 0x00800000)
+ dest |= 0xFF000000;
+ else
+ dest &= 0x00FFFFFF;
+ dest = (pc + 8) + dest;
+ buf += sprintf(buf, "%s REL(0x%08X)", op_mnemonic, dest);
+ }
+ else
+ {
+ /* absolute */
+ buf += sprintf(buf, "%s 0x%08X", op_mnemonic, dest);
+ }
+
+ switch(op & 0x000B0000)
+ {
+ case 0x00000000:
+ buf += sprintf(buf, ", NOT??");
+ break;
+
+ case 0x00080000:
+ break;
+
+ case 0x00020000:
+ case 0x00030000:
+ case 0x000A0000:
+ case 0x000B0000:
+ buf += sprintf(buf, ", %s%s %s",
+ (op & 0x00010000) ? "WHEN" : "IF",
+ (op & 0x00080000) ? "" : " NOT",
+ phases[(op >> 24) & 0x07]);
+ break;
+
+ default:
+ fatalerror("unknown op 0x%08X", op);
+ break;
+ }
+ result = 8;
+ }
+ else if ((op & 0xE0000000) == 0x00000000)
+ {
+ /* MOVE FROM */
+ dest = lsi53c810_dasm_fetch(pc + 4);
+
+ buf += sprintf(buf, "MOVE FROM 0x%08X, WHEN %s",
+ dest, phases[(op >> 24) & 0x07]);
+
+ result = 8;
+ }
+ else if ((op & 0xE0000000) == 0x20000000)
+ {
+ /* MOVE PTR */
+ dest = lsi53c810_dasm_fetch(pc + 4);
+
+ buf += sprintf(buf, "MOVE 0x%08X, PTR 0x%08X, WHEN %s",
+ (op & 0x00FFFFFF), dest, phases[(op >> 24) & 0x07]);
+
+ result = 8;
+ }
+ else
+ {
+ fatalerror("unknown op 0x%08X", op);
+ }
+ return result;
+}
+