mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
Fixed various recompiler issues and added functionality: (#13108)
* cpu/uml.cpp: Added BREAK, SETFLGS, MULSLW and MULULW opcodes. * cpu/uml.cpp: Limit range of immediate shift count arguments for consistency. * cpu/uml.cpp: Fix simplification of multiplication and division operations. * cpu/drcbec.cpp: Added more methods of accessing OP_CARRY. * cpu/drcbec.cpp: Fixed flag calculation for BSWAP and MULS opcodes. * cpu/drcbec.cpp: Made calculation for shift and rotation opcodes consistent. * cpu/drcbec.cpp: Return mapvar register ID instead of value for mapvars. * cpu/drcbex64.cpp, cpu/drcbex86.cpp: Fixed bugs in various opcodes to make them behave like the C backend. * cpu/drcbex64.cpp: Fixed SAVE, RESTORE and SETFMOD. * cpu/powerpc: Implement MULLWx and MULLWOx using the new MULSLW opcode.
This commit is contained in:
parent
ea130bcb8e
commit
2a0ae18957
@ -181,6 +181,7 @@ enum
|
||||
// compute C and V flags for 32-bit add/subtract
|
||||
#define FLAGS32_C_ADD(a,b) ((uint32_t)~(a) < (uint32_t)(b))
|
||||
#define FLAGS32_C_SUB(a,b) ((uint32_t)(b) > (uint32_t)(a))
|
||||
#define FLAGS32_C_SUBC(a,b,c) (((uint32_t)(c) != 0 && ((uint32_t)(b) + (uint32_t)(c)) == 0) || (uint32_t)(b) + (uint32_t)(c) > (uint32_t)(a))
|
||||
#define FLAGS32_V_SUB(r,a,b) (((((a) ^ (b)) & ((a) ^ (r))) >> 30) & FLAG_V)
|
||||
#define FLAGS32_V_ADD(r,a,b) (((~((a) ^ (b)) & ((a) ^ (r))) >> 30) & FLAG_V)
|
||||
|
||||
@ -188,10 +189,12 @@ enum
|
||||
#define FLAGS32_NZ(v) ((((v) >> 28) & FLAG_S) | (((uint32_t)(v) == 0) << 2))
|
||||
#define FLAGS32_NZCV_ADD(r,a,b) (FLAGS32_NZ(r) | FLAGS32_C_ADD(a,b) | FLAGS32_V_ADD(r,a,b))
|
||||
#define FLAGS32_NZCV_SUB(r,a,b) (FLAGS32_NZ(r) | FLAGS32_C_SUB(a,b) | FLAGS32_V_SUB(r,a,b))
|
||||
#define FLAGS32_NZCV_SUBC(r,a,b,c) (FLAGS32_NZ(r) | FLAGS32_C_SUBC(a,b,c) | FLAGS32_V_SUB(r,a,b))
|
||||
|
||||
// compute C and V flags for 64-bit add/subtract
|
||||
#define FLAGS64_C_ADD(a,b) ((uint64_t)~(a) < (uint64_t)(b))
|
||||
#define FLAGS64_C_SUB(a,b) ((uint64_t)(b) > (uint64_t)(a))
|
||||
#define FLAGS64_C_SUBC(a,b,c) (((uint64_t)(c) != 0 && ((uint64_t)(b) + (uint64_t)(c)) == 0) || (uint64_t)(b) + (uint64_t)(c) > (uint64_t)(a))
|
||||
#define FLAGS64_V_SUB(r,a,b) (((((a) ^ (b)) & ((a) ^ (r))) >> 62) & FLAG_V)
|
||||
#define FLAGS64_V_ADD(r,a,b) (((~((a) ^ (b)) & ((a) ^ (r))) >> 62) & FLAG_V)
|
||||
|
||||
@ -199,6 +202,7 @@ enum
|
||||
#define FLAGS64_NZ(v) ((((v) >> 60) & FLAG_S) | (((uint64_t)(v) == 0) << 2))
|
||||
#define FLAGS64_NZCV_ADD(r,a,b) (FLAGS64_NZ(r) | FLAGS64_C_ADD(a,b) | FLAGS64_V_ADD(r,a,b))
|
||||
#define FLAGS64_NZCV_SUB(r,a,b) (FLAGS64_NZ(r) | FLAGS64_C_SUB(a,b) | FLAGS64_V_SUB(r,a,b))
|
||||
#define FLAGS64_NZCV_SUBC(r,a,b,c) (FLAGS64_NZ(r) | FLAGS64_C_SUBC(a,b,c) | FLAGS64_V_SUB(r,a,b))
|
||||
|
||||
|
||||
|
||||
@ -359,9 +363,10 @@ void drcbe_c::generate(drcuml_block &block, const instruction *instlist, uint32_
|
||||
m_labels.set_codeptr(inst.param(0).label(), (drccodeptr)dst);
|
||||
break;
|
||||
|
||||
// ignore COMMENT and NOP opcodes
|
||||
// ignore COMMENT, NOP, and BREAK opcodes
|
||||
case OP_COMMENT:
|
||||
case OP_NOP:
|
||||
case OP_BREAK:
|
||||
break;
|
||||
|
||||
// when we hit a MAPVAR opcode, log the change for the current PC
|
||||
@ -518,6 +523,10 @@ int drcbe_c::execute(code_handle &entry)
|
||||
// these opcodes should be processed at compile-time only
|
||||
fatalerror("Unexpected opcode\n");
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_BREAK, 4, 0):
|
||||
osd_break_into_debugger("break from drc");
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_DEBUG, 4, 0): // DEBUG pc
|
||||
if (m_device.machine().debug_flags & DEBUG_FLAG_CALL_HOOK)
|
||||
m_device.debug()->instruction_hook(PARAM0);
|
||||
@ -628,6 +637,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
PARAM0 = flags & PARAM1;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_SETFLGS, 4, 0): // SETFLGS src
|
||||
case MAKE_OPCODE_SHORT(OP_SETFLGS, 4, 1):
|
||||
flags = PARAM0;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_SAVE, 4, 0): // SAVE dst
|
||||
*inst[0].state = m_state;
|
||||
inst[0].state->flags = flags;
|
||||
@ -826,7 +840,8 @@ int drcbe_c::execute(code_handle &entry)
|
||||
m_space[PARAM3]->write_dword(PARAM0, PARAM1, PARAM2);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_CARRY, 4, 1): // CARRY src,bitnum
|
||||
case MAKE_OPCODE_SHORT(OP_CARRY, 4, 0): // CARRY src,bitnum
|
||||
case MAKE_OPCODE_SHORT(OP_CARRY, 4, 1):
|
||||
flags = (flags & ~FLAG_C) | ((PARAM0 >> (PARAM1 & 31)) & FLAG_C);
|
||||
break;
|
||||
|
||||
@ -930,16 +945,7 @@ int drcbe_c::execute(code_handle &entry)
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_SUBB, 4, 1):
|
||||
temp32 = PARAM1 - PARAM2 - (flags & FLAG_C);
|
||||
temp64 = (uint64_t)PARAM1 - (uint64_t)PARAM2 - (uint64_t)(flags & FLAG_C);
|
||||
if (PARAM2 + 1 != 0)
|
||||
flags = FLAGS32_NZCV_SUB(temp32, PARAM1, PARAM2 + (flags & FLAG_C));
|
||||
else
|
||||
{
|
||||
flags = FLAGS32_NZCV_SUB(temp32, PARAM1 - (flags & FLAG_C), PARAM2);
|
||||
flags &= ~(FLAG_C | FLAG_V);
|
||||
flags |= ((temp64>>32) & 1) ? FLAG_C : 0;
|
||||
flags |= (((PARAM1) ^ (PARAM2)) & ((PARAM1) ^ (temp64)) & 0x80000000) ? FLAG_V : 0;
|
||||
}
|
||||
flags = FLAGS32_NZCV_SUBC(temp32, PARAM1, PARAM2, flags & FLAG_C);
|
||||
PARAM0 = temp32;
|
||||
break;
|
||||
|
||||
@ -964,6 +970,20 @@ int drcbe_c::execute(code_handle &entry)
|
||||
flags |= FLAG_V;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULULW, 4, 0): // MULULW dst,src1,src2[,f]
|
||||
temp64 = mulu_32x32(PARAM1, PARAM2);
|
||||
PARAM0 = (uint32_t)temp64;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULULW, 4, 1):
|
||||
temp64 = mulu_32x32(PARAM1, PARAM2);
|
||||
temp32 = (uint32_t)temp64;
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
PARAM0 = temp32;
|
||||
if (temp64 > temp32)
|
||||
flags |= FLAG_V;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULS, 4, 0): // MULS dst,edst,src1,src2[,f]
|
||||
temp64 = mul_32x32(PARAM2, PARAM3);
|
||||
PARAM1 = temp64 >> 32;
|
||||
@ -972,11 +992,24 @@ int drcbe_c::execute(code_handle &entry)
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULS, 4, 1):
|
||||
temp64 = mul_32x32(PARAM2, PARAM3);
|
||||
temp32 = (int32_t)temp64;
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
PARAM1 = temp64 >> 32;
|
||||
PARAM0 = (uint32_t)temp64;
|
||||
if (temp64 != (int32_t)temp64)
|
||||
if ((int64_t)temp64 != (int32_t)temp64)
|
||||
flags |= FLAG_V;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULSLW, 4, 0): // MULSLW dst,src1,src2[,f]
|
||||
temp64 = mul_32x32(PARAM1, PARAM2);
|
||||
PARAM0 = (int32_t)temp64;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULSLW, 4, 1):
|
||||
temp64 = mul_32x32(PARAM1, PARAM2);
|
||||
temp32 = (int32_t)temp64;
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
PARAM0 = temp32;
|
||||
if ((int64_t)temp64 != (int32_t)temp64)
|
||||
flags |= FLAG_V;
|
||||
break;
|
||||
|
||||
@ -1084,8 +1117,8 @@ int drcbe_c::execute(code_handle &entry)
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_BSWAP, 4, 1):
|
||||
temp32 = PARAM1;
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
PARAM0 = swapendian_int32(temp32);
|
||||
flags = FLAGS32_NZ(PARAM0);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_SHL, 4, 0): // SHL dst,src,count[,f]
|
||||
@ -1154,6 +1187,8 @@ int drcbe_c::execute(code_handle &entry)
|
||||
PARAM0 = (PARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (PARAM1 >> (33 - shift));
|
||||
else if (shift == 1)
|
||||
PARAM0 = (PARAM1 << shift) | (flags & FLAG_C);
|
||||
else
|
||||
PARAM0 = PARAM1;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_ROLC, 4, 1):
|
||||
@ -1164,8 +1199,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
temp32 = (PARAM1 << shift) | (flags & FLAG_C);
|
||||
else
|
||||
temp32 = PARAM1;
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
if (shift != 0) flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
flags |= ((PARAM1 << (shift - 1)) >> 31) & FLAG_C;
|
||||
}
|
||||
PARAM0 = temp32;
|
||||
break;
|
||||
|
||||
@ -1176,8 +1214,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
case MAKE_OPCODE_SHORT(OP_ROR, 4, 1):
|
||||
shift = PARAM2 & 31;
|
||||
temp32 = rotr_32(PARAM1, shift);
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
|
||||
}
|
||||
PARAM0 = temp32;
|
||||
break;
|
||||
|
||||
@ -1187,6 +1228,8 @@ int drcbe_c::execute(code_handle &entry)
|
||||
PARAM0 = (PARAM1 >> shift) | (((flags & FLAG_C) << 31) >> (shift - 1)) | (PARAM1 << (33 - shift));
|
||||
else if (shift == 1)
|
||||
PARAM0 = (PARAM1 >> shift) | ((flags & FLAG_C) << 31);
|
||||
else
|
||||
PARAM0 = PARAM1;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_RORC, 4, 1):
|
||||
@ -1197,8 +1240,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
temp32 = (PARAM1 >> shift) | ((flags & FLAG_C) << 31);
|
||||
else
|
||||
temp32 = PARAM1;
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
if (shift != 0) flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS32_NZ(temp32);
|
||||
flags |= (PARAM1 >> (shift - 1)) & FLAG_C;
|
||||
}
|
||||
PARAM0 = temp32;
|
||||
break;
|
||||
|
||||
@ -1454,6 +1500,7 @@ int drcbe_c::execute(code_handle &entry)
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_CARRY, 8, 0): // DCARRY src,bitnum
|
||||
case MAKE_OPCODE_SHORT(OP_CARRY, 8, 1):
|
||||
flags = (flags & ~FLAG_C) | ((DPARAM0 >> (DPARAM1 & 63)) & FLAG_C);
|
||||
break;
|
||||
|
||||
@ -1559,10 +1606,7 @@ int drcbe_c::execute(code_handle &entry)
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_SUBB, 8, 1):
|
||||
temp64 = DPARAM1 - DPARAM2 - (flags & FLAG_C);
|
||||
if (DPARAM2 + 1 != 0)
|
||||
flags = FLAGS64_NZCV_SUB(temp64, DPARAM1, DPARAM2 + (flags & FLAG_C));
|
||||
else
|
||||
flags = FLAGS64_NZCV_SUB(temp64, DPARAM1 - (flags & FLAG_C), DPARAM2);
|
||||
flags = FLAGS64_NZCV_SUBC(temp64, DPARAM1, DPARAM2, flags & FLAG_C);
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -1579,6 +1623,15 @@ int drcbe_c::execute(code_handle &entry)
|
||||
flags = dmulu(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, true);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULULW, 8, 0): // DMULULW dst,src1,src2[,f]
|
||||
dmulu(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, false);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULULW, 8, 1):
|
||||
flags = dmulu(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, true);
|
||||
flags = FLAGS64_NZ(DPARAM0) | (flags & FLAG_V);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULS, 8, 0): // DMULS dst,edst,src1,src2[,f]
|
||||
dmuls(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, false);
|
||||
break;
|
||||
@ -1587,6 +1640,15 @@ int drcbe_c::execute(code_handle &entry)
|
||||
flags = dmuls(*inst[0].puint64, *inst[1].puint64, DPARAM2, DPARAM3, true);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULSLW, 8, 0): // DMULSLW dst,src1,src2[,f]
|
||||
dmuls(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, false);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_MULSLW, 8, 1):
|
||||
flags = dmuls(*inst[0].puint64, *inst[0].puint64, DPARAM1, DPARAM2, true);
|
||||
flags = FLAGS64_NZ(DPARAM0) | (flags & FLAG_V);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_DIVU, 8, 0): // DDIVU dst,edst,src1,src2[,f]
|
||||
if (DPARAM3 != 0)
|
||||
{
|
||||
@ -1691,8 +1753,8 @@ int drcbe_c::execute(code_handle &entry)
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_BSWAP, 8, 1):
|
||||
temp64 = DPARAM1;
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
DPARAM0 = swapendian_int64(temp64);
|
||||
flags = FLAGS64_NZ(DPARAM0);
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_SHL, 8, 0): // DSHL dst,src,count[,f]
|
||||
@ -1702,8 +1764,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
case MAKE_OPCODE_SHORT(OP_SHL, 8, 1):
|
||||
shift = DPARAM2 & 63;
|
||||
temp64 = DPARAM1 << shift;
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
|
||||
}
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -1714,8 +1779,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
case MAKE_OPCODE_SHORT(OP_SHR, 8, 1):
|
||||
shift = DPARAM2 & 63;
|
||||
temp64 = DPARAM1 >> shift;
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
}
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -1725,9 +1793,12 @@ int drcbe_c::execute(code_handle &entry)
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_SAR, 8, 1):
|
||||
shift = DPARAM2 & 63;
|
||||
temp64 = (int32_t)DPARAM1 >> shift;
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
temp64 = (int64_t)DPARAM1 >> shift;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
}
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -1738,8 +1809,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
case MAKE_OPCODE_SHORT(OP_ROL, 8, 1):
|
||||
shift = DPARAM2 & 63;
|
||||
temp64 = rotl_64(DPARAM1, shift);
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
|
||||
}
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -1749,6 +1823,8 @@ int drcbe_c::execute(code_handle &entry)
|
||||
DPARAM0 = (DPARAM1 << shift) | ((flags & FLAG_C) << (shift - 1)) | (DPARAM1 >> (65 - shift));
|
||||
else if (shift == 1)
|
||||
DPARAM0 = (DPARAM1 << shift) | (flags & FLAG_C);
|
||||
else
|
||||
DPARAM0 = DPARAM1;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_ROLC, 8, 1):
|
||||
@ -1759,8 +1835,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
temp64 = (DPARAM1 << shift) | (flags & FLAG_C);
|
||||
else
|
||||
temp64 = DPARAM1;
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
if (shift != 0) flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
flags |= ((DPARAM1 << (shift - 1)) >> 63) & FLAG_C;
|
||||
}
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -1771,8 +1850,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
case MAKE_OPCODE_SHORT(OP_ROR, 8, 1):
|
||||
shift = DPARAM2 & 63;
|
||||
temp64 = rotr_64(DPARAM1, shift);
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
}
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -1782,6 +1864,8 @@ int drcbe_c::execute(code_handle &entry)
|
||||
DPARAM0 = (DPARAM1 >> shift) | ((((uint64_t)flags & FLAG_C) << 63) >> (shift - 1)) | (DPARAM1 << (65 - shift));
|
||||
else if (shift == 1)
|
||||
DPARAM0 = (DPARAM1 >> shift) | (((uint64_t)flags & FLAG_C) << 63);
|
||||
else
|
||||
DPARAM0 = DPARAM1;
|
||||
break;
|
||||
|
||||
case MAKE_OPCODE_SHORT(OP_RORC, 8, 1):
|
||||
@ -1792,8 +1876,11 @@ int drcbe_c::execute(code_handle &entry)
|
||||
temp64 = (DPARAM1 >> shift) | (((uint64_t)flags & FLAG_C) << 63);
|
||||
else
|
||||
temp64 = DPARAM1;
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
if (shift != 0) flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
if (shift != 0)
|
||||
{
|
||||
flags = FLAGS64_NZ(temp64);
|
||||
flags |= (DPARAM1 >> (shift - 1)) & FLAG_C;
|
||||
}
|
||||
DPARAM0 = temp64;
|
||||
break;
|
||||
|
||||
@ -2108,7 +2195,6 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int
|
||||
{
|
||||
drcbec_instruction *dst = *dstptr;
|
||||
void *immed = *immedptr;
|
||||
parameter temp_param;
|
||||
|
||||
switch (param.type())
|
||||
{
|
||||
@ -2145,8 +2231,7 @@ void drcbe_c::output_parameter(drcbec_instruction **dstptr, void **immedptr, int
|
||||
|
||||
// convert mapvars to immediates
|
||||
case parameter::PTYPE_MAPVAR:
|
||||
temp_param = m_map.get_last_value(param.mapvar());
|
||||
return output_parameter(dstptr, immedptr, size, temp_param);
|
||||
return output_parameter(dstptr, immedptr, size, param.mapvar());
|
||||
|
||||
// memory just points to the memory
|
||||
case parameter::PTYPE_MEMORY:
|
||||
@ -2239,7 +2324,7 @@ int drcbe_c::dmulu(uint64_t &dstlo, uint64_t &dsthi, uint64_t src1, uint64_t src
|
||||
// store the results
|
||||
dsthi = hi;
|
||||
dstlo = lo;
|
||||
return ((hi >> 60) & FLAG_S) | ((dsthi != 0) << 1);
|
||||
return ((hi >> 60) & FLAG_S) | ((hi != 0) << 1);
|
||||
}
|
||||
|
||||
|
||||
@ -2290,7 +2375,7 @@ int drcbe_c::dmuls(uint64_t &dstlo, uint64_t &dsthi, int64_t src1, int64_t src2,
|
||||
// store the results
|
||||
dsthi = hi;
|
||||
dstlo = lo;
|
||||
return ((hi >> 60) & FLAG_S) | ((dsthi != ((int64_t)lo >> 63)) << 1);
|
||||
return ((hi >> 60) & FLAG_S) | ((hi != ((int64_t)lo >> 63)) << 1);
|
||||
}
|
||||
|
||||
uint32_t drcbe_c::tzcount32(uint32_t value)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -135,6 +135,7 @@ private:
|
||||
void op_mapvar(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
|
||||
void op_nop(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_break(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_debug(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_exit(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_hashjmp(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
@ -149,6 +150,7 @@ private:
|
||||
void op_getfmod(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_getexp(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_getflgs(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_setflgs(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_save(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_restore(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
|
||||
@ -171,7 +173,9 @@ private:
|
||||
void op_subc(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_cmp(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_mulu(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_mululw(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_muls(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_mulslw(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_divu(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_divs(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_and(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
@ -208,7 +212,7 @@ private:
|
||||
// alu and shift operation helpers
|
||||
static bool ones(u64 const value, unsigned const size) noexcept { return (size == 4) ? u32(value) == 0xffffffffU : value == 0xffffffff'ffffffffULL; }
|
||||
void alu_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, asmjit::Operand const &dst, be_parameter const ¶m, std::function<bool(asmjit::x86::Assembler &a, asmjit::Operand const &dst, be_parameter const &src)> optimize = [](asmjit::x86::Assembler &a, asmjit::Operand dst, be_parameter const &src) { return false; });
|
||||
void shift_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, asmjit::Operand const &dst, be_parameter const ¶m);
|
||||
void shift_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, size_t opsize, asmjit::Operand const &dst, be_parameter const ¶m, bool update_flags);
|
||||
|
||||
// parameter helpers
|
||||
void mov_reg_param(asmjit::x86::Assembler &a, asmjit::x86::Gp const ®, be_parameter const ¶m, bool const keepflags = false);
|
||||
@ -225,6 +229,10 @@ private:
|
||||
void movsd_r128_p64(asmjit::x86::Assembler &a, asmjit::x86::Xmm const ®, be_parameter const ¶m);
|
||||
void movsd_p64_r128(asmjit::x86::Assembler &a, be_parameter const ¶m, asmjit::x86::Xmm const ®);
|
||||
|
||||
void calculate_status_flags(asmjit::x86::Assembler &a, uint32_t instsize, asmjit::Operand const &dst, u8 flags);
|
||||
void calculate_status_flags_mul(asmjit::x86::Assembler &a, uint32_t instsize, asmjit::x86::Gp const &lo, asmjit::x86::Gp const &hi);
|
||||
void calculate_status_flags_mul_low(asmjit::x86::Assembler &a, uint32_t instsize, asmjit::x86::Gp const &lo);
|
||||
|
||||
size_t emit(asmjit::CodeHolder &ch);
|
||||
|
||||
// internal state
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -117,6 +117,7 @@ private:
|
||||
asmjit::x86::Mem MABS(void const *base, u32 const size = 0) const { return asmjit::x86::Mem(u64(base), size); }
|
||||
void normalize_commutative(be_parameter &inner, be_parameter &outer);
|
||||
void emit_combine_z_flags(asmjit::x86::Assembler &a);
|
||||
void emit_combine_zs_flags(asmjit::x86::Assembler &a);
|
||||
void emit_combine_z_shl_flags(asmjit::x86::Assembler &a);
|
||||
void reset_last_upper_lower_reg();
|
||||
void set_last_lower_reg(asmjit::x86::Assembler &a, be_parameter const ¶m, asmjit::x86::Gp const ®lo);
|
||||
@ -134,6 +135,7 @@ private:
|
||||
void op_mapvar(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
|
||||
void op_nop(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_break(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_debug(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_exit(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_hashjmp(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
@ -148,6 +150,7 @@ private:
|
||||
void op_getfmod(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_getexp(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_getflgs(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_setflgs(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_save(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_restore(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
|
||||
@ -170,7 +173,9 @@ private:
|
||||
void op_subc(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_cmp(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_mulu(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_mululw(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_muls(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_mulslw(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_divu(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_divs(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
void op_and(asmjit::x86::Assembler &a, const uml::instruction &inst);
|
||||
@ -217,7 +222,7 @@ private:
|
||||
void emit_mov_p32_r32(asmjit::x86::Assembler &a, be_parameter const ¶m, asmjit::x86::Gp const ®);
|
||||
|
||||
void alu_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, asmjit::Operand const &dst, be_parameter const ¶m, std::function<bool(asmjit::x86::Assembler &a, asmjit::Operand const &dst, be_parameter const &src)> optimize = [](asmjit::x86::Assembler &a, asmjit::Operand dst, be_parameter const &src) { return false; });
|
||||
void shift_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, asmjit::Operand const &dst, be_parameter const ¶m, std::function<bool(asmjit::x86::Assembler &a, asmjit::Operand const &dst, be_parameter const &src)> optimize);
|
||||
void shift_op_param(asmjit::x86::Assembler &a, asmjit::x86::Inst::Id const opcode, size_t opsize, asmjit::Operand const &dst, be_parameter const ¶m, std::function<bool(asmjit::x86::Assembler &a, asmjit::Operand const &dst, be_parameter const &src)> optimize, bool update_flags);
|
||||
|
||||
// 64-bit code emission helpers
|
||||
void emit_mov_r64_p64(asmjit::x86::Assembler &a, asmjit::x86::Gp const ®lo, asmjit::x86::Gp const ®hi, be_parameter const ¶m);
|
||||
@ -246,11 +251,13 @@ private:
|
||||
void emit_fstp_p(asmjit::x86::Assembler &a, int size, be_parameter const ¶m);
|
||||
|
||||
// callback helpers
|
||||
static int dmulu(uint64_t &dstlo, uint64_t &dsthi, uint64_t src1, uint64_t src2, bool flags);
|
||||
static int dmuls(uint64_t &dstlo, uint64_t &dsthi, int64_t src1, int64_t src2, bool flags);
|
||||
static int dmulu(uint64_t &dstlo, uint64_t &dsthi, uint64_t src1, uint64_t src2, bool flags, bool halfmul_flags);
|
||||
static int dmuls(uint64_t &dstlo, uint64_t &dsthi, int64_t src1, int64_t src2, bool flags, bool halfmul_flags);
|
||||
static int ddivu(uint64_t &dstlo, uint64_t &dsthi, uint64_t src1, uint64_t src2);
|
||||
static int ddivs(uint64_t &dstlo, uint64_t &dsthi, int64_t src1, int64_t src2);
|
||||
|
||||
void calculate_status_flags(asmjit::x86::Assembler &a, asmjit::Operand const &dst, u8 flags);
|
||||
|
||||
size_t emit(asmjit::CodeHolder &ch);
|
||||
|
||||
// internal state
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
/* ----- Control Flow Operations ----- */
|
||||
#define UML_NOP(block) do { using namespace uml; block.append().nop(); } while (0)
|
||||
#define UML_BREAK(block) do { using namespace uml; block.append().break_(); } while (0)
|
||||
#define UML_DEBUG(block, pc) do { using namespace uml; block.append().debug(pc); } while (0)
|
||||
#define UML_EXIT(block, param) do { using namespace uml; block.append().exit(param); } while (0)
|
||||
#define UML_EXITc(block, cond, param) do { using namespace uml; block.append().exit(param, cond); } while (0)
|
||||
@ -53,6 +54,7 @@
|
||||
#define UML_GETFMOD(block, dst) do { using namespace uml; block.append().getfmod(dst); } while (0)
|
||||
#define UML_GETEXP(block, dst) do { using namespace uml; block.append().getexp(dst); } while (0)
|
||||
#define UML_GETFLGS(block, dst, flags) do { using namespace uml; block.append().getflgs(dst, flags); } while (0)
|
||||
#define UML_SETFLGS(block, flags) do { using namespace uml; block.append().setflgs(flags); } while (0)
|
||||
#define UML_SAVE(block, dst) do { using namespace uml; block.append().save(dst); } while (0)
|
||||
#define UML_RESTORE(block, src) do { using namespace uml; block.append().restore(src); } while (0)
|
||||
|
||||
@ -78,7 +80,9 @@
|
||||
#define UML_SUBB(block, dst, src1, src2) do { using namespace uml; block.append().subb(dst, src1, src2); } while (0)
|
||||
#define UML_CMP(block, src1, src2) do { using namespace uml; block.append().cmp(src1, src2); } while (0)
|
||||
#define UML_MULU(block, dst, edst, src1, src2) do { using namespace uml; block.append().mulu(dst, edst, src1, src2); } while (0)
|
||||
#define UML_MULULW(block, dst, src1, src2) do { using namespace uml; block.append().mululw(dst, src1, src2); } while (0)
|
||||
#define UML_MULS(block, dst, edst, src1, src2) do { using namespace uml; block.append().muls(dst, edst, src1, src2); } while (0)
|
||||
#define UML_MULSLW(block, dst, src1, src2) do { using namespace uml; block.append().mulslw(dst, src1, src2); } while (0)
|
||||
#define UML_DIVU(block, dst, edst, src1, src2) do { using namespace uml; block.append().divu(dst, edst, src1, src2); } while (0)
|
||||
#define UML_DIVS(block, dst, edst, src1, src2) do { using namespace uml; block.append().divs(dst, edst, src1, src2); } while (0)
|
||||
#define UML_AND(block, dst, src1, src2) do { using namespace uml; block.append()._and(dst, src1, src2); } while (0)
|
||||
@ -118,7 +122,9 @@
|
||||
#define UML_DSUBB(block, dst, src1, src2) do { using namespace uml; block.append().dsubb(dst, src1, src2); } while (0)
|
||||
#define UML_DCMP(block, src1, src2) do { using namespace uml; block.append().dcmp(src1, src2); } while (0)
|
||||
#define UML_DMULU(block, dst, edst, src1, src2) do { using namespace uml; block.append().dmulu(dst, edst, src1, src2); } while (0)
|
||||
#define UML_DMULULW(block, dst, src1, src2) do { using namespace uml; block.append().dmululw(dst, src1, src2); } while (0)
|
||||
#define UML_DMULS(block, dst, edst, src1, src2) do { using namespace uml; block.append().dmuls(dst, edst, src1, src2); } while (0)
|
||||
#define UML_DMULSLW(block, dst, src1, src2) do { using namespace uml; block.append().dmulslw(dst, src1, src2); } while (0)
|
||||
#define UML_DDIVU(block, dst, edst, src1, src2) do { using namespace uml; block.append().ddivu(dst, edst, src1, src2); } while (0)
|
||||
#define UML_DDIVS(block, dst, edst, src1, src2) do { using namespace uml; block.append().ddivs(dst, edst, src1, src2); } while (0)
|
||||
#define UML_DAND(block, dst, src1, src2) do { using namespace uml; block.append().dand(dst, src1, src2); } while (0)
|
||||
|
@ -2681,7 +2681,9 @@ bool ppc_device::generate_instruction_1f(drcuml_block &block, compiler_state *co
|
||||
|
||||
case 0x0eb: /* MULLWx */
|
||||
case 0x2eb: /* MULLWOx */
|
||||
UML_MULS(block, R32(G_RD(op)), R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // muls rd,rd,ra,rb
|
||||
// The flags are calculated based on the resulting 32-bit value from the 32x32=32 multiplication
|
||||
// reference: example 4 https://www.ibm.com/docs/en/aix/7.2?topic=set-mullw-muls-multiply-low-word-instruction
|
||||
UML_MULSLW(block, R32(G_RD(op)), R32(G_RA(op)), R32(G_RB(op))); // mulslw rd,ra,rb
|
||||
generate_compute_flags(block, desc, op & M_RC, ((op & M_OE) ? XER_OV : 0), false);// <update flags>
|
||||
return true;
|
||||
|
||||
|
@ -137,45 +137,49 @@ opcode_info const instruction::s_opcode_info_table[OP_MAX] =
|
||||
|
||||
// Control Flow Operations
|
||||
OPINFO0(NOP, "nop", 4, false, NONE, NONE, NONE)
|
||||
OPINFO1(DEBUG, "debug", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY))
|
||||
OPINFO1(DEBUG, "debug", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY)) // MAME debugger breakpoint
|
||||
OPINFO0(BREAK, "break", 4, false, NONE, NONE, NONE) // (for debugging) Issues a breakpoint exception to allow for debugging the generated assembly
|
||||
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))
|
||||
OPINFO2(EXH, "exh", 4, true, NONE, NONE, ALL, PINFO(IN, OP, HANDLE), PINFO(IN, OP, IANY)) // Call exception handler
|
||||
OPINFO1(CALLH, "callh", 4, true, NONE, NONE, ALL, PINFO(IN, OP, HANDLE)) // Call 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))
|
||||
OPINFO2(CALLC, "callc", 4, true, NONE, NONE, ALL, PINFO(IN, OP, CFUNC), PINFO(IN, OP, PTR)) // Call C function
|
||||
OPINFO2(RECOVER, "recover", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, MVAR)) // Get value from mapvar
|
||||
|
||||
// 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))
|
||||
OPINFO1(SETFMOD, "setfmod", 4, false, NONE, NONE, ALL, PINFO(IN, OP, IANY)) // Set floating point control mode
|
||||
OPINFO1(GETFMOD, "getfmod", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM)) // Get floating point control mode
|
||||
OPINFO1(GETEXP, "getexp", 4, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM)) // Get exception parameter value
|
||||
OPINFO2(GETFLGS, "getflgs", 4, false, P2, NONE, NONE, PINFO(OUT, OP, IRM), PINFO(IN, OP, IMV)) // Get status register flags
|
||||
OPINFO1(SETFLGS, "setflgs", 4, false, NONE, ALL, ALL, PINFO(IN, OP, IANY)) // (for debugging) Set status register flags
|
||||
OPINFO1(SAVE, "save", 4, false, ALL, NONE, ALL, PINFO(OUT, OP, STATE)) // Save current state to drcuml_machine_state
|
||||
OPINFO1(RESTORE, "restore", 4, false, NONE, ALL, ALL, PINFO(IN, OP, STATE)) // Load saved state from drcuml_machine_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))
|
||||
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)) // Load unsigned value from specified memory location
|
||||
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)) // Load signed value from specified memory location
|
||||
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)) // Store value to specified memory location
|
||||
OPINFO3(READ, "!read", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, IRM), PINFO(IN, 4, IANY), PINFO(IN, OP, SPSIZE)) // Read memory from emulated machine using memory space reader
|
||||
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)) // Read memory from emulated machine using memory space reader (masked)
|
||||
OPINFO3(WRITE, "!write", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, IANY), PINFO(IN, OP, SPSIZE)) // Write to emulated machine's memory using memory space writer
|
||||
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)) // Write to emulated machine's memory using memory space writer (masked)
|
||||
OPINFO2(CARRY, "!carry", 4|8, false, NONE, C, ALL, PINFO(IN, OP, IANY), PINFO(IN, OP, IANY)) // Set carry status flag on CPU
|
||||
OPINFO1(SET, "!set", 4|8, true, NONE, NONE, ALL, PINFO(OUT, OP, IRM)) // Get the state of the specified condition (e.g. calling UML_SET with COND_NZ will return 0 if the condition is not met and 1 if the condition is met)
|
||||
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))
|
||||
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)) // Rotate left + AND (see drcbec.cpp for implementation)
|
||||
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)) // Rotate left + OR (see drcbec.cpp for implementation)
|
||||
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(MULU, "!mulu", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY)) // Unsigned 32x32=64 and 64x64=128 multiplication
|
||||
OPINFO3(MULULW, "!mululw", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY)) // Unsigned 32x32=32 and 64x64=64 multiplication (overflow set based on 32x32=64 calculation but zero and sign based on 32-bit result)
|
||||
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)) // Signed 32x32=64 and 64x64=128 multiplication
|
||||
OPINFO3(MULSLW, "!mulslw", 4|8, false, NONE, SZV, ALL, PINFO(OUT, OP, IRM), PINFO(IN, OP, IANY), PINFO(IN, OP, IANY)) // Signed 32x32=32 and 64x64=64 multiplication (overflow set based on 32x32=64 calculation but zero and sign based on 32-bit result)
|
||||
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))
|
||||
@ -194,18 +198,18 @@ opcode_info const instruction::s_opcode_info_table[OP_MAX] =
|
||||
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))
|
||||
OPINFO3(FLOAD, "f#load", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, OP, PTR), PINFO(IN, 4, IANY)) // Load float/double value from specified memory location
|
||||
OPINFO3(FSTORE, "f#store", 4|8, false, NONE, NONE, ALL, PINFO(IN, OP, PTR), PINFO(IN, 4, IANY), PINFO(IN, OP, FRM)) // Save float/double value to specified memory location
|
||||
OPINFO3(FREAD, "f#read", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, 4, IANY), PINFO(IN, OP, SPSIZE)) // Read float/double value from emulated machine using memory space reader
|
||||
OPINFO3(FWRITE, "f#write", 4|8, false, NONE, NONE, ALL, PINFO(IN, 4, IANY), PINFO(IN, OP, FANY), PINFO(IN, OP, SPSIZE)) // Write float/double value to emulated machine using memory space writer
|
||||
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))
|
||||
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)) // Float/double to integer
|
||||
OPINFO3(FFRINT, "f#frint", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, IANY), PINFO(IN, OP, SIZE)) // Float/double from integer
|
||||
OPINFO3(FFRFLT, "f#frflt", 4|8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, FANY), PINFO(IN, OP, SIZE)) // Convert float to double or double to float
|
||||
OPINFO2(FRNDS, "f#rnds", 8, false, NONE, NONE, ALL, PINFO(OUT, OP, FRM), PINFO(IN, P3, FANY)) // Convert double to float and then back to double, or float to double and back to float
|
||||
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))
|
||||
OPINFO2(FCMP, "f#cmp", 4|8, false, NONE, UZC, ALL, PINFO(IN, OP, FANY), PINFO(IN, OP, FANY)) // Note: status flags except FLAG_U are undefined when comparing with NaN
|
||||
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))
|
||||
@ -213,8 +217,8 @@ opcode_info const instruction::s_opcode_info_table[OP_MAX] =
|
||||
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))
|
||||
OPINFO2(FCOPYI, "f#copyi", 4|8, false, NONE, NONE, NONE, PINFO(OUT, OP, FRM), PINFO(IN, OP, IRM))
|
||||
OPINFO2(ICOPYF, "icopyf#", 4|8, false, NONE, NONE, NONE, PINFO(OUT, OP, IRM), PINFO(IN, OP, FRM))
|
||||
OPINFO2(FCOPYI, "f#copyi", 4|8, false, NONE, NONE, NONE, PINFO(OUT, OP, FRM), PINFO(IN, OP, IRM)) // Load float/double value from integer representation (e.g. 0x3f800000 -> 1.0f)
|
||||
OPINFO2(ICOPYF, "icopyf#", 4|8, false, NONE, NONE, NONE, PINFO(OUT, OP, IRM), PINFO(IN, OP, FRM)) // Store float/double value as integer representation (e.g. 1.0f -> 0x3f800000)
|
||||
};
|
||||
|
||||
|
||||
@ -504,13 +508,26 @@ void uml::instruction::simplify()
|
||||
else if (m_param[2].is_immediate() && m_param[3].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(u32(u32(m_param[1].immediate()) * u32(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(u32(u32(m_param[2].immediate()) * u32(m_param[3].immediate())));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(u64(u64(m_param[1].immediate()) * u64(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(u64(u64(m_param[2].immediate()) * u64(m_param[3].immediate())));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// MULULW: convert simple form to MOV if immediate, or if multiplying by 0
|
||||
case OP_MULULW:
|
||||
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())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(u32(u32(m_param[1].immediate()) * u32(m_param[2].immediate())));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(u64(u64(m_param[1].immediate()) * u64(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])
|
||||
@ -520,13 +537,26 @@ void uml::instruction::simplify()
|
||||
else if (m_param[2].is_immediate() && m_param[3].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(s32(s32(m_param[1].immediate()) * s32(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(s32(s32(m_param[2].immediate()) * s32(m_param[3].immediate())));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(s64(s64(m_param[1].immediate()) * s64(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(s64(s64(m_param[2].immediate()) * s64(m_param[3].immediate())));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// MULSLW: convert simple form to MOV if immediate, or if multiplying by 0
|
||||
case OP_MULSLW:
|
||||
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())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(s32(s32(m_param[1].immediate()) * s32(m_param[2].immediate())));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(s64(s64(m_param[1].immediate()) * s64(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))
|
||||
@ -536,9 +566,9 @@ void uml::instruction::simplify()
|
||||
else if (m_param[2].is_immediate() && m_param[3].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(u32(u32(m_param[1].immediate()) / u32(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(u32(u32(m_param[2].immediate()) / u32(m_param[3].immediate())));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(u64(u64(m_param[1].immediate()) / u64(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(u64(u64(m_param[2].immediate()) / u64(m_param[3].immediate())));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -552,9 +582,9 @@ void uml::instruction::simplify()
|
||||
else if (m_param[2].is_immediate() && m_param[3].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(s32(s32(m_param[1].immediate()) / s32(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(s32(s32(m_param[2].immediate()) / s32(m_param[3].immediate())));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(s64(s64(m_param[1].immediate()) / s64(m_param[2].immediate())));
|
||||
convert_to_mov_immediate(s64(s64(m_param[2].immediate()) / s64(m_param[3].immediate())));
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -624,7 +654,12 @@ void uml::instruction::simplify()
|
||||
// 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());
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(u32(m_param[1].immediate()) << (m_param[2].immediate() & 31));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(u64(m_param[1].immediate()) << (m_param[2].immediate() & 63));
|
||||
}
|
||||
else if (m_param[2].is_immediate_value(0))
|
||||
convert_to_mov_param(1);
|
||||
break;
|
||||
@ -634,9 +669,9 @@ void uml::instruction::simplify()
|
||||
if (m_param[1].is_immediate() && m_param[2].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(u32(m_param[1].immediate()) >> m_param[2].immediate());
|
||||
convert_to_mov_immediate(u32(m_param[1].immediate()) >> (m_param[2].immediate() & 31));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(u64(m_param[1].immediate()) >> m_param[2].immediate());
|
||||
convert_to_mov_immediate(u64(m_param[1].immediate()) >> (m_param[2].immediate() & 63));
|
||||
}
|
||||
else if (m_param[2].is_immediate_value(0))
|
||||
convert_to_mov_param(1);
|
||||
@ -647,9 +682,9 @@ void uml::instruction::simplify()
|
||||
if (m_param[1].is_immediate() && m_param[2].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(s32(m_param[1].immediate()) >> m_param[2].immediate());
|
||||
convert_to_mov_immediate(s32(m_param[1].immediate()) >> (m_param[2].immediate() & 31));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(s64(m_param[1].immediate()) >> m_param[2].immediate());
|
||||
convert_to_mov_immediate(s64(m_param[1].immediate()) >> (m_param[2].immediate() & 63));
|
||||
}
|
||||
else if (m_param[2].is_immediate_value(0))
|
||||
convert_to_mov_param(1);
|
||||
@ -660,9 +695,9 @@ void uml::instruction::simplify()
|
||||
if (m_param[1].is_immediate() && m_param[2].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(rotl_32(m_param[1].immediate(), m_param[2].immediate()));
|
||||
convert_to_mov_immediate(rotl_32(m_param[1].immediate(), m_param[2].immediate() & 31));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(rotl_64(m_param[1].immediate(), m_param[2].immediate()));
|
||||
convert_to_mov_immediate(rotl_64(m_param[1].immediate(), m_param[2].immediate() & 63));
|
||||
}
|
||||
else if (m_param[2].is_immediate_value(0))
|
||||
convert_to_mov_param(1);
|
||||
@ -673,9 +708,9 @@ void uml::instruction::simplify()
|
||||
if (m_param[1].is_immediate() && m_param[2].is_immediate())
|
||||
{
|
||||
if (m_size == 4)
|
||||
convert_to_mov_immediate(rotr_32(m_param[1].immediate(), m_param[2].immediate()));
|
||||
convert_to_mov_immediate(rotr_32(m_param[1].immediate(), m_param[2].immediate() & 31));
|
||||
else if (m_size == 8)
|
||||
convert_to_mov_immediate(rotr_64(m_param[1].immediate(), m_param[2].immediate()));
|
||||
convert_to_mov_immediate(rotr_64(m_param[1].immediate(), m_param[2].immediate() & 63));
|
||||
}
|
||||
else if (m_param[2].is_immediate_value(0))
|
||||
convert_to_mov_param(1);
|
||||
|
@ -62,16 +62,16 @@ namespace uml
|
||||
{
|
||||
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_Z = 0x80, // requires Z (zero/equal)
|
||||
COND_NZ, // requires Z (not zero/unequal)
|
||||
COND_S, // requires S (signed)
|
||||
COND_NS, // requires S (not signed)
|
||||
COND_C, // requires C (carry)
|
||||
COND_NC, // requires C (no carry)
|
||||
COND_V, // requires V (overflow)
|
||||
COND_NV, // requires V (no overflow)
|
||||
COND_U, // requires U (unordered)
|
||||
COND_NU, // requires U (not unordered)
|
||||
COND_A, // requires CZ, unsigned
|
||||
COND_BE, // requires CZ, unsigned
|
||||
COND_G, // requires SVZ, signed
|
||||
@ -143,6 +143,7 @@ namespace uml
|
||||
// control flow operations
|
||||
OP_NOP, // NOP
|
||||
OP_DEBUG, // DEBUG pc
|
||||
OP_BREAK, // BREAK
|
||||
OP_EXIT, // EXIT src1[,c]
|
||||
OP_HASHJMP, // HASHJMP mode,pc,handle
|
||||
OP_JMP, // JMP imm[,c]
|
||||
@ -157,6 +158,7 @@ namespace uml
|
||||
OP_GETFMOD, // GETFMOD dst
|
||||
OP_GETEXP, // GETEXP dst
|
||||
OP_GETFLGS, // GETFLGS dst[,f]
|
||||
OP_SETFLGS, // SETFLGS src
|
||||
OP_SAVE, // SAVE mem
|
||||
OP_RESTORE, // RESTORE mem
|
||||
|
||||
@ -180,7 +182,9 @@ namespace uml
|
||||
OP_SUBB, // SUBB dst,src1,src2[,f]
|
||||
OP_CMP, // CMP src1,src2[,f]
|
||||
OP_MULU, // MULU dst,edst,src1,src2[,f]
|
||||
OP_MULULW, // MULULW dst,src1,src2[,f]
|
||||
OP_MULS, // MULS dst,edst,src1,src2[,f]
|
||||
OP_MULSLW, // MULSLW dst,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]
|
||||
@ -422,6 +426,7 @@ namespace uml
|
||||
|
||||
// control flow operations
|
||||
void nop() { configure(OP_NOP, 4); }
|
||||
void break_() { configure(OP_BREAK, 4); }
|
||||
void debug(u32 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); }
|
||||
@ -443,6 +448,7 @@ namespace uml
|
||||
void getfmod(parameter dst) { configure(OP_GETFMOD, 4, dst); }
|
||||
void getexp(parameter dst) { configure(OP_GETEXP, 4, dst); }
|
||||
void getflgs(parameter dst, u32 flags) { configure(OP_GETFLGS, 4, dst, flags); }
|
||||
void setflgs(u32 flags) { configure(OP_SETFLGS, 4, 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)); }
|
||||
|
||||
@ -467,7 +473,9 @@ namespace uml
|
||||
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 mululw(parameter dst, parameter src1, parameter src2) { configure(OP_MULULW, 4, dst, src1, src2); }
|
||||
void muls(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULS, 4, dst, edst, src1, src2); }
|
||||
void mulslw(parameter dst, parameter src1, parameter src2) { configure(OP_MULSLW, 4, dst, 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); }
|
||||
@ -506,7 +514,9 @@ namespace uml
|
||||
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 dmululw(parameter dst, parameter src1, parameter src2) { configure(OP_MULULW, 8, dst, src1, src2); }
|
||||
void dmuls(parameter dst, parameter edst, parameter src1, parameter src2) { configure(OP_MULS, 8, dst, edst, src1, src2); }
|
||||
void dmulslw(parameter dst, parameter src1, parameter src2) { configure(OP_MULSLW, 8, dst, 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); }
|
||||
|
Loading…
Reference in New Issue
Block a user