1 // license:BSD-3-Clause
2 // copyright-holders:Ryan Holtz
3 /******************************************************************************
4 *
5 * Sony Playstation 2 Vector Unit disassembler
6 *
7 */
8
9 #include "emu.h"
10 #include "vudasm.h"
11
12 /*static*/ char const *const sonyvu_disassembler::DEST_STR[] =
13 {
14 " ", "w ", "z ", "zw ", "y ", "yw ", "yz ", "yzw ",
15 "x ", "xw ", "xz ", "xzw ", "xy ", "xyw ", "xyz ", "xyzw"
16 };
17
18 /*static*/ char const *const sonyvu_disassembler::DEST_COMMA_STR[] =
19 {
20 ",", "w,", "z,", "zw,", "y,", "yw,", "yz,", "yzw,",
21 "x,", "xw,", "xz,", "xzw,", "xy,", "xyw,", "xyz,", "xyzw,"
22 };
23
24 /*static*/ char const *const sonyvu_disassembler::BC_STR[] = { "x", "y", "z", "w" };
25 /*static*/ char const *const sonyvu_disassembler::BC_COMMA_STR[] = { "x,", "y,", "z,", "w," };
26
27 /*static*/ char const *const sonyvu_disassembler::VFREG[] =
28 {
29 "$vf00", "$vf01", "$vf02", "$vf03", "$vf04", "$vf05", "$vf06", "$vf07",
30 "$vf08", "$vf09", "$vf10", "$vf11", "$vf12", "$vf13", "$vf14", "$vf15",
31 "$vf16", "$vf17", "$vf18", "$vf19", "$vf20", "$vf21", "$vf22", "$vf23",
32 "$vf24", "$vf25", "$vf26", "$vf27", "$vf28", "$vf29", "$vf30", "$vf31"
33 };
34
35 /*static*/ char const *const sonyvu_disassembler::VIREG[] =
36 {
37 "$vi00", "$vi01", "$vi02", "$vi03", "$vi04", "$vi05", "$vi06", "$vi07",
38 "$vi08", "$vi09", "$vi10", "$vi11", "$vi12", "$vi13", "$vi14", "$vi15",
39 "STATUS", "MACF", "CLIPF", "res19", "R", "I", "Q", "res23",
40 "res24", "res25", "TPC", "CMSAR0", "FBRST", "VPU_STAT", "res30", "CMSAR1"
41 };
42
disassemble(std::ostream & stream,offs_t pc,const data_buffer & opcodes,const data_buffer & params)43 offs_t sonyvu_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
44 {
45 uint64_t op = opcodes.r64(pc & ~7);
46 if (pc & 4)
47 {
48 if (op & 0x8000000000000000ULL)
49 {
50 util::stream_format(stream, "loi %f", *reinterpret_cast<float*>(&op));
51 }
52 else
53 {
54 dasm_lower(pc, (uint32_t)op, stream);
55 }
56 }
57 else
58 {
59 dasm_upper(pc, (uint32_t)(op >> 32), stream);
60 }
61 return 4 | SUPPORTED;
62 }
63
dasm_upper(uint32_t pc,uint32_t op,std::ostream & stream)64 void sonyvu_disassembler::dasm_upper(uint32_t pc, uint32_t op, std::ostream &stream)
65 {
66 const int rd = (op >> 6) & 31;
67 const int rs = (op >> 11) & 31;
68 const int rt = (op >> 16) & 31;
69 const char* bc = BC_STR[op & 3];
70 const char* dest = DEST_STR[(op >> 21) & 15];
71 const char* destc = DEST_COMMA_STR[(op >> 21) & 15];
72
73 switch (op & 0x3f)
74 {
75 case 0x08: case 0x09: case 0x0a: case 0x0b:
76 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;
77 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
78 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;
79 case 0x10: case 0x11: case 0x12: case 0x13:
80 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;
81 case 0x14: case 0x15: case 0x16: case 0x17:
82 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;
83 case 0x18: case 0x19: case 0x1a: case 0x1b:
84 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;
85 case 0x1c: util::stream_format(stream, "mulq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
86 case 0x1d: util::stream_format(stream, "maxi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
87 case 0x1e: util::stream_format(stream, "muli.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
88 case 0x1f: util::stream_format(stream, "minii.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
89 case 0x20: util::stream_format(stream, "addq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
90 case 0x21: util::stream_format(stream, "maddq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
91 case 0x22: util::stream_format(stream, "addi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
92 case 0x23: util::stream_format(stream, "maddi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
93 case 0x24: util::stream_format(stream, "subq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
94 case 0x25: util::stream_format(stream, "msubq.%s %s%s %s%s Q", dest, VFREG[rd], destc, VFREG[rs], destc); break;
95 case 0x26: util::stream_format(stream, "subi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
96 case 0x27: util::stream_format(stream, "msubi.%s %s%s %s%s I", dest, VFREG[rd], destc, VFREG[rs], destc); break;
97 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;
98 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;
99 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;
100 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;
101 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;
102 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;
103 case 0x2e: util::stream_format(stream, "opmsub.xyz %sxyz, %sxyz, %sxyz", VFREG[rd], VFREG[rs], VFREG[rt]); break;
104 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;
105 case 0x3c: case 0x3d: case 0x3e: case 0x3f:
106 {
107 const uint8_t type2_op = ((op & 0x3c0) >> 4) | (op & 3);
108 switch (type2_op)
109 {
110 case 0x00: case 0x01: case 0x02: case 0x03:
111 util::stream_format(stream, "adda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
112 case 0x04: case 0x05: case 0x06: case 0x07:
113 util::stream_format(stream, "suba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
114 case 0x08: case 0x09: case 0x0a: case 0x0b:
115 util::stream_format(stream, "madda%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
116 case 0x0c: case 0x0d: case 0x0e: case 0x0f:
117 util::stream_format(stream, "msuba%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
118 case 0x10: util::stream_format(stream, "itof0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
119 case 0x11: util::stream_format(stream, "itof4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
120 case 0x12: util::stream_format(stream, "itof12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
121 case 0x13: util::stream_format(stream, "itof15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
122 case 0x14: util::stream_format(stream, "ftoi0.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
123 case 0x15: util::stream_format(stream, "ftoi4.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
124 case 0x16: util::stream_format(stream, "ftoi12.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
125 case 0x17: util::stream_format(stream, "ftoi15.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
126 case 0x18: case 0x19: case 0x1a: case 0x1b:
127 util::stream_format(stream, "mula%s.%s ACC%s %s%s %s%s", bc, dest, destc, VFREG[rs], destc, VFREG[rt], bc); break;
128 case 0x1c: util::stream_format(stream, "mulaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
129 case 0x1d: util::stream_format(stream, "abs.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest); break;
130 case 0x1e: util::stream_format(stream, "mulai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
131 case 0x1f: util::stream_format(stream, "clipw.xyz %sxyz, %sw", VFREG[rs], VFREG[rt]); break;
132 case 0x20: util::stream_format(stream, "addaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
133 case 0x21: util::stream_format(stream, "maddaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
134 case 0x22: util::stream_format(stream, "addai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
135 case 0x23: util::stream_format(stream, "maddai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
136 case 0x24: util::stream_format(stream, "subaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
137 case 0x25: util::stream_format(stream, "msubaq.%s ACC%s %s%s Q", dest, destc, VFREG[rs], destc); break;
138 case 0x26: util::stream_format(stream, "subai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
139 case 0x27: util::stream_format(stream, "msubai.%s ACC%s %s%s I", dest, destc, VFREG[rs], destc); break;
140 case 0x28: util::stream_format(stream, "adda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
141 case 0x29: util::stream_format(stream, "madda.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
142 case 0x2a: util::stream_format(stream, "mula.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
143 // 2b?
144 case 0x2c: util::stream_format(stream, "suba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
145 case 0x2d: util::stream_format(stream, "msuba.%s ACC%s %s%s %s%s", dest, destc, VFREG[rs], destc, VFREG[rt], dest); break;
146 case 0x2e: util::stream_format(stream, "opmula.xyz ACCxyz, %sxyz, %sxyz", VFREG[rs], VFREG[rt]); break;
147 case 0x2f: util::stream_format(stream, "nop"); break;
148 default:
149 util::stream_format(stream, "invalid");
150 break;
151 }
152 break;
153 }
154 default:
155 util::stream_format(stream, "invalid");
156 break;
157 }
158 }
159
dasm_lower(uint32_t pc,uint32_t op,std::ostream & stream)160 void sonyvu_disassembler::dasm_lower(uint32_t pc, uint32_t op, std::ostream &stream)
161 {
162 const int rd = (op >> 6) & 31;
163 const int rs = (op >> 11) & 31;
164 const int rt = (op >> 16) & 31;
165 const char* dest = DEST_STR[(op >> 21) & 15];
166 const char* destc = DEST_COMMA_STR[(op >> 21) & 15];
167 const char* ftf = BC_STR[(op >> 23) & 3];
168 const char* fsf = BC_STR[(op >> 21) & 3];
169 const char* fsfc = BC_COMMA_STR[(op >> 21) & 3];
170
171 switch ((op >> 25) & 0x7f)
172 {
173 case 0x00: // LQ
174 util::stream_format(stream, "lq.%s %s%s %s(%s)", dest, VFREG[rt], destc, signed_11bit(op), VIREG[rs]);
175 break;
176 case 0x01: // SQ
177 util::stream_format(stream, "sq.%s %s%s %s(%s)", dest, VFREG[rs], destc, signed_11bit(op), VIREG[rt]);
178 break;
179 case 0x04: // ILW
180 util::stream_format(stream, "ilw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest);
181 break;
182 case 0x05: // ISW
183 util::stream_format(stream, "isw.%s %s, %s(%s)%s", dest, VIREG[rt], destc, signed_11bit(op), VIREG[rs], dest);
184 break;
185 case 0x08: // IADDIU
186 util::stream_format(stream, "iaddiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op));
187 break;
188 case 0x09: // ISUBIU
189 util::stream_format(stream, "isubiu %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit(op));
190 break;
191 case 0x10: // FCEQ
192 util::stream_format(stream, "fceq $vi01, %06x", op & 0xffffff);
193 break;
194 case 0x11: // FCSET
195 util::stream_format(stream, "fcset %06x", op & 0xffffff);
196 break;
197 case 0x12: // FCAND
198 util::stream_format(stream, "fcand $vi01, %06x", op & 0xffffff);
199 break;
200 case 0x13: // FCOR
201 util::stream_format(stream, "fcor $vi01, %06x", op & 0xffffff);
202 break;
203 case 0x14: // FSEQ
204 util::stream_format(stream, "fseq %s, %s", VIREG[rt], op & 0xfff);
205 break;
206 case 0x15: // FSSET
207 util::stream_format(stream, "fsset %03x", op & 0xfff);
208 break;
209 case 0x16: // FSAND
210 util::stream_format(stream, "fsand %s, %s", VIREG[rt], op & 0xfff);
211 break;
212 case 0x17: // FSOR
213 util::stream_format(stream, "fsor %s, %s", VIREG[rt], op & 0xfff);
214 break;
215 case 0x18: // FMEQ
216 util::stream_format(stream, "fmeq %s, %s", VIREG[rt], VIREG[rs]);
217 break;
218 case 0x1a: // FMAND
219 util::stream_format(stream, "fmand %s, %s", VIREG[rt], VIREG[rs]);
220 break;
221 case 0x1b: // FMOR
222 util::stream_format(stream, "fmor %s, %s", VIREG[rt], VIREG[rs]);
223 break;
224 case 0x1c: // FCGET
225 util::stream_format(stream, "fcget %s", VIREG[rt]);
226 break;
227 case 0x20: // B
228 util::stream_format(stream, "b %s", signed_11bit_x8(op));
229 break;
230 case 0x21: // BAL
231 util::stream_format(stream, "bal %s, %s", VIREG[rt], signed_11bit_x8(op));
232 break;
233 case 0x24: // JR
234 util::stream_format(stream, "jr %s", VIREG[rs]);
235 break;
236 case 0x25: // JALR
237 util::stream_format(stream, "jalr %s, %s", VIREG[rt], VIREG[rs]);
238 break;
239 case 0x28: // IBEQ
240 util::stream_format(stream, "ibeq %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op));
241 break;
242 case 0x29: // IBNE
243 util::stream_format(stream, "ibne %s, %s, %s", VIREG[rt], VIREG[rs], signed_11bit_x8(op));
244 break;
245 case 0x2c: // IBLTZ
246 util::stream_format(stream, "ibltz %s, %s", VIREG[rs], signed_11bit_x8(op));
247 break;
248 case 0x2d: // IBGTZ
249 util::stream_format(stream, "ibgtz %s, %s", VIREG[rs], signed_11bit_x8(op));
250 break;
251 case 0x2e: // IBLEZ
252 util::stream_format(stream, "iblez %s, %s", VIREG[rs], signed_11bit_x8(op));
253 break;
254 case 0x2f: // IBGEZ
255 util::stream_format(stream, "ibgez %s, %s", VIREG[rs], signed_11bit_x8(op));
256 break;
257 case 0x40: // SPECIAL
258 {
259 if ((op & 0x3c) == 0x3c)
260 {
261 uint8_t type4_op = ((op & 0x7c0) >> 4) | (op & 3);
262 switch (type4_op)
263 {
264 case 0x30: // MOVE
265 if (((op >> 21) & 15) == 0 && rt == 0 && rs == 0)
266 util::stream_format(stream, "nop");
267 else
268 util::stream_format(stream, "move.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest);
269 break;
270 case 0x31: // MR32
271 util::stream_format(stream, "mr32.%s %s%s %s%s", dest, VFREG[rt], destc, VFREG[rs], dest);
272 break;
273 case 0x34: // LQI
274 util::stream_format(stream, "lqi.%s %s%s (%s++)", dest, VFREG[rt], destc, VIREG[rs]);
275 break;
276 case 0x35: // SQI
277 util::stream_format(stream, "sqi.%s %s%s (%s++)", dest, VFREG[rs], destc, VIREG[rt]);
278 break;
279 case 0x36: // LQD
280 util::stream_format(stream, "lqi.%s %s%s (--%s)", dest, VFREG[rt], destc, VIREG[rs]);
281 break;
282 case 0x37: // SQD
283 util::stream_format(stream, "sqi.%s %s%s (--%s)", dest, VFREG[rs], destc, VIREG[rt]);
284 break;
285 case 0x38: // DIV
286 util::stream_format(stream, "div Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf);
287 break;
288 case 0x39: // SQRT
289 util::stream_format(stream, "sqrt Q, %s%s", dest, VFREG[rt], ftf);
290 break;
291 case 0x3a: // RSQRT
292 util::stream_format(stream, "rsqrt Q, %s%s %s%s", VFREG[rs], fsfc, VFREG[rt], ftf);
293 break;
294 case 0x3b: // WAITQ
295 util::stream_format(stream, "waitq");
296 break;
297 case 0x3c: // MTIR
298 util::stream_format(stream, "mtir %s, %s%s", VIREG[rt], VFREG[rs], fsf);
299 break;
300 case 0x3d: // MFIR
301 util::stream_format(stream, "mtir.%s %s%s %s", dest, VFREG[rt], destc, VIREG[rs] );
302 break;
303 case 0x3e: // ILWR
304 util::stream_format(stream, "ilwr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest);
305 break;
306 case 0x3f: // ISWR
307 util::stream_format(stream, "iswr.%s %s, (%s)%s", dest, VIREG[rt], VIREG[rs], dest);
308 break;
309 case 0x40: // RNEXT
310 util::stream_format(stream, "rnext.%s %s%s R", dest, VFREG[rt], destc);
311 break;
312 case 0x41: // RGET
313 util::stream_format(stream, "rget.%s %s%s R", dest, VFREG[rt], destc);
314 break;
315 case 0x42: // RINIT
316 util::stream_format(stream, "rinit R, %s%s", dest, VFREG[rs], dest);
317 break;
318 case 0x43: // RXOR
319 util::stream_format(stream, "rxor R, %s%s", dest, VFREG[rs], dest);
320 break;
321 case 0x64: // MFP
322 util::stream_format(stream, "mfp.%s %s%s P", dest, VFREG[rt], destc);
323 break;
324 case 0x68: // XTOP
325 util::stream_format(stream, "xtop %s", VIREG[rt]);
326 break;
327 case 0x69: // XITOP
328 util::stream_format(stream, "xitop %s", VIREG[rt]);
329 break;
330 case 0x6c: // XGKICK
331 util::stream_format(stream, "xgkick %s", VIREG[rs]);
332 break;
333 case 0x70: // ESADD
334 util::stream_format(stream, "esadd P, %s", VFREG[rs]);
335 break;
336 case 0x71: // ERSADD
337 util::stream_format(stream, "ersadd P, %s", VFREG[rs]);
338 break;
339 case 0x72: // ELENG
340 util::stream_format(stream, "eleng P, %s", VFREG[rs]);
341 break;
342 case 0x73: // ERLENG
343 util::stream_format(stream, "erleng P, %s", VFREG[rs]);
344 break;
345 case 0x74: // EATANxy
346 util::stream_format(stream, "eatanxy P, %s", VFREG[rs]);
347 break;
348 case 0x75: // EATANxz
349 util::stream_format(stream, "eatanxz P, %s", VFREG[rs]);
350 break;
351 case 0x76: // ESUM
352 util::stream_format(stream, "esum P, %s", VFREG[rs]);
353 break;
354 case 0x78: // ESQRT
355 util::stream_format(stream, "esqrt P, %s%s", VFREG[rs], fsf);
356 break;
357 case 0x79: // ERSQRT
358 util::stream_format(stream, "ersqrt P, %s%s", VFREG[rs], fsf);
359 break;
360 case 0x7a: // ERCPR
361 util::stream_format(stream, "ercpr P, %s%s", VFREG[rs], fsf);
362 break;
363 case 0x7b: // WAITP
364 util::stream_format(stream, "waitp");
365 break;
366 case 0x7c: // ESIN
367 util::stream_format(stream, "esin P, %s%s", VFREG[rs], fsf);
368 break;
369 case 0x7d: // EATAN
370 util::stream_format(stream, "eatan P, %s%s", VFREG[rs], fsf);
371 break;
372 case 0x7e: // EEXP
373 util::stream_format(stream, "eexp P, %s%s", VFREG[rs], fsf);
374 break;
375 default:
376 util::stream_format(stream, "invalid");
377 break;
378 }
379 break;
380 }
381 else
382 {
383 switch (op & 0x3f)
384 {
385 case 0x30: // IADD
386 util::stream_format(stream, "iadd %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
387 break;
388 case 0x31: // ISUB
389 util::stream_format(stream, "isub %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
390 break;
391 case 0x32: // IADDI
392 util::stream_format(stream, "iaddi %s, %s, %s", VIREG[rt], VIREG[rs], signed_5bit_rd(op));
393 break;
394 case 0x34: // IAND
395 util::stream_format(stream, "iand %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
396 break;
397 case 0x35: // IOR
398 util::stream_format(stream, "ior %s, %s, %s", VIREG[rd], VIREG[rs], VIREG[rt]);
399 break;
400 default:
401 util::stream_format(stream, "invalid");
402 break;
403 }
404 }
405 break;
406 }
407 default:
408 util::stream_format(stream, "invalid");
409 break;
410 }
411 }
412
opcode_alignment() const413 uint32_t sonyvu_disassembler::opcode_alignment() const
414 {
415 return 4;
416 }
417
signed_5bit(uint16_t val)418 std::string sonyvu_disassembler::signed_5bit(uint16_t val)
419 {
420 int16_t sval = (int32_t)val;
421 sval <<= 11;
422 sval >>= 11;
423
424 if (sval < 0)
425 return util::string_format("-$%x", -sval);
426 else
427 return util::string_format("$%x", sval);
428 }
429
signed_5bit_rd(uint16_t val)430 std::string sonyvu_disassembler::signed_5bit_rd(uint16_t val)
431 {
432 int16_t sval = (int32_t)((val >> 6) & 0x1f);
433 sval <<= 11;
434 sval >>= 11;
435
436 if (sval < 0)
437 return util::string_format("-$%x", -sval);
438 else
439 return util::string_format("$%x", sval);
440 }
441
unsigned_11bit(uint16_t val)442 std::string sonyvu_disassembler::unsigned_11bit(uint16_t val)
443 {
444 val <<= 5;
445 val >>= 5;
446 return util::string_format("$%x", val);
447 }
448
signed_11bit(uint16_t val)449 std::string sonyvu_disassembler::signed_11bit(uint16_t val)
450 {
451 int16_t sval = (int32_t)val;
452 sval <<= 5;
453 sval >>= 5;
454
455 if (sval < 0)
456 return util::string_format("-$%x", -sval);
457 else
458 return util::string_format("$%x", sval);
459 }
460
signed_11bit_x8(uint16_t val)461 std::string sonyvu_disassembler::signed_11bit_x8(uint16_t val)
462 {
463 int16_t sval = (int32_t)val;
464 sval <<= 5;
465 sval >>= 5;
466
467 if (sval < 0)
468 return util::string_format("-$%x", -sval * 8);
469 else
470 return util::string_format("$%x", sval * 8);
471 }
472