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