Problemas com os relocs
[pspdecompiler.git] / allegrex.c
blobd948faff9a1d9a85ed25875b36a9c90e1c7393c7
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)
35 * %C - code (for syscall)
36 * %? - Indicates vmmul special exception
39 #define RT(op) ((op >> 16) & 0x1F)
40 #define RS(op) ((op >> 21) & 0x1F)
41 #define RD(op) ((op >> 11) & 0x1F)
42 #define FT(op) ((op >> 16) & 0x1F)
43 #define FS(op) ((op >> 11) & 0x1F)
44 #define FD(op) ((op >> 6) & 0x1F)
45 #define SA(op) ((op >> 6) & 0x1F)
46 #define IMM(op) ((signed short) (op & 0xFFFF))
47 #define IMMU(op) ((unsigned short) (op & 0xFFFF))
48 #define JUMP(op, pc) ((pc & 0xF0000000) | ((op & 0x3FFFFFF) << 2))
49 #define CODE(op) ((op >> 6) & 0xFFFFF)
50 #define SIZE(op) ((op >> 11) & 0x1F)
51 #define POS(op) ((op >> 6) & 0x1F)
52 #define VO(op) (((op & 3) << 5) | ((op >> 16) & 0x1F))
53 #define VCC(op) ((op >> 18) & 7)
54 #define VD(op) (op & 0x7F)
55 #define VS(op) ((op >> 8) & 0x7F)
56 #define VT(op) ((op >> 16) & 0x7F)
58 /* [hlide] new #defines */
59 #define VED(op) (op & 0xFF)
60 #define VES(op) ((op >> 8) & 0xFF)
61 #define VCN(op) (op & 0x0F)
62 #define VI3(op) ((op >> 16) & 0x07)
63 #define VI5(op) ((op >> 16) & 0x1F)
64 #define VI8(op) ((op >> 16) & 0xFF)
66 /* VFPU 16-bit floating-point format. */
67 #define VFPU_FLOAT16_EXP_MAX 0x1f
68 #define VFPU_SH_FLOAT16_SIGN 15
69 #define VFPU_MASK_FLOAT16_SIGN 0x1
70 #define VFPU_SH_FLOAT16_EXP 10
71 #define VFPU_MASK_FLOAT16_EXP 0x1f
72 #define VFPU_SH_FLOAT16_FRAC 0
73 #define VFPU_MASK_FLOAT16_FRAC 0x3ff
75 /* VFPU prefix instruction operands. The *_SH_* values really specify where
76 the bitfield begins, as VFPU prefix instructions have four operands
77 encoded within the immediate field. */
78 #define VFPU_SH_PFX_NEG 16
79 #define VFPU_MASK_PFX_NEG 0x1 /* Negation. */
80 #define VFPU_SH_PFX_CST 12
81 #define VFPU_MASK_PFX_CST 0x1 /* Constant. */
82 #define VFPU_SH_PFX_ABS_CSTHI 8
83 #define VFPU_MASK_PFX_ABS_CSTHI 0x1 /* Abs/Constant (bit 2). */
84 #define VFPU_SH_PFX_SWZ_CSTLO 0
85 #define VFPU_MASK_PFX_SWZ_CSTLO 0x3 /* Swizzle/Constant (bits 0-1). */
86 #define VFPU_SH_PFX_MASK 8
87 #define VFPU_MASK_PFX_MASK 0x1 /* Mask. */
88 #define VFPU_SH_PFX_SAT 0
89 #define VFPU_MASK_PFX_SAT 0x3 /* Saturation. */
91 /* Special handling of the vrot instructions. */
92 #define VFPU_MASK_OP_SIZE 0x8080 /* Masks the operand size (pair, triple, quad). */
93 #define VFPU_OP_SIZE_PAIR 0x80
94 #define VFPU_OP_SIZE_TRIPLE 0x8000
95 #define VFPU_OP_SIZE_QUAD 0x8080
96 /* Note that these are within the rotators field, and not the full opcode. */
97 #define VFPU_SH_ROT_HI 2
98 #define VFPU_MASK_ROT_HI 0x3
99 #define VFPU_SH_ROT_LO 0
100 #define VFPU_MASK_ROT_LO 0x3
101 #define VFPU_SH_ROT_NEG 4 /* Negation. */
102 #define VFPU_MASK_ROT_NEG 0x1
105 struct allegrex_instruction
107 enum insn_type itype;
108 const char *name;
109 unsigned int opcode;
110 unsigned int mask;
111 const char *fmt;
114 static struct allegrex_instruction instructions[] =
116 /* Macro instructions */
117 { I_SLL, "nop", 0x00000000, 0xFFFFFFFF, "" },
118 { I_ADDIU, "li", 0x24000000, 0xFFE00000, "%t, %i" },
119 { I_ORI, "li", 0x34000000, 0xFFE00000, "%t, %I" },
120 { I_ADDU, "move", 0x00000021, 0xFC1F07FF, "%d, %s" },
121 { I_OR, "move", 0x00000025, 0xFC1F07FF, "%d, %s" },
122 { I_BEQ, "b", 0x10000000, 0xFFFF0000, "%O" },
123 { I_BGEZ, "b", 0x04010000, 0xFFFF0000, "%O" },
124 { I_BGEZAL, "bal", 0x04110000, 0xFFFF0000, "%O" },
125 { I_BNE, "bnez", 0x14000000, 0xFC1F0000, "%s, %O" },
126 { I_BNEL, "bnezl", 0x54000000, 0xFC1F0000, "%s, %O" },
127 { I_BEQ, "beqz", 0x10000000, 0xFC1F0000, "%s, %O" },
128 { I_BEQL, "beqzl", 0x50000000, 0xFC1F0000, "%s, %O" },
129 { I_SUB, "neg", 0x00000022, 0xFFE007FF, "%d, %t" },
130 { I_SUBU, "negu", 0x00000023, 0xFFE007FF, "%d, %t" },
131 { I_NOR, "not", 0x00000027, 0xFC1F07FF, "%d, %s" },
132 { I_JALR, "jalr", 0x0000F809, 0xFC1FFFFF, "%J" },
134 /* MIPS instructions */
135 { I_ADD, "add", 0x00000020, 0xFC0007FF, "%d, %s, %t" },
136 { I_ADDI, "addi", 0x20000000, 0xFC000000, "%t, %s, %i" },
137 { I_ADDIU, "addiu", 0x24000000, 0xFC000000, "%t, %s, %i" },
138 { I_ADDU, "addu", 0x00000021, 0xFC0007FF, "%d, %s, %t" },
139 { I_AND, "and", 0x00000024, 0xFC0007FF, "%d, %s, %t" },
140 { I_ANDI, "andi", 0x30000000, 0xFC000000, "%t, %s, %I" },
141 { I_BEQ, "beq", 0x10000000, 0xFC000000, "%s, %t, %O" },
142 { I_BEQL, "beql", 0x50000000, 0xFC000000, "%s, %t, %O" },
143 { I_BGEZ, "bgez", 0x04010000, 0xFC1F0000, "%s, %O" },
144 { I_BGEZAL, "bgezal", 0x04110000, 0xFC1F0000, "%s, %O" },
145 { I_BGEZL, "bgezl", 0x04030000, 0xFC1F0000, "%s, %O" },
146 { I_BGTZ, "bgtz", 0x1C000000, 0xFC1F0000, "%s, %O" },
147 { I_BGTZL, "bgtzl", 0x5C000000, 0xFC1F0000, "%s, %O" },
148 { I_BITREV, "bitrev", 0x7C000520, 0xFFE007FF, "%d, %t" },
149 { I_BLEZ, "blez", 0x18000000, 0xFC1F0000, "%s, %O" },
150 { I_BLEZL, "blezl", 0x58000000, 0xFC1F0000, "%s, %O" },
151 { I_BLTZ, "bltz", 0x04000000, 0xFC1F0000, "%s, %O" },
152 { I_BLTZL, "bltzl", 0x04020000, 0xFC1F0000, "%s, %O" },
153 { I_BLTZAL, "bltzal", 0x04100000, 0xFC1F0000, "%s, %O" },
154 { I_BLTZALL, "bltzall", 0x04120000, 0xFC1F0000, "%s, %O" },
155 { I_BNE, "bne", 0x14000000, 0xFC000000, "%s, %t, %O" },
156 { I_BNEL, "bnel", 0x54000000, 0xFC000000, "%s, %t, %O" },
157 { I_BREAK, "break", 0x0000000D, 0xFC00003F, "%c" },
158 { I_CACHE, "cache", 0xbc000000, 0xfc000000, "%k, %o" },
159 { I_CFC0, "cfc0", 0x40400000, 0xFFE007FF, "%t, %p" },
160 { I_CLO, "clo", 0x00000017, 0xFC1F07FF, "%d, %s" },
161 { I_CLZ, "clz", 0x00000016, 0xFC1F07FF, "%d, %s" },
162 { I_CTC0, "ctc0", 0x40C00000, 0xFFE007FF, "%t, %p" },
163 { I_MAX, "max", 0x0000002C, 0xFC0007FF, "%d, %s, %t" },
164 { I_MIN, "min", 0x0000002D, 0xFC0007FF, "%d, %s, %t" },
165 { I_DBREAK, "dbreak", 0x7000003F, 0xFFFFFFFF, "" },
166 { I_DIV, "div", 0x0000001A, 0xFC00FFFF, "%s, %t" },
167 { I_DIVU, "divu", 0x0000001B, 0xFC00FFFF, "%s, %t" },
168 { I_DRET, "dret", 0x7000003E, 0xFFFFFFFF, "" },
169 { I_ERET, "eret", 0x42000018, 0xFFFFFFFF, "" },
170 { I_EXT, "ext", 0x7C000000, 0xFC00003F, "%t, %s, %a, %ne" },
171 { I_INS, "ins", 0x7C000004, 0xFC00003F, "%t, %s, %a, %ni" },
172 { I_J, "j", 0x08000000, 0xFC000000, "%j" },
173 { I_JR, "jr", 0x00000008, 0xFC1FFFFF, "%J" },
174 { I_JALR, "jalr", 0x00000009, 0xFC1F07FF, "%J, %d" },
175 { I_JAL, "jal", 0x0C000000, 0xFC000000, "%j" },
176 { I_LB, "lb", 0x80000000, 0xFC000000, "%t, %o" },
177 { I_LBU, "lbu", 0x90000000, 0xFC000000, "%t, %o" },
178 { I_LH, "lh", 0x84000000, 0xFC000000, "%t, %o" },
179 { I_LHU, "lhu", 0x94000000, 0xFC000000, "%t, %o" },
180 { I_LL, "ll", 0xC0000000, 0xFC000000, "%t, %O" },
181 { I_LUI, "lui", 0x3C000000, 0xFFE00000, "%t, %I" },
182 { I_LW, "lw", 0x8C000000, 0xFC000000, "%t, %o" },
183 { I_LWL, "lwl", 0x88000000, 0xFC000000, "%t, %o" },
184 { I_LWR, "lwr", 0x98000000, 0xFC000000, "%t, %o" },
185 { I_MADD, "madd", 0x0000001C, 0xFC00FFFF, "%s, %t" },
186 { I_MADDU, "maddu", 0x0000001D, 0xFC00FFFF, "%s, %t" },
187 { I_MFC0, "mfc0", 0x40000000, 0xFFE007FF, "%t, %0" },
188 { I_MFDR, "mfdr", 0x7000003D, 0xFFE007FF, "%t, %r" },
189 { I_MFHI, "mfhi", 0x00000010, 0xFFFF07FF, "%d" },
190 { I_MFIC, "mfic", 0x70000024, 0xFFE007FF, "%t, %p" },
191 { I_MFLO, "mflo", 0x00000012, 0xFFFF07FF, "%d" },
192 { I_MOVN, "movn", 0x0000000B, 0xFC0007FF, "%d, %s, %t" },
193 { I_MOVZ, "movz", 0x0000000A, 0xFC0007FF, "%d, %s, %t" },
194 { I_MSUB, "msub", 0x0000002e, 0xfc00ffff, "%d, %t" },
195 { I_MSUBU, "msubu", 0x0000002f, 0xfc00ffff, "%d, %t" },
196 { I_MTC0, "mtc0", 0x40800000, 0xFFE007FF, "%t, %0" },
197 { I_MTDR, "mtdr", 0x7080003D, 0xFFE007FF, "%t, %r" },
198 { I_MTIC, "mtic", 0x70000026, 0xFFE007FF, "%t, %p" },
199 { I_HALT, "halt", 0x70000000, 0xFFFFFFFF, "" },
200 { I_MTHI, "mthi", 0x00000011, 0xFC1FFFFF, "%s" },
201 { I_MTLO, "mtlo", 0x00000013, 0xFC1FFFFF, "%s" },
202 { I_MULT, "mult", 0x00000018, 0xFC00FFFF, "%s, %t" },
203 { I_MULTU, "multu", 0x00000019, 0xFC0007FF, "%s, %t" },
204 { I_NOR, "nor", 0x00000027, 0xFC0007FF, "%d, %s, %t" },
205 { I_OR, "or", 0x00000025, 0xFC0007FF, "%d, %s, %t" },
206 { I_ORI, "ori", 0x34000000, 0xFC000000, "%t, %s, %I" },
207 { I_ROTR, "rotr", 0x00200002, 0xFFE0003F, "%d, %t, %a" },
208 { I_ROTV, "rotv", 0x00000046, 0xFC0007FF, "%d, %t, %s" },
209 { I_SEB, "seb", 0x7C000420, 0xFFE007FF, "%d, %t" },
210 { I_SEH, "seh", 0x7C000620, 0xFFE007FF, "%d, %t" },
211 { I_SB, "sb", 0xA0000000, 0xFC000000, "%t, %o" },
212 { I_SH, "sh", 0xA4000000, 0xFC000000, "%t, %o" },
213 { I_SLLV, "sllv", 0x00000004, 0xFC0007FF, "%d, %t, %s" },
214 { I_SLL, "sll", 0x00000000, 0xFFE0003F, "%d, %t, %a" },
215 { I_SLT, "slt", 0x0000002A, 0xFC0007FF, "%d, %s, %t" },
216 { I_SLTI, "slti", 0x28000000, 0xFC000000, "%t, %s, %i" },
217 { I_SLTIU, "sltiu", 0x2C000000, 0xFC000000, "%t, %s, %i" },
218 { I_SLTU, "sltu", 0x0000002B, 0xFC0007FF, "%d, %s, %t" },
219 { I_SRA, "sra", 0x00000003, 0xFFE0003F, "%d, %t, %a" },
220 { I_SRAV, "srav", 0x00000007, 0xFC0007FF, "%d, %t, %s" },
221 { I_SRLV, "srlv", 0x00000006, 0xFC0007FF, "%d, %t, %s" },
222 { I_SRL, "srl", 0x00000002, 0xFFE0003F, "%d, %t, %a" },
223 { I_SW, "sw", 0xAC000000, 0xFC000000, "%t, %o" },
224 { I_SWL, "swl", 0xA8000000, 0xFC000000, "%t, %o" },
225 { I_SWR, "swr", 0xB8000000, 0xFC000000, "%t, %o" },
226 { I_SUB, "sub", 0x00000022, 0xFC0007FF, "%d, %s, %t" },
227 { I_SUBU, "subu", 0x00000023, 0xFC0007FF, "%d, %s, %t" },
228 { I_SYNC, "sync", 0x0000000F, 0xFFFFFFFF, "" },
229 { I_SYSCALL, "syscall", 0x0000000C, 0xFC00003F, "%C" },
230 { I_XOR, "xor", 0x00000026, 0xFC0007FF, "%d, %s, %t" },
231 { I_XORI, "xori", 0x38000000, 0xFC000000, "%t, %s, %I" },
232 { I_WSBH, "wsbh", 0x7C0000A0, 0xFFE007FF, "%d, %t" },
233 { I_WSBW, "wsbw", 0x7C0000E0, 0xFFE007FF, "%d, %t" },
235 /* FPU instructions */
236 { I_ABS_S, "abs.s", 0x46000005, 0xFFFF003F, "%D, %S" },
237 { I_ADD_S, "add.s", 0x46000000, 0xFFE0003F, "%D, %S, %T" },
238 { I_BC1F, "bc1f", 0x45000000, 0xFFFF0000, "%O" },
239 { I_BC1FL, "bc1fl", 0x45020000, 0xFFFF0000, "%O" },
240 { I_BC1T, "bc1t", 0x45010000, 0xFFFF0000, "%O" },
241 { I_BC1TL, "bc1tl", 0x45030000, 0xFFFF0000, "%O" },
242 { I_C_F_S, "c.f.s", 0x46000030, 0xFFE007FF, "%S, %T" },
243 { I_C_UN_S, "c.un.s", 0x46000031, 0xFFE007FF, "%S, %T" },
244 { I_C_EQ_S, "c.eq.s", 0x46000032, 0xFFE007FF, "%S, %T" },
245 { I_C_UEQ_S, "c.ueq.s", 0x46000033, 0xFFE007FF, "%S, %T" },
246 { I_C_OLT_S, "c.olt.s", 0x46000034, 0xFFE007FF, "%S, %T" },
247 { I_C_ULT_S, "c.ult.s", 0x46000035, 0xFFE007FF, "%S, %T" },
248 { I_C_OLE_S, "c.ole.s", 0x46000036, 0xFFE007FF, "%S, %T" },
249 { I_C_ULE_S, "c.ule.s", 0x46000037, 0xFFE007FF, "%S, %T" },
250 { I_C_SF_S, "c.sf.s", 0x46000038, 0xFFE007FF, "%S, %T" },
251 { I_C_NGLE_S, "c.ngle.s", 0x46000039, 0xFFE007FF, "%S, %T" },
252 { I_C_SEQ_S, "c.seq.s", 0x4600003A, 0xFFE007FF, "%S, %T" },
253 { I_C_NGL_S, "c.ngl.s", 0x4600003B, 0xFFE007FF, "%S, %T" },
254 { I_C_LT_S, "c.lt.s", 0x4600003C, 0xFFE007FF, "%S, %T" },
255 { I_C_NGE_S, "c.nge.s", 0x4600003D, 0xFFE007FF, "%S, %T" },
256 { I_C_LE_S, "c.le.s", 0x4600003E, 0xFFE007FF, "%S, %T" },
257 { I_C_NGT_S, "c.ngt.s", 0x4600003F, 0xFFE007FF, "%S, %T" },
258 { I_CEIL_W_S, "ceil.w.s", 0x4600000E, 0xFFFF003F, "%D, %S" },
259 { I_CFC1, "cfc1", 0x44400000, 0xFFE007FF, "%t, %p" },
260 { I_CTC1, "ctc1", 0x44c00000, 0xFFE007FF, "%t, %p" },
261 { I_CVT_S_W, "cvt.s.w", 0x46800020, 0xFFFF003F, "%D, %S" },
262 { I_CVT_W_S, "cvt.w.s", 0x46000024, 0xFFFF003F, "%D, %S" },
263 { I_DIV_S, "div.s", 0x46000003, 0xFFE0003F, "%D, %S, %T" },
264 { I_FLOOR_W_S, "floor.w.s", 0x4600000F, 0xFFFF003F, "%D, %S" },
265 { I_LWC1, "lwc1", 0xc4000000, 0xFC000000, "%T, %o" },
266 { I_MFC1, "mfc1", 0x44000000, 0xFFE007FF, "%t, %1" },
267 { I_MOV_S, "mov.s", 0x46000006, 0xFFFF003F, "%D, %S" },
268 { I_MTC1, "mtc1", 0x44800000, 0xFFE007FF, "%t, %1" },
269 { I_MUL_S, "mul.s", 0x46000002, 0xFFE0003F, "%D, %S, %T" },
270 { I_NEG_S, "neg.s", 0x46000007, 0xFFFF003F, "%D, %S" },
271 { I_ROUND_W_S, "round.w.s", 0x4600000C, 0xFFFF003F, "%D, %S" },
272 { I_SQRT_S, "sqrt.s", 0x46000004, 0xFFFF003F, "%D, %S" },
273 { I_SUB_S, "sub.s", 0x46000001, 0xFFE0003F, "%D, %S, %T" },
274 { I_SWC1, "swc1", 0xe4000000, 0xFC000000, "%T, %o" },
275 { I_TRUNC_W_S, "trunc.w.s", 0x4600000D, 0xFFFF003F, "%D, %S" },
277 /* VPU instructions */
278 { I_BVF, "bvf", 0x49000000, 0xFFE30000, "%Zc, %O" }, /* [hlide] %Z -> %Zc */
279 { I_BVFL, "bvfl", 0x49020000, 0xFFE30000, "%Zc, %O" }, /* [hlide] %Z -> %Zc */
280 { I_BVT, "bvt", 0x49010000, 0xFFE30000, "%Zc, %O" }, /* [hlide] %Z -> %Zc */
281 { I_BVTL, "bvtl", 0x49030000, 0xFFE30000, "%Zc, %O" }, /* [hlide] %Z -> %Zc */
282 { I_LV_Q, "lv.q", 0xD8000000, 0xFC000002, "%Xq, %Y" },
283 { I_LV_S, "lv.s", 0xC8000000, 0xFC000000, "%Xs, %Y" },
284 { I_LVL_Q, "lvl.q", 0xD4000000, 0xFC000002, "%Xq, %Y" },
285 { I_LVR_Q, "lvr.q", 0xD4000002, 0xFC000002, "%Xq, %Y" },
286 { I_MFV, "mfv", 0x48600000, 0xFFE0FF80, "%t, %zs" }, /* [hlide] added "%t, %zs" */
287 { I_MFVC, "mfvc", 0x48600000, 0xFFE0FF00, "%t, %2d" }, /* [hlide] added "%t, %2d" */
288 { I_MTV, "mtv", 0x48E00000, 0xFFE0FF80, "%t, %zs" }, /* [hlide] added "%t, %zs" */
289 { I_MTVC, "mtvc", 0x48E00000, 0xFFE0FF00, "%t, %2d" }, /* [hlide] added "%t, %2d" */
290 { I_SV_Q, "sv.q", 0xF8000000, 0xFC000002, "%Xq, %Y" },
291 { I_SV_S, "sv.s", 0xE8000000, 0xFC000000, "%Xs, %Y" },
292 { I_SVL_Q, "svl.q", 0xF4000000, 0xFC000002, "%Xq, %Y" },
293 { I_SVR_Q, "svr.q", 0xF4000002, 0xFC000002, "%Xq, %Y" },
294 { I_VABS_P, "vabs.p", 0xD0010080, 0xFFFF8080, "%zp, %yp" },
295 { I_VABS_Q, "vabs.q", 0xD0018080, 0xFFFF8080, "%zq, %yq" },
296 { I_VABS_S, "vabs.s", 0xD0010000, 0xFFFF8080, "%zs, %ys" },
297 { I_VABS_T, "vabs.t", 0xD0018000, 0xFFFF8080, "%zt, %yt" },
298 { I_VADD_P, "vadd.p", 0x60000080, 0xFF808080, "%zp, %yp, %xp" },
299 { I_VADD_Q, "vadd.q", 0x60008080, 0xFF808080, "%zq, %yq, %xq" },
300 { I_VADD_S, "vadd.s", 0x60000000, 0xFF808080, "%zs, %ys, %xs" }, /* [hlide] %yz -> %ys */
301 { I_VADD_T, "vadd.t", 0x60008000, 0xFF808080, "%zt, %yt, %xt" },
302 { I_VASIN_P, "vasin.p", 0xD0170080, 0xFFFF8080, "%zp, %yp" },
303 { I_VASIN_Q, "vasin.q", 0xD0178080, 0xFFFF8080, "%zq, %yq" },
304 { I_VASIN_S, "vasin.s", 0xD0170000, 0xFFFF8080, "%zs, %ys" },
305 { I_VASIN_T, "vasin.t", 0xD0178000, 0xFFFF8080, "%zt, %yt" },
306 { I_VAVG_P, "vavg.p", 0xD0470080, 0xFFFF8080, "%zp, %yp" },
307 { I_VAVG_Q, "vavg.q", 0xD0478080, 0xFFFF8080, "%zq, %yq" },
308 { I_VAVG_T, "vavg.t", 0xD0478000, 0xFFFF8080, "%zt, %yt" },
309 { I_VBFY1_P, "vbfy1.p", 0xD0420080, 0xFFFF8080, "%zp, %yp" },
310 { I_VBFY1_Q, "vbfy1.q", 0xD0428080, 0xFFFF8080, "%zq, %yq" },
311 { I_VBFY2_Q, "vbfy2.q", 0xD0438080, 0xFFFF8080, "%zq, %yq" },
312 { I_VCMOVF_P, "vcmovf.p", 0xD2A80080, 0xFFF88080, "%zp, %yp, %v3" }, /* [hlide] added "%zp, %yp, %v3" */
313 { I_VCMOVF_Q, "vcmovf.q", 0xD2A88080, 0xFFF88080, "%zq, %yq, %v3" }, /* [hlide] added "%zq, %yq, %v3" */
314 { I_VCMOVF_S, "vcmovf.s", 0xD2A80000, 0xFFF88080, "%zs, %ys, %v3" }, /* [hlide] added "%zs, %ys, %v3" */
315 { I_VCMOVF_T, "vcmovf.t", 0xD2A88000, 0xFFF88080, "%zt, %yt, %v3" }, /* [hlide] added "%zt, %yt, %v3" */
316 { I_VCMOVT_P, "vcmovt.p", 0xD2A00080, 0xFFF88080, "%zp, %yp, %v3" }, /* [hlide] added "%zp, %yp, %v3" */
317 { I_VCMOVT_Q, "vcmovt.q", 0xD2A08080, 0xFFF88080, "%zq, %yq, %v3" }, /* [hlide] added "%zq, %yq, %v3" */
318 { I_VCMOVT_S, "vcmovt.s", 0xD2A00000, 0xFFF88080, "%zs, %ys, %v3" }, /* [hlide] added "%zs, %ys, %v3" */
319 { I_VCMOVT_T, "vcmovt.t", 0xD2A08000, 0xFFF88080, "%zt, %yt, %v3" }, /* [hlide] added "%zt, %yt, %v3" */
320 { I_VCMP_P, "vcmp.p", 0x6C000080, 0xFFFFFFF0, "%Zn" }, /* [hlide] added "%Zn" */
321 { I_VCMP_P, "vcmp.p", 0x6C000080, 0xFFFF80F0, "%Zn, %yp" }, /* [hlide] added "%Zn, %xp" */
322 { I_VCMP_P, "vcmp.p", 0x6C000080, 0xFF8080F0, "%Zn, %yp, %xp" }, /* [hlide] added "%Zn, %zp, %xp" */
323 { I_VCMP_Q, "vcmp.q", 0x6C008080, 0xFFFFFFF0, "%Zn" }, /* [hlide] added "%Zn" */
324 { I_VCMP_Q, "vcmp.q", 0x6C008080, 0xFFFF80F0, "%Zn, %yq" }, /* [hlide] added "%Zn, %yq" */
325 { I_VCMP_Q, "vcmp.q", 0x6C008080, 0xFF8080F0, "%Zn, %yq, %xq" }, /* [hlide] added "%Zn, %yq, %xq" */
326 { I_VCMP_S, "vcmp.s", 0x6C000000, 0xFFFFFFF0, "%Zn" }, /* [hlide] added "%Zn" */
327 { I_VCMP_S, "vcmp.s", 0x6C000000, 0xFFFF80F0, "%Zn, %ys" }, /* [hlide] added "%Zn, %ys" */
328 { I_VCMP_S, "vcmp.s", 0x6C000000, 0xFF8080F0, "%Zn, %ys, %xs" }, /* [hlide] added "%Zn, %ys, %xs" */
329 { I_VCMP_T, "vcmp.t", 0x6C008000, 0xFFFFFFF0, "%Zn" }, /* [hlide] added "%zp" */
330 { I_VCMP_T, "vcmp.t", 0x6C008000, 0xFFFF80F0, "%Zn, %yt" }, /* [hlide] added "%Zn, %yt" */
331 { I_VCMP_T, "vcmp.t", 0x6C008000, 0xFF8080F0, "%Zn, %yt, %xt" }, /* [hlide] added "%Zn, %yt, %xt" */
332 { I_VCOS_P, "vcos.p", 0xD0130080, 0xFFFF8080, "%zp, %yp" },
333 { I_VCOS_Q, "vcos.q", 0xD0138080, 0xFFFF8080, "%zq, %yq" },
334 { I_VCOS_S, "vcos.s", 0xD0130000, 0xFFFF8080, "%zs, %ys" },
335 { I_VCOS_T, "vcos.t", 0xD0138000, 0xFFFF8080, "%zt, %yt" },
336 { I_VCRS_T, "vcrs.t", 0x66808000, 0xFF808080, "%zt, %yt, %xt" },
337 { I_VCRSP_T, "vcrsp.t", 0xF2808000, 0xFF808080, "%zt, %yt, %xt" },
338 { I_VCST_P, "vcst.p", 0xD0600080, 0xFFE0FF80, "%zp, %vk" }, /* [hlide] "%zp, %yp, %xp" -> "%zp, %vk" */
339 { I_VCST_Q, "vcst.q", 0xD0608080, 0xFFE0FF80, "%zq, %vk" }, /* [hlide] "%zq, %yq, %xq" -> "%zq, %vk" */
340 { I_VCST_S, "vcst.s", 0xD0600000, 0xFFE0FF80, "%zs, %vk" }, /* [hlide] "%zs, %ys, %xs" -> "%zs, %vk" */
341 { I_VCST_T, "vcst.t", 0xD0608000, 0xFFE0FF80, "%zt, %vk" }, /* [hlide] "%zt, %yt, %xt" -> "%zt, %vk" */
342 { I_VDET_P, "vdet.p", 0x67000080, 0xFF808080, "%zs, %yp, %xp" },
343 { I_VDIV_P, "vdiv.p", 0x63800080, 0xFF808080, "%zp, %yp, %xp" },
344 { I_VDIV_Q, "vdiv.q", 0x63808080, 0xFF808080, "%zq, %yq, %xq" },
345 { I_VDIV_S, "vdiv.s", 0x63800000, 0xFF808080, "%zs, %ys, %xs" }, /* [hlide] %yz -> %ys */
346 { I_VDIV_T, "vdiv.t", 0x63808000, 0xFF808080, "%zt, %yt, %xt" },
347 { I_VDOT_P, "vdot.p", 0x64800080, 0xFF808080, "%zs, %yp, %xp" },
348 { I_VDOT_Q, "vdot.q", 0x64808080, 0xFF808080, "%zs, %yq, %xq" },
349 { I_VDOT_T, "vdot.t", 0x64808000, 0xFF808080, "%zs, %yt, %xt" },
350 { I_VEXP2_P, "vexp2.p", 0xD0140080, 0xFFFF8080, "%zp, %yp" },
351 { I_VEXP2_Q, "vexp2.q", 0xD0148080, 0xFFFF8080, "%zq, %yq" },
352 { I_VEXP2_S, "vexp2.s", 0xD0140000, 0xFFFF8080, "%zs, %ys" },
353 { I_VEXP2_T, "vexp2.t", 0xD0148000, 0xFFFF8080, "%zt, %yt" },
354 { I_VF2H_P, "vf2h.p", 0xD0320080, 0xFFFF8080, "%zs, %yp" }, /* [hlide] %zp -> %zs */
355 { I_VF2H_Q, "vf2h.q", 0xD0328080, 0xFFFF8080, "%zp, %yq" }, /* [hlide] %zq -> %zp */
356 { I_VF2ID_P, "vf2id.p", 0xD2600080, 0xFFE08080, "%zp, %yp, %v5" }, /* [hlide] added "%zp, %yp, %v5" */
357 { I_VF2ID_Q, "vf2id.q", 0xD2608080, 0xFFE08080, "%zq, %yq, %v5" }, /* [hlide] added "%zq, %yq, %v5" */
358 { I_VF2ID_S, "vf2id.s", 0xD2600000, 0xFFE08080, "%zs, %ys, %v5" }, /* [hlide] added "%zs, %ys, %v5" */
359 { I_VF2ID_T, "vf2id.t", 0xD2608000, 0xFFE08080, "%zt, %yt, %v5" }, /* [hlide] added "%zt, %yt, %v5" */
360 { I_VF2IN_P, "vf2in.p", 0xD2000080, 0xFFE08080, "%zp, %yp, %v5" }, /* [hlide] added "%zp, %yp, %v5" */
361 { I_VF2IN_Q, "vf2in.q", 0xD2008080, 0xFFE08080, "%zq, %yq, %v5" }, /* [hlide] added "%zq, %yq, %v5" */
362 { I_VF2IN_S, "vf2in.s", 0xD2000000, 0xFFE08080, "%zs, %ys, %v5" }, /* [hlide] added "%zs, %ys, %v5" */
363 { I_VF2IN_T, "vf2in.t", 0xD2008000, 0xFFE08080, "%zt, %yt, %v5" }, /* [hlide] added "%zt, %yt, %v5" */
364 { I_VF2IU_P, "vf2iu.p", 0xD2400080, 0xFFE08080, "%zp, %yp, %v5" }, /* [hlide] added "%zp, %yp, %v5" */
365 { I_VF2IU_Q, "vf2iu.q", 0xD2408080, 0xFFE08080, "%zq, %yq, %v5" }, /* [hlide] added "%zq, %yq, %v5" */
366 { I_VF2IU_S, "vf2iu.s", 0xD2400000, 0xFFE08080, "%zs, %ys, %v5" }, /* [hlide] added "%zs, %ys, %v5" */
367 { I_VF2IU_T, "vf2iu.t", 0xD2408000, 0xFFE08080, "%zt, %yt, %v5" }, /* [hlide] added "%zt, %yt, %v5" */
368 { I_VF2IZ_P, "vf2iz.p", 0xD2200080, 0xFFE08080, "%zp, %yp, %v5" }, /* [hlide] added "%zp, %yp, %v5" */
369 { I_VF2IZ_Q, "vf2iz.q", 0xD2208080, 0xFFE08080, "%zq, %yq, %v5" }, /* [hlide] added "%zq, %yq, %v5" */
370 { I_VF2IZ_S, "vf2iz.s", 0xD2200000, 0xFFE08080, "%zs, %ys, %v5" }, /* [hlide] added "%zs, %ys, %v5" */
371 { I_VF2IZ_T, "vf2iz.t", 0xD2208000, 0xFFE08080, "%zt, %yt, %v5" }, /* [hlide] added "%zt, %yt, %v5" */
372 { I_VFAD_P, "vfad.p", 0xD0460080, 0xFFFF8080, "%zp, %yp" },
373 { I_VFAD_Q, "vfad.q", 0xD0468080, 0xFFFF8080, "%zq, %yq" },
374 { I_VFAD_T, "vfad.t", 0xD0468000, 0xFFFF8080, "%zt, %yt" },
375 { I_VFIM_S, "vfim.s", 0xDF800000, 0xFF800000, "%xs, %vh" }, /* [hlide] added "%xs, %vh" */
376 { I_VFLUSH, "vflush", 0xFFFF040D, 0xFFFFFFFF, "" },
377 { I_VH2F_P, "vh2f.p", 0xD0330080, 0xFFFF8080, "%zq, %yp" }, /* [hlide] %zp -> %zq */
378 { I_VH2F_S, "vh2f.s", 0xD0330000, 0xFFFF8080, "%zp, %ys" }, /* [hlide] %zs -> %zp */
379 { I_VHDP_P, "vhdp.p", 0x66000080, 0xFF808080, "%zs, %yp, %xp" }, /* [hlide] added "%zs, %yp, %xp" */
380 { I_VHDP_Q, "vhdp.q", 0x66008080, 0xFF808080, "%zs, %yq, %xq" }, /* [hlide] added "%zs, %yq, %xq" */
381 { I_VHDP_T, "vhdp.t", 0x66008000, 0xFF808080, "%zs, %yt, %xt" }, /* [hlide] added "%zs, %yt, %xt" */
382 { I_VHTFM2_P, "vhtfm2.p", 0xF0800000, 0xFF808080, "%zp, %ym, %xp" }, /* [hlide] added "%zp, %ym, %xp" */
383 { I_VHTFM3_T, "vhtfm3.t", 0xF1000080, 0xFF808080, "%zt, %yn, %xt" }, /* [hlide] added "%zt, %yn, %xt" */
384 { I_VHTFM4_Q, "vhtfm4.q", 0xF1808000, 0xFF808080, "%zq, %yo, %xq" }, /* [hlide] added "%zq, %yo, %xq" */
385 { I_VI2C_Q, "vi2c.q", 0xD03D8080, 0xFFFF8080, "%zs, %yq" }, /* [hlide] added "%zs, %yq" */
386 { I_VI2F_P, "vi2f.p", 0xD2800080, 0xFFE08080, "%zp, %yp, %v5" }, /* [hlide] added "%zp, %yp, %v5" */
387 { I_VI2F_Q, "vi2f.q", 0xD2808080, 0xFFE08080, "%zq, %yq, %v5" }, /* [hlide] added "%zq, %yq, %v5" */
388 { I_VI2F_S, "vi2f.s", 0xD2800000, 0xFFE08080, "%zs, %ys, %v5" }, /* [hlide] added "%zs, %ys, %v5" */
389 { I_VI2F_T, "vi2f.t", 0xD2808000, 0xFFE08080, "%zt, %yt, %v5" }, /* [hlide] added "%zt, %yt, %v5" */
390 { I_VI2S_P, "vi2s.p", 0xD03F0080, 0xFFFF8080, "%zs, %yp" }, /* [hlide] added "%zs, %yp" */
391 { I_VI2S_Q, "vi2s.q", 0xD03F8080, 0xFFFF8080, "%zp, %yq" }, /* [hlide] added "%zp, %yq" */
392 { I_VI2UC_Q, "vi2uc.q", 0xD03C8080, 0xFFFF8080, "%zq, %yq" }, /* [hlide] %zp -> %zq */
393 { I_VI2US_P, "vi2us.p", 0xD03E0080, 0xFFFF8080, "%zq, %yq" }, /* [hlide] %zp -> %zq */
394 { I_VI2US_Q, "vi2us.q", 0xD03E8080, 0xFFFF8080, "%zq, %yq" }, /* [hlide] %zp -> %zq */
395 { I_VIDT_P, "vidt.p", 0xD0030080, 0xFFFFFF80, "%zp" },
396 { I_VIDT_Q, "vidt.q", 0xD0038080, 0xFFFFFF80, "%zq" },
397 { I_VIIM_S, "viim.s", 0xDF000000, 0xFF800000, "%xs, %vi" }, /* [hlide] added "%xs, %vi" */
398 { I_VLGB_S, "vlgb.s", 0xD0370000, 0xFFFF8080, "%zs, %ys" },
399 { I_VLOG2_P, "vlog2.p", 0xD0150080, 0xFFFF8080, "%zp, %yp" },
400 { I_VLOG2_Q, "vlog2.q", 0xD0158080, 0xFFFF8080, "%zq, %yq" },
401 { I_VLOG2_S, "vlog2.s", 0xD0150000, 0xFFFF8080, "%zs, %ys" },
402 { I_VLOG2_T, "vlog2.t", 0xD0158000, 0xFFFF8080, "%zt, %yt" },
403 { I_VMAX_P, "vmax.p", 0x6D800080, 0xFF808080, "%zp, %yp, %xp" },
404 { I_VMAX_Q, "vmax.q", 0x6D808080, 0xFF808080, "%zq, %yq, %xq" },
405 { I_VMAX_S, "vmax.s", 0x6D800000, 0xFF808080, "%zs, %ys, %xs" },
406 { I_VMAX_T, "vmax.t", 0x6D808000, 0xFF808080, "%zt, %yt, %xt" },
407 { I_VMFVC, "vmfvc", 0xD0500000, 0xFFFF0080, "%zs, %2s" }, /* [hlide] added "%zs, %2s" */
408 { I_VMIDT_P, "vmidt.p", 0xF3830080, 0xFFFFFF80, "%zm" }, /* [hlide] %zp -> %zm */
409 { I_VMIDT_Q, "vmidt.q", 0xF3838080, 0xFFFFFF80, "%zo" }, /* [hlide] %zq -> %zo */
410 { I_VMIDT_T, "vmidt.t", 0xF3838000, 0xFFFFFF80, "%zn" }, /* [hlide] %zt -> %zn */
411 { I_VMIN_P, "vmin.p", 0x6D000080, 0xFF808080, "%zp, %yp, %xp" },
412 { I_VMIN_Q, "vmin.q", 0x6D008080, 0xFF808080, "%zq, %yq, %xq" },
413 { I_VMIN_S, "vmin.s", 0x6D000000, 0xFF808080, "%zs, %ys, %xs" },
414 { I_VMIN_T, "vmin.t", 0x6D008000, 0xFF808080, "%zt, %yt, %xt" },
415 { I_VMMOV_P, "vmmov.p", 0xF3800080, 0xFFFF8080, "%zm, %ym" }, /* [hlide] added "%zm, %ym" */
416 { I_VMMOV_Q, "vmmov.q", 0xF3808080, 0xFFFF8080, "%zo, %yo" },
417 { I_VMMOV_T, "vmmov.t", 0xF3808000, 0xFFFF8080, "%zn, %yn" }, /* [hlide] added "%zn, %yn" */
418 { I_VMMUL_P, "vmmul.p", 0xF0000080, 0xFF808080, "%?%zm, %ym, %xm" }, /* [hlide] added "%?%zm, %ym, %xm" */
419 { I_VMMUL_Q, "vmmul.q", 0xF0008080, 0xFF808080, "%?%zo, %yo, %xo" },
420 { I_VMMUL_T, "vmmul.t", 0xF0008000, 0xFF808080, "%?%zn, %yn, %xn" }, /* [hlide] added "%?%zn, %yn, %xn" */
421 { I_VMONE_P, "vmone.p", 0xF3870080, 0xFFFFFF80, "%zp" },
422 { I_VMONE_Q, "vmone.q", 0xF3878080, 0xFFFFFF80, "%zq" },
423 { I_VMONE_T, "vmone.t", 0xF3878000, 0xFFFFFF80, "%zt" },
424 { I_VMOV_P, "vmov.p", 0xD0000080, 0xFFFF8080, "%zp, %yp" },
425 { I_VMOV_Q, "vmov.q", 0xD0008080, 0xFFFF8080, "%zq, %yq" },
426 { I_VMOV_S, "vmov.s", 0xD0000000, 0xFFFF8080, "%zs, %ys" },
427 { I_VMOV_T, "vmov.t", 0xD0008000, 0xFFFF8080, "%zt, %yt" },
428 { I_VMSCL_P, "vmscl.p", 0xF2000080, 0xFF808080, "%zm, %ym, %xs" }, /* [hlide] %zp, %yp, %xp -> %zm, %ym, %xs */
429 { I_VMSCL_Q, "vmscl.q", 0xF2008080, 0xFF808080, "%zo, %yo, %xs" }, /* [hlide] %zq, %yq, %xp -> %zo, %yo, %xs */
430 { I_VMSCL_T, "vmscl.t", 0xF2008000, 0xFF808080, "%zn, %yn, %xs" }, /* [hlide] %zt, %yt, %xp -> %zn, %yn, %xs */
431 { I_VMTVC, "vmtvc", 0xD0510000, 0xFFFF8000, "%2d, %ys" }, /* [hlide] added "%2d, %ys" */
432 { I_VMUL_P, "vmul.p", 0x64000080, 0xFF808080, "%zp, %yp, %xp" },
433 { I_VMUL_Q, "vmul.q", 0x64008080, 0xFF808080, "%zq, %yq, %xq" },
434 { I_VMUL_S, "vmul.s", 0x64000000, 0xFF808080, "%zs, %ys, %xs" },
435 { I_VMUL_T, "vmul.t", 0x64008000, 0xFF808080, "%zt, %yt, %xt" },
436 { I_VMZERO_P, "vmzero.p", 0xF3860080, 0xFFFFFF80, "%zm" }, /* [hlide] %zp -> %zm */
437 { I_VMZERO_Q, "vmzero.q", 0xF3868080, 0xFFFFFF80, "%zo" }, /* [hlide] %zq -> %zo */
438 { I_VMZERO_T, "vmzero.t", 0xF3868000, 0xFFFFFF80, "%zn" }, /* [hlide] %zt -> %zn */
439 { I_VNEG_P, "vneg.p", 0xD0020080, 0xFFFF8080, "%zp, %yp" },
440 { I_VNEG_Q, "vneg.q", 0xD0028080, 0xFFFF8080, "%zq, %yq" },
441 { I_VNEG_S, "vneg.s", 0xD0020000, 0xFFFF8080, "%zs, %ys" },
442 { I_VNEG_T, "vneg.t", 0xD0028000, 0xFFFF8080, "%zt, %yt" },
443 { I_VNOP, "vnop", 0xFFFF0000, 0xFFFFFFFF, "" },
444 { I_VNRCP_P, "vnrcp.p", 0xD0180080, 0xFFFF8080, "%zp, %yp" },
445 { I_VNRCP_Q, "vnrcp.q", 0xD0188080, 0xFFFF8080, "%zq, %yq" },
446 { I_VNRCP_S, "vnrcp.s", 0xD0180000, 0xFFFF8080, "%zs, %ys" },
447 { I_VNRCP_T, "vnrcp.t", 0xD0188000, 0xFFFF8080, "%zt, %yt" },
448 { I_VNSIN_P, "vnsin.p", 0xD01A0080, 0xFFFF8080, "%zp, %yp" },
449 { I_VNSIN_Q, "vnsin.q", 0xD01A8080, 0xFFFF8080, "%zq, %yq" },
450 { I_VNSIN_S, "vnsin.s", 0xD01A0000, 0xFFFF8080, "%zs, %ys" },
451 { I_VNSIN_T, "vnsin.t", 0xD01A8000, 0xFFFF8080, "%zt, %yt" },
452 { I_VOCP_P, "vocp.p", 0xD0440080, 0xFFFF8080, "%zp, %yp" },
453 { I_VOCP_Q, "vocp.q", 0xD0448080, 0xFFFF8080, "%zq, %yq" },
454 { I_VOCP_S, "vocp.s", 0xD0440000, 0xFFFF8080, "%zs, %ys" },
455 { I_VOCP_T, "vocp.t", 0xD0448000, 0xFFFF8080, "%zt, %yt" },
456 { I_VONE_P, "vone.p", 0xD0070080, 0xFFFFFF80, "%zp" },
457 { I_VONE_Q, "vone.q", 0xD0078080, 0xFFFFFF80, "%zq" },
458 { I_VONE_S, "vone.s", 0xD0070000, 0xFFFFFF80, "%zs" },
459 { I_VONE_T, "vone.t", 0xD0078000, 0xFFFFFF80, "%zt" },
460 { I_VPFXD, "vpfxd", 0xDE000000, 0xFF000000, "[%vp4, %vp5, %vp6, %vp7]" }, /* [hlide] added "[%vp4, %vp5, %vp6, %vp7]" */
461 { I_VPFXS, "vpfxs", 0xDC000000, 0xFF000000, "[%vp0, %vp1, %vp2, %vp3]" }, /* [hlide] added "[%vp0, %vp1, %vp2, %vp3]" */
462 { I_VPFXT, "vpfxt", 0xDD000000, 0xFF000000, "[%vp0, %vp1, %vp2, %vp3]" }, /* [hlide] added "[%vp0, %vp1, %vp2, %vp3]" */
463 { I_VQMUL_Q, "vqmul.q", 0xF2808080, 0xFF808080, "%zq, %yq, %xq" }, /* [hlide] added "%zq, %yq, %xq" */
464 { I_VRCP_P, "vrcp.p", 0xD0100080, 0xFFFF8080, "%zp, %yp" },
465 { I_VRCP_Q, "vrcp.q", 0xD0108080, 0xFFFF8080, "%zq, %yq" },
466 { I_VRCP_S, "vrcp.s", 0xD0100000, 0xFFFF8080, "%zs, %ys" },
467 { I_VRCP_T, "vrcp.t", 0xD0108000, 0xFFFF8080, "%zt, %yt" },
468 { I_VREXP2_P, "vrexp2.p", 0xD01C0080, 0xFFFF8080, "%zp, %yp" },
469 { I_VREXP2_Q, "vrexp2.q", 0xD01C8080, 0xFFFF8080, "%zq, %yq" },
470 { I_VREXP2_S, "vrexp2.s", 0xD01C0000, 0xFFFF8080, "%zs, %ys" },
471 { I_VREXP2_T, "vrexp2.t", 0xD01C8000, 0xFFFF8080, "%zt, %yt" },
472 { I_VRNDF1_P, "vrndf1.p", 0xD0220080, 0xFFFFFF80, "%zp" },
473 { I_VRNDF1_Q, "vrndf1.q", 0xD0228080, 0xFFFFFF80, "%zq" },
474 { I_VRNDF1_S, "vrndf1.s", 0xD0220000, 0xFFFFFF80, "%zs" },
475 { I_VRNDF1_T, "vrndf1.t", 0xD0228000, 0xFFFFFF80, "%zt" },
476 { I_VRNDF2_P, "vrndf2.p", 0xD0230080, 0xFFFFFF80, "%zp" },
477 { I_VRNDF2_Q, "vrndf2.q", 0xD0238080, 0xFFFFFF80, "%zq" },
478 { I_VRNDF2_S, "vrndf2.s", 0xD0230000, 0xFFFFFF80, "%zs" },
479 { I_VRNDF2_T, "vrndf2.t", 0xD0238000, 0xFFFFFF80, "%zt" },
480 { I_VRNDI_P, "vrndi.p", 0xD0210080, 0xFFFFFF80, "%zp" },
481 { I_VRNDI_Q, "vrndi.q", 0xD0218080, 0xFFFFFF80, "%zq" },
482 { I_VRNDI_S, "vrndi.s", 0xD0210000, 0xFFFFFF80, "%zs" },
483 { I_VRNDI_T, "vrndi.t", 0xD0218000, 0xFFFFFF80, "%zt" },
484 { I_VRNDS_S, "vrnds.s", 0xD0200000, 0xFFFF80FF, "%ys" },
485 { I_VROT_P, "vrot.p", 0xF3A00080, 0xFFE08080, "%zp, %ys, %vr" }, /* [hlide] added "%zp, %ys, %vr" */
486 { I_VROT_Q, "vrot.q", 0xF3A08080, 0xFFE08080, "%zq, %ys, %vr" }, /* [hlide] added "%zq, %ys, %vr" */
487 { I_VROT_T, "vrot.t", 0xF3A08000, 0xFFE08080, "%zt, %ys, %vr" }, /* [hlide] added "%zt, %ys, %vr" */
488 { I_VRSQ_P, "vrsq.p", 0xD0110080, 0xFFFF8080, "%zp, %yp" },
489 { I_VRSQ_Q, "vrsq.q", 0xD0118080, 0xFFFF8080, "%zq, %yq" },
490 { I_VRSQ_S, "vrsq.s", 0xD0110000, 0xFFFF8080, "%zs, %ys" },
491 { I_VRSQ_T, "vrsq.t", 0xD0118000, 0xFFFF8080, "%zt, %yt" },
492 { I_VS2I_P, "vs2i.p", 0xD03B0080, 0xFFFF8080, "%zq, %yp" }, /* [hlide] %zp -> %zq */
493 { I_VS2I_S, "vs2i.s", 0xD03B0000, 0xFFFF8080, "%zp, %ys" }, /* [hlide] %zs -> %zp */
494 { I_VSAT0_P, "vsat0.p", 0xD0040080, 0xFFFF8080, "%zp, %yp" },
495 { I_VSAT0_Q, "vsat0.q", 0xD0048080, 0xFFFF8080, "%zq, %yq" },
496 { I_VSAT0_S, "vsat0.s", 0xD0040000, 0xFFFF8080, "%zs, %ys" },
497 { I_VSAT0_T, "vsat0.t", 0xD0048000, 0xFFFF8080, "%zt, %yt" },
498 { I_VSAT1_P, "vsat1.p", 0xD0050080, 0xFFFF8080, "%zp, %yp" },
499 { I_VSAT1_Q, "vsat1.q", 0xD0058080, 0xFFFF8080, "%zq, %yq" },
500 { I_VSAT1_S, "vsat1.s", 0xD0050000, 0xFFFF8080, "%zs, %ys" },
501 { I_VSAT1_T, "vsat1.t", 0xD0058000, 0xFFFF8080, "%zt, %yt" },
502 { I_VSBN_S, "vsbn.s", 0x61000000, 0xFF808080, "%zs, %ys, %xs" },
503 { I_VSBZ_S, "vsbz.s", 0xD0360000, 0xFFFF8080, "%zs, %ys" },
504 { I_VSCL_P, "vscl.p", 0x65000080, 0xFF808080, "%zp, %yp, %xs" }, /* [hlide] %xp -> %xs */
505 { I_VSCL_Q, "vscl.q", 0x65008080, 0xFF808080, "%zq, %yq, %xs" }, /* [hlide] %xq -> %xs */
506 { I_VSCL_T, "vscl.t", 0x65008000, 0xFF808080, "%zt, %yt, %xs" }, /* [hlide] %xt -> %xs */
507 { I_VSCMP_P, "vscmp.p", 0x6E800080, 0xFF808080, "%zp, %yp, %xp" },
508 { I_VSCMP_Q, "vscmp.q", 0x6E808080, 0xFF808080, "%zq, %yq, %xq" },
509 { I_VSCMP_S, "vscmp.s", 0x6E800000, 0xFF808080, "%zs, %ys, %xs" },
510 { I_VSCMP_T, "vscmp.t", 0x6E808000, 0xFF808080, "%zt, %yt, %xt" },
511 { I_VSGE_P, "vsge.p", 0x6F000080, 0xFF808080, "%zp, %yp, %xp" },
512 { I_VSGE_Q, "vsge.q", 0x6F008080, 0xFF808080, "%zq, %yq, %xq" },
513 { I_VSGE_S, "vsge.s", 0x6F000000, 0xFF808080, "%zs, %ys, %xs" },
514 { I_VSGE_T, "vsge.t", 0x6F008000, 0xFF808080, "%zt, %yt, %xt" },
515 { I_VSGN_P, "vsgn.p", 0xD04A0080, 0xFFFF8080, "%zp, %yp" },
516 { I_VSGN_Q, "vsgn.q", 0xD04A8080, 0xFFFF8080, "%zq, %yq" },
517 { I_VSGN_S, "vsgn.s", 0xD04A0000, 0xFFFF8080, "%zs, %ys" },
518 { I_VSGN_T, "vsgn.t", 0xD04A8000, 0xFFFF8080, "%zt, %yt" },
519 { I_VSIN_P, "vsin.p", 0xD0120080, 0xFFFF8080, "%zp, %yp" },
520 { I_VSIN_Q, "vsin.q", 0xD0128080, 0xFFFF8080, "%zq, %yq" },
521 { I_VSIN_S, "vsin.s", 0xD0120000, 0xFFFF8080, "%zs, %ys" },
522 { I_VSIN_T, "vsin.t", 0xD0128000, 0xFFFF8080, "%zt, %yt" },
523 { I_VSLT_P, "vslt.p", 0x6F800080, 0xFF808080, "%zp, %yp, %xp" },
524 { I_VSLT_Q, "vslt.q", 0x6F808080, 0xFF808080, "%zq, %yq, %xq" },
525 { I_VSLT_S, "vslt.s", 0x6F800000, 0xFF808080, "%zs, %ys, %xs" },
526 { I_VSLT_T, "vslt.t", 0x6F808000, 0xFF808080, "%zt, %yt, %xt" },
527 { I_VSOCP_P, "vsocp.p", 0xD0450080, 0xFFFF8080, "%zq, %yp" }, /* [hlide] %zp -> %zq */
528 { I_VSOCP_S, "vsocp.s", 0xD0450000, 0xFFFF8080, "%zp, %ys" }, /* [hlide] %zs -> %zp */
529 { I_VSQRT_P, "vsqrt.p", 0xD0160080, 0xFFFF8080, "%zp, %yp" },
530 { I_VSQRT_Q, "vsqrt.q", 0xD0168080, 0xFFFF8080, "%zq, %yq" },
531 { I_VSQRT_S, "vsqrt.s", 0xD0160000, 0xFFFF8080, "%zs, %ys" },
532 { I_VSQRT_T, "vsqrt.t", 0xD0168000, 0xFFFF8080, "%zt, %yt" },
533 { I_VSRT1_Q, "vsrt1.q", 0xD0408080, 0xFFFF8080, "%zq, %yq" },
534 { I_VSRT2_Q, "vsrt2.q", 0xD0418080, 0xFFFF8080, "%zq, %yq" },
535 { I_VSRT3_Q, "vsrt3.q", 0xD0488080, 0xFFFF8080, "%zq, %yq" },
536 { I_VSRT4_Q, "vsrt4.q", 0xD0498080, 0xFFFF8080, "%zq, %yq" },
537 { I_VSUB_P, "vsub.p", 0x60800080, 0xFF808080, "%zp, %yp, %xp" },
538 { I_VSUB_Q, "vsub.q", 0x60808080, 0xFF808080, "%zq, %yq, %xq" },
539 { I_VSUB_S, "vsub.s", 0x60800000, 0xFF808080, "%zs, %ys, %xs" },
540 { I_VSUB_T, "vsub.t", 0x60808000, 0xFF808080, "%zt, %yt, %xt" },
541 { I_VSYNC, "vsync", 0xFFFF0320, 0xFFFFFFFF, "" },
542 { I_VSYNC, "vsync", 0xFFFF0000, 0xFFFF0000, "%I" },
543 { I_VT4444_Q, "vt4444.q", 0xD0598080, 0xFFFF8080, "%zq, %yq" }, /* [hlide] %zq -> %zp */
544 { I_VT5551_Q, "vt5551.q", 0xD05A8080, 0xFFFF8080, "%zq, %yq" }, /* [hlide] %zq -> %zp */
545 { I_VT5650_Q, "vt5650.q", 0xD05B8080, 0xFFFF8080, "%zq, %yq" }, /* [hlide] %zq -> %zp */
546 { I_VTFM2_P, "vtfm2.p", 0xF0800080, 0xFF808080, "%zp, %ym, %xp" }, /* [hlide] added "%zp, %ym, %xp" */
547 { I_VTFM3_T, "vtfm3.t", 0xF1008000, 0xFF808080, "%zt, %yn, %xt" }, /* [hlide] added "%zt, %yn, %xt" */
548 { I_VTFM4_Q, "vtfm4.q", 0xF1808080, 0xFF808080, "%zq, %yo, %xq" }, /* [hlide] added "%zq, %yo, %xq" */
549 { I_VUS2I_P, "vus2i.p", 0xD03A0080, 0xFFFF8080, "%zq, %yp" }, /* [hlide] added "%zq, %yp" */
550 { I_VUS2I_S, "vus2i.s", 0xD03A0000, 0xFFFF8080, "%zp, %ys" }, /* [hlide] added "%zp, %ys" */
551 { I_VWB_Q, "vwb.q", 0xF8000002, 0xFC000002, "%Xq, %Y" },
552 { I_VWBN_S, "vwbn.s", 0xD3000000, 0xFF008080, "%zs, %xs, %I" },
553 { I_VZERO_P, "vzero.p", 0xD0060080, 0xFFFFFF80, "%zp" },
554 { I_VZERO_Q, "vzero.q", 0xD0068080, 0xFFFFFF80, "%zq" },
555 { I_VZERO_S, "vzero.s", 0xD0060000, 0xFFFFFF80, "%zs" },
556 { I_VZERO_T, "vzero.t", 0xD0068000, 0xFFFFFF80, "%zt" },
557 { I_MFVME, "mfvme", 0x68000000, 0xFC000000, "%t, %i" },
558 { I_MTVME, "mtvme", 0xb0000000, 0xFC000000, "%t, %i" },
561 static char buffer[1024];
562 static const char *gpr_names[] =
564 "zr", "at", "v0", "v1", "a0", "a1", "a2", "a3",
565 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
566 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
567 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
570 static const char *cop0_regs[] =
572 "COP0_0", "COP0_1", "COP0_2", "COP0_3", "COP0_4", "COP0_5", "COP0_6", "COP0_7",
573 "BadVaddr", "Count", "COP0_10", "Compare", "Status", "Cause", "EPC", "PrID",
574 "Config", "COP0_17", "COP0_18", "COP0_19", "COP0_20", "COP0_21", "COP0_22", "COP0_23",
575 "COP0_24", "EBase", "COP0_26", "COP0_27", "TagLo", "TagHi", "ErrorPC", "COP0_31"
579 static const char *debug_regs[] =
581 "DRCNTL", "DEPC", "DDATA0", "DDATA1", "IBC", "DBC", "Debug06", "Debug07",
582 "IBA", "IBAM", "Debug10", "Debug11", "DBA", "DBAM", "DBD", "DBDM",
583 "Debug16", "Debug17", "Debug18", "Debug19", "Debug20", "Debug21", "Debug22", "Debug23",
584 "Debug24", "Debug25", "Debug26", "Debug27", "Debug28", "Debug29", "Debug30", "Debug31"
587 static const char *vfpu_cond_names[] =
589 "FL", "EQ", "LT", "LE",
590 "TR", "NE", "GE", "GT",
591 "EZ", "EN", "EI", "ES",
592 "NZ", "NN", "NI", "NS"
595 static const char *vfpu_constants[] = {
596 "VFPU_CONST0",
597 "VFPU_HUGE",
598 "VFPU_SQRT2",
599 "VFPU_SQRT1_2",
600 "VFPU_2_SQRTPI",
601 "VFPU_2_PI",
602 "VFPU_1_PI",
603 "VFPU_PI_4",
604 "VFPU_PI_2",
605 "VFPU_PI",
606 "VFPU_E",
607 "VFPU_LOG2E",
608 "VFPU_LOG10E",
609 "VFPU_LN2",
610 "VFPU_LN10",
611 "VFPU_2PI",
612 "VFPU_PI_6",
613 "VFPU_LOG10TWO",
614 "VFPU_LOG2TEN",
615 "VFPU_SQRT3_2",
616 "VFPU_CONST20",
617 "VFPU_CONST21",
618 "VFPU_CONST22",
619 "VFPU_CONST23",
620 "VFPU_CONST24",
621 "VFPU_CONST25",
622 "VFPU_CONST26",
623 "VFPU_CONST27",
624 "VFPU_CONST28",
625 "VFPU_CONST29",
626 "VFPU_CONST30",
627 "VFPU_CONST31",
630 static const char *pfx_cst_names[] =
632 "0", "1", "2", "1/2", "3", "1/3", "1/4", "1/6"
635 static const char *pfx_swz_names[] =
637 "x", "y", "z", "w"
640 static const char *pfx_sat_names[] =
642 "", "[0:1]", "", "[-1:1]"
645 /* [hlide] added vfpu_extra_regs */
646 static const char *vfpu_extra_regs[] =
648 "VFPU_PFXS",
649 "VFPU_PFXT",
650 "VFPU_PFXD",
651 "VFPU_CC ",
652 "VFPU_INF4",
653 NULL,
654 NULL,
655 "VFPU_REV",
656 "VFPU_RCX0",
657 "VFPU_RCX1",
658 "VFPU_RCX2",
659 "VFPU_RCX3",
660 "VFPU_RCX4",
661 "VFPU_RCX5",
662 "VFPU_RCX6",
663 "VFPU_RCX7"
666 static
667 int print_vfpu_single (int reg, char *output)
669 return sprintf (output, "S%d%d%d", (reg >> 2) & 7, reg & 3, (reg >> 5) & 3);
672 static
673 int print_vfpu_reg (int reg, int offset, char one, char two, char *output)
675 if ((reg >> 5) & 1) {
676 return sprintf (output, "%c%d%d%d", two, (reg >> 2) & 7, offset, reg & 3);
677 } else {
678 return sprintf (output, "%c%d%d%d", one, (reg >> 2) & 7, reg & 3, offset);
682 static
683 int print_vfpu_quad (int reg, char *output)
685 return print_vfpu_reg (reg, 0, 'C', 'R', output);
688 static
689 int print_vfpu_pair (int reg, char *output)
691 if ((reg >> 6) & 1) {
692 return print_vfpu_reg (reg, 2, 'C', 'R', output);
693 } else {
694 return print_vfpu_reg (reg, 0, 'C', 'R', output);
698 static
699 int print_vfpu_triple (int reg, char *output)
701 if ((reg >> 6) & 1) {
702 return print_vfpu_reg (reg, 1, 'C', 'R', output);
703 } else {
704 return print_vfpu_reg (reg, 0, 'C', 'R', output);
708 static
709 int print_vfpu_mpair (int reg, char *output)
711 if ((reg >> 6) & 1) {
712 return print_vfpu_reg (reg, 2, 'M', 'E', output);
713 } else {
714 return print_vfpu_reg (reg, 0, 'M', 'E', output);
718 static
719 int print_vfpu_mtriple (int reg, char *output)
721 if ((reg >> 6) & 1) {
722 return print_vfpu_reg (reg, 1, 'M', 'E', output);
723 } else {
724 return print_vfpu_reg (reg, 0, 'M', 'E', output);
728 static
729 int print_vfpu_matrix (int reg, char *output)
731 return print_vfpu_reg (reg, 0, 'M', 'E', output);
734 static
735 int print_vfpu_register (int reg, char type, char *output)
737 switch (type) {
738 case 's': return print_vfpu_single (reg, output);
739 case 'q': return print_vfpu_quad (reg, output);
740 case 'p': return print_vfpu_pair (reg, output);
741 case 't': return print_vfpu_triple (reg, output);
742 case 'm': return print_vfpu_mpair (reg, output);
743 case 'n': return print_vfpu_mtriple (reg, output);
744 case 'o': return print_vfpu_matrix (reg, output);
747 return 0;
750 static
751 int print_vfpu_halffloat (int l, char *output)
753 unsigned short float16 = l & 0xFFFF;
754 unsigned int sign = (float16 >> VFPU_SH_FLOAT16_SIGN) & VFPU_MASK_FLOAT16_SIGN;
755 int exponent = (float16 >> VFPU_SH_FLOAT16_EXP) & VFPU_MASK_FLOAT16_EXP;
756 unsigned int fraction = float16 & VFPU_MASK_FLOAT16_FRAC;
757 char signchar = '+' + ((sign == 1) * 2);
758 int len;
759 /* Convert a VFPU 16-bit floating-point number to IEEE754. */
760 union float2int
762 unsigned int i;
763 float f;
764 } float2int;
766 if (exponent == VFPU_FLOAT16_EXP_MAX) {
767 if (fraction == 0)
768 len = sprintf (output, "%cInf", signchar);
769 else
770 len = sprintf (output, "%cNaN", signchar);
771 } else if (exponent == 0 && fraction == 0) {
772 len = sprintf (output, "%c0", signchar);
773 } else {
774 if (exponent == 0) {
775 do {
776 fraction <<= 1;
777 exponent--;
778 } while (!(fraction & (VFPU_MASK_FLOAT16_FRAC + 1)));
780 fraction &= VFPU_MASK_FLOAT16_FRAC;
783 /* Convert to 32-bit single-precision IEEE754. */
784 float2int.i = sign << 31;
785 float2int.i |= (exponent + 112) << 23;
786 float2int.i |= fraction << 13;
787 len = sprintf (output, "%g", float2int.f);
790 return len;
793 /* [hlide] added print_vfpu_prefix */
794 static
795 int print_vfpu_prefix (int l, unsigned int pos, char *output)
797 int len = 0;
799 switch (pos)
801 case '0':
802 case '1':
803 case '2':
804 case '3':
806 unsigned int base = '0';
807 unsigned int negation = (l >> (pos - (base - VFPU_SH_PFX_NEG))) & VFPU_MASK_PFX_NEG;
808 unsigned int constant = (l >> (pos - (base - VFPU_SH_PFX_CST))) & VFPU_MASK_PFX_CST;
809 unsigned int abs_consthi = (l >> (pos - (base - VFPU_SH_PFX_ABS_CSTHI))) & VFPU_MASK_PFX_ABS_CSTHI;
810 unsigned int swz_constlo = (l >> ((pos - base) * 2)) & VFPU_MASK_PFX_SWZ_CSTLO;
812 if (negation)
813 len = sprintf (output, "-");
814 if (constant) {
815 len += sprintf (output + len, "%s", pfx_cst_names[(abs_consthi << 2) | swz_constlo]);
816 } else {
817 if (abs_consthi)
818 len += sprintf (output + len, "|%s|", pfx_swz_names[swz_constlo]);
819 else
820 len += sprintf (output + len, "%s", pfx_swz_names[swz_constlo]);
823 break;
825 case '4':
826 case '5':
827 case '6':
828 case '7':
830 unsigned int base = '4';
831 unsigned int mask = (l >> (pos - (base - VFPU_SH_PFX_MASK))) & VFPU_MASK_PFX_MASK;
832 unsigned int saturation = (l >> ((pos - base) * 2)) & VFPU_MASK_PFX_SAT;
834 if (mask)
835 len += sprintf (output, "m");
836 else
837 len += sprintf (output, "%s", pfx_sat_names[saturation]);
839 break;
842 return len;
846 static
847 int print_vfpu_rotator (int l, char *output)
849 int len;
851 const char *elements[4];
853 unsigned int opcode = l & VFPU_MASK_OP_SIZE;
854 unsigned int rotators = (l >> 16) & 0x1f;
855 unsigned int opsize, rothi, rotlo, negation, i;
857 /* Determine the operand size so we'll know how many elements to output. */
858 if (opcode == VFPU_OP_SIZE_PAIR)
859 opsize = 2;
860 else if (opcode == VFPU_OP_SIZE_TRIPLE)
861 opsize = 3;
862 else
863 opsize = (opcode == VFPU_OP_SIZE_QUAD) * 4; /* Sanity check. */
865 rothi = (rotators >> VFPU_SH_ROT_HI) & VFPU_MASK_ROT_HI;
866 rotlo = (rotators >> VFPU_SH_ROT_LO) & VFPU_MASK_ROT_LO;
867 negation = (rotators >> VFPU_SH_ROT_NEG) & VFPU_MASK_ROT_NEG;
869 if (rothi == rotlo) {
870 if (negation) {
871 elements[0] = "-s";
872 elements[1] = "-s";
873 elements[2] = "-s";
874 elements[3] = "-s";
875 } else {
876 elements[0] = "s";
877 elements[1] = "s";
878 elements[2] = "s";
879 elements[3] = "s";
881 } else {
882 elements[0] = "0";
883 elements[1] = "0";
884 elements[2] = "0";
885 elements[3] = "0";
887 if (negation)
888 elements[rothi] = "-s";
889 else
890 elements[rothi] = "s";
891 elements[rotlo] = "c";
893 len = sprintf (output, "[");
894 for (i = 0;;) {
895 len += sprintf (output + len, "%s", elements[i++]);
896 if (i >= opsize)
897 break;
898 sprintf (output + len, " ,");
901 len += sprintf (output + len, "]");
903 return len;
906 /* [hlide] added print_cop2 */
907 static
908 int print_cop2 (int reg, char *output)
910 int len;
912 if ((reg >= 128) && (reg < 128+16) && (vfpu_extra_regs[reg - 128])) {
913 len = sprintf (output, "%s", vfpu_extra_regs[reg - 128]);
914 } else {
915 len = sprintf (output, "VFPU_COP2_%d", reg);
918 return len;
922 static
923 void decode_instruction (struct allegrex_instruction *insn, unsigned int opcode, unsigned int PC)
925 int i = 0, len = 0, vmmul = 0;
926 unsigned int data = opcode;
927 len += sprintf (buffer, "\t0x%08X: 0x%08X '", PC, opcode);
928 for (i = 0; i < 4; i++) {
929 char c = (char) (data & 0xFF);
930 if (isprint (c)) { len += sprintf (&buffer[len], "%c", c); }
931 else { len += sprintf (&buffer[len], "."); }
932 data >>= 8;
934 sprintf (&buffer[len], "' - %s ", insn->name);
935 len = 44;
937 i = 0;
938 while (1) {
939 char c = insn->fmt[i++];
940 if (c == '\0') break;
941 if (c == '%') {
942 c = insn->fmt[i++];
943 switch (c) {
944 case 'd':
945 len += sprintf (&buffer[len], "$%s", gpr_names[RD (opcode)]);
946 break;
947 case 'D':
948 len += sprintf (&buffer[len], "$fpr%02d", FD (opcode));
949 break;
950 case 't':
951 len += sprintf (&buffer[len], "$%s", gpr_names[RT (opcode)]);
952 break;
953 case 'T':
954 len += sprintf (&buffer[len], "$fpr%02d", FT (opcode));
955 break;
956 case 's':
957 len += sprintf (&buffer[len], "$%s", gpr_names[RS (opcode)]);
958 break;
959 case 'S':
960 len += sprintf (&buffer[len], "$fpr%02d", FS (opcode));
961 break;
962 case 'J':
963 len += sprintf (&buffer[len], "$%s", gpr_names[RS (opcode)]);
964 break;
965 case 'i':
966 len += sprintf (&buffer[len], "%d", IMM (opcode));
967 break;
968 case 'I':
969 len += sprintf (&buffer[len], "0x%04X", IMMU (opcode));
970 break;
971 case 'j':
972 len += sprintf (&buffer[len], "0x%08X", JUMP (opcode, PC));
973 break;
974 case 'O':
975 len += sprintf (&buffer[len], "0x%08X", PC + 4 + 4 * ((int) IMM (opcode)));
976 break;
977 case 'o':
978 len += sprintf (&buffer[len], "%d($%s)", IMM (opcode), gpr_names[RS (opcode)]);
979 break;
980 case 'c':
981 len += sprintf (&buffer[len], "0x%05X", CODE (opcode));
982 break;
983 case 'C':
984 len += sprintf (&buffer[len], "0x%05X", CODE (opcode));
985 break;
986 case 'k':
987 len += sprintf (&buffer[len], "0x%X", RT (opcode));
988 break;
989 case 'p':
990 len += sprintf (&buffer[len], "$%d", RD (opcode));
991 break;
992 case 'a':
993 len += sprintf (&buffer[len], "%d", SA (opcode));
994 break;
995 case 'r':
996 len += sprintf (&buffer[len], "%s", debug_regs[RD (opcode)]);
997 break;
998 case '0':
999 len += sprintf (&buffer[len], "%s", cop0_regs[RD (opcode)]);
1000 break;
1001 case '1':
1002 len += sprintf (&buffer[len], "$fcr%d", RD (opcode));
1003 break;
1004 case '2':
1005 c = insn->fmt[i++];
1006 if (c == 'd') {
1007 len += print_cop2 (VED (opcode), &buffer[len]);
1008 } else { /* 's'*/
1009 len += print_cop2 (VES (opcode), &buffer[len]);
1011 break;
1012 case 'z':
1013 c = insn->fmt[i++];
1014 len += print_vfpu_register (VD (opcode), c, &buffer[len]);
1015 break;
1016 case 'Z':
1017 c = insn->fmt[i++];
1018 if (c == 'c') {
1019 len += sprintf (&buffer[len], "%d", VCC (opcode));
1020 } else { /* 'n' */
1021 len += sprintf (&buffer[len], "%s", vfpu_cond_names[VCN (opcode)]);
1023 break;
1024 case 'n':
1025 c = insn->fmt[i++];
1026 if (c == 'e') {
1027 len += sprintf (&buffer[len], "%d", RD (opcode) + 1);
1028 } else { /* 'i' */
1029 len += sprintf (&buffer[len], "%d", RD (opcode) - SA (opcode) + 1);
1031 break;
1032 case 'X':
1033 c = insn->fmt[i++];
1034 len += print_vfpu_register (VO (opcode), c, &buffer[len]);
1035 break;
1036 case 'x':
1037 c = insn->fmt[i++];
1038 len += print_vfpu_register (VT (opcode), c, &buffer[len]);
1039 break;
1040 case 'Y':
1041 len += sprintf (&buffer[len], "%d($%s)", IMM (opcode) & ~3, gpr_names[RS (opcode)]);
1042 break;
1043 case 'y':
1045 int reg = VS (opcode);
1046 if (vmmul) { if (reg & 0x20) { reg &= 0x5F; } else { reg |= 0x20; } }
1047 c = insn->fmt[i++];
1048 len += print_vfpu_register (reg, c, &buffer[len]);
1050 break;
1051 case 'v':
1052 c = insn->fmt[i++];
1053 switch (c) {
1054 case '3' : len += sprintf (&buffer[len], "%d", VI3 (opcode)); break;
1055 case '5' : len += sprintf (&buffer[len], "%d", VI5 (opcode)); break;
1056 case '8' : len += sprintf (&buffer[len], "%d", VI8 (opcode)); break;
1057 case 'k' : len += sprintf (&buffer[len], "%s", vfpu_constants [VI5 (opcode)]); break;
1058 case 'i' : len += sprintf (&buffer[len], "%d", IMM (opcode)); break;
1059 case 'h' : len += print_vfpu_halffloat (opcode, &buffer[len]); break;
1060 case 'r' : len += print_vfpu_rotator (opcode, &buffer[len]); break;
1061 case 'p' : c = insn->fmt[i++]; len += print_vfpu_prefix (opcode, c, &buffer[len]); break;
1063 break;
1064 case '?':
1065 vmmul = 1;
1066 break;
1068 } else {
1069 len += sprintf (&buffer[len], "%c", c);
1072 buffer[len] = '\0';
1075 char *allegrex_disassemble (unsigned int opcode, unsigned int PC)
1077 int i;
1079 for (i = 0; i < sizeof (instructions) / sizeof (struct allegrex_instruction); i++) {
1080 if ((instructions[i].mask & opcode) == instructions[i].opcode) {
1081 decode_instruction (&instructions[i], opcode, PC);
1082 break;
1085 return (char *) buffer;
1088 enum insn_type allegrex_insn_type (unsigned int opcode)
1090 int i;
1092 for (i = 0; i < sizeof (instructions) / sizeof (struct allegrex_instruction); i++) {
1093 if ((instructions[i].mask & opcode) == instructions[i].opcode) {
1094 return instructions[i].itype;
1097 return I_INVALID;
1100 #ifdef TEST_DISASSEMBLE
1102 #include <stdlib.h>
1104 int main (int argc, char **argv)
1106 int i;
1108 for (i = 0; i < sizeof (instructions) / sizeof (struct allegrex_instruction); i++) {
1109 unsigned int opcode = rand ();
1110 opcode = (opcode & (~instructions[i].mask)) | instructions[i].opcode;
1111 printf ("%s\n", allegrex_disassemble (opcode, 4 * i));
1114 return 0;
1117 #endif /* TEST_DISASSEMBLE */