summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/mips/vudasm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/mips/vudasm.cpp')
-rw-r--r--src/devices/cpu/mips/vudasm.cpp461
1 files changed, 461 insertions, 0 deletions
diff --git a/src/devices/cpu/mips/vudasm.cpp b/src/devices/cpu/mips/vudasm.cpp
new file mode 100644
index 00000000000..da376798d92
--- /dev/null
+++ b/src/devices/cpu/mips/vudasm.cpp
@@ -0,0 +1,461 @@
+// license:BSD-3-Clause
+// copyright-holders:Ryan Holtz
+/******************************************************************************
+*
+* Sony Playstation 2 Vector Unit disassembler
+*
+*/
+
+#include "emu.h"
+#include "vudasm.h"
+
+/*static*/ const char* sonyvu_disassembler::DEST_STR[] =
+{
+ " ", "w ", "z ", "zw ", "y ", "yw ", "yz ", "yzw ",
+ "x ", "xw ", "xz ", "xzw ", "xy ", "xyw ", "xyz ", "xyzw"
+};
+
+/*static*/ const char* sonyvu_disassembler::DEST_COMMA_STR[] =
+{
+ ",", "w,", "z,", "zw,", "y,", "yw,", "yz,", "yzw,",
+ "x,", "xw,", "xz,", "xzw,", "xy,", "xyw,", "xyz,", "xyzw,"
+};
+
+/*static*/ const char* sonyvu_disassembler::BC_STR[] = { "x", "y", "z", "w" };
+/*static*/ const char* sonyvu_disassembler::BC_COMMA_STR[] = { "x,", "y,", "z,", "w," };
+
+/*static*/ const char* sonyvu_disassembler::VFREG[] =
+{
+ "$vf00", "$vf01", "$vf02", "$vf03", "$vf04", "$vf05", "$vf06", "$vf07",
+ "$vf08", "$vf09", "$vf10", "$vf11", "$vf12", "$vf13", "$vf14", "$vf15",
+ "$vf16", "$vf17", "$vf18", "$vf19", "$vf20", "$vf21", "$vf22", "$vf23",
+ "$vf24", "$vf25", "$vf26", "$vf27", "$vf28", "$vf29", "$vf30", "$vf31"
+};
+
+/*static*/ const char* sonyvu_disassembler::VIREG[] =
+{
+ "$vi00", "$vi01", "$vi02", "$vi03", "$vi04", "$vi05", "$vi06", "$vi07",
+ "$vi08", "$vi09", "$vi10", "$vi11", "$vi12", "$vi13", "$vi14", "$vi15",
+ "STATUS", "MACF", "CLIPF", "res19", "R", "I", "Q", "res23",
+ "res24", "res25", "TPC", "CMSAR0", "FBRST", "VPU_STAT", "res30", "CMSAR1"
+};
+
+offs_t sonyvu_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
+{
+ uint64_t op = opcodes.r64(pc & ~7);
+ if (pc & 4)
+ {
+ if (op & 0x8000000000000000ULL)
+ {
+ util::stream_format(stream, "loi %f", *reinterpret_cast<float*>(&op));
+ }
+ else
+ {
+ dasm_lower(pc, (uint32_t)op, stream);
+ }
+ }
+ else
+ {
+ dasm_upper(pc, (uint32_t)(op >> 32), stream);
+ }
+ return 4 | SUPPORTED;
+}
+
+void sonyvu_disassembler::dasm_upper(uint32_t pc, uint32_t op, std::ostream &stream)
+{
+ const int rd = (op >> 6) & 31;
+ const int rs = (op >> 11) & 31;
+ const int rt = (op >> 16) & 31;
+ const char* bc = BC_STR[op & 3];
+ const char* dest = DEST_STR[(op >> 21) & 15];
+ const char* destc = DEST_COMMA_STR[(op >> 21) & 15];
+
+ switch (op & 0x3f)
+ {
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ util::stream_format(stream, "madd%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ util::stream_format(stream, "msub%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x10: case 0x11: case 0x12: case 0x13:
+ util::stream_format(stream, "max%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x14: case 0x15: case 0x16: case 0x17:
+ util::stream_format(stream, "mini%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ util::stream_format(stream, "mul%s.%s %s%s %s%s %s%s", bc, dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x1c: util::stream_format(stream, "mulq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x1d: util::stream_format(stream, "maxi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x1e: util::stream_format(stream, "muli.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x1f: util::stream_format(stream, "minii.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x20: util::stream_format(stream, "addq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x21: util::stream_format(stream, "maddq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x22: util::stream_format(stream, "addi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x23: util::stream_format(stream, "maddi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x24: util::stream_format(stream, "subq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x25: util::stream_format(stream, "msubq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x26: util::stream_format(stream, "subi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x27: util::stream_format(stream, "msubi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
+ case 0x28: util::stream_format(stream, "add.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x29: util::stream_format(stream, "madd.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2a: util::stream_format(stream, "mul.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2b: util::stream_format(stream, "max.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2c: util::stream_format(stream, "sub.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2d: util::stream_format(stream, "msub.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2e: util::stream_format(stream, "opmsub.xyz %sxyz, %sxyz, %sxyz", VFREG[rd], VFREG[rs], VFREG[rt]); break;
+ case 0x2f: util::stream_format(stream, "mini.%s %s%s %s%s %s%s", dest, VFREG[rd], destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ {
+ const uint8_t type2_op = ((op & 0x3c0) >> 4) | (op & 3);
+ switch (type2_op)
+ {
+ case 0x00: case 0x01: case 0x02: case 0x03:
+ util::stream_format(stream, "adda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x04: case 0x05: case 0x06: case 0x07:
+ util::stream_format(stream, "suba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x08: case 0x09: case 0x0a: case 0x0b:
+ util::stream_format(stream, "madda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x0c: case 0x0d: case 0x0e: case 0x0f:
+ util::stream_format(stream, "msuba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x10: util::stream_format(stream, "itof0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x11: util::stream_format(stream, "itof4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x12: util::stream_format(stream, "itof12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x13: util::stream_format(stream, "itof15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x14: util::stream_format(stream, "ftoi0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x15: util::stream_format(stream, "ftoi4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x16: util::stream_format(stream, "ftoi12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x17: util::stream_format(stream, "ftoi15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x18: case 0x19: case 0x1a: case 0x1b:
+ util::stream_format(stream, "mula%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
+ case 0x1c: util::stream_format(stream, "mulaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
+ case 0x1d: util::stream_format(stream, "abs.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
+ case 0x1e: util::stream_format(stream, "mulai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
+ case 0x1f: util::stream_format(stream, "clipw.xyz %sxyz, %sw", VFREG[rs], VFREG[rt]); break;
+ case 0x20: util::stream_format(stream, "addaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
+ case 0x21: util::stream_format(stream, "maddaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
+ case 0x22: util::stream_format(stream, "addai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
+ case 0x23: util::stream_format(stream, "maddai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
+ case 0x24: util::stream_format(stream, "subaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
+ case 0x25: util::stream_format(stream, "msubaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
+ case 0x26: util::stream_format(stream, "subai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
+ case 0x27: util::stream_format(stream, "msubai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
+ case 0x28: util::stream_format(stream, "adda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x29: util::stream_format(stream, "madda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2a: util::stream_format(stream, "mula.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ // 2b?
+ case 0x2c: util::stream_format(stream, "suba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2d: util::stream_format(stream, "msuba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
+ case 0x2e: util::stream_format(stream, "opmula.xyz ACCxyz, %sxyz, %sxyz", VFREG[rs], VFREG[rt]); break;
+ case 0x2f: util::stream_format(stream, "nop"); break;
+ default:
+ util::stream_format(stream, "invalid");
+ break;
+ }
+ break;
+ }
+ default:
+ util::stream_format(stream, "invalid");
+ break;
+ }
+}
+
+void sonyvu_disassembler::dasm_lower(uint32_t pc, uint32_t op, std::ostream &stream)
+{
+ const int rd = (op >> 6) & 31;
+ const int rs = (op >> 11) & 31;
+ const int rt = (op >> 16) & 31;
+ const char* dest = DEST_STR[(op >> 21) & 15];
+ const char* destc = DEST_COMMA_STR[(op >> 21) & 15];
+ const char* ftf = BC_STR[(op >> 23) & 3];
+ const char* fsf = BC_STR[(op >> 21) & 3];
+ const char* fsfc = BC_COMMA_STR[(op >> 21) & 3];
+
+ switch ((op >> 25) & 0x7f)
+ {
+ case 0x00: // LQ
+ util::stream_format(stream, "lq.%s %s%s %s(%s)", dest, VFREG[rt], destc, signed_11bit(op), VIREG[rs]);
+ break;
+ case 0x01: // SQ
+ util::stream_format(stream, "sq.%s %s%s %s(%s)", dest, VFREG[rs], destc, signed_11bit(op), VIREG[rt]);
+ break;
+ case 0x04: // ILW
+ util::stream_format(stream, "ilw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest);
+ break;
+ case 0x05: // ISW
+ util::stream_format(stream, "isw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest);
+ break;
+ case 0x08: // IADDIU
+ util::stream_format(stream, "iaddiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op));
+ break;
+ case 0x09: // ISUBIU
+ util::stream_format(stream, "isubiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op));
+ break;
+ case 0x10: // FCEQ
+ util::stream_format(stream, "fceq $vi01, %06x", op & 0xffffff);
+ break;
+ case 0x11: // FCSET
+ util::stream_format(stream, "fcset %06x", op & 0xffffff);
+ break;
+ case 0x12: // FCAND
+ util::stream_format(stream, "fcand $vi01, %06x", op & 0xffffff);
+ break;
+ case 0x13: // FCOR
+ util::stream_format(stream, "fcor $vi01, %06x", op & 0xffffff);
+ break;
+ case 0x14: // FSEQ
+ util::stream_format(stream, "fseq %s, %s", VIREG[rt], op & 0xfff);
+ break;
+ case 0x15: // FSSET
+ util::stream_format(stream, "fsset %03x", op & 0xfff);
+ break;
+ case 0x16: // FSAND
+ util::stream_format(stream, "fsand %s, %s", VIREG[rt], op & 0xfff);
+ break;
+ case 0x17: // FSOR
+ util::stream_format(stream, "fsor %s, %s", VIREG[rt], op & 0xfff);
+ break;
+ case 0x18: // FMEQ
+ util::stream_format(stream, "fmeq %s, %s", VIREG[rt], VIREG[rs]);
+ break;
+ case 0x1a: // FMAND
+ util::stream_format(stream, "fmand %s, %s", VIREG[rt], VIREG[rs]);
+ break;
+ case 0x1b: // FMOR
+ util::stream_format(stream, "fmor %s, %s", VIREG[rt], VIREG[rs]);
+ break;
+ case 0x1c: // FCGET
+ util::stream_format(stream, "fcget %s", VIREG[rt]);
+ break;
+ case 0x20: // B
+ util::stream_format(stream, "b %s", signed_11bit_x8(op));
+ break;
+ case 0x21: // BAL
+ util::stream_format(stream, "bal %s, %s", VIREG[rt], signed_11bit_x8(op));
+ break;
+ case 0x24: // JR
+ util::stream_format(stream, "jr %s", VIREG[rs]);
+ break;
+ case 0x25: // JALR
+ util::stream_format(stream, "jalr %s, %s", VIREG[rt], VIREG[rs]);
+ break;
+ case 0x28: // IBEQ
+ util::stream_format(stream, "ibeq %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op));
+ break;
+ case 0x29: // IBNE
+ util::stream_format(stream, "ibne %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op));
+ break;
+ case 0x2c: // IBLTZ
+ util::stream_format(stream, "ibltz %s, %s", VIREG[rs], signed_11bit_x8(op));
+ break;
+ case 0x2d: // IBGTZ
+ util::stream_format(stream, "ibgtz %s, %s", VIREG[rs], signed_11bit_x8(op));
+ break;
+ case 0x2e: // IBLEZ
+ util::stream_format(stream, "iblez %s, %s", VIREG[rs], signed_11bit_x8(op));
+ break;
+ case 0x2f: // IBGEZ
+ util::stream_format(stream, "ibgez %s, %s", VIREG[rs], signed_11bit_x8(op));
+ break;
+ case 0x40: // SPECIAL
+ {
+ if ((op & 0x3c) == 0x3c)
+ {
+ uint8_t type4_op = ((op & 0x7c0) >> 4) | (op & 3);
+ switch (type4_op)
+ {
+ case 0x30: // MOVE
+ util::stream_format(stream, "move.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest);
+ break;
+ case 0x31: // MR32
+ util::stream_format(stream, "mr32.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest);
+ break;
+ case 0x34: // LQI
+ util::stream_format(stream, "lqi.%s %s%s (%s++)", dest, VFREG[rt], destc, VIREG[rs]);
+ break;
+ case 0x35: // SQI
+ util::stream_format(stream, "sqi.%s %s%s (%s++)", dest, VFREG[rs], destc, VIREG[rt]);
+ break;
+ case 0x36: // LQD
+ util::stream_format(stream, "lqi.%s %s%s (--%s)", dest, VFREG[rt], destc, VIREG[rs]);
+ break;
+ case 0x37: // SQD
+ util::stream_format(stream, "sqi.%s %s%s (--%s)", dest, VFREG[rs], destc, VIREG[rt]);
+ break;
+ case 0x38: // DIV
+ util::stream_format(stream, "div Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf);
+ break;
+ case 0x39: // SQRT
+ util::stream_format(stream, "sqrt Q, %s%s", dest, VFREG[rt], ftf);
+ break;
+ case 0x3a: // RSQRT
+ util::stream_format(stream, "rsqrt Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf);
+ break;
+ case 0x3b: // WAITQ
+ util::stream_format(stream, "waitq");
+ break;
+ case 0x3c: // MTIR
+ util::stream_format(stream, "mtir %s, %s%s", VIREG[rt], VFREG[rs], fsf);
+ break;
+ case 0x3d: // MFIR
+ util::stream_format(stream, "mtir.%s %s%s %s", dest, VFREG[rt], destc, VIREG[rs] );
+ break;
+ case 0x3e: // ILWR
+ util::stream_format(stream, "ilwr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest);
+ break;
+ case 0x3f: // ISWR
+ util::stream_format(stream, "iswr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest);
+ break;
+ case 0x40: // RNEXT
+ util::stream_format(stream, "rnext.%s %s%s R", dest, VFREG[rt], destc);
+ break;
+ case 0x41: // RGET
+ util::stream_format(stream, "rget.%s %s%s R", dest, VFREG[rt], destc);
+ break;
+ case 0x42: // RINIT
+ util::stream_format(stream, "rinit R, %s%s", dest, VFREG[rs], dest);
+ break;
+ case 0x43: // RXOR
+ util::stream_format(stream, "rxor R, %s%s", dest, VFREG[rs], dest);
+ break;
+ case 0x64: // MFP
+ util::stream_format(stream, "mfp.%s %s%s P", dest, VFREG[rt], destc);
+ break;
+ case 0x68: // XTOP
+ util::stream_format(stream, "xtop %s", VIREG[rt]);
+ break;
+ case 0x69: // XITOP
+ util::stream_format(stream, "xitop %s", VIREG[rt]);
+ break;
+ case 0x6c: // XGKICK
+ util::stream_format(stream, "xgkick %s", VIREG[rs]);
+ break;
+ case 0x70: // ESADD
+ util::stream_format(stream, "esadd P, %s", VFREG[rs]);
+ break;
+ case 0x71: // ERSADD
+ util::stream_format(stream, "ersadd P, %s", VFREG[rs]);
+ break;
+ case 0x72: // ELENG
+ util::stream_format(stream, "eleng P, %s", VFREG[rs]);
+ break;
+ case 0x73: // ERLENG
+ util::stream_format(stream, "erleng P, %s", VFREG[rs]);
+ break;
+ case 0x74: // EATANxy
+ util::stream_format(stream, "eatanxy P, %s", VFREG[rs]);
+ break;
+ case 0x75: // EATANxz
+ util::stream_format(stream, "eatanxz P, %s", VFREG[rs]);
+ break;
+ case 0x76: // ESUM
+ util::stream_format(stream, "esum P, %s", VFREG[rs]);
+ break;
+ case 0x78: // ESQRT
+ util::stream_format(stream, "esqrt P, %s%s", VFREG[rs], fsf);
+ break;
+ case 0x79: // ERSQRT
+ util::stream_format(stream, "ersqrt P, %s%s", VFREG[rs], fsf);
+ break;
+ case 0x7a: // ERCPR
+ util::stream_format(stream, "ercpr P, %s%s", VFREG[rs], fsf);
+ break;
+ case 0x7b: // WAITP
+ util::stream_format(stream, "waitp");
+ break;
+ case 0x7c: // ESIN
+ util::stream_format(stream, "esin P, %s%s", VFREG[rs], fsf);
+ break;
+ case 0x7d: // EATAN
+ util::stream_format(stream, "eatan P, %s%s", VFREG[rs], fsf);
+ break;
+ case 0x7e: // EEXP
+ util::stream_format(stream, "eexp P, %s%s", VFREG[rs], fsf);
+ break;
+ default:
+ util::stream_format(stream, "invalid");
+ break;
+ }
+ break;
+ }
+ else
+ {
+ switch (op & 0x3f)
+ {
+ case 0x30: // IADD
+ util::stream_format(stream, "iadd %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
+ break;
+ case 0x31: // ISUB
+ util::stream_format(stream, "isub %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
+ break;
+ case 0x32: // IADDI
+ util::stream_format(stream, "iaddi %s, %s, %s", VIREG[rt], VIREG[rs], signed_5bit(op));
+ break;
+ case 0x34: // IAND
+ util::stream_format(stream, "iand %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
+ break;
+ case 0x35: // IOR
+ util::stream_format(stream, "ior %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
+ break;
+ default:
+ util::stream_format(stream, "invalid");
+ break;
+ }
+ }
+ break;
+ }
+ default:
+ util::stream_format(stream, "invalid");
+ break;
+ }
+}
+
+uint32_t sonyvu_disassembler::opcode_alignment() const
+{
+ return 4;
+}
+
+std::string sonyvu_disassembler::signed_5bit(uint16_t val)
+{
+ int16_t sval = (int32_t)val;
+ sval <<= 11;
+ sval >>= 11;
+
+ if (sval < 0)
+ return util::string_format("-$%x", -sval);
+ else
+ return util::string_format("$%x", sval);
+}
+
+std::string sonyvu_disassembler::signed_11bit(uint16_t val)
+{
+ int16_t sval = (int32_t)val;
+ sval <<= 5;
+ sval >>= 5;
+
+ if (sval < 0)
+ return util::string_format("-$%x", -sval);
+ else
+ return util::string_format("$%x", sval);
+}
+
+std::string sonyvu_disassembler::signed_11bit_x8(uint16_t val)
+{
+ int16_t sval = (int32_t)val;
+ sval <<= 5;
+ sval >>= 5;
+
+ if (sval < 0)
+ return util::string_format("-$%x", -sval * 8);
+ else
+ return util::string_format("$%x", sval * 8);
+}
+
+std::string sonyvu_disassembler::signed_15bit(uint16_t val)
+{
+ int16_t sval = (int32_t)val;
+ sval <<= 1;
+ sval >>= 1;
+
+ if (sval < 0)
+ return util::string_format("-$%x", -sval);
+ else
+ return util::string_format("$%x", sval);
+}