summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/uml.c
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
commitf88cefad27a1737c76e09d99c9fb43e173506081 (patch)
tree2d8167d03579c46e226471747eb4407bd00ed6fa /src/emu/cpu/uml.c
parente92ac9e0fa8e99869894bea00589bbb526be30aa (diff)
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/emu/cpu/uml.c')
-rw-r--r--src/emu/cpu/uml.c1029
1 files changed, 0 insertions, 1029 deletions
diff --git a/src/emu/cpu/uml.c b/src/emu/cpu/uml.c
deleted file mode 100644
index f7b0584431f..00000000000
--- a/src/emu/cpu/uml.c
+++ /dev/null
@@ -1,1029 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-/***************************************************************************
-
- uml.c
-
- Universal machine language definitions and classes.
-
-****************************************************************************
-
- Future improvements/changes:
-
- * UML optimizer:
- - constant folding
-
- * Write a back-end validator:
- - checks all combinations of memory/register/immediate on all params
- - checks behavior of all opcodes
-
- * Extend registers to 16? Depends on if PPC can use them
-
- * Support for FPU exceptions
-
- * New instructions?
- - FCOPYI, ICOPYF
- copy raw between float and integer registers
-
- - VALID opcode_desc,handle,param
- checksum/compare code referenced by opcode_desc; if not
- matching, generate exception with handle,param
-
- - RECALL handle
- change code at caller to call handle in the future
-
-***************************************************************************/
-
-#include "emu.h"
-#include "drcuml.h"
-#include "drcumlsh.h"
-
-using namespace uml;
-
-
-
-//**************************************************************************
-// DEBUGGING
-//**************************************************************************
-
-#define VALIDATE_BACKEND (0)
-#define LOG_SIMPLIFICATIONS (0)
-
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-// opcode validation condition/flag valid bitmasks
-#define OPFLAGS_NONE 0x00
-#define OPFLAGS_C FLAG_C
-#define OPFLAGS_SZ (FLAG_S | FLAG_Z)
-#define OPFLAGS_SZC (FLAG_S | FLAG_Z | FLAG_C)
-#define OPFLAGS_SZV (FLAG_S | FLAG_Z | FLAG_V)
-#define OPFLAGS_SZVC (FLAG_S | FLAG_Z | FLAG_V | FLAG_C)
-#define OPFLAGS_UZC (FLAG_U | FLAG_Z | FLAG_C)
-#define OPFLAGS_ALL 0x1f
-#define OPFLAGS_P1 0x81
-#define OPFLAGS_P2 0x82
-#define OPFLAGS_P3 0x83
-#define OPFLAGS_P4 0x84
-
-// parameter input/output states
-#define PIO_IN 0x01
-#define PIO_OUT 0x02
-#define PIO_INOUT (PIO_IN | PIO_OUT)
-
-// parameter sizes
-#define PSIZE_4 SIZE_DWORD
-#define PSIZE_8 SIZE_QWORD
-#define PSIZE_OP 0x80
-#define PSIZE_P1 0x81
-#define PSIZE_P2 0x82
-#define PSIZE_P3 0x83
-#define PSIZE_P4 0x84
-
-// basic parameter types
-#define PTYPES_NONE 0
-#define PTYPES_IMM (1 << parameter::PTYPE_IMMEDIATE)
-#define PTYPES_IREG (1 << parameter::PTYPE_INT_REGISTER)
-#define PTYPES_FREG (1 << parameter::PTYPE_FLOAT_REGISTER)
-#define PTYPES_VREG (1 << parameter::PTYPE_VECTOR_REGISTER)
-#define PTYPES_MVAR (1 << parameter::PTYPE_MAPVAR)
-#define PTYPES_MEM (1 << parameter::PTYPE_MEMORY)
-#define PTYPES_SIZE (1 << parameter::PTYPE_SIZE)
-#define PTYPES_SCSIZE (1 << parameter::PTYPE_SIZE_SCALE)
-#define PTYPES_SPSIZE (1 << parameter::PTYPE_SIZE_SPACE)
-#define PTYPES_HANDLE (1 << parameter::PTYPE_CODE_HANDLE)
-#define PTYPES_LABEL (1 << parameter::PTYPE_CODE_LABEL)
-#define PTYPES_CFUNC (1 << parameter::PTYPE_C_FUNCTION)
-#define PTYPES_ROUND (1 << parameter::PTYPE_ROUNDING)
-#define PTYPES_STR (1 << parameter::PTYPE_STRING)
-
-// special parameter types
-#define PTYPES_PTR (PTYPES_MEM | 0x1000)
-#define PTYPES_STATE (PTYPES_MEM | 0x2000)
-
-// combinations of types
-#define PTYPES_IRM (PTYPES_IREG | PTYPES_MEM)
-#define PTYPES_FRM (PTYPES_FREG | PTYPES_MEM)
-#define PTYPES_IMV (PTYPES_IMM | PTYPES_MVAR)
-#define PTYPES_IANY (PTYPES_IRM | PTYPES_IMV)
-#define PTYPES_FANY (PTYPES_FRM)
-
-
-
-//**************************************************************************
-// TABLES
-//**************************************************************************
-
-// macro to simplify the table
-#define PINFO(inout, size, types) { PIO_##inout, PSIZE_##size, PTYPES_##types }
-#define OPINFO0(op,str,sizes,cond,iflag,oflag,mflag) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { { 0 } } },
-#define OPINFO1(op,str,sizes,cond,iflag,oflag,mflag,p0) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0 } },
-#define OPINFO2(op,str,sizes,cond,iflag,oflag,mflag,p0,p1) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0, p1 } },
-#define OPINFO3(op,str,sizes,cond,iflag,oflag,mflag,p0,p1,p2) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0, p1, p2 } },
-#define OPINFO4(op,str,sizes,cond,iflag,oflag,mflag,p0,p1,p2,p3) { OP_##op, str, sizes, cond, OPFLAGS_##iflag, OPFLAGS_##oflag, OPFLAGS_##mflag, { p0, p1, p2, p3 } },
-
-// opcode validation table
-const opcode_info instruction::s_opcode_info_table[OP_MAX] =
-{
- OPINFO0(INVALID, "invalid", 4, false, NONE, NONE, NONE)
-
- // Compile-time opcodes
- OPINFO1(HANDLE, "handle", 4, false, NONE, NONE, NONE, PINFO(IN, OP, HANDLE))
- OPINFO2(HASH, "hash", 4, false, NONE, NONE, NONE, PINFO(IN, OP, IMV), PINFO(IN, OP, IMV))
- OPINFO1(LABEL, "label", 4, false, NONE, NONE, NONE, PINFO(IN, OP, LABEL))
- OPINFO1(COMMENT, "comment", 4, false, NONE, NONE, NONE, PINFO(IN, OP, STR))
- OPINFO2(MAPVAR, "mapvar", 4, false, NONE, NONE, NONE, PINFO(OUT, OP, MVAR), PINFO(IN, OP, IMV))
-
- // Control Flow Operations
- OPINFO0(NOP, "nop", 4, false, NONE, NONE, NONE)
- OPINFO1(DEBUG, "debug", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY))
- OPINFO1(EXIT, "exit", 4, true, NONE, NONE, ALL, PINFO(IN, OP, IANY))
- OPINFO3(HASHJMP, "hashjmp", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, HANDLE))
- OPINFO1(JMP, "jmp", 4, true, NONE, NONE, NONE, PINFO(IN, OP, LABEL))
- OPINFO2(EXH, "exh", 4, true, NONE, NONE, ALL, PINFO(IN, OP, HANDLE), PINFO(IN, OP, IANY))
- OPINFO1(CALLH, "callh", 4, true, NONE, NONE, ALL, PINFO(IN, OP, HANDLE))
- OPINFO0(RET, "ret", 4, true, NONE, NONE, ALL)
- OPINFO2(CALLC, "callc", 4, true, NONE, NONE, ALL, PINFO(IN, OP, CFUNC), PINFO(IN, OP, PTR))
- OPINFO2(RECOVER, "recover", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, MVAR))
-
- // Internal Register Operations
- OPINFO1(SETFMOD, "setfmod", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY))
- OPINFO1(GETFMOD, "getfmod", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM))
- OPINFO1(GETEXP, "getexp", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM))
- OPINFO2(GETFLGS, "getflgs", 4, false, P2, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IMV))
- OPINFO1(SAVE, "save", 4, false, ALL, NONE, ALL, PINFO(OUT, OP, STATE))
- OPINFO1(RESTORE, "restore", 4, false, NONE, ALL, ALL, PINFO(IN, OP, STATE))
-
- // Integer Operations
- OPINFO4(LOAD, "!load", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, SCSIZE))
- OPINFO4(LOADS, "!loads", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, SCSIZE))
- OPINFO4(STORE, "!store", 4|8, false, NONE, NONE, ALL, PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SCSIZE))
- OPINFO3(READ, "!read", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, 4, IANY), PINFO(IN, OP, SPSIZE))
- OPINFO4(READM, "!readm", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SPSIZE))
- OPINFO3(WRITE, "!write", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SPSIZE))
- OPINFO4(WRITEM, "!writem", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SPSIZE))
- OPINFO2(CARRY, "!carry", 4|8, false, NONE, C, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO1(SET, "!set", 4|8, true, NONE, NONE, ALL, PINFO(OUT, OP, IRM))
- OPINFO2(MOV, "!mov", 4|8, true, NONE, NONE, NONE, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
- OPINFO3(SEXT, "!sext", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, P3, IANY), PINFO(IN, OP, SIZE))
- OPINFO4(ROLAND, "!roland", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO4(ROLINS, "!rolins", 4|8, false, NONE, SZ, ALL, PINFO(INOUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(ADD, "!add", 4|8, false, NONE, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(ADDC, "!addc", 4|8, false, C, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(SUB, "!sub", 4|8, false, NONE, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(SUBB, "!subb", 4|8, false, C, SZVC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO2(CMP, "!cmp", 4|8, false, NONE, SZVC, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO4(MULU, "!mulu", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO4(MULS, "!muls", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO4(DIVU, "!divu", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO4(DIVS, "!divs", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(AND, "!and", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO2(TEST, "!test", 4|8, false, NONE, SZ, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(OR, "!or", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(XOR, "!xor", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO2(LZCNT, "!lzcnt", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
- OPINFO2(BSWAP, "!bswap", 4|8, false, NONE, SZ, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY))
- OPINFO3(SHL, "!shl", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(SHR, "!shr", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(SAR, "!sar", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(ROL, "!rol", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(ROLC, "!rolc", 4|8, false, C, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(ROR, "!ror", 4|8, false, NONE, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
- OPINFO3(RORC, "!rorc", 4|8, false, C, SZC, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY))
-
- // Floating Point Operations
- OPINFO3(FLOAD, "f#load", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, PTR), PINFO(IN, 4, IANY))
- OPINFO3(FSTORE, "f#store", 4|8, false, NONE, NONE, ALL, PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, FRM))
- OPINFO3(FREAD, "f#read", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, 4, IANY), PINFO(IN, OP, SPSIZE))
- OPINFO3(FWRITE, "f#write", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, FANY), PINFO(IN, OP, SPSIZE))
- OPINFO2(FMOV, "f#mov", 4|8, true, NONE, NONE, NONE, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
- OPINFO4(FTOINT, "f#toint", 4|8, false, NONE, NONE, ALL, PINFO(OUT, P3, IRM), PINFO(IN, OP, FANY), PINFO(IN, OP, SIZE), PINFO(IN, OP, ROUND))
- OPINFO3(FFRINT, "f#frint", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, IANY), PINFO(IN, OP, SIZE))
- OPINFO3(FFRFLT, "f#frflt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, FANY), PINFO(IN, OP, SIZE))
- OPINFO2(FRNDS, "f#rnds", 8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, FANY))
- OPINFO3(FADD, "f#add", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
- OPINFO3(FSUB, "f#sub", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
- OPINFO2(FCMP, "f#cmp", 4|8, false, NONE, UZC, ALL, PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
- OPINFO3(FMUL, "f#mul", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
- OPINFO3(FDIV, "f#div", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY), PINFO(IN, OP, FANY))
- OPINFO2(FNEG, "f#neg", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
- OPINFO2(FABS, "f#abs", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
- OPINFO2(FSQRT, "f#sqrt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
- OPINFO2(FRECIP, "f#recip", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
- OPINFO2(FRSQRT, "f#rsqrt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, FANY))
-};
-
-
-
-//**************************************************************************
-// INLINE FUNCTIONS
-//**************************************************************************
-
-//-------------------------------------------------
-// rol32 - perform a 32-bit left rotate
-//-------------------------------------------------
-
-inline UINT32 rol32(UINT32 source, UINT8 count)
-{
- count &= 31;
- return (source << count) | (source >> (32 - count));
-}
-
-
-//-------------------------------------------------
-// rol64 - perform a 64-bit left rotate
-//-------------------------------------------------
-
-inline UINT64 rol64(UINT64 source, UINT8 count)
-{
- count &= 63;
- return (source << count) | (source >> (64 - count));
-}
-
-
-
-//**************************************************************************
-// UML CODE HANDLE
-//**************************************************************************
-
-//-------------------------------------------------
-// code_handle - constructor
-//-------------------------------------------------
-
-uml::code_handle::code_handle(drcuml_state &drcuml, const char *name)
- : m_code(reinterpret_cast<drccodeptr *>(drcuml.cache().alloc_near(sizeof(drccodeptr)))),
- m_string(name),
- m_next(NULL),
- m_drcuml(drcuml)
-{
- if (m_code == NULL)
- throw std::bad_alloc();
- *m_code = NULL;
-}
-
-
-//-------------------------------------------------
-// set_codeptr - set a new code pointer
-//-------------------------------------------------
-
-void uml::code_handle::set_codeptr(drccodeptr code)
-{
- assert(*m_code == NULL);
- assert_in_cache(m_drcuml.cache(), code);
- *m_code = code;
-}
-
-
-
-//**************************************************************************
-// UML INSTRUCTION
-//**************************************************************************
-
-//-------------------------------------------------
-// instruction - constructor
-//-------------------------------------------------
-
-uml::instruction::instruction()
- : m_opcode(OP_INVALID),
- m_condition(COND_ALWAYS),
- m_flags(0),
- m_size(4),
- m_numparams(0)
-{
-}
-
-
-//-------------------------------------------------
-// configure - configure an opcode with no
-// parameters
-//-------------------------------------------------
-
-void uml::instruction::configure(opcode_t op, UINT8 size, condition_t condition)
-{
- // fill in the instruction
- m_opcode = (opcode_t)(UINT8)op;
- m_size = size;
- m_condition = condition;
- m_flags = 0;
- m_numparams = 0;
-
- // validate
- validate();
-}
-
-
-//-------------------------------------------------
-// configure - configure an opcode with 1
-// parameter
-//-------------------------------------------------
-
-void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, condition_t condition)
-{
- // fill in the instruction
- m_opcode = (opcode_t)(UINT8)op;
- m_size = size;
- m_condition = condition;
- m_flags = 0;
- m_numparams = 1;
- m_param[0] = p0;
-
- // validate
- validate();
-}
-
-
-//-------------------------------------------------
-// configure - configure an opcode with 2
-// parameters
-//-------------------------------------------------
-
-void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, parameter p1, condition_t condition)
-{
- // fill in the instruction
- m_opcode = (opcode_t)(UINT8)op;
- m_size = size;
- m_condition = condition;
- m_flags = 0;
- m_numparams = 2;
- m_param[0] = p0;
- m_param[1] = p1;
-
- // validate
- validate();
-}
-
-
-//-------------------------------------------------
-// configure - configure an opcode with 3
-// parameters
-//-------------------------------------------------
-
-void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, condition_t condition)
-{
- // fill in the instruction
- m_opcode = (opcode_t)(UINT8)op;
- m_size = size;
- m_condition = condition;
- m_flags = 0;
- m_numparams = 3;
- m_param[0] = p0;
- m_param[1] = p1;
- m_param[2] = p2;
-
- // validate
- validate();
-}
-
-
-//-------------------------------------------------
-// configure - configure an opcode with 4
-// parameters
-//-------------------------------------------------
-
-void uml::instruction::configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, parameter p3, condition_t condition)
-{
- // fill in the instruction
- m_opcode = (opcode_t)(UINT8)op;
- m_size = size;
- m_condition = condition;
- m_flags = 0;
- m_numparams = 4;
- m_param[0] = p0;
- m_param[1] = p1;
- m_param[2] = p2;
- m_param[3] = p3;
-
- // validate
- validate();
-}
-
-
-//-------------------------------------------------
-// simplify - simplify instructions that have
-// immediate values we can evaluate at compile
-// time
-//-------------------------------------------------
-
-void uml::instruction::simplify()
-{
- // can't simplify if flags are in play
- if (m_flags != 0)
- return;
-
- static const UINT64 instsizemask[] = { 0, 0, 0, 0, 0xffffffff, 0, 0, 0, U64(0xffffffffffffffff) };
- static const UINT64 paramsizemask[] = { 0xff, 0xffff, 0xffffffff, U64(0xffffffffffffffff) };
-
- // loop until we've simplified all we can
- opcode_t origop;
- do
- {
- // switch off the opcode
- origop = m_opcode;
- switch (m_opcode)
- {
- // READM: convert to READ if the mask is wide open
- case OP_READM:
- if (m_param[2].is_immediate_value(paramsizemask[m_param[3].size()]))
- {
- m_opcode = OP_READ;
- m_numparams = 2;
- m_param[2] = m_param[3];
- }
- break;
-
- // WRITEM: convert to WRITE if the mask is wide open
- case OP_WRITEM:
- if (m_param[2].is_immediate_value(paramsizemask[m_param[3].size()]))
- {
- m_opcode = OP_WRITE;
- m_numparams = 2;
- m_param[2] = m_param[3];
- }
- break;
-
- // SET: convert to MOV if constant condition
- case OP_SET:
- if (m_condition == COND_ALWAYS)
- convert_to_mov_immediate(1);
- break;
-
- // MOV: convert to NOP if move-to-self
- case OP_MOV:
- if (m_param[0] == m_param[1])
- nop();
- break;
-
- // SEXT: convert immediates to MOV
- case OP_SEXT:
- if (m_param[1].is_immediate())
- switch (m_param[2].size())
- {
- case SIZE_BYTE: convert_to_mov_immediate((INT8)m_param[1].immediate()); break;
- case SIZE_WORD: convert_to_mov_immediate((INT16)m_param[1].immediate()); break;
- case SIZE_DWORD: convert_to_mov_immediate((INT32)m_param[1].immediate()); break;
- case SIZE_QWORD: convert_to_mov_immediate((INT64)m_param[1].immediate()); break;
- case SIZE_DQWORD: fatalerror("Invalid SEXT target size\n");
- }
- break;
-
- // ROLAND: convert to MOV if all immediate, or to ROL or AND if one is not needed, or to SHL/SHR if the mask is right
- case OP_ROLAND:
- if (m_param[1].is_immediate() && m_param[2].is_immediate() && m_param[3].is_immediate())
- {
- assert(m_size == 4 || m_size == 8);
- if (m_size == 4)
- convert_to_mov_immediate(rol32(m_param[1].immediate(), m_param[2].immediate()) & m_param[3].immediate());
- else
- convert_to_mov_immediate(rol64(m_param[1].immediate(), m_param[2].immediate()) & m_param[3].immediate());
- }
- else if (m_param[2].is_immediate_value(0))
- {
- m_opcode = OP_AND;
- m_numparams = 3;
- m_param[2] = m_param[3];
- }
- else if (m_param[3].is_immediate_value(instsizemask[m_size]))
- {
- m_opcode = OP_ROL;
- m_numparams = 3;
- }
- else if (m_param[2].is_immediate() && m_param[3].is_immediate_value((U64(0xffffffffffffffff) << m_param[2].immediate()) & instsizemask[m_size]))
- {
- m_opcode = OP_SHL;
- m_numparams = 3;
- }
- else if (m_param[2].is_immediate() && m_param[3].is_immediate_value(instsizemask[m_size] >> (8 * m_size - m_param[2].immediate())))
- {
- m_opcode = OP_SHR;
- m_numparams = 3;
- m_param[2] = 8 * m_size - m_param[2].immediate();
- }
- break;
-
- // ROLINS: convert to ROLAND if the mask is full
- case OP_ROLINS:
- if (m_param[3].is_immediate_value(instsizemask[m_size]))
- m_opcode = OP_ROLAND;
- break;
-
- // ADD: convert to MOV if immediate, or if adding 0
- case OP_ADD:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- convert_to_mov_immediate(m_param[1].immediate() + m_param[2].immediate());
- else if (m_param[1].is_immediate_value(0))
- convert_to_mov_param(2);
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // SUB: convert to MOV if immediate, or if subtracting 0
- case OP_SUB:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- convert_to_mov_immediate(m_param[1].immediate() - m_param[2].immediate());
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // CMP: no-op if no flags needed, compare i0 to i0 if the parameters are equal
- case OP_CMP:
- if (m_flags == 0)
- nop();
- else if (m_param[0] == m_param[1])
- cmp(I0, I0);
- break;
-
- // MULU: convert simple form to MOV if immediate, or if multiplying by 0
- case OP_MULU:
- if (m_param[0] == m_param[1])
- {
- if (m_param[2].is_immediate_value(0) || m_param[3].is_immediate_value(0))
- convert_to_mov_immediate(0);
- else if (m_param[2].is_immediate() && m_param[3].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate((UINT32)((UINT32)m_param[1].immediate() * (UINT32)m_param[2].immediate()));
- else if (m_size == 8)
- convert_to_mov_immediate((UINT64)((UINT64)m_param[1].immediate() * (UINT64)m_param[2].immediate()));
- }
- }
- break;
-
- // MULS: convert simple form to MOV if immediate, or if multiplying by 0
- case OP_MULS:
- if (m_param[0] == m_param[1])
- {
- if (m_param[2].is_immediate_value(0) || m_param[3].is_immediate_value(0))
- convert_to_mov_immediate(0);
- else if (m_param[2].is_immediate() && m_param[3].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate((INT32)((INT32)m_param[1].immediate() * (INT32)m_param[2].immediate()));
- else if (m_size == 8)
- convert_to_mov_immediate((INT64)((INT64)m_param[1].immediate() * (INT64)m_param[2].immediate()));
- }
- }
- break;
-
- // DIVU: convert simple form to MOV if immediate, or if dividing with 0
- case OP_DIVU:
- if (m_param[0] == m_param[1] && !m_param[3].is_immediate_value(0))
- {
- if (m_param[2].is_immediate_value(0))
- convert_to_mov_immediate(0);
- else if (m_param[2].is_immediate() && m_param[3].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate((UINT32)((UINT32)m_param[1].immediate() / (UINT32)m_param[2].immediate()));
- else if (m_size == 8)
- convert_to_mov_immediate((UINT64)((UINT64)m_param[1].immediate() / (UINT64)m_param[2].immediate()));
- }
- }
- break;
-
- // DIVS: convert simple form to MOV if immediate, or if dividing with 0
- case OP_DIVS:
- if (m_param[0] == m_param[1] && !m_param[3].is_immediate_value(0))
- {
- if (m_param[2].is_immediate_value(0))
- convert_to_mov_immediate(0);
- else if (m_param[2].is_immediate() && m_param[3].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate((INT32)((INT32)m_param[1].immediate() / (INT32)m_param[2].immediate()));
- else if (m_size == 8)
- convert_to_mov_immediate((INT64)((INT64)m_param[1].immediate() / (INT64)m_param[2].immediate()));
- }
- }
- break;
-
- // AND: convert to MOV if immediate, or if anding against 0 or 0xffffffff
- case OP_AND:
- if (m_param[1].is_immediate_value(0) || m_param[2].is_immediate_value(0))
- convert_to_mov_immediate(0);
- else if (m_param[1].is_immediate() && m_param[2].is_immediate())
- convert_to_mov_immediate(m_param[1].immediate() & m_param[2].immediate());
- else if (m_param[1].is_immediate_value(instsizemask[m_size]))
- convert_to_mov_param(2);
- else if (m_param[2].is_immediate_value(instsizemask[m_size]))
- convert_to_mov_param(1);
- break;
-
- // TEST: no-op if no flags needed
- case OP_TEST:
- if (m_flags == 0)
- nop();
- break;
-
- // OR: convert to MOV if immediate, or if oring against 0 or 0xffffffff
- case OP_OR:
- if (m_param[1].is_immediate_value(instsizemask[m_size]) || m_param[2].is_immediate_value(instsizemask[m_size]))
- convert_to_mov_immediate(instsizemask[m_size]);
- else if (m_param[1].is_immediate() && m_param[2].is_immediate())
- convert_to_mov_immediate(m_param[1].immediate() | m_param[2].immediate());
- else if (m_param[1].is_immediate_value(0))
- convert_to_mov_param(2);
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // XOR: convert to MOV if immediate, or if xoring against 0
- case OP_XOR:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- convert_to_mov_immediate(m_param[1].immediate() ^ m_param[2].immediate());
- else if (m_param[1].is_immediate_value(0))
- convert_to_mov_param(2);
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // LZCNT: convert to MOV if immediate
- case OP_LZCNT:
- if (m_param[1].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate(count_leading_zeros(m_param[1].immediate()));
- else if (m_size == 8)
- {
- if ((m_param[1].immediate() >> 32) == 0)
- convert_to_mov_immediate(32 + count_leading_zeros(m_param[1].immediate()));
- else
- convert_to_mov_immediate(count_leading_zeros(m_param[1].immediate() >> 32));
- }
- }
- break;
-
- // BSWAP: convert to MOV if immediate
- case OP_BSWAP:
- if (m_param[1].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate(FLIPENDIAN_INT32(m_param[1].immediate()));
- else if (m_size == 8)
- convert_to_mov_immediate(FLIPENDIAN_INT64(m_param[1].immediate()));
- }
- break;
-
- // SHL: convert to MOV if immediate or shifting by 0
- case OP_SHL:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- convert_to_mov_immediate(m_param[1].immediate() << m_param[2].immediate());
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // SHR: convert to MOV if immediate or shifting by 0
- case OP_SHR:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate((UINT32)m_param[1].immediate() >> m_param[2].immediate());
- else if (m_size == 8)
- convert_to_mov_immediate((UINT64)m_param[1].immediate() >> m_param[2].immediate());
- }
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // SAR: convert to MOV if immediate or shifting by 0
- case OP_SAR:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate((INT32)m_param[1].immediate() >> m_param[2].immediate());
- else if (m_size == 8)
- convert_to_mov_immediate((INT64)m_param[1].immediate() >> m_param[2].immediate());
- }
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // ROL: convert to NOP if immediate or rotating by 0
- case OP_ROL:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate(rol32(m_param[1].immediate(), m_param[2].immediate()));
- else if (m_size == 8)
- convert_to_mov_immediate(rol64(m_param[1].immediate(), m_param[2].immediate()));
- }
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // ROR: convert to NOP if immediate or rotating by 0
- case OP_ROR:
- if (m_param[1].is_immediate() && m_param[2].is_immediate())
- {
- if (m_size == 4)
- convert_to_mov_immediate(rol32(m_param[1].immediate(), 32 - m_param[2].immediate()));
- else if (m_size == 8)
- convert_to_mov_immediate(rol64(m_param[1].immediate(), 64 - m_param[2].immediate()));
- }
- else if (m_param[2].is_immediate_value(0))
- convert_to_mov_param(1);
- break;
-
- // FMOV: convert to NOP if move-to-self
- case OP_FMOV:
- if (m_param[0] == m_param[1])
- nop();
- break;
-
- default:
- break;
- }
-
- /*
- if (LOG_SIMPLIFICATIONS && memcmp(&orig, inst, sizeof(orig)) != 0)
- {
- std::string disasm1, disasm2;
- orig.disasm(disasm1, block->drcuml);
- inst->disasm(disasm2, block->drcuml);
- osd_printf_debug("Simplified: %-50.50s -> %s\n", disasm1.c_str(), disasm2.c_str());
- }
- */
-
- // loop until we stop changing opcodes
- } while (m_opcode != origop);
-}
-
-
-//-------------------------------------------------
-// validate - verify that the instruction created
-// meets all requirements
-//-------------------------------------------------
-
-void uml::instruction::validate()
-{
-#ifdef MAME_DEBUG
- const opcode_info &opinfo = s_opcode_info_table[m_opcode];
- assert(opinfo.opcode == m_opcode);
-
- // validate raw information
- assert(m_opcode != OP_INVALID && m_opcode < OP_MAX);
- assert(m_size == 1 || m_size == 2 || m_size == 4 || m_size == 8);
-
- // validate against opcode limits
- assert((opinfo.sizes & m_size) != 0);
- assert(m_condition == COND_ALWAYS || opinfo.condition);
-
- // validate each parameter
- for (int pnum = 0; pnum < m_numparams; pnum++)
- {
- // ensure the type is valid
- const parameter &param = m_param[pnum];
- assert((opinfo.param[pnum].typemask >> param.type()) & 1);
- }
-
- // make sure we aren't missing any parameters
- if (m_numparams < ARRAY_LENGTH(opinfo.param))
- assert(opinfo.param[m_numparams].typemask == 0);
-#endif
-}
-
-
-//-------------------------------------------------
-// input_flags - return the effective input flags
-// based on any conditions encoded in an
-// instruction
-//-------------------------------------------------
-
-UINT8 uml::instruction::input_flags() const
-{
- static const UINT8 flags_for_condition[] =
- {
- FLAG_Z, // COND_Z
- FLAG_Z, // COND_NZ
- FLAG_S, // COND_S
- FLAG_S, // COND_NS
- FLAG_C, // COND_C
- FLAG_C, // COND_NC
- FLAG_V, // COND_V
- FLAG_V, // COND_NV
- FLAG_U, // COND_U
- FLAG_U, // COND_NU
- FLAG_C | FLAG_Z, // COND_A
- FLAG_C | FLAG_Z, // COND_BE
- FLAG_S | FLAG_V | FLAG_Z, // COND_G
- FLAG_S | FLAG_V | FLAG_Z, // COND_LE
- FLAG_S | FLAG_V, // COND_L
- FLAG_S | FLAG_V // COND_GE
- };
-
- UINT8 flags = s_opcode_info_table[m_opcode].inflags;
- if (flags & 0x80)
- flags = m_param[flags - OPFLAGS_P1].immediate() & OPFLAGS_ALL;
- if (m_condition != COND_ALWAYS)
- flags |= flags_for_condition[m_condition & 0x0f];
- return flags;
-}
-
-
-//-------------------------------------------------
-// output_flags - return the effective output
-// flags based on any conditions encoded in an
-// instruction
-//-------------------------------------------------
-
-UINT8 uml::instruction::output_flags() const
-{
- UINT8 flags = s_opcode_info_table[m_opcode].outflags;
- if (flags & 0x80)
- flags = m_param[flags - OPFLAGS_P1].immediate() & OPFLAGS_ALL;
- return flags;
-}
-
-
-//-------------------------------------------------
-// modified_flags - return the effective output
-// flags based on any conditions encoded in an
-// instruction
-//-------------------------------------------------
-
-UINT8 uml::instruction::modified_flags() const
-{
- return s_opcode_info_table[m_opcode].modflags;
-}
-
-
-//-------------------------------------------------
-// disasm - disassemble an instruction to the
-// given buffer
-//-------------------------------------------------
-
-const char *uml::instruction::disasm(std::string &buffer, drcuml_state *drcuml) const
-{
- static const char *const conditions[] = { "z", "nz", "s", "ns", "c", "nc", "v", "nv", "u", "nu", "a", "be", "g", "le", "l", "ge" };
- static const char *const pound_size[] = { "?", "?", "?", "?", "s", "?", "?", "?", "d" };
- static const char *const bang_size[] = { "?", "b", "h", "?", "", "?", "?", "?", "d" };
- static const char *const fmods[] = { "trunc", "round", "ceil", "floor", "default" };
- static const char *const spaces[] = { "program", "data", "io", "3", "4", "5", "6", "7" };
- static const char *const sizes[] = { "byte", "word", "dword", "qword" };
-
- const opcode_info &opinfo = s_opcode_info_table[m_opcode];
-
- assert(m_opcode != OP_INVALID && m_opcode < OP_MAX);
-
- // start with the raw mnemonic and substitute sizes
- buffer.clear();
- for (const char *opsrc = opinfo.mnemonic; *opsrc != 0; opsrc++)
- if (*opsrc == '!')
- strcatprintf(buffer, "%s", bang_size[m_size]);
- else if (*opsrc == '#')
- strcatprintf(buffer, "%s", pound_size[m_size]);
- else
- buffer.push_back(*opsrc);
-
- // pad to 8 spaces
- int pad = 8 - buffer.length();
- for (int ch = 0; ch < pad; ch++)
- buffer.push_back(' ');
-
- // iterate through parameters
- for (int pnum = 0; pnum < m_numparams; pnum++)
- {
- const parameter &param = m_param[pnum];
-
- // start with a comma for all except the first parameter
- if (pnum != 0)
- buffer.push_back(',');
-
- // ouput based on type
- switch (param.type())
- {
- // immediates have several special cases
- case parameter::PTYPE_IMMEDIATE:
- {
- // determine the size of the immediate
- int size;
- switch (opinfo.param[pnum].size)
- {
- case PSIZE_4: size = 4; break;
- case PSIZE_8: size = 8; break;
- case PSIZE_P1: size = 1 << m_param[0].size(); break;
- case PSIZE_P2: size = 1 << m_param[1].size(); break;
- case PSIZE_P3: size = 1 << m_param[2].size(); break;
- case PSIZE_P4: size = 1 << m_param[3].size(); break;
- default:
- case PSIZE_OP: size = m_size; break;
- }
-
- // truncate to size
- UINT64 value = param.immediate();
- if (size == 1) value = (UINT8)value;
- if (size == 2) value = (UINT16)value;
- if (size == 4) value = (UINT32)value;
- if ((UINT32)value == value)
- strcatprintf(buffer, "$%X", (UINT32)value);
- else
- strcatprintf(buffer, "$%X%08X", (UINT32)(value >> 32), (UINT32)value);
- }
- break;
-
- // immediates have several special cases
- case parameter::PTYPE_SIZE:
- strcatprintf(buffer, "%s", sizes[param.size()]);
- break;
-
- // size + address space immediate
- case parameter::PTYPE_SIZE_SPACE:
- strcatprintf(buffer, "%s_%s", spaces[param.space()], sizes[param.size()]);
- break;
-
- // size + scale immediate
- case parameter::PTYPE_SIZE_SCALE:
- {
- int scale = param.scale();
- int size = param.size();
- if (scale == size)
- strcatprintf(buffer, "%s", sizes[size]);
- else
- strcatprintf(buffer, "%s_x%d", sizes[size], 1 << scale);
- }
- break;
-
- // fmod immediate
- case parameter::PTYPE_ROUNDING:
- strcatprintf(buffer, "%s", fmods[param.rounding()]);
- break;
-
- // integer registers
- case parameter::PTYPE_INT_REGISTER:
- strcatprintf(buffer, "i%d", param.ireg() - REG_I0);
- break;
-
- // floating point registers
- case parameter::PTYPE_FLOAT_REGISTER:
- strcatprintf(buffer, "f%d", param.freg() - REG_F0);
- break;
-
- // map variables
- case parameter::PTYPE_MAPVAR:
- strcatprintf(buffer, "m%d", param.mapvar() - MAPVAR_M0);
- break;
-
- // memory
- case parameter::PTYPE_MEMORY:
- {
- const char *symbol;
- UINT32 symoffset;
-
- // symbol
- if (drcuml != NULL && (symbol = drcuml->symbol_find(param.memory(), &symoffset)) != NULL)
- {
- if (symoffset == 0)
- strcatprintf(buffer, "[%s]", symbol);
- else
- strcatprintf(buffer, "[%s+$%X]", symbol, symoffset);
- }
-
- // cache memory
- else if (drcuml != NULL && drcuml->cache().contains_pointer(param.memory()))
- strcatprintf(buffer, "[+$%X]", (UINT32)(FPTR)((drccodeptr)param.memory() - drcuml->cache().near()));
-
- // general memory
- else
- strcatprintf(buffer, "[[$%p]]", param.memory());
- break;
- }
-
- // string pointer
- case parameter::PTYPE_STRING:
- strcatprintf(buffer, "%s", (const char *)(FPTR)param.string());
- break;
-
- // handle pointer
- case parameter::PTYPE_CODE_HANDLE:
- strcatprintf(buffer, "%s", param.handle().string());
- break;
-
- default:
- strcatprintf(buffer, "???");
- break;
- }
- }
-
- // if there's a condition, append it
- if (m_condition != COND_ALWAYS)
- strcatprintf(buffer, ",%s", conditions[m_condition & 0x0f]);
-
- // if there are flags, append them
- if (m_flags != 0)
- {
- buffer.push_back(',');
- if (m_flags & FLAG_U)
- buffer.push_back('U');
- if (m_flags & FLAG_S)
- buffer.push_back('S');
- if (m_flags & FLAG_Z)
- buffer.push_back('Z');
- if (m_flags & FLAG_V)
- buffer.push_back('V');
- if (m_flags & FLAG_C)
- buffer.push_back('C');
- }
- return buffer.c_str();
-}