summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/uml.h
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/uml.h')
-rw-r--r--trunk/src/emu/cpu/uml.h690
1 files changed, 690 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/uml.h b/trunk/src/emu/cpu/uml.h
new file mode 100644
index 00000000000..f90f8ccd7d6
--- /dev/null
+++ b/trunk/src/emu/cpu/uml.h
@@ -0,0 +1,690 @@
+/***************************************************************************
+
+ uml.h
+
+ Universal machine language definitions and classes.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __UML_H__
+#define __UML_H__
+
+#include "drccache.h"
+
+
+//**************************************************************************
+// TYPE DEFINITIONS
+//**************************************************************************
+
+// opaque structure describing UML generation state
+class drcuml_state;
+
+struct drcuml_machine_state;
+
+
+// use a namespace to wrap all the UML instruction concepts so that
+// we can keep names short
+namespace uml
+{
+ // integer registers
+ const int REG_I0 = 0x400;
+ const int REG_I_COUNT = 10;
+ const int REG_I_END = REG_I0 + REG_I_COUNT;
+
+ // floating point registers
+ const int REG_F0 = 0x800;
+ const int REG_F_COUNT = 10;
+ const int REG_F_END = REG_F0 + REG_F_COUNT;
+
+ // vector registers
+ const int REG_V0 = 0xc00;
+ const int REG_V_COUNT = 10;
+ const int REG_V_END = REG_V0 + REG_V_COUNT;
+
+ // map variables
+ const int MAPVAR_M0 = 0x1000;
+ const int MAPVAR_COUNT = 10;
+ const int MAPVAR_END = MAPVAR_M0 + MAPVAR_COUNT;
+
+ // flag definitions
+ const UINT8 FLAG_C = 0x01; // carry flag
+ const UINT8 FLAG_V = 0x02; // overflow flag (defined for integer only)
+ const UINT8 FLAG_Z = 0x04; // zero flag
+ const UINT8 FLAG_S = 0x08; // sign flag (defined for integer only)
+ const UINT8 FLAG_U = 0x10; // unordered flag (defined for FP only)
+
+ // testable conditions; note that these are defined such that (condition ^ 1) is
+ // always the opposite
+ enum condition_t
+ {
+ COND_ALWAYS = 0,
+
+ COND_Z = 0x80, // requires Z
+ COND_NZ, // requires Z
+ COND_S, // requires S
+ COND_NS, // requires S
+ COND_C, // requires C
+ COND_NC, // requires C
+ COND_V, // requires V
+ COND_NV, // requires V
+ COND_U, // requires U
+ COND_NU, // requires U
+ COND_A, // requires CZ
+ COND_BE, // requires CZ
+ COND_G, // requires SVZ
+ COND_LE, // requires SVZ
+ COND_L, // requires SV
+ COND_GE, // requires SV
+
+ COND_MAX,
+
+ // basic condition code aliases
+ COND_E = COND_Z,
+ COND_NE = COND_NZ,
+ COND_B = COND_C,
+ COND_AE = COND_NC
+ };
+
+ // floating point rounding modes
+ enum float_rounding_mode
+ {
+ ROUND_TRUNC = 0, // truncate
+ ROUND_ROUND, // round
+ ROUND_CEIL, // round up
+ ROUND_FLOOR, // round down
+ ROUND_DEFAULT
+ };
+
+ // operand sizes
+ enum operand_size
+ {
+ SIZE_BYTE = 0, // 1-byte
+ SIZE_WORD, // 2-byte
+ SIZE_DWORD, // 4-byte
+ SIZE_QWORD, // 8-byte
+ SIZE_DQWORD, // 16-byte (vector)
+ SIZE_SHORT = SIZE_DWORD, // 4-byte (float)
+ SIZE_DOUBLE = SIZE_QWORD // 8-byte (float)
+ };
+
+ // memory scale factors
+ enum memory_scale
+ {
+ SCALE_x1 = 0, // index * 1
+ SCALE_x2, // index * 2
+ SCALE_x4, // index * 4
+ SCALE_x8, // index * 8
+ SCALE_DEFAULT
+ };
+
+ // spaces
+ enum memory_space
+ {
+ SPACE_PROGRAM = AS_PROGRAM,
+ SPACE_DATA = AS_DATA,
+ SPACE_IO = AS_IO
+ };
+
+ // opcodes
+ enum opcode_t
+ {
+ OP_INVALID,
+
+ // compile-time opcodes
+ OP_HANDLE, // HANDLE handle
+ OP_HASH, // HASH mode,pc
+ OP_LABEL, // LABEL imm
+ OP_COMMENT, // COMMENT string
+ OP_MAPVAR, // MAPVAR mapvar,value
+
+ // control flow operations
+ OP_NOP, // NOP
+ OP_DEBUG, // DEBUG pc
+ OP_EXIT, // EXIT src1[,c]
+ OP_HASHJMP, // HASHJMP mode,pc,handle
+ OP_JMP, // JMP imm[,c]
+ OP_EXH, // EXH handle,param[,c]
+ OP_CALLH, // CALLH handle[,c]
+ OP_RET, // RET [c]
+ OP_CALLC, // CALLC func,ptr[,c]
+ OP_RECOVER, // RECOVER dst,mapvar
+
+ // internal register operations
+ OP_SETFMOD, // SETFMOD src
+ OP_GETFMOD, // GETFMOD dst
+ OP_GETEXP, // GETEXP dst
+ OP_GETFLGS, // GETFLGS dst[,f]
+ OP_SAVE, // SAVE mem
+ OP_RESTORE, // RESTORE mem
+
+ // integer operations
+ OP_LOAD, // LOAD dst,base,index,size
+ OP_LOADS, // LOADS dst,base,index,size
+ OP_STORE, // STORE base,index,src,size
+ OP_READ, // READ dst,src1,space/size
+ OP_READM, // READM dst,src1,mask,space/size
+ OP_WRITE, // WRITE dst,src1,space/size
+ OP_WRITEM, // WRITEM dst,mask,src1,space/size
+ OP_CARRY, // CARRY src,bitnum
+ OP_SET, // SET dst,c
+ OP_MOV, // MOV dst,src[,c]
+ OP_SEXT, // SEXT dst,src,size
+ OP_ROLAND, // ROLAND dst,src,shift,mask
+ OP_ROLINS, // ROLINS dst,src,shift,mask
+ OP_ADD, // ADD dst,src1,src2[,f]
+ OP_ADDC, // ADDC dst,src1,src2[,f]
+ OP_SUB, // SUB dst,src1,src2[,f]
+ OP_SUBB, // SUBB dst,src1,src2[,f]
+ OP_CMP, // CMP src1,src2[,f]
+ OP_MULU, // MULU dst,edst,src1,src2[,f]
+ OP_MULS, // MULS dst,edst,src1,src2[,f]
+ OP_DIVU, // DIVU dst,edst,src1,src2[,f]
+ OP_DIVS, // DIVS dst,edst,src1,src2[,f]
+ OP_AND, // AND dst,src1,src2[,f]
+ OP_TEST, // TEST src1,src2[,f]
+ OP_OR, // OR dst,src1,src2[,f]
+ OP_XOR, // XOR dst,src1,src2[,f]
+ OP_LZCNT, // LZCNT dst,src
+ OP_BSWAP, // BSWAP dst,src
+ OP_SHL, // SHL dst,src,count[,f]
+ OP_SHR, // SHR dst,src,count[,f]
+ OP_SAR, // SAR dst,src,count[,f]
+ OP_ROL, // ROL dst,src,count[,f]
+ OP_ROLC, // ROLC dst,src,count[,f]
+ OP_ROR, // ROL dst,src,count[,f]
+ OP_RORC, // ROLC dst,src,count[,f]
+
+ // floating point operations
+ OP_FLOAD, // FLOAD dst,base,index
+ OP_FSTORE, // FSTORE base,index,src
+ OP_FREAD, // FREAD dst,space,src1
+ OP_FWRITE, // FWRITE space,dst,src1
+ OP_FMOV, // FMOV dst,src1[,c]
+ OP_FTOINT, // FTOINT dst,src1,size,round
+ OP_FFRINT, // FFRINT dst,src1,size
+ OP_FFRFLT, // FFRFLT dst,src1,size
+ OP_FRNDS, // FRNDS dst,src1
+ OP_FADD, // FADD dst,src1,src2
+ OP_FSUB, // FSUB dst,src1,src2
+ OP_FCMP, // FCMP src1,src2
+ OP_FMUL, // FMUL dst,src1,src2
+ OP_FDIV, // FDIV dst,src1,src2
+ OP_FNEG, // FNEG dst,src1
+ OP_FABS, // FABS dst,src1
+ OP_FSQRT, // FSQRT dst,src1
+ OP_FRECIP, // FRECIP dst,src1
+ OP_FRSQRT, // FRSQRT dst,src1
+
+ OP_MAX
+ };
+
+ // C function callback deinition
+ typedef void (*c_function)(void *ptr);
+
+ // class describing a global code handle
+ class code_handle
+ {
+ friend class ::drcuml_state;
+ friend class ::simple_list<code_handle>;
+
+ // construction/destruction
+ code_handle(drcuml_state &drcuml, const char *name);
+
+ public:
+ // getters
+ code_handle *next() const { return m_next; }
+ drccodeptr codeptr() const { return *m_code; }
+ drccodeptr *codeptr_addr() { return m_code; }
+ const char *string() const { return m_string; }
+
+ // setters
+ void set_codeptr(drccodeptr code);
+
+ private:
+ // internal state
+ drccodeptr * m_code; // pointer in the cache to the associated code
+ astring m_string; // pointer to string attached to handle
+ code_handle * m_next; // link to next handle in the list
+ drcuml_state & m_drcuml; // pointer to owning object
+ };
+
+ // class describing a local code label
+ class code_label
+ {
+ public:
+ // construction
+ code_label(UINT32 label = 0) : m_label(label) { }
+
+ // operators
+ operator UINT32 &() { return m_label; }
+ bool operator==(const code_label &rhs) const { return (m_label == rhs.m_label); }
+ bool operator!=(const code_label &rhs) const { return (m_label != rhs.m_label); }
+
+ // getters
+ UINT32 label() const { return m_label; }
+
+ private:
+ UINT32 m_label;
+ };
+
+ // a parameter for a UML instructon is encoded like this
+ class parameter
+ {
+ public:
+ // opcode parameter types
+ enum parameter_type
+ {
+ PTYPE_NONE = 0, // invalid
+ PTYPE_IMMEDIATE, // immediate; value = sign-extended to 64 bits
+ PTYPE_INT_REGISTER, // integer register; value = REG_I0 - REG_I_END
+ PTYPE_FLOAT_REGISTER, // floating point register; value = REG_F0 - REG_F_END
+ PTYPE_VECTOR_REGISTER, // vector register; value = REG_V0 - REG_V_END
+ PTYPE_MAPVAR, // map variable; value = MAPVAR_M0 - MAPVAR_END
+ PTYPE_MEMORY, // memory; value = pointer to memory
+ PTYPE_SIZE, // size; value = operand_size
+ PTYPE_SIZE_SCALE, // scale + size; value = memory_scale * 16 + operand_size
+ PTYPE_SIZE_SPACE, // space + size; value = memory_space * 16 + operand_size
+ PTYPE_CODE_HANDLE, // code handle; value = pointer to handle
+ PTYPE_CODE_LABEL, // code label; value = label index
+ PTYPE_C_FUNCTION, // C function; value = pointer to C code
+ PTYPE_ROUNDING, // floating point rounding mode; value = float_rounding_mode
+ PTYPE_STRING, // string parameter; value = pointer to string
+ PTYPE_MAX
+ };
+
+ // represents the value of an opcode parameter
+ typedef UINT64 parameter_value;
+
+ // construction
+ parameter() : m_type(PTYPE_NONE), m_value(0) { }
+ parameter(const parameter &param) : m_type(param.m_type), m_value(param.m_value) { }
+ parameter(UINT64 val) : m_type(PTYPE_IMMEDIATE), m_value(val) { }
+ parameter(operand_size size, memory_scale scale) : m_type(PTYPE_SIZE_SCALE), m_value((scale << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); assert(scale >= SCALE_x1 && scale <= SCALE_x8); }
+ parameter(operand_size size, memory_space space) : m_type(PTYPE_SIZE_SPACE), m_value((space << 4) | size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); assert(space >= SPACE_PROGRAM && space <= SPACE_IO); }
+ parameter(code_handle &handle) : m_type(PTYPE_CODE_HANDLE), m_value(reinterpret_cast<parameter_value>(&handle)) { }
+ parameter(code_label &label) : m_type(PTYPE_CODE_LABEL), m_value(label) { }
+
+ // creators for types that don't safely default
+ static inline parameter make_ireg(int regnum) { assert(regnum >= REG_I0 && regnum < REG_I_END); return parameter(PTYPE_INT_REGISTER, regnum); }
+ static inline parameter make_freg(int regnum) { assert(regnum >= REG_F0 && regnum < REG_F_END); return parameter(PTYPE_FLOAT_REGISTER, regnum); }
+ static inline parameter make_vreg(int regnum) { assert(regnum >= REG_V0 && regnum < REG_V_END); return parameter(PTYPE_VECTOR_REGISTER, regnum); }
+ static inline parameter make_mapvar(int mvnum) { assert(mvnum >= MAPVAR_M0 && mvnum < MAPVAR_END); return parameter(PTYPE_MAPVAR, mvnum); }
+ static inline parameter make_memory(void *base) { return parameter(PTYPE_MEMORY, reinterpret_cast<parameter_value>(base)); }
+ static inline parameter make_memory(const void *base) { return parameter(PTYPE_MEMORY, reinterpret_cast<parameter_value>(const_cast<void *>(base))); }
+ static inline parameter make_size(operand_size size) { assert(size >= SIZE_BYTE && size <= SIZE_DQWORD); return parameter(PTYPE_SIZE, size); }
+ static inline parameter make_string(const char *string) { return parameter(PTYPE_STRING, reinterpret_cast<parameter_value>(const_cast<char *>(string))); }
+ static inline parameter make_cfunc(c_function func) { return parameter(PTYPE_C_FUNCTION, reinterpret_cast<parameter_value>(func)); }
+ static inline parameter make_rounding(float_rounding_mode mode) { assert(mode >= ROUND_TRUNC && mode <= ROUND_DEFAULT); return parameter(PTYPE_ROUNDING, mode); }
+
+ // operators
+ bool operator==(const parameter &rhs) const { return (m_type == rhs.m_type && m_value == rhs.m_value); }
+ bool operator!=(const parameter &rhs) const { return (m_type != rhs.m_type || m_value != rhs.m_value); }
+
+ // getters
+ parameter_type type() const { return m_type; }
+ UINT64 immediate() const { assert(m_type == PTYPE_IMMEDIATE); return m_value; }
+ int ireg() const { assert(m_type == PTYPE_INT_REGISTER); assert(m_value >= REG_I0 && m_value < REG_I_END); return m_value; }
+ int freg() const { assert(m_type == PTYPE_FLOAT_REGISTER); assert(m_value >= REG_F0 && m_value < REG_F_END); return m_value; }
+ int vreg() const { assert(m_type == PTYPE_VECTOR_REGISTER); assert(m_value >= REG_V0 && m_value < REG_V_END); return m_value; }
+ int mapvar() const { assert(m_type == PTYPE_MAPVAR); assert(m_value >= MAPVAR_M0 && m_value < MAPVAR_END); return m_value; }
+ void *memory() const { assert(m_type == PTYPE_MEMORY); return reinterpret_cast<void *>(m_value); }
+ operand_size size() const { assert(m_type == PTYPE_SIZE || m_type == PTYPE_SIZE_SCALE || m_type == PTYPE_SIZE_SPACE); return operand_size(m_value & 15); }
+ memory_scale scale() const { assert(m_type == PTYPE_SIZE_SCALE); return memory_scale(m_value >> 4); }
+ memory_space space() const { assert(m_type == PTYPE_SIZE_SPACE); return memory_space(m_value >> 4); }
+ code_handle &handle() const { assert(m_type == PTYPE_CODE_HANDLE); return *reinterpret_cast<code_handle *>(m_value); }
+ code_label label() const { assert(m_type == PTYPE_CODE_LABEL); return code_label(m_value); }
+ c_function cfunc() const { assert(m_type == PTYPE_C_FUNCTION); return reinterpret_cast<c_function>(m_value); }
+ float_rounding_mode rounding() const { assert(m_type == PTYPE_ROUNDING); return float_rounding_mode(m_value); }
+ const char *string() const { assert(m_type == PTYPE_STRING); return reinterpret_cast<const char *>(m_value); }
+
+ // type queries
+ bool is_immediate() const { return (m_type == PTYPE_IMMEDIATE); }
+ bool is_int_register() const { return (m_type == PTYPE_INT_REGISTER); }
+ bool is_float_register() const { return (m_type == PTYPE_FLOAT_REGISTER); }
+ bool is_vector_register() const { return (m_type == PTYPE_VECTOR_REGISTER); }
+ bool is_mapvar() const { return (m_type == PTYPE_MAPVAR); }
+ bool is_memory() const { return (m_type == PTYPE_MEMORY); }
+ bool is_size() const { return (m_type == PTYPE_SIZE); }
+ bool is_size_scale() const { return (m_type == PTYPE_SIZE_SCALE); }
+ bool is_size_space() const { return (m_type == PTYPE_SIZE_SPACE); }
+ bool is_code_handle() const { return (m_type == PTYPE_CODE_HANDLE); }
+ bool is_code_label() const { return (m_type == PTYPE_CODE_LABEL); }
+ bool is_c_function() const { return (m_type == PTYPE_C_FUNCTION); }
+ bool is_rounding() const { return (m_type == PTYPE_ROUNDING); }
+ bool is_string() const { return (m_type == PTYPE_STRING); }
+
+ // other queries
+ bool is_immediate_value(UINT64 value) const { return (m_type == PTYPE_IMMEDIATE && m_value == value); }
+
+ private:
+ // private constructor
+ parameter(parameter_type type, parameter_value value) : m_type(type), m_value(value) { }
+
+ // internals
+ parameter_type m_type; // parameter type
+ parameter_value m_value; // parameter value
+ };
+
+ // structure describing rules for opcode encoding
+ struct opcode_info
+ {
+ struct parameter_info
+ {
+ UINT8 output; // input or output?
+ UINT8 size; // size of the parameter
+ UINT16 typemask; // types allowed
+ };
+
+ opcode_t opcode; // the opcode itself
+ const char * mnemonic; // mnemonic string
+ UINT8 sizes; // allowed sizes
+ bool condition; // conditions allowed?
+ UINT8 inflags; // input flags
+ UINT8 outflags; // output flags
+ UINT8 modflags; // modified flags
+ parameter_info param[4]; // information about parameters
+ };
+
+ // a single UML instructon is encoded like this
+ class instruction
+ {
+ public:
+ // construction/destruction
+ instruction();
+
+ // getters
+ opcode_t opcode() const { return m_opcode; }
+ condition_t condition() const { return m_condition; }
+ UINT8 flags() const { return m_flags; }
+ UINT8 size() const { return m_size; }
+ UINT8 numparams() const { return m_numparams; }
+ const parameter &param(int index) const { assert(index < m_numparams); return m_param[index]; }
+
+ // setters
+ void set_flags(UINT8 flags) { m_flags = flags; }
+ void set_mapvar(int paramnum, UINT32 value) { assert(paramnum < m_numparams); assert(m_param[paramnum].is_mapvar()); m_param[paramnum] = value; }
+
+ // misc
+ const char *disasm(astring &string, drcuml_state *drcuml = NULL) const;
+ UINT8 input_flags() const;
+ UINT8 output_flags() const;
+ UINT8 modified_flags() const;
+ void simplify();
+
+ // compile-time opcodes
+ void handle(code_handle &hand) { configure(OP_HANDLE, 4, hand); }
+ void hash(UINT32 mode, UINT32 pc) { configure(OP_HASH, 4, mode, pc); }
+ void label(code_label lab) { configure(OP_LABEL, 4, lab); }
+ void comment(const char *string) { configure(OP_COMMENT, 4, parameter::make_string(string)); }
+ void mapvar(parameter mapvar, UINT32 value) { assert(mapvar.is_mapvar()); configure(OP_MAPVAR, 4, mapvar, value); }
+
+ // control flow operations
+ void nop() { configure(OP_NOP, 4); }
+ void debug(UINT32 pc) { configure(OP_DEBUG, 4, pc); }
+ void exit(parameter param) { configure(OP_EXIT, 4, param); }
+ void exit(condition_t cond, parameter param) { configure(OP_EXIT, 4, param, cond); }
+ void hashjmp(parameter mode, parameter pc, code_handle &handle) { configure(OP_HASHJMP, 4, mode, pc, handle); }
+ void jmp(code_label label) { configure(OP_JMP, 4, label); }
+ void jmp(condition_t cond, code_label label) { configure(OP_JMP, 4, label, cond); }
+ void exh(code_handle &handle, parameter param) { configure(OP_EXH, 4, handle, param); }
+ void exh(condition_t cond, code_handle &handle, parameter param) { configure(OP_EXH, 4, handle, param, cond); }
+ void callh(code_handle &handle) { configure(OP_CALLH, 4, handle); }
+ void callh(condition_t cond, code_handle &handle) { configure(OP_CALLH, 4, handle, cond); }
+ void ret() { configure(OP_RET, 4); }
+ void ret(condition_t cond) { configure(OP_RET, 4, cond); }
+ void callc(c_function func, void *ptr) { configure(OP_CALLC, 4, parameter::make_cfunc(func), parameter::make_memory(ptr)); }
+ void callc(condition_t cond, c_function func, void *ptr) { configure(OP_CALLC, 4, parameter::make_cfunc(func), parameter::make_memory(ptr), cond); }
+ void recover(parameter dst, parameter mapvar) { assert(mapvar.is_mapvar()); configure(OP_RECOVER, 4, dst, mapvar); }
+
+ // internal register operations
+ void setfmod(parameter mode) { configure(OP_SETFMOD, 4, mode); }
+ void getfmod(parameter dst) { configure(OP_GETFMOD, 4, dst); }
+ void getexp(parameter dst) { configure(OP_GETEXP, 4, dst); }
+ void getflgs(parameter dst, UINT32 flags) { configure(OP_GETFLGS, 4, dst, flags); }
+ void save(drcuml_machine_state *dst) { configure(OP_SAVE, 4, parameter::make_memory(dst)); }
+ void restore(drcuml_machine_state *src) { configure(OP_RESTORE, 4, parameter::make_memory(src)); }
+
+ // 32-bit integer operations
+ void load(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOAD, 4, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void loads(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOADS, 4, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void store(void *base, parameter index, parameter src1, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_STORE, 4, parameter::make_memory(base), index, src1, parameter(size, scale)); }
+ void read(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READ, 4, dst, src1, parameter(size, space)); }
+ void readm(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READM, 4, dst, src1, mask, parameter(size, space)); }
+ void write(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITE, 4, dst, src1, parameter(size, space)); }
+ void writem(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITEM, 4, dst, src1, mask, parameter(size, space)); }
+ void carry(parameter src, parameter bitnum) { configure(OP_CARRY, 4, src, bitnum); }
+ void set(condition_t cond, parameter dst) { configure(OP_SET, 4, dst, cond); }
+ void mov(parameter dst, parameter src1) { configure(OP_MOV, 4, dst, src1); }
+ void mov(condition_t cond, parameter dst, parameter src1) { configure(OP_MOV, 4, dst, src1, cond); }
+ void sext(parameter dst, parameter src1, operand_size size) { configure(OP_SEXT, 4, dst, src1, parameter::make_size(size)); }
+ void roland(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLAND, 4, dst, src, shift, mask); }
+ void rolins(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLINS, 4, dst, src, shift, mask); }
+ void add(parameter dst, parameter src1, parameter src2) { configure(OP_ADD, 4, dst, src1, src2); }
+ void addc(parameter dst, parameter src1, parameter src2) { configure(OP_ADDC, 4, dst, src1, src2); }
+ void sub(parameter dst, parameter src1, parameter src2) { configure(OP_SUB, 4, dst, src1, src2); }
+ void subb(parameter dst, parameter src1, parameter src2) { configure(OP_SUBB, 4, dst, src1, src2); }
+ void cmp(parameter src1, parameter src2) { configure(OP_CMP, 4, src1, src2); }
+ void mulu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULU, 4, dst, edst, src1, src2); }
+ void muls(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULS, 4, dst, edst, src1, src2); }
+ void divu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVU, 4, dst, edst, src1, src2); }
+ void divs(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVS, 4, dst, edst, src1, src2); }
+ void _and(parameter dst, parameter src1, parameter src2) { configure(OP_AND, 4, dst, src1, src2); }
+ void test(parameter src1, parameter src2) { configure(OP_TEST, 4, src1, src2); }
+ void _or(parameter dst, parameter src1, parameter src2) { configure(OP_OR, 4, dst, src1, src2); }
+ void _xor(parameter dst, parameter src1, parameter src2) { configure(OP_XOR, 4, dst, src1, src2); }
+ void lzcnt(parameter dst, parameter src) { configure(OP_LZCNT, 4, dst, src); }
+ void bswap(parameter dst, parameter src) { configure(OP_BSWAP, 4, dst, src); }
+ void shl(parameter dst, parameter src, parameter count) { configure(OP_SHL, 4, dst, src, count); }
+ void shr(parameter dst, parameter src, parameter count) { configure(OP_SHR, 4, dst, src, count); }
+ void sar(parameter dst, parameter src, parameter count) { configure(OP_SAR, 4, dst, src, count); }
+ void rol(parameter dst, parameter src, parameter count) { configure(OP_ROL, 4, dst, src, count); }
+ void rolc(parameter dst, parameter src, parameter count) { configure(OP_ROLC, 4, dst, src, count); }
+ void ror(parameter dst, parameter src, parameter count) { configure(OP_ROR, 4, dst, src, count); }
+ void rorc(parameter dst, parameter src, parameter count) { configure(OP_RORC, 4, dst, src, count); }
+
+ // 64-bit integer operations
+ void dload(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOAD, 8, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void dloads(parameter dst, const void *base, parameter index, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_LOADS, 8, dst, parameter::make_memory(base), index, parameter(size, scale)); }
+ void dstore(void *base, parameter index, parameter src1, operand_size size, memory_scale scale = SCALE_DEFAULT) { configure(OP_STORE, 8, parameter::make_memory(base), index, src1, parameter(size, scale)); }
+ void dread(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READ, 8, dst, src1, parameter(size, space)); }
+ void dreadm(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_READM, 8, dst, src1, mask, parameter(size, space)); }
+ void dwrite(parameter dst, parameter src1, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITE, 8, dst, src1, parameter(size, space)); }
+ void dwritem(parameter dst, parameter src1, parameter mask, operand_size size, memory_space space = SPACE_PROGRAM) { configure(OP_WRITEM, 8, dst, src1, mask, parameter(size, space)); }
+ void dcarry(parameter src, parameter bitnum) { configure(OP_CARRY, 8, src, bitnum); }
+ void dset(condition_t cond, parameter dst) { configure(OP_SET, 8, dst, cond); }
+ void dmov(parameter dst, parameter src1) { configure(OP_MOV, 8, dst, src1); }
+ void dmov(condition_t cond, parameter dst, parameter src1) { configure(OP_MOV, 8, dst, src1, cond); }
+ void dsext(parameter dst, parameter src1, operand_size size) { configure(OP_SEXT, 8, dst, src1, parameter::make_size(size)); }
+ void droland(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLAND, 8, dst, src, shift, mask); }
+ void drolins(parameter dst, parameter src, parameter shift, parameter mask) { configure(OP_ROLINS, 8, dst, src, shift, mask); }
+ void dadd(parameter dst, parameter src1, parameter src2) { configure(OP_ADD, 8, dst, src1, src2); }
+ void daddc(parameter dst, parameter src1, parameter src2) { configure(OP_ADDC, 8, dst, src1, src2); }
+ void dsub(parameter dst, parameter src1, parameter src2) { configure(OP_SUB, 8, dst, src1, src2); }
+ void dsubb(parameter dst, parameter src1, parameter src2) { configure(OP_SUBB, 8, dst, src1, src2); }
+ void dcmp(parameter src1, parameter src2) { configure(OP_CMP, 8, src1, src2); }
+ void dmulu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULU, 8, dst, edst, src1, src2); }
+ void dmuls(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULS, 8, dst, edst, src1, src2); }
+ void ddivu(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVU, 8, dst, edst, src1, src2); }
+ void ddivs(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_DIVS, 8, dst, edst, src1, src2); }
+ void dand(parameter dst, parameter src1, parameter src2) { configure(OP_AND, 8, dst, src1, src2); }
+ void dtest(parameter src1, parameter src2) { configure(OP_TEST, 8, src1, src2); }
+ void dor(parameter dst, parameter src1, parameter src2) { configure(OP_OR, 8, dst, src1, src2); }
+ void dxor(parameter dst, parameter src1, parameter src2) { configure(OP_XOR, 8, dst, src1, src2); }
+ void dlzcnt(parameter dst, parameter src) { configure(OP_LZCNT, 8, dst, src); }
+ void dbswap(parameter dst, parameter src) { configure(OP_BSWAP, 8, dst, src); }
+ void dshl(parameter dst, parameter src, parameter count) { configure(OP_SHL, 8, dst, src, count); }
+ void dshr(parameter dst, parameter src, parameter count) { configure(OP_SHR, 8, dst, src, count); }
+ void dsar(parameter dst, parameter src, parameter count) { configure(OP_SAR, 8, dst, src, count); }
+ void drol(parameter dst, parameter src, parameter count) { configure(OP_ROL, 8, dst, src, count); }
+ void drolc(parameter dst, parameter src, parameter count) { configure(OP_ROLC, 8, dst, src, count); }
+ void dror(parameter dst, parameter src, parameter count) { configure(OP_ROR, 8, dst, src, count); }
+ void drorc(parameter dst, parameter src, parameter count) { configure(OP_RORC, 8, dst, src, count); }
+
+ // 32-bit floating point operations
+ void fsload(parameter dst, const void *base, parameter index) { configure(OP_FLOAD, 4, dst, parameter::make_memory(base), index); }
+ void fsstore(void *base, parameter index, parameter src1) { configure(OP_FSTORE, 4, parameter::make_memory(base), index, src1); }
+ void fsread(parameter dst, parameter src1, memory_space space) { configure(OP_FREAD, 4, dst, src1, parameter(SIZE_SHORT, space)); }
+ void fswrite(parameter dst, parameter src1, memory_space space) { configure(OP_FWRITE, 4, dst, src1, parameter(SIZE_SHORT, space)); }
+ void fsmov(parameter dst, parameter src1) { configure(OP_FMOV, 4, dst, src1); }
+ void fsmov(condition_t cond, parameter dst, parameter src1) { configure(OP_FMOV, 4, dst, src1, cond); }
+ void fstoint(parameter dst, parameter src1, operand_size size, float_rounding_mode round) { configure(OP_FTOINT, 4, dst, src1, parameter::make_size(size), parameter::make_rounding(round)); }
+ void fsfrint(parameter dst, parameter src1, operand_size size) { configure(OP_FFRINT, 4, dst, src1, parameter::make_size(size)); }
+ void fsfrflt(parameter dst, parameter src1, operand_size size) { configure(OP_FFRFLT, 4, dst, src1, parameter::make_size(size)); }
+ void fsadd(parameter dst, parameter src1, parameter src2) { configure(OP_FADD, 4, dst, src1, src2); }
+ void fssub(parameter dst, parameter src1, parameter src2) { configure(OP_FSUB, 4, dst, src1, src2); }
+ void fscmp(parameter src1, parameter src2) { configure(OP_FCMP, 4, src1, src2); }
+ void fsmul(parameter dst, parameter src1, parameter src2) { configure(OP_FMUL, 4, dst, src1, src2); }
+ void fsdiv(parameter dst, parameter src1, parameter src2) { configure(OP_FDIV, 4, dst, src1, src2); }
+ void fsneg(parameter dst, parameter src1) { configure(OP_FNEG, 4, dst, src1); }
+ void fsabs(parameter dst, parameter src1) { configure(OP_FABS, 4, dst, src1); }
+ void fssqrt(parameter dst, parameter src1) { configure(OP_FSQRT, 4, dst, src1); }
+ void fsrecip(parameter dst, parameter src1) { configure(OP_FRECIP, 4, dst, src1); }
+ void fsrsqrt(parameter dst, parameter src1) { configure(OP_FRSQRT, 4, dst, src1); }
+
+ // 64-bit floating point operations
+ void fdload(parameter dst, const void *base, parameter index) { configure(OP_FLOAD, 8, dst, parameter::make_memory(base), index); }
+ void fdstore(void *base, parameter index, parameter src1) { configure(OP_FSTORE, 8, parameter::make_memory(base), index, src1); }
+ void fdread(parameter dst, parameter src1, memory_space space) { configure(OP_FREAD, 8, dst, src1, parameter(SIZE_DOUBLE, space)); }
+ void fdwrite(parameter dst, parameter src1, memory_space space) { configure(OP_FWRITE, 8, dst, src1, parameter(SIZE_DOUBLE, space)); }
+ void fdmov(parameter dst, parameter src1) { configure(OP_FMOV, 8, dst, src1); }
+ void fdmov(condition_t cond, parameter dst, parameter src1) { configure(OP_FMOV, 8, dst, src1, cond); }
+ void fdtoint(parameter dst, parameter src1, operand_size size, float_rounding_mode round) { configure(OP_FTOINT, 8, dst, src1, parameter::make_size(size), parameter::make_rounding(round)); }
+ void fdfrint(parameter dst, parameter src1, operand_size size) { configure(OP_FFRINT, 8, dst, src1, parameter::make_size(size)); }
+ void fdfrflt(parameter dst, parameter src1, operand_size size) { configure(OP_FFRFLT, 8, dst, src1, parameter::make_size(size)); }
+ void fdrnds(parameter dst, parameter src1) { configure(OP_FRNDS, 8, dst, src1); }
+ void fdadd(parameter dst, parameter src1, parameter src2) { configure(OP_FADD, 8, dst, src1, src2); }
+ void fdsub(parameter dst, parameter src1, parameter src2) { configure(OP_FSUB, 8, dst, src1, src2); }
+ void fdcmp(parameter src1, parameter src2) { configure(OP_FCMP, 8, src1, src2); }
+ void fdmul(parameter dst, parameter src1, parameter src2) { configure(OP_FMUL, 8, dst, src1, src2); }
+ void fddiv(parameter dst, parameter src1, parameter src2) { configure(OP_FDIV, 8, dst, src1, src2); }
+ void fdneg(parameter dst, parameter src1) { configure(OP_FNEG, 8, dst, src1); }
+ void fdabs(parameter dst, parameter src1) { configure(OP_FABS, 8, dst, src1); }
+ void fdsqrt(parameter dst, parameter src1) { configure(OP_FSQRT, 8, dst, src1); }
+ void fdrecip(parameter dst, parameter src1) { configure(OP_FRECIP, 8, dst, src1); }
+ void fdrsqrt(parameter dst, parameter src1) { configure(OP_FRSQRT, 8, dst, src1); }
+
+ // constants
+ static const int MAX_PARAMS = 4;
+
+ private:
+ // internal configuration
+ void configure(opcode_t op, UINT8 size, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, parameter p1, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, condition_t cond = COND_ALWAYS);
+ void configure(opcode_t op, UINT8 size, parameter p0, parameter p1, parameter p2, parameter p3, condition_t cond = COND_ALWAYS);
+
+ // opcode validation and simplification
+ void validate();
+ void convert_to_mov_immediate(UINT64 immediate) { m_opcode = OP_MOV; m_numparams = 2; m_param[1] = immediate; }
+ void convert_to_mov_param(int pnum) { m_opcode = OP_MOV; m_numparams = 2; m_param[1] = m_param[pnum]; }
+
+ // internal state
+ opcode_t m_opcode; // opcode
+ condition_t m_condition; // condition
+ UINT8 m_flags; // flags
+ UINT8 m_size; // operation size
+ UINT8 m_numparams; // number of parameters
+ parameter m_param[MAX_PARAMS];// up to 4 parameters
+
+ static const opcode_info s_opcode_info_table[OP_MAX];
+ };
+
+ // structure describing rules for parameter encoding
+ struct parameter_info
+ {
+ UINT8 output; // input or output?
+ UINT8 size; // size of the parameter
+ UINT16 typemask; // types allowed
+ };
+
+ // global inline functions to specify a register parameter by index
+ inline parameter ireg(int n) { return parameter::make_ireg(REG_I0 + n); }
+ inline parameter freg(int n) { return parameter::make_freg(REG_F0 + n); }
+ inline parameter vreg(int n) { return parameter::make_vreg(REG_V0 + n); }
+ inline parameter mapvar(int n) { return parameter::make_mapvar(MAPVAR_M0 + n); }
+
+ // global inline functions to define memory parameters
+ inline parameter mem(const void *ptr) { return parameter::make_memory(ptr); }
+
+ // global register objects for direct access
+ const parameter I0(parameter::make_ireg(REG_I0 + 0));
+ const parameter I1(parameter::make_ireg(REG_I0 + 1));
+ const parameter I2(parameter::make_ireg(REG_I0 + 2));
+ const parameter I3(parameter::make_ireg(REG_I0 + 3));
+ const parameter I4(parameter::make_ireg(REG_I0 + 4));
+ const parameter I5(parameter::make_ireg(REG_I0 + 5));
+ const parameter I6(parameter::make_ireg(REG_I0 + 6));
+ const parameter I7(parameter::make_ireg(REG_I0 + 7));
+ const parameter I8(parameter::make_ireg(REG_I0 + 8));
+ const parameter I9(parameter::make_ireg(REG_I0 + 9));
+
+ const parameter F0(parameter::make_freg(REG_F0 + 0));
+ const parameter F1(parameter::make_freg(REG_F0 + 1));
+ const parameter F2(parameter::make_freg(REG_F0 + 2));
+ const parameter F3(parameter::make_freg(REG_F0 + 3));
+ const parameter F4(parameter::make_freg(REG_F0 + 4));
+ const parameter F5(parameter::make_freg(REG_F0 + 5));
+ const parameter F6(parameter::make_freg(REG_F0 + 6));
+ const parameter F7(parameter::make_freg(REG_F0 + 7));
+ const parameter F8(parameter::make_freg(REG_F0 + 8));
+ const parameter F9(parameter::make_freg(REG_F0 + 9));
+
+ const parameter V0(parameter::make_vreg(REG_V0 + 0));
+ const parameter V1(parameter::make_vreg(REG_V0 + 1));
+ const parameter V2(parameter::make_vreg(REG_V0 + 2));
+ const parameter V3(parameter::make_vreg(REG_V0 + 3));
+ const parameter V4(parameter::make_vreg(REG_V0 + 4));
+ const parameter V5(parameter::make_vreg(REG_V0 + 5));
+ const parameter V6(parameter::make_vreg(REG_V0 + 6));
+ const parameter V7(parameter::make_vreg(REG_V0 + 7));
+ const parameter V8(parameter::make_vreg(REG_V0 + 8));
+ const parameter V9(parameter::make_vreg(REG_V0 + 9));
+
+ const parameter M0(parameter::make_mapvar(MAPVAR_M0 + 0));
+ const parameter M1(parameter::make_mapvar(MAPVAR_M0 + 1));
+ const parameter M2(parameter::make_mapvar(MAPVAR_M0 + 2));
+ const parameter M3(parameter::make_mapvar(MAPVAR_M0 + 3));
+ const parameter M4(parameter::make_mapvar(MAPVAR_M0 + 4));
+ const parameter M5(parameter::make_mapvar(MAPVAR_M0 + 5));
+ const parameter M6(parameter::make_mapvar(MAPVAR_M0 + 6));
+ const parameter M7(parameter::make_mapvar(MAPVAR_M0 + 7));
+ const parameter M8(parameter::make_mapvar(MAPVAR_M0 + 8));
+ const parameter M9(parameter::make_mapvar(MAPVAR_M0 + 9));
+};
+
+
+#endif /* __UML_H__ */