SLLV, SRLV, SRAV and ROTV have reverse order of operands
[pspdecompiler.git] / allegrex.c
blob3cb99c88931b2270c1ba6685472fbfb78ddc6a67
1 /**
2 * Author: Humberto Naves (hsnaves@gmail.com)
3 * Special thanks to Tyranid for the prxtool "disasm.C"
4 */
5 #include <stdio.h>
6 #include <ctype.h>
8 #include "allegrex.h"
10 /* Format codes
11 * %d - Rd
12 * %t - Rt
13 * %s - Rs
14 * %i - 16bit signed immediate
15 * %I - 16bit unsigned immediate (always printed in hex)
16 * %o - 16bit signed offset (rs base)
17 * %O - 16bit signed offset (PC relative)
18 * %j - 26bit absolute offset
19 * %J - Register jump
20 * %a - SA
21 * %0 - Cop0 register
22 * %1 - Cop1 register
23 * %2? - Cop2 register (? is (s, d))
24 * %p - General cop (i.e. numbered) register
25 * %n? - ins/ext size, ? (e, i)
26 * %r - Debug register
27 * %k - Cache function
28 * %D - Fd
29 * %T - Ft
30 * %S - Fs
31 * %x? - Vt (? is (s/scalar, p/pair, t/triple, q/quad, m/matrix pair, n/matrix triple, o/matrix quad)
32 * %y? - Vs
33 * %z? - Vd
34 * %X? - Vo (? is (s, q))
35 * %Y - VFPU offset
36 * %Z? - VFPU condition code/name (? is (c, n))
37 * %v? - VFPU immediate, ? (3, 5, 8, k, i, h, r, p? (? is (0, 1, 2, 3, 4, 5, 6, 7)))
38 * %c - code (for break/dbreak/syscall)
39 * %? - Indicates vmmul special exception
42 #define RT(op) ((op >> 16) & 0x1F)
43 #define RS(op) ((op >> 21) & 0x1F)
44 #define RD(op) ((op >> 11) & 0x1F)
45 #define FT(op) ((op >> 16) & 0x1F)
46 #define FS(op) ((op >> 11) & 0x1F)
47 #define FD(op) ((op >> 6) & 0x1F)
48 #define SA(op) ((op >> 6) & 0x1F)
49 #define IMM(op) ((signed short) (op & 0xFFFF))
50 #define IMMU(op) ((unsigned short) (op & 0xFFFF))
51 #define JUMP(op, pc) ((pc & 0xF0000000) | ((op & 0x3FFFFFF) << 2))
52 #define CODE(op) ((op >> 6) & 0xFFFFF)
53 #define SIZE(op) ((op >> 11) & 0x1F)
54 #define POS(op) ((op >> 6) & 0x1F)
55 #define VO(op) (((op & 3) << 5) | ((op >> 16) & 0x1F))
56 #define VCC(op) ((op >> 18) & 7)
57 #define VD(op) (op & 0x7F)
58 #define VS(op) ((op >> 8) & 0x7F)
59 #define VT(op) ((op >> 16) & 0x7F)
61 /* [hlide] new #defines */
62 #define VED(op) (op & 0xFF)
63 #define VES(op) ((op >> 8) & 0xFF)
64 #define VCN(op) (op & 0x0F)
65 #define VI3(op) ((op >> 16) & 0x07)
66 #define VI5(op) ((op >> 16) & 0x1F)
67 #define VI8(op) ((op >> 16) & 0xFF)
69 /* VFPU 16-bit floating-point format. */
70 #define VFPU_FLOAT16_EXP_MAX 0x1f
71 #define VFPU_SH_FLOAT16_SIGN 15
72 #define VFPU_MASK_FLOAT16_SIGN 0x1
73 #define VFPU_SH_FLOAT16_EXP 10
74 #define VFPU_MASK_FLOAT16_EXP 0x1f
75 #define VFPU_SH_FLOAT16_FRAC 0
76 #define VFPU_MASK_FLOAT16_FRAC 0x3ff
78 /* VFPU prefix instruction operands. The *_SH_* values really specify where
79 the bitfield begins, as VFPU prefix instructions have four operands
80 encoded within the immediate field. */
81 #define VFPU_SH_PFX_NEG 16
82 #define VFPU_MASK_PFX_NEG 0x1 /* Negation. */
83 #define VFPU_SH_PFX_CST 12
84 #define VFPU_MASK_PFX_CST 0x1 /* Constant. */
85 #define VFPU_SH_PFX_ABS_CSTHI 8
86 #define VFPU_MASK_PFX_ABS_CSTHI 0x1 /* Abs/Constant (bit 2). */
87 #define VFPU_SH_PFX_SWZ_CSTLO 0
88 #define VFPU_MASK_PFX_SWZ_CSTLO 0x3 /* Swizzle/Constant (bits 0-1). */
89 #define VFPU_SH_PFX_MASK 8
90 #define VFPU_MASK_PFX_MASK 0x1 /* Mask. */
91 #define VFPU_SH_PFX_SAT 0
92 #define VFPU_MASK_PFX_SAT 0x3 /* Saturation. */
94 /* Special handling of the vrot instructions. */
95 #define VFPU_MASK_OP_SIZE 0x8080 /* Masks the operand size (pair, triple, quad). */
96 #define VFPU_OP_SIZE_PAIR 0x80
97 #define VFPU_OP_SIZE_TRIPLE 0x8000
98 #define VFPU_OP_SIZE_QUAD 0x8080
99 /* Note that these are within the rotators field, and not the full opcode. */
100 #define VFPU_SH_ROT_HI 2
101 #define VFPU_MASK_ROT_HI 0x3
102 #define VFPU_SH_ROT_LO 0
103 #define VFPU_MASK_ROT_LO 0x3
104 #define VFPU_SH_ROT_NEG 4 /* Negation. */
105 #define VFPU_MASK_ROT_NEG 0x1
107 /* Alias (shorter version) */
108 #define _AL INSN_ALIAS
109 #define _RS INSN_READ_GPR_S
110 #define _RT INSN_READ_GPR_T
111 #define _RD INSN_READ_GPR_D
112 #define _Rs INSN_READ_FPR_S
113 #define _Rt INSN_READ_FPR_T
114 #define _RC INSN_READ_COND_CODE
115 #define _RH INSN_READ_HI
116 #define _RL INSN_READ_LO
117 #define _WD INSN_WRITE_GPR_D
118 #define _WT INSN_WRITE_GPR_T
119 #define _Wd INSN_WRITE_FPR_D
120 #define _Wt INSN_WRITE_FPR_T
121 #define _WC INSN_WRITE_COND_CODE
122 #define _WH INSN_WRITE_HI
123 #define _WL INSN_WRITE_LO
124 #define _JP INSN_JUMP
125 #define _BR INSN_BRANCH
126 #define _BL INSN_BRANCHLIKELY
127 #define _LK INSN_LINK
128 #define _LD INSN_LOAD
129 #define _ST INSN_STORE
131 #define _SP INSN_SPECIAL
132 #define _DB INSN_DEBUG
133 #define _C0 INSN_COP0
134 #define _C1 INSN_FPU
135 #define _C2 INSN_VFPU
137 #define COMMAND_INDEX 1
138 #define COMMAND_BSEARCH 2
139 #define COMMAND_TEST 3
140 #define COMMAND_END 4
142 struct disasm_command {
143 int type;
144 unsigned int param1;
145 unsigned int param2;
146 unsigned int param3;
149 struct bsearch_index {
150 int index;
151 unsigned int opcode;
155 static const struct allegrex_instruction instructions[] =
157 /* MIPS instructions */
158 { I_ADD, "add", 0x00000020, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
159 { I_ADDI, "addi", 0x20000000, 0xFC000000, "%t, %s, %i", _RS|_WT },
160 { I_ADDIU, "li", 0x24000000, 0xFFE00000, "%t, %i", _AL|_WT },
161 { I_ADDIU, "addiu", 0x24000000, 0xFC000000, "%t, %s, %i", _RS|_WT },
162 { I_ADDU, "move", 0x00000021, 0xFC1F07FF, "%d, %s", _AL|_RS|_WD },
163 { I_ADDU, "addu", 0x00000021, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
164 { I_AND, "and", 0x00000024, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
165 { I_ANDI, "andi", 0x30000000, 0xFC000000, "%t, %s, %I", _RS|_WT },
166 { I_BEQ, "b", 0x10000000, 0xFFFF0000, "%O", _AL|_BR },
167 { I_BEQ, "beqz", 0x10000000, 0xFC1F0000, "%s, %O", _AL|_RS|_BR },
168 { I_BEQ, "beq", 0x10000000, 0xFC000000, "%s, %t, %O", _RS|_RT|_BR },
169 { I_BEQL, "beqzl", 0x50000000, 0xFC1F0000, "%s, %O", _AL|_RS|_BR|_BL },
170 { I_BEQL, "beql", 0x50000000, 0xFC000000, "%s, %t, %O", _RS|_RT|_BR|_BL },
171 { I_BGEZ, "b", 0x04010000, 0xFFFF0000, "%O", _AL|_BR },
172 { I_BGEZ, "bgez", 0x04010000, 0xFC1F0000, "%s, %O", _RS|_BR },
173 { I_BGEZAL, "bal", 0x04110000, 0xFFFF0000, "%O", _AL|_BR|_LK },
174 { I_BGEZAL, "bgezal", 0x04110000, 0xFC1F0000, "%s, %O", _RS|_BR|_LK },
175 { I_BGEZL, "bgezl", 0x04030000, 0xFC1F0000, "%s, %O", _RS|_BR|_BL },
176 { I_BGTZ, "bgtz", 0x1C000000, 0xFC1F0000, "%s, %O", _RS|_BR },
177 { I_BGTZL, "bgtzl", 0x5C000000, 0xFC1F0000, "%s, %O", _RS|_BR|_BL },
178 { I_BITREV, "bitrev", 0x7C000520, 0xFFE007FF, "%d, %t", _RT|_WD },
179 { I_BLEZ, "blez", 0x18000000, 0xFC1F0000, "%s, %O", _RS|_BR },
180 { I_BLEZL, "blezl", 0x58000000, 0xFC1F0000, "%s, %O", _RS|_BR|_BL },
181 { I_BLTZ, "bltz", 0x04000000, 0xFC1F0000, "%s, %O", _RS|_BR },
182 { I_BLTZL, "bltzl", 0x04020000, 0xFC1F0000, "%s, %O", _RS|_BR|_BL },
183 { I_BLTZAL, "bltzal", 0x04100000, 0xFC1F0000, "%s, %O", _RS|_BR|_LK },
184 { I_BLTZALL, "bltzall", 0x04120000, 0xFC1F0000, "%s, %O", _RS|_BR|_BL|_LK },
185 { I_BNE, "bnez", 0x14000000, 0xFC1F0000, "%s, %O", _AL|_RS|_BR },
186 { I_BNE, "bne", 0x14000000, 0xFC000000, "%s, %t, %O", _RS|_RT|_BR },
187 { I_BNEL, "bnezl", 0x54000000, 0xFC1F0000, "%s, %O", _AL|_RS|_BR|_BL },
188 { I_BNEL, "bnel", 0x54000000, 0xFC000000, "%s, %t, %O", _RS|_RT|_BR|_BL },
189 { I_BREAK, "break", 0x0000000D, 0xFC00003F, "%c", _SP },
190 { I_CACHE, "cache", 0xBC000000, 0xFC000000, "%k, %o", _RS|_C0 },
191 { I_CFC0, "cfc0", 0x40400000, 0xFFE007FF, "%t, %p", _WT|_C0 },
192 { I_CLO, "clo", 0x00000017, 0xFC1F07FF, "%d, %s", _RS|_WD },
193 { I_CLZ, "clz", 0x00000016, 0xFC1F07FF, "%d, %s", _RS|_WD },
194 { I_CTC0, "ctc0", 0x40C00000, 0xFFE007FF, "%t, %p", _RT|_C0 },
195 { I_MAX, "max", 0x0000002C, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
196 { I_MIN, "min", 0x0000002D, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
197 { I_DBREAK, "dbreak", 0x7000003F, 0xFC00003F, "%c", _DB },
198 { I_DIV, "div", 0x0000001A, 0xFC00FFFF, "%s, %t", _RS|_RT|_WH|_WL },
199 { I_DIVU, "divu", 0x0000001B, 0xFC00FFFF, "%s, %t", _RS|_RT|_WH|_WL },
200 { I_DRET, "dret", 0x7000003E, 0xFFFFFFFF, "", _JP|_DB },
201 { I_ERET, "eret", 0x42000018, 0xFFFFFFFF, "", _JP|_C0 },
202 { I_EXT, "ext", 0x7C000000, 0xFC00003F, "%t, %s, %a, %ne", _RS|_WT },
203 { I_INS, "ins", 0x7C000004, 0xFC00003F, "%t, %s, %a, %ni", _RS|_RT|_WT },
204 { I_J, "j", 0x08000000, 0xFC000000, "%j", _JP },
205 { I_JR, "jr", 0x00000008, 0xFC1FFFFF, "%J", _RS|_JP },
206 { I_JALR, "jalr", 0x0000F809, 0xFC1FFFFF, "%J", _AL|_RS|_WD|_JP },
207 { I_JALR, "jalr", 0x00000009, 0xFC1F07FF, "%J, %d", _RS|_WD|_JP },
208 { I_JAL, "jal", 0x0C000000, 0xFC000000, "%j", _JP|_LK },
209 { I_LB, "lb", 0x80000000, 0xFC000000, "%t, %o", _RS|_WT|_LD },
210 { I_LBU, "lbu", 0x90000000, 0xFC000000, "%t, %o", _RS|_WT|_LD },
211 { I_LH, "lh", 0x84000000, 0xFC000000, "%t, %o", _RS|_WT|_LD },
212 { I_LHU, "lhu", 0x94000000, 0xFC000000, "%t, %o", _RS|_WT|_LD },
213 { I_LL, "ll", 0xC0000000, 0xFC000000, "%t, %o", _RS|_WT|_LD },
214 { I_LUI, "lui", 0x3C000000, 0xFFE00000, "%t, %I", _WT },
215 { I_LW, "lw", 0x8C000000, 0xFC000000, "%t, %o", _RS|_WT|_LD },
216 { I_LWL, "lwl", 0x88000000, 0xFC000000, "%t, %o", _RS|_RT|_WT|_LD },
217 { I_LWR, "lwr", 0x98000000, 0xFC000000, "%t, %o", _RS|_RT|_WT|_LD },
218 { I_MADD, "madd", 0x0000001C, 0xFC00FFFF, "%s, %t", _RS|_RT|_RL|_RH|_WL|_WH },
219 { I_MADDU, "maddu", 0x0000001D, 0xFC00FFFF, "%s, %t", _RS|_RT|_RL|_RH|_WL|_WH },
220 { I_MFC0, "mfc0", 0x40000000, 0xFFE007FF, "%t, %0", _WT|_C0 },
221 { I_MFDR, "mfdr", 0x7000003D, 0xFFE007FF, "%t, %r", _WT|_DB },
222 { I_MFHI, "mfhi", 0x00000010, 0xFFFF07FF, "%d", _WD|_RH },
223 { I_MFIC, "mfic", 0x70000024, 0xFFE007FF, "%t, %p", _WT|_DB },
224 { I_MFLO, "mflo", 0x00000012, 0xFFFF07FF, "%d", _WD|_RL },
225 { I_MOVN, "movn", 0x0000000B, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_RD|_WD },
226 { I_MOVZ, "movz", 0x0000000A, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_RD|_WD },
227 { I_MSUB, "msub", 0x0000002e, 0xfc00ffff, "%d, %t", _RS|_RT|_RL|_RH|_WL|_WH },
228 { I_MSUBU, "msubu", 0x0000002f, 0xfc00ffff, "%d, %t", _RS|_RT|_RL|_RH|_WL|_WH },
229 { I_MTC0, "mtc0", 0x40800000, 0xFFE007FF, "%t, %0", _RT|_C0 },
230 { I_MTDR, "mtdr", 0x7080003D, 0xFFE007FF, "%t, %r", _RT|_DB },
231 { I_MTIC, "mtic", 0x70000026, 0xFFE007FF, "%t, %p", _RT|_DB },
232 { I_HALT, "halt", 0x70000000, 0xFFFFFFFF, "", _DB },
233 { I_MTHI, "mthi", 0x00000011, 0xFC1FFFFF, "%s", _RS|_WH },
234 { I_MTLO, "mtlo", 0x00000013, 0xFC1FFFFF, "%s", _RS|_WL },
235 { I_MULT, "mult", 0x00000018, 0xFC00FFFF, "%s, %t", _RS|_RT|_WL|_WH },
236 { I_MULTU, "multu", 0x00000019, 0xFC0007FF, "%s, %t", _RS|_RT|_WL|_WH },
237 { I_NOR, "not", 0x00000027, 0xFC1F07FF, "%d, %s", _AL|_RS|_WD },
238 { I_NOR, "nor", 0x00000027, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
239 { I_OR, "move", 0x00000025, 0xFC1F07FF, "%d, %s", _AL|_RS|_WD },
240 { I_OR, "or", 0x00000025, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
241 { I_ORI, "li", 0x34000000, 0xFFE00000, "%t, %I", _AL|_WT },
242 { I_ORI, "ori", 0x34000000, 0xFC000000, "%t, %s, %I", _RS|_WT },
243 { I_ROTR, "rotr", 0x00200002, 0xFFE0003F, "%d, %t, %a", _RT|_WD },
244 { I_ROTV, "rotv", 0x00000046, 0xFC0007FF, "%d, %t, %s", _RS|_RT|_WD },
245 { I_SEB, "seb", 0x7C000420, 0xFFE007FF, "%d, %t", _RT|_WD },
246 { I_SEH, "seh", 0x7C000620, 0xFFE007FF, "%d, %t", _RT|_WD },
247 { I_SB, "sb", 0xA0000000, 0xFC000000, "%t, %o", _RS|_RT|_ST },
248 { I_SC, "sc", 0xE0000000, 0xFC000000, "%t, %o", _RS|_RT|_ST },
249 { I_SH, "sh", 0xA4000000, 0xFC000000, "%t, %o", _RS|_RT|_ST },
250 { I_SLLV, "sllv", 0x00000004, 0xFC0007FF, "%d, %t, %s", _RS|_RT|_WD },
251 { I_SLL, "nop", 0x00000000, 0xFFFFFFFF, "", _AL },
252 { I_SLL, "sll", 0x00000000, 0xFFE0003F, "%d, %t, %a", _RT|_WD },
253 { I_SLT, "slt", 0x0000002A, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
254 { I_SLTI, "slti", 0x28000000, 0xFC000000, "%t, %s, %i", _RS|_WT },
255 { I_SLTIU, "sltiu", 0x2C000000, 0xFC000000, "%t, %s, %i", _RS|_WT },
256 { I_SLTU, "sltu", 0x0000002B, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
257 { I_SRA, "sra", 0x00000003, 0xFFE0003F, "%d, %t, %a", _RT|_WD },
258 { I_SRAV, "srav", 0x00000007, 0xFC0007FF, "%d, %t, %s", _RS|_RT|_WD },
259 { I_SRLV, "srlv", 0x00000006, 0xFC0007FF, "%d, %t, %s", _RS|_RT|_WD },
260 { I_SRL, "srl", 0x00000002, 0xFFE0003F, "%d, %t, %a", _RT|_WD },
261 { I_SW, "sw", 0xAC000000, 0xFC000000, "%t, %o", _RS|_RT|_ST },
262 { I_SWL, "swl", 0xA8000000, 0xFC000000, "%t, %o", _RS|_RT|_ST },
263 { I_SWR, "swr", 0xB8000000, 0xFC000000, "%t, %o", _RS|_RT|_ST },
264 { I_SUB, "neg", 0x00000022, 0xFFE007FF, "%d, %t", _AL|_RT|_WD },
265 { I_SUB, "sub", 0x00000022, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
266 { I_SUBU, "negu", 0x00000023, 0xFFE007FF, "%d, %t", _AL|_RT|_WD },
267 { I_SUBU, "subu", 0x00000023, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
268 { I_SYNC, "sync", 0x0000000F, 0xFFFFFFFF, "", _SP },
269 { I_SYSCALL, "syscall", 0x0000000C, 0xFC00003F, "%c", _SP },
270 { I_XOR, "xor", 0x00000026, 0xFC0007FF, "%d, %s, %t", _RS|_RT|_WD },
271 { I_XORI, "xori", 0x38000000, 0xFC000000, "%t, %s, %I", _RS|_WT },
272 { I_WSBH, "wsbh", 0x7C0000A0, 0xFFE007FF, "%d, %t", _RT|_WD },
273 { I_WSBW, "wsbw", 0x7C0000E0, 0xFFE007FF, "%d, %t", _RT|_WD },
275 /* FPU instructions */
276 { I_ABS_S, "abs.s", 0x46000005, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
277 { I_ADD_S, "add.s", 0x46000000, 0xFFE0003F, "%D, %S, %T", _Rs|_Rt|_Wd|_C1 },
278 { I_BC1F, "bc1f", 0x45000000, 0xFFFF0000, "%O", _RC|_BR|_C1 },
279 { I_BC1FL, "bc1fl", 0x45020000, 0xFFFF0000, "%O", _RC|_BR|_BL|_C1 },
280 { I_BC1T, "bc1t", 0x45010000, 0xFFFF0000, "%O", _RC|_BR|_C1 },
281 { I_BC1TL, "bc1tl", 0x45030000, 0xFFFF0000, "%O", _RC|_BR|_BL|_C1 },
282 { I_C_F_S, "c.f.s", 0x46000030, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
283 { I_C_UN_S, "c.un.s", 0x46000031, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
284 { I_C_EQ_S, "c.eq.s", 0x46000032, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
285 { I_C_UEQ_S, "c.ueq.s", 0x46000033, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
286 { I_C_OLT_S, "c.olt.s", 0x46000034, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
287 { I_C_ULT_S, "c.ult.s", 0x46000035, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
288 { I_C_OLE_S, "c.ole.s", 0x46000036, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
289 { I_C_ULE_S, "c.ule.s", 0x46000037, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
290 { I_C_SF_S, "c.sf.s", 0x46000038, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
291 { I_C_NGLE_S, "c.ngle.s", 0x46000039, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
292 { I_C_SEQ_S, "c.seq.s", 0x4600003A, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
293 { I_C_NGL_S, "c.ngl.s", 0x4600003B, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
294 { I_C_LT_S, "c.lt.s", 0x4600003C, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
295 { I_C_NGE_S, "c.nge.s", 0x4600003D, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
296 { I_C_LE_S, "c.le.s", 0x4600003E, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
297 { I_C_NGT_S, "c.ngt.s", 0x4600003F, 0xFFE007FF, "%S, %T", _Rs|_Rt|_WC|_C1 },
298 { I_CEIL_W_S, "ceil.w.s", 0x4600000E, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
299 { I_CFC1, "cfc1", 0x44400000, 0xFFE007FF, "%t, %p", _WT|_C1 },
300 { I_CTC1, "ctc1", 0x44c00000, 0xFFE007FF, "%t, %p", _RT|_C1 },
301 { I_CVT_S_W, "cvt.s.w", 0x46800020, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
302 { I_CVT_W_S, "cvt.w.s", 0x46000024, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
303 { I_DIV_S, "div.s", 0x46000003, 0xFFE0003F, "%D, %S, %T", _Rs|_Rt|_Wd|_C1 },
304 { I_FLOOR_W_S, "floor.w.s", 0x4600000F, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
305 { I_LWC1, "lwc1", 0xc4000000, 0xFC000000, "%T, %o", _Rs|_Wt|_LD|_C1 },
306 { I_MFC1, "mfc1", 0x44000000, 0xFFE007FF, "%t, %1", _WT|_C1 },
307 { I_MOV_S, "mov.s", 0x46000006, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
308 { I_MTC1, "mtc1", 0x44800000, 0xFFE007FF, "%t, %1", _RT|_C1 },
309 { I_MUL_S, "mul.s", 0x46000002, 0xFFE0003F, "%D, %S, %T", _Rs|_Rt|_Wd|_C1 },
310 { I_NEG_S, "neg.s", 0x46000007, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
311 { I_ROUND_W_S, "round.w.s", 0x4600000C, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
312 { I_SQRT_S, "sqrt.s", 0x46000004, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
313 { I_SUB_S, "sub.s", 0x46000001, 0xFFE0003F, "%D, %S, %T", _Rs|_Rt|_Wd|_C1 },
314 { I_SWC1, "swc1", 0xe4000000, 0xFC000000, "%T, %o", _RS|_Rt|_ST|_C1 },
315 { I_TRUNC_W_S, "trunc.w.s", 0x4600000D, 0xFFFF003F, "%D, %S", _Rs|_Wd|_C1 },
317 /* VPU instructions */
318 { I_BVF, "bvf", 0x49000000, 0xFFE30000, "%Zc, %O", _RC|_BR|_C2 }, /* [hlide] %Z -> %Zc */
319 { I_BVFL, "bvfl", 0x49020000, 0xFFE30000, "%Zc, %O", _RC|_BR|_BL|_C2 }, /* [hlide] %Z -> %Zc */
320 { I_BVT, "bvt", 0x49010000, 0xFFE30000, "%Zc, %O", _RC|_BR|_C2 }, /* [hlide] %Z -> %Zc */
321 { I_BVTL, "bvtl", 0x49030000, 0xFFE30000, "%Zc, %O", _RC|_BR|_BL|_C2 }, /* [hlide] %Z -> %Zc */
322 { I_LV_Q, "lv.q", 0xD8000000, 0xFC000002, "%Xq, %Y", _RS|_LD|_C2 },
323 { I_LV_S, "lv.s", 0xC8000000, 0xFC000000, "%Xs, %Y", _RS|_LD|_C2 },
324 { I_LVL_Q, "lvl.q", 0xD4000000, 0xFC000002, "%Xq, %Y", _RS|_LD|_C2 },
325 { I_LVR_Q, "lvr.q", 0xD4000002, 0xFC000002, "%Xq, %Y", _RS|_LD|_C2 },
326 { I_MFV, "mfv", 0x48600000, 0xFFE0FF80, "%t, %zs", _WT|_C2 }, /* [hlide] added "%t, %zs" */
327 { I_MFVC, "mfvc", 0x48600000, 0xFFE0FF00, "%t, %2d", _WT|_C2 }, /* [hlide] added "%t, %2d" */
328 { I_MTV, "mtv", 0x48E00000, 0xFFE0FF80, "%t, %zs", _RT|_C2 }, /* [hlide] added "%t, %zs" */
329 { I_MTVC, "mtvc", 0x48E00000, 0xFFE0FF00, "%t, %2d", _RT|_C2 }, /* [hlide] added "%t, %2d" */
330 { I_SV_Q, "sv.q", 0xF8000000, 0xFC000002, "%Xq, %Y", _RS|_ST|_C2 },
331 { I_SV_S, "sv.s", 0xE8000000, 0xFC000000, "%Xs, %Y", _RS|_ST|_C2 },
332 { I_SVL_Q, "svl.q", 0xF4000000, 0xFC000002, "%Xq, %Y", _RS|_ST|_C2 },
333 { I_SVR_Q, "svr.q", 0xF4000002, 0xFC000002, "%Xq, %Y", _RS|_ST|_C2 },
334 { I_VABS_P, "vabs.p", 0xD0010080, 0xFFFF8080, "%zp, %yp", _C2 },
335 { I_VABS_Q, "vabs.q", 0xD0018080, 0xFFFF8080, "%zq, %yq", _C2 },
336 { I_VABS_S, "vabs.s", 0xD0010000, 0xFFFF8080, "%zs, %ys", _C2 },
337 { I_VABS_T, "vabs.t", 0xD0018000, 0xFFFF8080, "%zt, %yt", _C2 },
338 { I_VADD_P, "vadd.p", 0x60000080, 0xFF808080, "%zp, %yp, %xp", _C2 },
339 { I_VADD_Q, "vadd.q", 0x60008080, 0xFF808080, "%zq, %yq, %xq", _C2 },
340 { I_VADD_S, "vadd.s", 0x60000000, 0xFF808080, "%zs, %ys, %xs", _C2 }, /* [hlide] %yz -> %ys */
341 { I_VADD_T, "vadd.t", 0x60008000, 0xFF808080, "%zt, %yt, %xt", _C2 },
342 { I_VASIN_P, "vasin.p", 0xD0170080, 0xFFFF8080, "%zp, %yp", _C2 },
343 { I_VASIN_Q, "vasin.q", 0xD0178080, 0xFFFF8080, "%zq, %yq", _C2 },
344 { I_VASIN_S, "vasin.s", 0xD0170000, 0xFFFF8080, "%zs, %ys", _C2 },
345 { I_VASIN_T, "vasin.t", 0xD0178000, 0xFFFF8080, "%zt, %yt", _C2 },
346 { I_VAVG_P, "vavg.p", 0xD0470080, 0xFFFF8080, "%zp, %yp", _C2 },
347 { I_VAVG_Q, "vavg.q", 0xD0478080, 0xFFFF8080, "%zq, %yq", _C2 },
348 { I_VAVG_T, "vavg.t", 0xD0478000, 0xFFFF8080, "%zt, %yt", _C2 },
349 { I_VBFY1_P, "vbfy1.p", 0xD0420080, 0xFFFF8080, "%zp, %yp", _C2 },
350 { I_VBFY1_Q, "vbfy1.q", 0xD0428080, 0xFFFF8080, "%zq, %yq", _C2 },
351 { I_VBFY2_Q, "vbfy2.q", 0xD0438080, 0xFFFF8080, "%zq, %yq", _C2 },
352 { I_VCMOVF_P, "vcmovf.p", 0xD2A80080, 0xFFF88080, "%zp, %yp, %v3", _RC|_C2 }, /* [hlide] added "%zp, %yp, %v3" */
353 { I_VCMOVF_Q, "vcmovf.q", 0xD2A88080, 0xFFF88080, "%zq, %yq, %v3", _RC|_C2 }, /* [hlide] added "%zq, %yq, %v3" */
354 { I_VCMOVF_S, "vcmovf.s", 0xD2A80000, 0xFFF88080, "%zs, %ys, %v3", _RC|_C2 }, /* [hlide] added "%zs, %ys, %v3" */
355 { I_VCMOVF_T, "vcmovf.t", 0xD2A88000, 0xFFF88080, "%zt, %yt, %v3", _RC|_C2 }, /* [hlide] added "%zt, %yt, %v3" */
356 { I_VCMOVT_P, "vcmovt.p", 0xD2A00080, 0xFFF88080, "%zp, %yp, %v3", _RC|_C2 }, /* [hlide] added "%zp, %yp, %v3" */
357 { I_VCMOVT_Q, "vcmovt.q", 0xD2A08080, 0xFFF88080, "%zq, %yq, %v3", _RC|_C2 }, /* [hlide] added "%zq, %yq, %v3" */
358 { I_VCMOVT_S, "vcmovt.s", 0xD2A00000, 0xFFF88080, "%zs, %ys, %v3", _RC|_C2 }, /* [hlide] added "%zs, %ys, %v3" */
359 { I_VCMOVT_T, "vcmovt.t", 0xD2A08000, 0xFFF88080, "%zt, %yt, %v3", _RC|_C2 }, /* [hlide] added "%zt, %yt, %v3" */
360 { I_VCMP_P, "vcmp.p", 0x6C000080, 0xFFFFFFF0, "%Zn", _AL|_WC|_C2 }, /* [hlide] added "%Zn" */
361 { I_VCMP_P, "vcmp.p", 0x6C000080, 0xFFFF80F0, "%Zn, %yp", _AL|_WC|_C2 }, /* [hlide] added "%Zn, %xp" */
362 { I_VCMP_P, "vcmp.p", 0x6C000080, 0xFF8080F0, "%Zn, %yp, %xp", _WC|_C2 }, /* [hlide] added "%Zn, %zp, %xp" */
363 { I_VCMP_Q, "vcmp.q", 0x6C008080, 0xFFFFFFF0, "%Zn", _AL|_WC|_C2 }, /* [hlide] added "%Zn" */
364 { I_VCMP_Q, "vcmp.q", 0x6C008080, 0xFFFF80F0, "%Zn, %yq", _AL|_WC|_C2 }, /* [hlide] added "%Zn, %yq" */
365 { I_VCMP_Q, "vcmp.q", 0x6C008080, 0xFF8080F0, "%Zn, %yq, %xq", _WC|_C2 }, /* [hlide] added "%Zn, %yq, %xq" */
366 { I_VCMP_S, "vcmp.s", 0x6C000000, 0xFFFFFFF0, "%Zn", _AL|_WC|_C2 }, /* [hlide] added "%Zn" */
367 { I_VCMP_S, "vcmp.s", 0x6C000000, 0xFFFF80F0, "%Zn, %ys", _AL|_WC|_C2 }, /* [hlide] added "%Zn, %ys" */
368 { I_VCMP_S, "vcmp.s", 0x6C000000, 0xFF8080F0, "%Zn, %ys, %xs", _WC|_C2 }, /* [hlide] added "%Zn, %ys, %xs" */
369 { I_VCMP_T, "vcmp.t", 0x6C008000, 0xFFFFFFF0, "%Zn", _AL|_WC|_C2 }, /* [hlide] added "%zp" */
370 { I_VCMP_T, "vcmp.t", 0x6C008000, 0xFFFF80F0, "%Zn, %yt", _AL|_WC|_C2 }, /* [hlide] added "%Zn, %yt" */
371 { I_VCMP_T, "vcmp.t", 0x6C008000, 0xFF8080F0, "%Zn, %yt, %xt", _WC|_C2 }, /* [hlide] added "%Zn, %yt, %xt" */
372 { I_VCOS_P, "vcos.p", 0xD0130080, 0xFFFF8080, "%zp, %yp", _C2 },
373 { I_VCOS_Q, "vcos.q", 0xD0138080, 0xFFFF8080, "%zq, %yq", _C2 },
374 { I_VCOS_S, "vcos.s", 0xD0130000, 0xFFFF8080, "%zs, %ys", _C2 },
375 { I_VCOS_T, "vcos.t", 0xD0138000, 0xFFFF8080, "%zt, %yt", _C2 },
376 { I_VCRS_T, "vcrs.t", 0x66808000, 0xFF808080, "%zt, %yt, %xt", _C2 },
377 { I_VCRSP_T, "vcrsp.t", 0xF2808000, 0xFF808080, "%zt, %yt, %xt", _C2 },
378 { I_VCST_P, "vcst.p", 0xD0600080, 0xFFE0FF80, "%zp, %vk", }, /* [hlide] "%zp, %yp, %xp", -> "%zp, %vk" */
379 { I_VCST_Q, "vcst.q", 0xD0608080, 0xFFE0FF80, "%zq, %vk", _C2 }, /* [hlide] "%zq, %yq, %xq", -> "%zq, %vk" */
380 { I_VCST_S, "vcst.s", 0xD0600000, 0xFFE0FF80, "%zs, %vk", _C2 }, /* [hlide] "%zs, %ys, %xs", -> "%zs, %vk" */
381 { I_VCST_T, "vcst.t", 0xD0608000, 0xFFE0FF80, "%zt, %vk", _C2 }, /* [hlide] "%zt, %yt, %xt", -> "%zt, %vk" */
382 { I_VDET_P, "vdet.p", 0x67000080, 0xFF808080, "%zs, %yp, %xp", _C2 },
383 { I_VDIV_P, "vdiv.p", 0x63800080, 0xFF808080, "%zp, %yp, %xp", _C2 },
384 { I_VDIV_Q, "vdiv.q", 0x63808080, 0xFF808080, "%zq, %yq, %xq", _C2 },
385 { I_VDIV_S, "vdiv.s", 0x63800000, 0xFF808080, "%zs, %ys, %xs", _C2 }, /* [hlide] %yz -> %ys */
386 { I_VDIV_T, "vdiv.t", 0x63808000, 0xFF808080, "%zt, %yt, %xt", _C2 },
387 { I_VDOT_P, "vdot.p", 0x64800080, 0xFF808080, "%zs, %yp, %xp", _C2 },
388 { I_VDOT_Q, "vdot.q", 0x64808080, 0xFF808080, "%zs, %yq, %xq", _C2 },
389 { I_VDOT_T, "vdot.t", 0x64808000, 0xFF808080, "%zs, %yt, %xt", _C2 },
390 { I_VEXP2_P, "vexp2.p", 0xD0140080, 0xFFFF8080, "%zp, %yp", _C2 },
391 { I_VEXP2_Q, "vexp2.q", 0xD0148080, 0xFFFF8080, "%zq, %yq", _C2 },
392 { I_VEXP2_S, "vexp2.s", 0xD0140000, 0xFFFF8080, "%zs, %ys", _C2 },
393 { I_VEXP2_T, "vexp2.t", 0xD0148000, 0xFFFF8080, "%zt, %yt", _C2 },
394 { I_VF2H_P, "vf2h.p", 0xD0320080, 0xFFFF8080, "%zs, %yp", _C2 }, /* [hlide] %zp -> %zs */
395 { I_VF2H_Q, "vf2h.q", 0xD0328080, 0xFFFF8080, "%zp, %yq", _C2 }, /* [hlide] %zq -> %zp */
396 { I_VF2ID_P, "vf2id.p", 0xD2600080, 0xFFE08080, "%zp, %yp, %v5", _C2 }, /* [hlide] added "%zp, %yp, %v5" */
397 { I_VF2ID_Q, "vf2id.q", 0xD2608080, 0xFFE08080, "%zq, %yq, %v5", _C2 }, /* [hlide] added "%zq, %yq, %v5" */
398 { I_VF2ID_S, "vf2id.s", 0xD2600000, 0xFFE08080, "%zs, %ys, %v5", _C2 }, /* [hlide] added "%zs, %ys, %v5" */
399 { I_VF2ID_T, "vf2id.t", 0xD2608000, 0xFFE08080, "%zt, %yt, %v5", _C2 }, /* [hlide] added "%zt, %yt, %v5" */
400 { I_VF2IN_P, "vf2in.p", 0xD2000080, 0xFFE08080, "%zp, %yp, %v5", _C2 }, /* [hlide] added "%zp, %yp, %v5" */
401 { I_VF2IN_Q, "vf2in.q", 0xD2008080, 0xFFE08080, "%zq, %yq, %v5", _C2 }, /* [hlide] added "%zq, %yq, %v5" */
402 { I_VF2IN_S, "vf2in.s", 0xD2000000, 0xFFE08080, "%zs, %ys, %v5", _C2 }, /* [hlide] added "%zs, %ys, %v5" */
403 { I_VF2IN_T, "vf2in.t", 0xD2008000, 0xFFE08080, "%zt, %yt, %v5", _C2 }, /* [hlide] added "%zt, %yt, %v5" */
404 { I_VF2IU_P, "vf2iu.p", 0xD2400080, 0xFFE08080, "%zp, %yp, %v5", _C2 }, /* [hlide] added "%zp, %yp, %v5" */
405 { I_VF2IU_Q, "vf2iu.q", 0xD2408080, 0xFFE08080, "%zq, %yq, %v5", _C2 }, /* [hlide] added "%zq, %yq, %v5" */
406 { I_VF2IU_S, "vf2iu.s", 0xD2400000, 0xFFE08080, "%zs, %ys, %v5", _C2 }, /* [hlide] added "%zs, %ys, %v5" */
407 { I_VF2IU_T, "vf2iu.t", 0xD2408000, 0xFFE08080, "%zt, %yt, %v5", _C2 }, /* [hlide] added "%zt, %yt, %v5" */
408 { I_VF2IZ_P, "vf2iz.p", 0xD2200080, 0xFFE08080, "%zp, %yp, %v5", _C2 }, /* [hlide] added "%zp, %yp, %v5" */
409 { I_VF2IZ_Q, "vf2iz.q", 0xD2208080, 0xFFE08080, "%zq, %yq, %v5", _C2 }, /* [hlide] added "%zq, %yq, %v5" */
410 { I_VF2IZ_S, "vf2iz.s", 0xD2200000, 0xFFE08080, "%zs, %ys, %v5", _C2 }, /* [hlide] added "%zs, %ys, %v5" */
411 { I_VF2IZ_T, "vf2iz.t", 0xD2208000, 0xFFE08080, "%zt, %yt, %v5", _C2 }, /* [hlide] added "%zt, %yt, %v5" */
412 { I_VFAD_P, "vfad.p", 0xD0460080, 0xFFFF8080, "%zp, %yp", _C2 },
413 { I_VFAD_Q, "vfad.q", 0xD0468080, 0xFFFF8080, "%zq, %yq", _C2 },
414 { I_VFAD_T, "vfad.t", 0xD0468000, 0xFFFF8080, "%zt, %yt", _C2 },
415 { I_VFIM_S, "vfim.s", 0xDF800000, 0xFF800000, "%xs, %vh", _C2 }, /* [hlide] added "%xs, %vh" */
416 { I_VFLUSH, "vflush", 0xFFFF040D, 0xFFFFFFFF, "", _C2 },
417 { I_VH2F_P, "vh2f.p", 0xD0330080, 0xFFFF8080, "%zq, %yp", _C2 }, /* [hlide] %zp -> %zq */
418 { I_VH2F_S, "vh2f.s", 0xD0330000, 0xFFFF8080, "%zp, %ys", _C2 }, /* [hlide] %zs -> %zp */
419 { I_VHDP_P, "vhdp.p", 0x66000080, 0xFF808080, "%zs, %yp, %xp", _C2 }, /* [hlide] added "%zs, %yp, %xp" */
420 { I_VHDP_Q, "vhdp.q", 0x66008080, 0xFF808080, "%zs, %yq, %xq", _C2 }, /* [hlide] added "%zs, %yq, %xq" */
421 { I_VHDP_T, "vhdp.t", 0x66008000, 0xFF808080, "%zs, %yt, %xt", _C2 }, /* [hlide] added "%zs, %yt, %xt" */
422 { I_VHTFM2_P, "vhtfm2.p", 0xF0800000, 0xFF808080, "%zp, %ym, %xp", _C2 }, /* [hlide] added "%zp, %ym, %xp" */
423 { I_VHTFM3_T, "vhtfm3.t", 0xF1000080, 0xFF808080, "%zt, %yn, %xt", _C2 }, /* [hlide] added "%zt, %yn, %xt" */
424 { I_VHTFM4_Q, "vhtfm4.q", 0xF1808000, 0xFF808080, "%zq, %yo, %xq", _C2 }, /* [hlide] added "%zq, %yo, %xq" */
425 { I_VI2C_Q, "vi2c.q", 0xD03D8080, 0xFFFF8080, "%zs, %yq", _C2 }, /* [hlide] added "%zs, %yq" */
426 { I_VI2F_P, "vi2f.p", 0xD2800080, 0xFFE08080, "%zp, %yp, %v5", _C2 }, /* [hlide] added "%zp, %yp, %v5" */
427 { I_VI2F_Q, "vi2f.q", 0xD2808080, 0xFFE08080, "%zq, %yq, %v5", _C2 }, /* [hlide] added "%zq, %yq, %v5" */
428 { I_VI2F_S, "vi2f.s", 0xD2800000, 0xFFE08080, "%zs, %ys, %v5", _C2 }, /* [hlide] added "%zs, %ys, %v5" */
429 { I_VI2F_T, "vi2f.t", 0xD2808000, 0xFFE08080, "%zt, %yt, %v5", _C2 }, /* [hlide] added "%zt, %yt, %v5" */
430 { I_VI2S_P, "vi2s.p", 0xD03F0080, 0xFFFF8080, "%zs, %yp", _C2 }, /* [hlide] added "%zs, %yp" */
431 { I_VI2S_Q, "vi2s.q", 0xD03F8080, 0xFFFF8080, "%zp, %yq", _C2 }, /* [hlide] added "%zp, %yq" */
432 { I_VI2UC_Q, "vi2uc.q", 0xD03C8080, 0xFFFF8080, "%zq, %yq", _C2 }, /* [hlide] %zp -> %zq */
433 { I_VI2US_P, "vi2us.p", 0xD03E0080, 0xFFFF8080, "%zq, %yq", _C2 }, /* [hlide] %zp -> %zq */
434 { I_VI2US_Q, "vi2us.q", 0xD03E8080, 0xFFFF8080, "%zq, %yq", _C2 }, /* [hlide] %zp -> %zq */
435 { I_VIDT_P, "vidt.p", 0xD0030080, 0xFFFFFF80, "%zp", _C2 },
436 { I_VIDT_Q, "vidt.q", 0xD0038080, 0xFFFFFF80, "%zq", _C2 },
437 { I_VIIM_S, "viim.s", 0xDF000000, 0xFF800000, "%xs, %vi", _C2 }, /* [hlide] added "%xs, %vi" */
438 { I_VLGB_S, "vlgb.s", 0xD0370000, 0xFFFF8080, "%zs, %ys", _C2 },
439 { I_VLOG2_P, "vlog2.p", 0xD0150080, 0xFFFF8080, "%zp, %yp", _C2 },
440 { I_VLOG2_Q, "vlog2.q", 0xD0158080, 0xFFFF8080, "%zq, %yq", _C2 },
441 { I_VLOG2_S, "vlog2.s", 0xD0150000, 0xFFFF8080, "%zs, %ys", _C2 },
442 { I_VLOG2_T, "vlog2.t", 0xD0158000, 0xFFFF8080, "%zt, %yt", _C2 },
443 { I_VMAX_P, "vmax.p", 0x6D800080, 0xFF808080, "%zp, %yp, %xp", _C2 },
444 { I_VMAX_Q, "vmax.q", 0x6D808080, 0xFF808080, "%zq, %yq, %xq", _C2 },
445 { I_VMAX_S, "vmax.s", 0x6D800000, 0xFF808080, "%zs, %ys, %xs", _C2 },
446 { I_VMAX_T, "vmax.t", 0x6D808000, 0xFF808080, "%zt, %yt, %xt", _C2 },
447 { I_VMFVC, "vmfvc", 0xD0500000, 0xFFFF0080, "%zs, %2s", _C2 }, /* [hlide] added "%zs, %2s" */
448 { I_VMIDT_P, "vmidt.p", 0xF3830080, 0xFFFFFF80, "%zm", _C2 }, /* [hlide] %zp -> %zm */
449 { I_VMIDT_Q, "vmidt.q", 0xF3838080, 0xFFFFFF80, "%zo", _C2 }, /* [hlide] %zq -> %zo */
450 { I_VMIDT_T, "vmidt.t", 0xF3838000, 0xFFFFFF80, "%zn", _C2 }, /* [hlide] %zt -> %zn */
451 { I_VMIN_P, "vmin.p", 0x6D000080, 0xFF808080, "%zp, %yp, %xp", _C2 },
452 { I_VMIN_Q, "vmin.q", 0x6D008080, 0xFF808080, "%zq, %yq, %xq", _C2 },
453 { I_VMIN_S, "vmin.s", 0x6D000000, 0xFF808080, "%zs, %ys, %xs", _C2 },
454 { I_VMIN_T, "vmin.t", 0x6D008000, 0xFF808080, "%zt, %yt, %xt", _C2 },
455 { I_VMMOV_P, "vmmov.p", 0xF3800080, 0xFFFF8080, "%zm, %ym", _C2 }, /* [hlide] added "%zm, %ym" */
456 { I_VMMOV_Q, "vmmov.q", 0xF3808080, 0xFFFF8080, "%zo, %yo", _C2 },
457 { I_VMMOV_T, "vmmov.t", 0xF3808000, 0xFFFF8080, "%zn, %yn", _C2 }, /* [hlide] added "%zn, %yn" */
458 { I_VMMUL_P, "vmmul.p", 0xF0000080, 0xFF808080, "%?%zm, %ym, %xm",_C2 }, /* [hlide] added "%?%zm, %ym, %xm" */
459 { I_VMMUL_Q, "vmmul.q", 0xF0008080, 0xFF808080, "%?%zo, %yo, %xo",_C2 },
460 { I_VMMUL_T, "vmmul.t", 0xF0008000, 0xFF808080, "%?%zn, %yn, %xn",_C2 }, /* [hlide] added "%?%zn, %yn, %xn" */
461 { I_VMONE_P, "vmone.p", 0xF3870080, 0xFFFFFF80, "%zp", _C2 },
462 { I_VMONE_Q, "vmone.q", 0xF3878080, 0xFFFFFF80, "%zq", _C2 },
463 { I_VMONE_T, "vmone.t", 0xF3878000, 0xFFFFFF80, "%zt", _C2 },
464 { I_VMOV_P, "vmov.p", 0xD0000080, 0xFFFF8080, "%zp, %yp", _C2 },
465 { I_VMOV_Q, "vmov.q", 0xD0008080, 0xFFFF8080, "%zq, %yq", _C2 },
466 { I_VMOV_S, "vmov.s", 0xD0000000, 0xFFFF8080, "%zs, %ys", _C2 },
467 { I_VMOV_T, "vmov.t", 0xD0008000, 0xFFFF8080, "%zt, %yt", _C2 },
468 { I_VMSCL_P, "vmscl.p", 0xF2000080, 0xFF808080, "%zm, %ym, %xs", _C2 }, /* [hlide] %zp, %yp, %xp -> %zm, %ym, %xs */
469 { I_VMSCL_Q, "vmscl.q", 0xF2008080, 0xFF808080, "%zo, %yo, %xs", _C2 }, /* [hlide] %zq, %yq, %xp -> %zo, %yo, %xs */
470 { I_VMSCL_T, "vmscl.t", 0xF2008000, 0xFF808080, "%zn, %yn, %xs", _C2 }, /* [hlide] %zt, %yt, %xp -> %zn, %yn, %xs */
471 { I_VMTVC, "vmtvc", 0xD0510000, 0xFFFF8000, "%2d, %ys", _C2 }, /* [hlide] added "%2d, %ys" */
472 { I_VMUL_P, "vmul.p", 0x64000080, 0xFF808080, "%zp, %yp, %xp", _C2 },
473 { I_VMUL_Q, "vmul.q", 0x64008080, 0xFF808080, "%zq, %yq, %xq", _C2 },
474 { I_VMUL_S, "vmul.s", 0x64000000, 0xFF808080, "%zs, %ys, %xs", _C2 },
475 { I_VMUL_T, "vmul.t", 0x64008000, 0xFF808080, "%zt, %yt, %xt", _C2 },
476 { I_VMZERO_P, "vmzero.p", 0xF3860080, 0xFFFFFF80, "%zm", _C2 }, /* [hlide] %zp -> %zm */
477 { I_VMZERO_Q, "vmzero.q", 0xF3868080, 0xFFFFFF80, "%zo", _C2 }, /* [hlide] %zq -> %zo */
478 { I_VMZERO_T, "vmzero.t", 0xF3868000, 0xFFFFFF80, "%zn", _C2 }, /* [hlide] %zt -> %zn */
479 { I_VNEG_P, "vneg.p", 0xD0020080, 0xFFFF8080, "%zp, %yp", _C2 },
480 { I_VNEG_Q, "vneg.q", 0xD0028080, 0xFFFF8080, "%zq, %yq", _C2 },
481 { I_VNEG_S, "vneg.s", 0xD0020000, 0xFFFF8080, "%zs, %ys", _C2 },
482 { I_VNEG_T, "vneg.t", 0xD0028000, 0xFFFF8080, "%zt, %yt", _C2 },
483 { I_VNOP, "vnop", 0xFFFF0000, 0xFFFFFFFF, "", _C2 },
484 { I_VNRCP_P, "vnrcp.p", 0xD0180080, 0xFFFF8080, "%zp, %yp", _C2 },
485 { I_VNRCP_Q, "vnrcp.q", 0xD0188080, 0xFFFF8080, "%zq, %yq", _C2 },
486 { I_VNRCP_S, "vnrcp.s", 0xD0180000, 0xFFFF8080, "%zs, %ys", _C2 },
487 { I_VNRCP_T, "vnrcp.t", 0xD0188000, 0xFFFF8080, "%zt, %yt", _C2 },
488 { I_VNSIN_P, "vnsin.p", 0xD01A0080, 0xFFFF8080, "%zp, %yp", _C2 },
489 { I_VNSIN_Q, "vnsin.q", 0xD01A8080, 0xFFFF8080, "%zq, %yq", _C2 },
490 { I_VNSIN_S, "vnsin.s", 0xD01A0000, 0xFFFF8080, "%zs, %ys", _C2 },
491 { I_VNSIN_T, "vnsin.t", 0xD01A8000, 0xFFFF8080, "%zt, %yt", _C2 },
492 { I_VOCP_P, "vocp.p", 0xD0440080, 0xFFFF8080, "%zp, %yp", _C2 },
493 { I_VOCP_Q, "vocp.q", 0xD0448080, 0xFFFF8080, "%zq, %yq", _C2 },
494 { I_VOCP_S, "vocp.s", 0xD0440000, 0xFFFF8080, "%zs, %ys", _C2 },
495 { I_VOCP_T, "vocp.t", 0xD0448000, 0xFFFF8080, "%zt, %yt", _C2 },
496 { I_VONE_P, "vone.p", 0xD0070080, 0xFFFFFF80, "%zp", _C2 },
497 { I_VONE_Q, "vone.q", 0xD0078080, 0xFFFFFF80, "%zq", _C2 },
498 { I_VONE_S, "vone.s", 0xD0070000, 0xFFFFFF80, "%zs", _C2 },
499 { I_VONE_T, "vone.t", 0xD0078000, 0xFFFFFF80, "%zt", _C2 },
500 { I_VPFXD, "vpfxd", 0xDE000000, 0xFF000000, "[%vp4, %vp5, %vp6, %vp7]",_C2 }, /* [hlide] added "[%vp4, %vp5, %vp6, %vp7]" */
501 { I_VPFXS, "vpfxs", 0xDC000000, 0xFF000000, "[%vp0, %vp1, %vp2, %vp3]",_C2 }, /* [hlide] added "[%vp0, %vp1, %vp2, %vp3]" */
502 { I_VPFXT, "vpfxt", 0xDD000000, 0xFF000000, "[%vp0, %vp1, %vp2, %vp3]",_C2 }, /* [hlide] added "[%vp0, %vp1, %vp2, %vp3]" */
503 { I_VQMUL_Q, "vqmul.q", 0xF2808080, 0xFF808080, "%zq, %yq, %xq", _C2 }, /* [hlide] added "%zq, %yq, %xq" */
504 { I_VRCP_P, "vrcp.p", 0xD0100080, 0xFFFF8080, "%zp, %yp", _C2 },
505 { I_VRCP_Q, "vrcp.q", 0xD0108080, 0xFFFF8080, "%zq, %yq", _C2 },
506 { I_VRCP_S, "vrcp.s", 0xD0100000, 0xFFFF8080, "%zs, %ys", _C2 },
507 { I_VRCP_T, "vrcp.t", 0xD0108000, 0xFFFF8080, "%zt, %yt", _C2 },
508 { I_VREXP2_P, "vrexp2.p", 0xD01C0080, 0xFFFF8080, "%zp, %yp", _C2 },
509 { I_VREXP2_Q, "vrexp2.q", 0xD01C8080, 0xFFFF8080, "%zq, %yq", _C2 },
510 { I_VREXP2_S, "vrexp2.s", 0xD01C0000, 0xFFFF8080, "%zs, %ys", _C2 },
511 { I_VREXP2_T, "vrexp2.t", 0xD01C8000, 0xFFFF8080, "%zt, %yt", _C2 },
512 { I_VRNDF1_P, "vrndf1.p", 0xD0220080, 0xFFFFFF80, "%zp", _C2 },
513 { I_VRNDF1_Q, "vrndf1.q", 0xD0228080, 0xFFFFFF80, "%zq", _C2 },
514 { I_VRNDF1_S, "vrndf1.s", 0xD0220000, 0xFFFFFF80, "%zs", _C2 },
515 { I_VRNDF1_T, "vrndf1.t", 0xD0228000, 0xFFFFFF80, "%zt", _C2 },
516 { I_VRNDF2_P, "vrndf2.p", 0xD0230080, 0xFFFFFF80, "%zp", _C2 },
517 { I_VRNDF2_Q, "vrndf2.q", 0xD0238080, 0xFFFFFF80, "%zq", _C2 },
518 { I_VRNDF2_S, "vrndf2.s", 0xD0230000, 0xFFFFFF80, "%zs", _C2 },
519 { I_VRNDF2_T, "vrndf2.t", 0xD0238000, 0xFFFFFF80, "%zt", _C2 },
520 { I_VRNDI_P, "vrndi.p", 0xD0210080, 0xFFFFFF80, "%zp", _C2 },
521 { I_VRNDI_Q, "vrndi.q", 0xD0218080, 0xFFFFFF80, "%zq", _C2 },
522 { I_VRNDI_S, "vrndi.s", 0xD0210000, 0xFFFFFF80, "%zs", _C2 },
523 { I_VRNDI_T, "vrndi.t", 0xD0218000, 0xFFFFFF80, "%zt", _C2 },
524 { I_VRNDS_S, "vrnds.s", 0xD0200000, 0xFFFF80FF, "%ys", _C2 },
525 { I_VROT_P, "vrot.p", 0xF3A00080, 0xFFE08080, "%zp, %ys, %vr", _C2 }, /* [hlide] added "%zp, %ys, %vr" */
526 { I_VROT_Q, "vrot.q", 0xF3A08080, 0xFFE08080, "%zq, %ys, %vr", _C2 }, /* [hlide] added "%zq, %ys, %vr" */
527 { I_VROT_T, "vrot.t", 0xF3A08000, 0xFFE08080, "%zt, %ys, %vr", _C2 }, /* [hlide] added "%zt, %ys, %vr" */
528 { I_VRSQ_P, "vrsq.p", 0xD0110080, 0xFFFF8080, "%zp, %yp", _C2 },
529 { I_VRSQ_Q, "vrsq.q", 0xD0118080, 0xFFFF8080, "%zq, %yq", _C2 },
530 { I_VRSQ_S, "vrsq.s", 0xD0110000, 0xFFFF8080, "%zs, %ys", _C2 },
531 { I_VRSQ_T, "vrsq.t", 0xD0118000, 0xFFFF8080, "%zt, %yt", _C2 },
532 { I_VS2I_P, "vs2i.p", 0xD03B0080, 0xFFFF8080, "%zq, %yp", _C2 }, /* [hlide] %zp -> %zq */
533 { I_VS2I_S, "vs2i.s", 0xD03B0000, 0xFFFF8080, "%zp, %ys", _C2 }, /* [hlide] %zs -> %zp */
534 { I_VSAT0_P, "vsat0.p", 0xD0040080, 0xFFFF8080, "%zp, %yp", _C2 },
535 { I_VSAT0_Q, "vsat0.q", 0xD0048080, 0xFFFF8080, "%zq, %yq", _C2 },
536 { I_VSAT0_S, "vsat0.s", 0xD0040000, 0xFFFF8080, "%zs, %ys", _C2 },
537 { I_VSAT0_T, "vsat0.t", 0xD0048000, 0xFFFF8080, "%zt, %yt", _C2 },
538 { I_VSAT1_P, "vsat1.p", 0xD0050080, 0xFFFF8080, "%zp, %yp", _C2 },
539 { I_VSAT1_Q, "vsat1.q", 0xD0058080, 0xFFFF8080, "%zq, %yq", _C2 },
540 { I_VSAT1_S, "vsat1.s", 0xD0050000, 0xFFFF8080, "%zs, %ys", _C2 },
541 { I_VSAT1_T, "vsat1.t", 0xD0058000, 0xFFFF8080, "%zt, %yt", _C2 },
542 { I_VSBN_S, "vsbn.s", 0x61000000, 0xFF808080, "%zs, %ys, %xs", _C2 },
543 { I_VSBZ_S, "vsbz.s", 0xD0360000, 0xFFFF8080, "%zs, %ys", _C2 },
544 { I_VSCL_P, "vscl.p", 0x65000080, 0xFF808080, "%zp, %yp, %xs", _C2 }, /* [hlide] %xp -> %xs */
545 { I_VSCL_Q, "vscl.q", 0x65008080, 0xFF808080, "%zq, %yq, %xs", _C2 }, /* [hlide] %xq -> %xs */
546 { I_VSCL_T, "vscl.t", 0x65008000, 0xFF808080, "%zt, %yt, %xs", _C2 }, /* [hlide] %xt -> %xs */
547 { I_VSCMP_P, "vscmp.p", 0x6E800080, 0xFF808080, "%zp, %yp, %xp", _C2 },
548 { I_VSCMP_Q, "vscmp.q", 0x6E808080, 0xFF808080, "%zq, %yq, %xq", _C2 },
549 { I_VSCMP_S, "vscmp.s", 0x6E800000, 0xFF808080, "%zs, %ys, %xs", _C2 },
550 { I_VSCMP_T, "vscmp.t", 0x6E808000, 0xFF808080, "%zt, %yt, %xt", _C2 },
551 { I_VSGE_P, "vsge.p", 0x6F000080, 0xFF808080, "%zp, %yp, %xp", _C2 },
552 { I_VSGE_Q, "vsge.q", 0x6F008080, 0xFF808080, "%zq, %yq, %xq", _C2 },
553 { I_VSGE_S, "vsge.s", 0x6F000000, 0xFF808080, "%zs, %ys, %xs", _C2 },
554 { I_VSGE_T, "vsge.t", 0x6F008000, 0xFF808080, "%zt, %yt, %xt", _C2 },
555 { I_VSGN_P, "vsgn.p", 0xD04A0080, 0xFFFF8080, "%zp, %yp", _C2 },
556 { I_VSGN_Q, "vsgn.q", 0xD04A8080, 0xFFFF8080, "%zq, %yq", _C2 },
557 { I_VSGN_S, "vsgn.s", 0xD04A0000, 0xFFFF8080, "%zs, %ys", _C2 },
558 { I_VSGN_T, "vsgn.t", 0xD04A8000, 0xFFFF8080, "%zt, %yt", _C2 },
559 { I_VSIN_P, "vsin.p", 0xD0120080, 0xFFFF8080, "%zp, %yp", _C2 },
560 { I_VSIN_Q, "vsin.q", 0xD0128080, 0xFFFF8080, "%zq, %yq", _C2 },
561 { I_VSIN_S, "vsin.s", 0xD0120000, 0xFFFF8080, "%zs, %ys", _C2 },
562 { I_VSIN_T, "vsin.t", 0xD0128000, 0xFFFF8080, "%zt, %yt", _C2 },
563 { I_VSLT_P, "vslt.p", 0x6F800080, 0xFF808080, "%zp, %yp, %xp", _C2 },
564 { I_VSLT_Q, "vslt.q", 0x6F808080, 0xFF808080, "%zq, %yq, %xq", _C2 },
565 { I_VSLT_S, "vslt.s", 0x6F800000, 0xFF808080, "%zs, %ys, %xs", _C2 },
566 { I_VSLT_T, "vslt.t", 0x6F808000, 0xFF808080, "%zt, %yt, %xt", _C2 },
567 { I_VSOCP_P, "vsocp.p", 0xD0450080, 0xFFFF8080, "%zq, %yp", _C2 }, /* [hlide] %zp -> %zq */
568 { I_VSOCP_S, "vsocp.s", 0xD0450000, 0xFFFF8080, "%zp, %ys", _C2 }, /* [hlide] %zs -> %zp */
569 { I_VSQRT_P, "vsqrt.p", 0xD0160080, 0xFFFF8080, "%zp, %yp", _C2 },
570 { I_VSQRT_Q, "vsqrt.q", 0xD0168080, 0xFFFF8080, "%zq, %yq", _C2 },
571 { I_VSQRT_S, "vsqrt.s", 0xD0160000, 0xFFFF8080, "%zs, %ys", _C2 },
572 { I_VSQRT_T, "vsqrt.t", 0xD0168000, 0xFFFF8080, "%zt, %yt", _C2 },
573 { I_VSRT1_Q, "vsrt1.q", 0xD0408080, 0xFFFF8080, "%zq, %yq", _C2 },
574 { I_VSRT2_Q, "vsrt2.q", 0xD0418080, 0xFFFF8080, "%zq, %yq", _C2 },
575 { I_VSRT3_Q, "vsrt3.q", 0xD0488080, 0xFFFF8080, "%zq, %yq", _C2 },
576 { I_VSRT4_Q, "vsrt4.q", 0xD0498080, 0xFFFF8080, "%zq, %yq", _C2 },
577 { I_VSUB_P, "vsub.p", 0x60800080, 0xFF808080, "%zp, %yp, %xp", _C2 },
578 { I_VSUB_Q, "vsub.q", 0x60808080, 0xFF808080, "%zq, %yq, %xq", _C2 },
579 { I_VSUB_S, "vsub.s", 0x60800000, 0xFF808080, "%zs, %ys, %xs", _C2 },
580 { I_VSUB_T, "vsub.t", 0x60808000, 0xFF808080, "%zt, %yt, %xt", _C2 },
581 { I_VSYNC, "vsync", 0xFFFF0320, 0xFFFFFFFF, "", _AL|_C2 },
582 { I_VSYNC, "vsync", 0xFFFF0000, 0xFFFF0000, "%I", _C2 },
583 { I_VT4444_Q, "vt4444.q", 0xD0598080, 0xFFFF8080, "%zq, %yq", _C2 }, /* [hlide] %zq -> %zp */
584 { I_VT5551_Q, "vt5551.q", 0xD05A8080, 0xFFFF8080, "%zq, %yq", _C2 }, /* [hlide] %zq -> %zp */
585 { I_VT5650_Q, "vt5650.q", 0xD05B8080, 0xFFFF8080, "%zq, %yq", _C2 }, /* [hlide] %zq -> %zp */
586 { I_VTFM2_P, "vtfm2.p", 0xF0800080, 0xFF808080, "%zp, %ym, %xp", _C2 }, /* [hlide] added "%zp, %ym, %xp" */
587 { I_VTFM3_T, "vtfm3.t", 0xF1008000, 0xFF808080, "%zt, %yn, %xt", _C2 }, /* [hlide] added "%zt, %yn, %xt" */
588 { I_VTFM4_Q, "vtfm4.q", 0xF1808080, 0xFF808080, "%zq, %yo, %xq", _C2 }, /* [hlide] added "%zq, %yo, %xq" */
589 { I_VUS2I_P, "vus2i.p", 0xD03A0080, 0xFFFF8080, "%zq, %yp", _C2 }, /* [hlide] added "%zq, %yp" */
590 { I_VUS2I_S, "vus2i.s", 0xD03A0000, 0xFFFF8080, "%zp, %ys", _C2 }, /* [hlide] added "%zp, %ys" */
591 { I_VWB_Q, "vwb.q", 0xF8000002, 0xFC000002, "%Xq, %Y", _RS|_ST|_C2 },
592 { I_VWBN_S, "vwbn.s", 0xD3000000, 0xFF008080, "%zs, %xs, %I", _C2 },
593 { I_VZERO_P, "vzero.p", 0xD0060080, 0xFFFFFF80, "%zp", _C2 },
594 { I_VZERO_Q, "vzero.q", 0xD0068080, 0xFFFFFF80, "%zq", _C2 },
595 { I_VZERO_S, "vzero.s", 0xD0060000, 0xFFFFFF80, "%zs", _C2 },
596 { I_VZERO_T, "vzero.t", 0xD0068000, 0xFFFFFF80, "%zt", _C2 },
597 { I_MFVME, "mfvme", 0x68000000, 0xFC000000, "%t, %i", _WT|_C2 },
598 { I_MTVME, "mtvme", 0xb0000000, 0xFC000000, "%t, %i", _RT|_C2 },
601 #define NUM_INSTRUCTIONS (sizeof (instructions) / sizeof (struct allegrex_instruction))
603 static char buffer[1024];
604 const char *gpr_names[] =
606 "zr", "at", "v0", "v1", "a0", "a1", "a2", "a3",
607 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
608 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
609 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
612 static const char *cop0_regs[] =
614 "COP0_0", "COP0_1", "COP0_2", "COP0_3", "COP0_4", "COP0_5", "COP0_6", "COP0_7",
615 "BadVaddr", "Count", "COP0_10", "Compare", "Status", "Cause", "EPC", "PrID",
616 "Config", "COP0_17", "COP0_18", "COP0_19", "COP0_20", "COP0_21", "COP0_22", "COP0_23",
617 "COP0_24", "EBase", "COP0_26", "COP0_27", "TagLo", "TagHi", "ErrorPC", "COP0_31"
621 static const char *debug_regs[] =
623 "DRCNTL", "DEPC", "DDATA0", "DDATA1", "IBC", "DBC", "Debug06", "Debug07",
624 "IBA", "IBAM", "Debug10", "Debug11", "DBA", "DBAM", "DBD", "DBDM",
625 "Debug16", "Debug17", "Debug18", "Debug19", "Debug20", "Debug21", "Debug22", "Debug23",
626 "Debug24", "Debug25", "Debug26", "Debug27", "Debug28", "Debug29", "Debug30", "Debug31"
629 static const char *vfpu_cond_names[] =
631 "FL", "EQ", "LT", "LE",
632 "TR", "NE", "GE", "GT",
633 "EZ", "EN", "EI", "ES",
634 "NZ", "NN", "NI", "NS"
637 static const char *vfpu_constants[] = {
638 "VFPU_CONST0",
639 "VFPU_HUGE",
640 "VFPU_SQRT2",
641 "VFPU_SQRT1_2",
642 "VFPU_2_SQRTPI",
643 "VFPU_2_PI",
644 "VFPU_1_PI",
645 "VFPU_PI_4",
646 "VFPU_PI_2",
647 "VFPU_PI",
648 "VFPU_E",
649 "VFPU_LOG2E",
650 "VFPU_LOG10E",
651 "VFPU_LN2",
652 "VFPU_LN10",
653 "VFPU_2PI",
654 "VFPU_PI_6",
655 "VFPU_LOG10TWO",
656 "VFPU_LOG2TEN",
657 "VFPU_SQRT3_2",
658 "VFPU_CONST20",
659 "VFPU_CONST21",
660 "VFPU_CONST22",
661 "VFPU_CONST23",
662 "VFPU_CONST24",
663 "VFPU_CONST25",
664 "VFPU_CONST26",
665 "VFPU_CONST27",
666 "VFPU_CONST28",
667 "VFPU_CONST29",
668 "VFPU_CONST30",
669 "VFPU_CONST31",
672 static const char *pfx_cst_names[] =
674 "0", "1", "2", "1/2", "3", "1/3", "1/4", "1/6"
677 static const char *pfx_swz_names[] =
679 "x", "y", "z", "w"
682 static const char *pfx_sat_names[] =
684 "", "[0:1]", "", "[-1:1]"
687 /* [hlide] added vfpu_extra_regs */
688 static const char *vfpu_extra_regs[] =
690 "VFPU_PFXS",
691 "VFPU_PFXT",
692 "VFPU_PFXD",
693 "VFPU_CC ",
694 "VFPU_INF4",
695 NULL,
696 NULL,
697 "VFPU_REV",
698 "VFPU_RCX0",
699 "VFPU_RCX1",
700 "VFPU_RCX2",
701 "VFPU_RCX3",
702 "VFPU_RCX4",
703 "VFPU_RCX5",
704 "VFPU_RCX6",
705 "VFPU_RCX7"
708 static
709 int print_vfpu_single (int reg, char *output)
711 return sprintf (output, "S%d%d%d", (reg >> 2) & 7, reg & 3, (reg >> 5) & 3);
714 static
715 int print_vfpu_reg (int reg, int offset, char one, char two, char *output)
717 if ((reg >> 5) & 1) {
718 return sprintf (output, "%c%d%d%d", two, (reg >> 2) & 7, offset, reg & 3);
719 } else {
720 return sprintf (output, "%c%d%d%d", one, (reg >> 2) & 7, reg & 3, offset);
724 static
725 int print_vfpu_quad (int reg, char *output)
727 return print_vfpu_reg (reg, 0, 'C', 'R', output);
730 static
731 int print_vfpu_pair (int reg, char *output)
733 if ((reg >> 6) & 1) {
734 return print_vfpu_reg (reg, 2, 'C', 'R', output);
735 } else {
736 return print_vfpu_reg (reg, 0, 'C', 'R', output);
740 static
741 int print_vfpu_triple (int reg, char *output)
743 if ((reg >> 6) & 1) {
744 return print_vfpu_reg (reg, 1, 'C', 'R', output);
745 } else {
746 return print_vfpu_reg (reg, 0, 'C', 'R', output);
750 static
751 int print_vfpu_mpair (int reg, char *output)
753 if ((reg >> 6) & 1) {
754 return print_vfpu_reg (reg, 2, 'M', 'E', output);
755 } else {
756 return print_vfpu_reg (reg, 0, 'M', 'E', output);
760 static
761 int print_vfpu_mtriple (int reg, char *output)
763 if ((reg >> 6) & 1) {
764 return print_vfpu_reg (reg, 1, 'M', 'E', output);
765 } else {
766 return print_vfpu_reg (reg, 0, 'M', 'E', output);
770 static
771 int print_vfpu_matrix (int reg, char *output)
773 return print_vfpu_reg (reg, 0, 'M', 'E', output);
776 static
777 int print_vfpu_register (int reg, char type, char *output)
779 switch (type) {
780 case 's': return print_vfpu_single (reg, output);
781 case 'q': return print_vfpu_quad (reg, output);
782 case 'p': return print_vfpu_pair (reg, output);
783 case 't': return print_vfpu_triple (reg, output);
784 case 'm': return print_vfpu_mpair (reg, output);
785 case 'n': return print_vfpu_mtriple (reg, output);
786 case 'o': return print_vfpu_matrix (reg, output);
789 return 0;
792 static
793 int print_vfpu_halffloat (int l, char *output)
795 unsigned short float16 = l & 0xFFFF;
796 unsigned int sign = (float16 >> VFPU_SH_FLOAT16_SIGN) & VFPU_MASK_FLOAT16_SIGN;
797 int exponent = (float16 >> VFPU_SH_FLOAT16_EXP) & VFPU_MASK_FLOAT16_EXP;
798 unsigned int fraction = float16 & VFPU_MASK_FLOAT16_FRAC;
799 char signchar = '+' + ((sign == 1) * 2);
800 int len;
801 /* Convert a VFPU 16-bit floating-point number to IEEE754. */
802 union float2int
804 unsigned int i;
805 float f;
806 } float2int;
808 if (exponent == VFPU_FLOAT16_EXP_MAX) {
809 if (fraction == 0)
810 len = sprintf (output, "%cInf", signchar);
811 else
812 len = sprintf (output, "%cNaN", signchar);
813 } else if (exponent == 0 && fraction == 0) {
814 len = sprintf (output, "%c0", signchar);
815 } else {
816 if (exponent == 0) {
817 do {
818 fraction <<= 1;
819 exponent--;
820 } while (!(fraction & (VFPU_MASK_FLOAT16_FRAC + 1)));
822 fraction &= VFPU_MASK_FLOAT16_FRAC;
825 /* Convert to 32-bit single-precision IEEE754. */
826 float2int.i = sign << 31;
827 float2int.i |= (exponent + 112) << 23;
828 float2int.i |= fraction << 13;
829 len = sprintf (output, "%g", float2int.f);
832 return len;
835 /* [hlide] added print_vfpu_prefix */
836 static
837 int print_vfpu_prefix (int l, unsigned int pos, char *output)
839 int len = 0;
841 switch (pos)
843 case '0':
844 case '1':
845 case '2':
846 case '3':
848 unsigned int base = '0';
849 unsigned int negation = (l >> (pos - (base - VFPU_SH_PFX_NEG))) & VFPU_MASK_PFX_NEG;
850 unsigned int constant = (l >> (pos - (base - VFPU_SH_PFX_CST))) & VFPU_MASK_PFX_CST;
851 unsigned int abs_consthi = (l >> (pos - (base - VFPU_SH_PFX_ABS_CSTHI))) & VFPU_MASK_PFX_ABS_CSTHI;
852 unsigned int swz_constlo = (l >> ((pos - base) * 2)) & VFPU_MASK_PFX_SWZ_CSTLO;
854 if (negation)
855 len = sprintf (output, "-");
856 if (constant) {
857 len += sprintf (output + len, "%s", pfx_cst_names[(abs_consthi << 2) | swz_constlo]);
858 } else {
859 if (abs_consthi)
860 len += sprintf (output + len, "|%s|", pfx_swz_names[swz_constlo]);
861 else
862 len += sprintf (output + len, "%s", pfx_swz_names[swz_constlo]);
865 break;
867 case '4':
868 case '5':
869 case '6':
870 case '7':
872 unsigned int base = '4';
873 unsigned int mask = (l >> (pos - (base - VFPU_SH_PFX_MASK))) & VFPU_MASK_PFX_MASK;
874 unsigned int saturation = (l >> ((pos - base) * 2)) & VFPU_MASK_PFX_SAT;
876 if (mask)
877 len += sprintf (output, "m");
878 else
879 len += sprintf (output, "%s", pfx_sat_names[saturation]);
881 break;
884 return len;
888 static
889 int print_vfpu_rotator (int l, char *output)
891 int len;
893 const char *elements[4];
895 unsigned int opcode = l & VFPU_MASK_OP_SIZE;
896 unsigned int rotators = (l >> 16) & 0x1f;
897 unsigned int opsize, rothi, rotlo, negation, i;
899 /* Determine the operand size so we'll know how many elements to output. */
900 if (opcode == VFPU_OP_SIZE_PAIR)
901 opsize = 2;
902 else if (opcode == VFPU_OP_SIZE_TRIPLE)
903 opsize = 3;
904 else
905 opsize = (opcode == VFPU_OP_SIZE_QUAD) * 4; /* Sanity check. */
907 rothi = (rotators >> VFPU_SH_ROT_HI) & VFPU_MASK_ROT_HI;
908 rotlo = (rotators >> VFPU_SH_ROT_LO) & VFPU_MASK_ROT_LO;
909 negation = (rotators >> VFPU_SH_ROT_NEG) & VFPU_MASK_ROT_NEG;
911 if (rothi == rotlo) {
912 if (negation) {
913 elements[0] = "-s";
914 elements[1] = "-s";
915 elements[2] = "-s";
916 elements[3] = "-s";
917 } else {
918 elements[0] = "s";
919 elements[1] = "s";
920 elements[2] = "s";
921 elements[3] = "s";
923 } else {
924 elements[0] = "0";
925 elements[1] = "0";
926 elements[2] = "0";
927 elements[3] = "0";
929 if (negation)
930 elements[rothi] = "-s";
931 else
932 elements[rothi] = "s";
933 elements[rotlo] = "c";
935 len = sprintf (output, "[");
936 for (i = 0;;) {
937 len += sprintf (output + len, "%s", elements[i++]);
938 if (i >= opsize)
939 break;
940 sprintf (output + len, " ,");
943 len += sprintf (output + len, "]");
945 return len;
948 /* [hlide] added print_cop2 */
949 static
950 int print_cop2 (int reg, char *output)
952 int len;
954 if ((reg >= 128) && (reg < 128+16) && (vfpu_extra_regs[reg - 128])) {
955 len = sprintf (output, "%s", vfpu_extra_regs[reg - 128]);
956 } else {
957 len = sprintf (output, "VFPU_COP2_%d", reg);
960 return len;
964 static
965 void print_instruction (const struct allegrex_instruction *insn, unsigned int opcode, unsigned int PC, int prtall)
967 int i = 0, len = 0, vmmul = 0;
968 unsigned int data = opcode;
970 if (prtall) {
971 len += sprintf (buffer, "0x%08X: 0x%08X '", PC, opcode);
972 for (i = 0; i < 4; i++) {
973 char c = (char) (data & 0xFF);
974 if (isprint (c)) { len += sprintf (&buffer[len], "%c", c); }
975 else { len += sprintf (&buffer[len], "."); }
976 data >>= 8;
978 len += sprintf (&buffer[len], "' - ");
980 if (!insn) {
981 sprintf (&buffer[len], "Invalid");
982 return;
984 len += sprintf (&buffer[len], "%-10s ", insn->name);
986 i = 0;
987 while (1) {
988 char c = insn->fmt[i++];
989 if (c == '\0') break;
990 if (c == '%') {
991 c = insn->fmt[i++];
992 switch (c) {
993 case 'd':
994 len += sprintf (&buffer[len], "$%s", gpr_names[RD (opcode)]);
995 break;
996 case 'D':
997 len += sprintf (&buffer[len], "$fpr%02d", FD (opcode));
998 break;
999 case 't':
1000 len += sprintf (&buffer[len], "$%s", gpr_names[RT (opcode)]);
1001 break;
1002 case 'T':
1003 len += sprintf (&buffer[len], "$fpr%02d", FT (opcode));
1004 break;
1005 case 's':
1006 len += sprintf (&buffer[len], "$%s", gpr_names[RS (opcode)]);
1007 break;
1008 case 'S':
1009 len += sprintf (&buffer[len], "$fpr%02d", FS (opcode));
1010 break;
1011 case 'J':
1012 len += sprintf (&buffer[len], "$%s", gpr_names[RS (opcode)]);
1013 break;
1014 case 'i':
1015 len += sprintf (&buffer[len], "%d", IMM (opcode));
1016 break;
1017 case 'I':
1018 len += sprintf (&buffer[len], "0x%04X", IMMU (opcode));
1019 break;
1020 case 'j':
1021 len += sprintf (&buffer[len], "0x%08X", JUMP (opcode, PC));
1022 break;
1023 case 'O':
1024 len += sprintf (&buffer[len], "0x%08X", PC + 4 + 4 * ((int) IMM (opcode)));
1025 break;
1026 case 'o':
1027 len += sprintf (&buffer[len], "%d($%s)", IMM (opcode), gpr_names[RS (opcode)]);
1028 break;
1029 case 'c':
1030 if (CODE(opcode) != 0)
1031 len += sprintf (&buffer[len], "0x%05X", CODE (opcode));
1032 break;
1033 case 'k':
1034 len += sprintf (&buffer[len], "0x%X", RT (opcode));
1035 break;
1036 case 'p':
1037 len += sprintf (&buffer[len], "$%d", RD (opcode));
1038 break;
1039 case 'a':
1040 len += sprintf (&buffer[len], "%d", SA (opcode));
1041 break;
1042 case 'r':
1043 len += sprintf (&buffer[len], "%s", debug_regs[RD (opcode)]);
1044 break;
1045 case '0':
1046 len += sprintf (&buffer[len], "%s", cop0_regs[RD (opcode)]);
1047 break;
1048 case '1':
1049 len += sprintf (&buffer[len], "$fpr%d", RD (opcode));
1050 break;
1051 case '2':
1052 c = insn->fmt[i++];
1053 if (c == 'd') {
1054 len += print_cop2 (VED (opcode), &buffer[len]);
1055 } else { /* 's'*/
1056 len += print_cop2 (VES (opcode), &buffer[len]);
1058 break;
1059 case 'z':
1060 c = insn->fmt[i++];
1061 len += print_vfpu_register (VD (opcode), c, &buffer[len]);
1062 break;
1063 case 'Z':
1064 c = insn->fmt[i++];
1065 if (c == 'c') {
1066 len += sprintf (&buffer[len], "%d", VCC (opcode));
1067 } else { /* 'n' */
1068 len += sprintf (&buffer[len], "%s", vfpu_cond_names[VCN (opcode)]);
1070 break;
1071 case 'n':
1072 c = insn->fmt[i++];
1073 if (c == 'e') {
1074 len += sprintf (&buffer[len], "%d", RD (opcode) + 1);
1075 } else { /* 'i' */
1076 len += sprintf (&buffer[len], "%d", RD (opcode) - SA (opcode) + 1);
1078 break;
1079 case 'X':
1080 c = insn->fmt[i++];
1081 len += print_vfpu_register (VO (opcode), c, &buffer[len]);
1082 break;
1083 case 'x':
1084 c = insn->fmt[i++];
1085 len += print_vfpu_register (VT (opcode), c, &buffer[len]);
1086 break;
1087 case 'Y':
1088 len += sprintf (&buffer[len], "%d($%s)", IMM (opcode) & ~3, gpr_names[RS (opcode)]);
1089 break;
1090 case 'y':
1092 int reg = VS (opcode);
1093 if (vmmul) { if (reg & 0x20) { reg &= 0x5F; } else { reg |= 0x20; } }
1094 c = insn->fmt[i++];
1095 len += print_vfpu_register (reg, c, &buffer[len]);
1097 break;
1098 case 'v':
1099 c = insn->fmt[i++];
1100 switch (c) {
1101 case '3' : len += sprintf (&buffer[len], "%d", VI3 (opcode)); break;
1102 case '5' : len += sprintf (&buffer[len], "%d", VI5 (opcode)); break;
1103 case '8' : len += sprintf (&buffer[len], "%d", VI8 (opcode)); break;
1104 case 'k' : len += sprintf (&buffer[len], "%s", vfpu_constants [VI5 (opcode)]); break;
1105 case 'i' : len += sprintf (&buffer[len], "%d", IMM (opcode)); break;
1106 case 'h' : len += print_vfpu_halffloat (opcode, &buffer[len]); break;
1107 case 'r' : len += print_vfpu_rotator (opcode, &buffer[len]); break;
1108 case 'p' : c = insn->fmt[i++]; len += print_vfpu_prefix (opcode, c, &buffer[len]); break;
1110 break;
1111 case '?':
1112 vmmul = 1;
1113 break;
1115 } else {
1116 len += sprintf (&buffer[len], "%c", c);
1119 while (buffer[len-1] == ' ' && len > 0) len--;
1120 buffer[len] = '\0';
1123 #ifdef SLOW_VERSION
1124 const struct allegrex_instruction *allegrex_decode (unsigned int opcode, int allowalias)
1126 int i;
1128 for (i = 0; i < sizeof (instructions) / sizeof (struct allegrex_instruction); i++) {
1129 printf ("Scanning %s 0x%08X 0x%08X\n", instructions[i].name, instructions[i].mask & opcode, instructions[i].opcode);
1130 if ((instructions[i].mask & opcode) == instructions[i].opcode) {
1131 if (allowalias || !(instructions[i].flags & INSN_ALIAS))
1132 return &instructions[i];
1135 return NULL;
1138 #else /* !SLOW_VERSION */
1140 #include "allefast.c"
1142 const struct allegrex_instruction *allegrex_decode (unsigned int opcode, int allowalias)
1144 int cmdpos = 0;
1145 unsigned int temp;
1146 int low, high, pos;
1148 while (1) {
1149 struct disasm_command *cmd = &command[cmdpos];
1150 switch (cmd->type) {
1151 case COMMAND_TEST:
1152 case COMMAND_END:
1153 if ((cmd->param2 & opcode) == cmd->param1) {
1154 if (allowalias || !(instructions[cmd->param3].flags & INSN_ALIAS))
1155 return &instructions[cmd->param3];
1157 if (cmd->type == COMMAND_TEST) {
1158 cmdpos++;
1159 } else {
1160 return NULL;
1163 break;
1164 case COMMAND_INDEX:
1165 temp = (opcode >> cmd->param1) & cmd->param2;
1166 cmdpos = arrayidx[cmd->param3 + temp];
1167 if (cmdpos == -1) return NULL;
1168 break;
1169 case COMMAND_BSEARCH:
1170 low = cmd->param1;
1171 high = cmd->param2;
1172 temp = opcode & cmd->param3;
1173 while (high >= low) {
1174 pos = (low + high) / 2;
1175 if (bsidx[pos].opcode == temp) {
1176 cmdpos = bsidx[pos].index;
1177 break;
1178 } else if (bsidx[pos].opcode > temp) {
1179 high = pos - 1;
1180 } else {
1181 low = pos + 1;
1184 if (high < low) return NULL;
1185 break;
1190 #endif /* !SLOW_VERSION */
1192 char *allegrex_disassemble (unsigned int opcode, unsigned int PC, int prtall)
1194 const struct allegrex_instruction *insn = allegrex_decode (opcode, 1);
1195 print_instruction (insn, opcode, PC, prtall);
1196 return (char *) buffer;
1199 #ifdef TEST_DISASSEMBLE
1201 #include <stdlib.h>
1203 int main (int argc, char **argv)
1205 int i;
1207 for (i = 0; i < NUM_INSTRUCTIONS; i++) {
1208 unsigned int opcode = rand ();
1209 opcode = (opcode & (~instructions[i].mask)) | instructions[i].opcode;
1210 printf ("%s\n", allegrex_disassemble (opcode, 4 * i, 1));
1213 return 0;
1216 #endif /* TEST_DISASSEMBLE */
1218 #ifdef MAKE_INDEX
1220 #include <stdlib.h>
1222 static unsigned int cmp_mask;
1223 static struct allegrex_instruction _instructions[NUM_INSTRUCTIONS];
1224 static int _arrayidx_pos, _bsidx_pos, _command_pos;
1225 static struct disasm_command _command[1024];
1226 static struct bsearch_index _bsidx[1024];
1227 static int _arrayidx[1024];
1228 static int max_cmd_count;
1230 int cmp_func (const void *p1, const void *p2)
1232 const struct allegrex_instruction *i1 = p1;
1233 const struct allegrex_instruction *i2 = p2;
1235 if ((i1->opcode & cmp_mask) > (i2->opcode & cmp_mask)) return 1;
1236 if ((i1->opcode & cmp_mask) < (i2->opcode & cmp_mask)) return -11;
1237 if ((i1->insn) > (i2->insn)) return 1;
1238 if ((i1->insn) < (i2->insn)) return -1;
1239 if ((i1->mask) > (i2->mask)) return 1;
1240 if ((i1->mask) > (i2->mask)) return -1;
1241 return 0;
1244 void sort (int bpos, int epos, unsigned int oldmask, int cmdcount)
1246 int i, j, numgroups;
1247 unsigned int temp, mask;
1249 cmp_mask = ~0;
1250 for (i = bpos; i < epos; i++) {
1251 cmp_mask &= _instructions[i].mask;
1253 mask = cmp_mask;
1254 qsort (&_instructions[bpos], epos - bpos, sizeof (struct allegrex_instruction), &cmp_func);
1256 numgroups = 1;
1257 temp = _instructions[bpos].opcode & mask;
1258 for (i = bpos; i < epos; i++) {
1259 if ((_instructions[i].opcode & mask) != temp) {
1260 temp = _instructions[i].opcode & mask;
1261 numgroups++;
1265 if (numgroups == 1) {
1266 for (i = bpos; i < epos; i++) {
1267 _command[_command_pos].type = (i == (epos - 1)) ? COMMAND_END : COMMAND_TEST;
1268 _command[_command_pos].param1 = _instructions[i].opcode;
1269 _command[_command_pos].param2 = _instructions[i].mask;
1270 _command[_command_pos].param3 = _instructions[i].insn;
1271 _command_pos++;
1273 cmdcount += epos - bpos;
1274 } else {
1275 unsigned int shift = 0, nbits = 0, bits = 0;
1276 temp = mask ^ oldmask;
1278 while ((temp & 0x01) == 0) {
1279 shift++; temp >>= 1;
1281 while ((temp & 0x01) == 1) {
1282 nbits++; temp >>= 1;
1285 if (temp == 0 && nbits <= 6) {
1286 int arraypos = _arrayidx_pos;
1287 bits = (1 << nbits) - 1;
1288 _arrayidx_pos += (1 << nbits);
1289 for (i = arraypos; i < _arrayidx_pos; i++)
1290 _arrayidx[i] = -1;
1291 _command[_command_pos].type = COMMAND_INDEX;
1292 _command[_command_pos].param1 = shift;
1293 _command[_command_pos].param2 = bits;
1294 _command[_command_pos].param3 = arraypos;
1295 _command_pos++;
1297 cmdcount++;
1298 temp = _instructions[bpos].opcode & mask;
1299 for (i = j = bpos; i < epos; i++) {
1300 if ((_instructions[i].opcode & mask) != temp) {
1301 _arrayidx[arraypos + ((temp >> shift) & bits)] = _command_pos;
1302 sort (j, i, mask, cmdcount);
1304 j = i; temp = _instructions[i].opcode & mask;
1307 _arrayidx[arraypos + ((temp >> shift) & bits)] = _command_pos;
1308 sort (j, i, mask, cmdcount);
1310 } else {
1311 int bsearchpos = _bsidx_pos;
1312 _bsidx_pos += numgroups;
1313 _command[_command_pos].type = COMMAND_BSEARCH;
1314 _command[_command_pos].param1 = bsearchpos;
1315 _command[_command_pos].param2 = _bsidx_pos - 1;
1316 _command[_command_pos].param3 = mask;
1317 _command_pos++;
1319 temp = numgroups;
1320 cmdcount++;
1321 while (temp) {
1322 temp >>= 1;
1323 cmdcount++;
1326 temp = _instructions[bpos].opcode & mask;
1327 for (i = j = bpos; i < epos; i++) {
1328 if ((_instructions[i].opcode & mask) != temp) {
1329 _bsidx[bsearchpos].index = _command_pos;
1330 _bsidx[bsearchpos++].opcode = temp;
1331 sort (j, i, mask, cmdcount);
1333 j = i; temp = _instructions[i].opcode & mask;
1336 _bsidx[bsearchpos].index = _command_pos;
1337 _bsidx[bsearchpos++].opcode = temp;
1338 sort (j, i, mask, cmdcount);
1342 if (cmdcount > max_cmd_count)
1343 max_cmd_count = cmdcount;
1347 int main (int argc, char **argv)
1349 int i;
1351 for (i = 0; i < NUM_INSTRUCTIONS; i++) {
1352 _instructions[i] = instructions[i];
1353 _instructions[i].insn = i;
1356 sort (0, NUM_INSTRUCTIONS, 0, 0);
1357 fprintf (stderr, "max_cmd_count = %d\n", max_cmd_count);
1358 fprintf (stderr, "_arrayidx_pos = %d, _bsidx_pos = %d, _command_pos = %d\n",
1359 _arrayidx_pos, _bsidx_pos, _command_pos);
1362 printf ("static int arrayidx[] = {\n");
1363 for (i = 0; i < _arrayidx_pos; i++) {
1364 printf (" %d", _arrayidx[i]);
1365 if (i != (_arrayidx_pos - 1)) printf (",");
1366 printf ("\n");
1368 printf ("};\n");
1370 printf ("static struct bsearch_index bsidx[] = {\n");
1371 for (i = 0; i < _bsidx_pos; i++) {
1372 printf (" { %8d, 0x%08X }", _bsidx[i].index, _bsidx[i].opcode);
1373 if (i != (_bsidx_pos - 1)) printf (",");
1374 printf ("\n");
1376 printf ("};\n");
1378 printf ("static struct disasm_command command[] = {\n");
1379 for (i = 0; i < _command_pos; i++) {
1380 switch (_command[i].type) {
1381 case COMMAND_BSEARCH:
1382 printf (" { COMMAND_BSEARCH, %10d, %10d, 0x%08X }",
1383 _command[i].param1, _command[i].param2, _command[i].param3);
1384 break;
1385 case COMMAND_INDEX:
1386 printf (" { COMMAND_INDEX, %10d, 0x%08X, %-10d }",
1387 _command[i].param1, _command[i].param2, _command[i].param3);
1388 break;
1389 case COMMAND_TEST:
1390 printf (" { COMMAND_TEST, 0x%08X, 0x%08X, %-10d }",
1391 _command[i].param1, _command[i].param2, _command[i].param3);
1392 break;
1393 case COMMAND_END:
1394 printf (" { COMMAND_END, 0x%08X, 0x%08X, %-10d }",
1395 _command[i].param1, _command[i].param2, _command[i].param3);
1396 break;
1398 if (i != (_command_pos - 1)) printf (",");
1399 printf ("\n");
1401 printf ("};\n");
1403 return 0;
1407 #endif /* MAKE_INDEX */