cpu: Move breakpoints field from CPU_COMMON to CPUState
[qemu.git] / target-mips / translate.c
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "cpu.h"
25 #include "disas/disas.h"
26 #include "tcg-op.h"
27
28 #include "helper.h"
29 #define GEN_HELPER 1
30 #include "helper.h"
31
32 #define MIPS_DEBUG_DISAS 0
33 //#define MIPS_DEBUG_SIGN_EXTENSIONS
34
35 /* MIPS major opcodes */
36 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
37
38 enum {
39 /* indirect opcode tables */
40 OPC_SPECIAL = (0x00 << 26),
41 OPC_REGIMM = (0x01 << 26),
42 OPC_CP0 = (0x10 << 26),
43 OPC_CP1 = (0x11 << 26),
44 OPC_CP2 = (0x12 << 26),
45 OPC_CP3 = (0x13 << 26),
46 OPC_SPECIAL2 = (0x1C << 26),
47 OPC_SPECIAL3 = (0x1F << 26),
48 /* arithmetic with immediate */
49 OPC_ADDI = (0x08 << 26),
50 OPC_ADDIU = (0x09 << 26),
51 OPC_SLTI = (0x0A << 26),
52 OPC_SLTIU = (0x0B << 26),
53 /* logic with immediate */
54 OPC_ANDI = (0x0C << 26),
55 OPC_ORI = (0x0D << 26),
56 OPC_XORI = (0x0E << 26),
57 OPC_LUI = (0x0F << 26),
58 /* arithmetic with immediate */
59 OPC_DADDI = (0x18 << 26),
60 OPC_DADDIU = (0x19 << 26),
61 /* Jump and branches */
62 OPC_J = (0x02 << 26),
63 OPC_JAL = (0x03 << 26),
64 OPC_JALS = OPC_JAL | 0x5,
65 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
66 OPC_BEQL = (0x14 << 26),
67 OPC_BNE = (0x05 << 26),
68 OPC_BNEL = (0x15 << 26),
69 OPC_BLEZ = (0x06 << 26),
70 OPC_BLEZL = (0x16 << 26),
71 OPC_BGTZ = (0x07 << 26),
72 OPC_BGTZL = (0x17 << 26),
73 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
74 OPC_JALXS = OPC_JALX | 0x5,
75 /* Load and stores */
76 OPC_LDL = (0x1A << 26),
77 OPC_LDR = (0x1B << 26),
78 OPC_LB = (0x20 << 26),
79 OPC_LH = (0x21 << 26),
80 OPC_LWL = (0x22 << 26),
81 OPC_LW = (0x23 << 26),
82 OPC_LWPC = OPC_LW | 0x5,
83 OPC_LBU = (0x24 << 26),
84 OPC_LHU = (0x25 << 26),
85 OPC_LWR = (0x26 << 26),
86 OPC_LWU = (0x27 << 26),
87 OPC_SB = (0x28 << 26),
88 OPC_SH = (0x29 << 26),
89 OPC_SWL = (0x2A << 26),
90 OPC_SW = (0x2B << 26),
91 OPC_SDL = (0x2C << 26),
92 OPC_SDR = (0x2D << 26),
93 OPC_SWR = (0x2E << 26),
94 OPC_LL = (0x30 << 26),
95 OPC_LLD = (0x34 << 26),
96 OPC_LD = (0x37 << 26),
97 OPC_LDPC = OPC_LD | 0x5,
98 OPC_SC = (0x38 << 26),
99 OPC_SCD = (0x3C << 26),
100 OPC_SD = (0x3F << 26),
101 /* Floating point load/store */
102 OPC_LWC1 = (0x31 << 26),
103 OPC_LWC2 = (0x32 << 26),
104 OPC_LDC1 = (0x35 << 26),
105 OPC_LDC2 = (0x36 << 26),
106 OPC_SWC1 = (0x39 << 26),
107 OPC_SWC2 = (0x3A << 26),
108 OPC_SDC1 = (0x3D << 26),
109 OPC_SDC2 = (0x3E << 26),
110 /* MDMX ASE specific */
111 OPC_MDMX = (0x1E << 26),
112 /* Cache and prefetch */
113 OPC_CACHE = (0x2F << 26),
114 OPC_PREF = (0x33 << 26),
115 /* Reserved major opcode */
116 OPC_MAJOR3B_RESERVED = (0x3B << 26),
117 };
118
119 /* MIPS special opcodes */
120 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
121
122 enum {
123 /* Shifts */
124 OPC_SLL = 0x00 | OPC_SPECIAL,
125 /* NOP is SLL r0, r0, 0 */
126 /* SSNOP is SLL r0, r0, 1 */
127 /* EHB is SLL r0, r0, 3 */
128 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
129 OPC_ROTR = OPC_SRL | (1 << 21),
130 OPC_SRA = 0x03 | OPC_SPECIAL,
131 OPC_SLLV = 0x04 | OPC_SPECIAL,
132 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
133 OPC_ROTRV = OPC_SRLV | (1 << 6),
134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
137 OPC_DROTRV = OPC_DSRLV | (1 << 6),
138 OPC_DSRAV = 0x17 | OPC_SPECIAL,
139 OPC_DSLL = 0x38 | OPC_SPECIAL,
140 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
141 OPC_DROTR = OPC_DSRL | (1 << 21),
142 OPC_DSRA = 0x3B | OPC_SPECIAL,
143 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
144 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
145 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
146 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
147 /* Multiplication / division */
148 OPC_MULT = 0x18 | OPC_SPECIAL,
149 OPC_MULTU = 0x19 | OPC_SPECIAL,
150 OPC_DIV = 0x1A | OPC_SPECIAL,
151 OPC_DIVU = 0x1B | OPC_SPECIAL,
152 OPC_DMULT = 0x1C | OPC_SPECIAL,
153 OPC_DMULTU = 0x1D | OPC_SPECIAL,
154 OPC_DDIV = 0x1E | OPC_SPECIAL,
155 OPC_DDIVU = 0x1F | OPC_SPECIAL,
156 /* 2 registers arithmetic / logic */
157 OPC_ADD = 0x20 | OPC_SPECIAL,
158 OPC_ADDU = 0x21 | OPC_SPECIAL,
159 OPC_SUB = 0x22 | OPC_SPECIAL,
160 OPC_SUBU = 0x23 | OPC_SPECIAL,
161 OPC_AND = 0x24 | OPC_SPECIAL,
162 OPC_OR = 0x25 | OPC_SPECIAL,
163 OPC_XOR = 0x26 | OPC_SPECIAL,
164 OPC_NOR = 0x27 | OPC_SPECIAL,
165 OPC_SLT = 0x2A | OPC_SPECIAL,
166 OPC_SLTU = 0x2B | OPC_SPECIAL,
167 OPC_DADD = 0x2C | OPC_SPECIAL,
168 OPC_DADDU = 0x2D | OPC_SPECIAL,
169 OPC_DSUB = 0x2E | OPC_SPECIAL,
170 OPC_DSUBU = 0x2F | OPC_SPECIAL,
171 /* Jumps */
172 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
173 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
174 OPC_JALRC = OPC_JALR | (0x5 << 6),
175 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
176 /* Traps */
177 OPC_TGE = 0x30 | OPC_SPECIAL,
178 OPC_TGEU = 0x31 | OPC_SPECIAL,
179 OPC_TLT = 0x32 | OPC_SPECIAL,
180 OPC_TLTU = 0x33 | OPC_SPECIAL,
181 OPC_TEQ = 0x34 | OPC_SPECIAL,
182 OPC_TNE = 0x36 | OPC_SPECIAL,
183 /* HI / LO registers load & stores */
184 OPC_MFHI = 0x10 | OPC_SPECIAL,
185 OPC_MTHI = 0x11 | OPC_SPECIAL,
186 OPC_MFLO = 0x12 | OPC_SPECIAL,
187 OPC_MTLO = 0x13 | OPC_SPECIAL,
188 /* Conditional moves */
189 OPC_MOVZ = 0x0A | OPC_SPECIAL,
190 OPC_MOVN = 0x0B | OPC_SPECIAL,
191
192 OPC_MOVCI = 0x01 | OPC_SPECIAL,
193
194 /* Special */
195 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
196 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
197 OPC_BREAK = 0x0D | OPC_SPECIAL,
198 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
199 OPC_SYNC = 0x0F | OPC_SPECIAL,
200
201 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
202 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
203 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
204 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
205 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
206 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
207 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
208 };
209
210 /* Multiplication variants of the vr54xx. */
211 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
212
213 enum {
214 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
215 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
216 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
217 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
218 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
219 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
220 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
221 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
222 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
223 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
224 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
225 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
226 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
227 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
228 };
229
230 /* REGIMM (rt field) opcodes */
231 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
232
233 enum {
234 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
235 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
236 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
237 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
238 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
239 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
240 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
241 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
242 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
243 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
244 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
245 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
246 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
247 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
248 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
249 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
250 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
251 };
252
253 /* Special2 opcodes */
254 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
255
256 enum {
257 /* Multiply & xxx operations */
258 OPC_MADD = 0x00 | OPC_SPECIAL2,
259 OPC_MADDU = 0x01 | OPC_SPECIAL2,
260 OPC_MUL = 0x02 | OPC_SPECIAL2,
261 OPC_MSUB = 0x04 | OPC_SPECIAL2,
262 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
263 /* Loongson 2F */
264 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
265 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
266 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
267 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
268 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
269 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
270 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
271 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
272 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
273 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
274 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
275 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
276 /* Misc */
277 OPC_CLZ = 0x20 | OPC_SPECIAL2,
278 OPC_CLO = 0x21 | OPC_SPECIAL2,
279 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
280 OPC_DCLO = 0x25 | OPC_SPECIAL2,
281 /* Special */
282 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
283 };
284
285 /* Special3 opcodes */
286 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
287
288 enum {
289 OPC_EXT = 0x00 | OPC_SPECIAL3,
290 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
291 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
292 OPC_DEXT = 0x03 | OPC_SPECIAL3,
293 OPC_INS = 0x04 | OPC_SPECIAL3,
294 OPC_DINSM = 0x05 | OPC_SPECIAL3,
295 OPC_DINSU = 0x06 | OPC_SPECIAL3,
296 OPC_DINS = 0x07 | OPC_SPECIAL3,
297 OPC_FORK = 0x08 | OPC_SPECIAL3,
298 OPC_YIELD = 0x09 | OPC_SPECIAL3,
299 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
300 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
301 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
302
303 /* Loongson 2E */
304 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
305 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
306 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
307 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
308 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
309 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
310 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
311 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
312 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
313 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
314 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
315 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
316
317 /* MIPS DSP Load */
318 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
319 /* MIPS DSP Arithmetic */
320 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
321 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
322 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
323 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
324 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
325 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
326 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
327 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
328 /* MIPS DSP GPR-Based Shift Sub-class */
329 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
330 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
331 /* MIPS DSP Multiply Sub-class insns */
332 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
333 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
334 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
335 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
336 /* DSP Bit/Manipulation Sub-class */
337 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
338 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
339 /* MIPS DSP Append Sub-class */
340 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
341 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
342 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
343 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
344 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
345 };
346
347 /* BSHFL opcodes */
348 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
349
350 enum {
351 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
352 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
353 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
354 };
355
356 /* DBSHFL opcodes */
357 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
358
359 enum {
360 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
361 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
362 };
363
364 /* MIPS DSP REGIMM opcodes */
365 enum {
366 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
367 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
368 };
369
370 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
371 /* MIPS DSP Load */
372 enum {
373 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
374 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
375 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
376 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
377 };
378
379 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
380 enum {
381 /* MIPS DSP Arithmetic Sub-class */
382 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
383 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
384 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
385 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
386 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
387 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
388 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
389 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
390 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
391 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
392 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
393 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
394 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
395 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
396 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
397 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
398 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
399 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
400 /* MIPS DSP Multiply Sub-class insns */
401 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
402 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
403 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
404 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
405 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
406 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
407 };
408
409 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
410 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
411 enum {
412 /* MIPS DSP Arithmetic Sub-class */
413 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
414 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
415 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
416 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
417 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
418 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
419 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
420 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
421 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
422 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
423 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
424 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
425 /* MIPS DSP Multiply Sub-class insns */
426 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
427 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
428 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
429 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
430 };
431
432 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
433 enum {
434 /* MIPS DSP Arithmetic Sub-class */
435 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
436 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
437 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
438 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
439 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
440 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
441 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
442 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
443 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
444 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
445 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
446 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
447 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
448 /* DSP Bit/Manipulation Sub-class */
449 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
450 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
451 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
452 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
453 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
454 };
455
456 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
457 enum {
458 /* MIPS DSP Arithmetic Sub-class */
459 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
460 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
461 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
462 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
463 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
464 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
465 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
466 /* DSP Compare-Pick Sub-class */
467 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
468 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
469 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
470 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
471 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
472 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
473 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
474 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
475 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
476 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
477 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
478 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
479 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
480 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
481 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
482 };
483
484 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
485 enum {
486 /* MIPS DSP GPR-Based Shift Sub-class */
487 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
488 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
489 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
490 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
491 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
492 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
493 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
494 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
495 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
496 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
497 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
498 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
499 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
500 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
501 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
502 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
503 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
504 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
505 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
506 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
507 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
508 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
509 };
510
511 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
512 enum {
513 /* MIPS DSP Multiply Sub-class insns */
514 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
515 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
516 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
517 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
518 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
519 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
520 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
521 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
522 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
523 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
524 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
525 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
526 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
527 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
528 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
529 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
530 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
531 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
532 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
533 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
534 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
535 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
536 };
537
538 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
539 enum {
540 /* DSP Bit/Manipulation Sub-class */
541 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
542 };
543
544 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
545 enum {
546 /* MIPS DSP Append Sub-class */
547 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
548 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
549 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
550 };
551
552 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553 enum {
554 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
555 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
556 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
557 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
558 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
559 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
560 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
561 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
562 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
563 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
564 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
565 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
566 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
567 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
568 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
569 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
570 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
571 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
572 };
573
574 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
578 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
579 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
580 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
581 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
582 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
583 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
584 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
585 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
586 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
587 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
588 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
589 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
590 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
591 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
592 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
593 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
594 /* DSP Bit/Manipulation Sub-class */
595 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
596 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
597 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
598 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
599 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
600 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
601 };
602
603 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
604 enum {
605 /* MIPS DSP Multiply Sub-class insns */
606 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
607 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
608 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
609 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
610 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
611 /* MIPS DSP Arithmetic Sub-class */
612 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
613 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
614 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
615 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
616 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
617 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
618 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
619 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
620 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
621 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
622 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
623 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
624 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
625 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
626 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
627 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
628 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
629 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
630 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
631 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
632 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
633 };
634
635 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
636 enum {
637 /* DSP Compare-Pick Sub-class */
638 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
639 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
640 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
641 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
642 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
643 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
644 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
645 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
646 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
647 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
648 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
649 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
650 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
651 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
652 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
653 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
654 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
655 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
656 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
657 /* MIPS DSP Arithmetic Sub-class */
658 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
659 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
660 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
661 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
662 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
663 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
664 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
665 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
666 };
667
668 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669 enum {
670 /* DSP Append Sub-class */
671 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
672 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
673 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
674 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
675 };
676
677 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
678 enum {
679 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
680 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
681 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
682 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
683 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
684 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
685 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
686 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
687 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
688 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
689 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
690 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
691 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
692 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
693 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
694 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
695 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
696 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
697 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
698 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
699 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
700 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
701 };
702
703 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
704 enum {
705 /* DSP Bit/Manipulation Sub-class */
706 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
707 };
708
709 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
710 enum {
711 /* MIPS DSP Multiply Sub-class insns */
712 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
713 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
714 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
715 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
716 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
717 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
718 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
719 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
720 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
721 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
722 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
723 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
724 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
725 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
726 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
727 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
728 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
729 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
730 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
731 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
732 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
733 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
734 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
735 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
736 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
737 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
738 };
739
740 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
741 enum {
742 /* MIPS DSP GPR-Based Shift Sub-class */
743 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
744 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
745 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
746 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
747 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
748 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
749 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
750 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
751 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
752 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
753 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
754 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
755 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
756 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
757 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
758 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
759 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
760 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
761 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
762 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
763 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
764 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
765 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
766 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
767 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
768 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
769 };
770
771 /* Coprocessor 0 (rs field) */
772 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
773
774 enum {
775 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
776 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
777 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
778 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
779 OPC_MFTR = (0x08 << 21) | OPC_CP0,
780 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
781 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
782 OPC_MTTR = (0x0C << 21) | OPC_CP0,
783 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
784 OPC_C0 = (0x10 << 21) | OPC_CP0,
785 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
786 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
787 };
788
789 /* MFMC0 opcodes */
790 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
791
792 enum {
793 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
794 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
795 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
796 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
797 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
798 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
799 };
800
801 /* Coprocessor 0 (with rs == C0) */
802 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
803
804 enum {
805 OPC_TLBR = 0x01 | OPC_C0,
806 OPC_TLBWI = 0x02 | OPC_C0,
807 OPC_TLBWR = 0x06 | OPC_C0,
808 OPC_TLBP = 0x08 | OPC_C0,
809 OPC_RFE = 0x10 | OPC_C0,
810 OPC_ERET = 0x18 | OPC_C0,
811 OPC_DERET = 0x1F | OPC_C0,
812 OPC_WAIT = 0x20 | OPC_C0,
813 };
814
815 /* Coprocessor 1 (rs field) */
816 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
817
818 /* Values for the fmt field in FP instructions */
819 enum {
820 /* 0 - 15 are reserved */
821 FMT_S = 16, /* single fp */
822 FMT_D = 17, /* double fp */
823 FMT_E = 18, /* extended fp */
824 FMT_Q = 19, /* quad fp */
825 FMT_W = 20, /* 32-bit fixed */
826 FMT_L = 21, /* 64-bit fixed */
827 FMT_PS = 22, /* paired single fp */
828 /* 23 - 31 are reserved */
829 };
830
831 enum {
832 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
833 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
834 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
835 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
836 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
837 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
838 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
839 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
840 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
841 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
842 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
843 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
844 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
845 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
846 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
847 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
848 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
849 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
850 };
851
852 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
853 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
854
855 enum {
856 OPC_BC1F = (0x00 << 16) | OPC_BC1,
857 OPC_BC1T = (0x01 << 16) | OPC_BC1,
858 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
859 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
860 };
861
862 enum {
863 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
864 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
865 };
866
867 enum {
868 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
869 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
870 };
871
872 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
873
874 enum {
875 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
876 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
877 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
878 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
879 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
880 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
881 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
882 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
883 OPC_BC2 = (0x08 << 21) | OPC_CP2,
884 };
885
886 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
887
888 enum {
889 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
890 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
891 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
892 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
893 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
894 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
895 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
896 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
897
898 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
899 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
900 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
901 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
902 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
903 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
904 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
905 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
906
907 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
908 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
909 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
910 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
911 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
912 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
913 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
914 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
915
916 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
917 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
918 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
919 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
920 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
921 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
922 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
923 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
924
925 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
926 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
927 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
928 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
929 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
930 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
931
932 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
933 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
934 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
935 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
936 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
937 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
938
939 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
940 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
941 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
942 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
943 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
944 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
945
946 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
947 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
948 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
949 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
950 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
951 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
952
953 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
954 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
955 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
956 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
957 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
958 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
959
960 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
961 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
962 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
963 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
964 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
965 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
966
967 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
968 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
969 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
970 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
971 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
972 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
973
974 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
975 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
976 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
977 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
978 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
979 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
980 };
981
982
983 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
984
985 enum {
986 OPC_LWXC1 = 0x00 | OPC_CP3,
987 OPC_LDXC1 = 0x01 | OPC_CP3,
988 OPC_LUXC1 = 0x05 | OPC_CP3,
989 OPC_SWXC1 = 0x08 | OPC_CP3,
990 OPC_SDXC1 = 0x09 | OPC_CP3,
991 OPC_SUXC1 = 0x0D | OPC_CP3,
992 OPC_PREFX = 0x0F | OPC_CP3,
993 OPC_ALNV_PS = 0x1E | OPC_CP3,
994 OPC_MADD_S = 0x20 | OPC_CP3,
995 OPC_MADD_D = 0x21 | OPC_CP3,
996 OPC_MADD_PS = 0x26 | OPC_CP3,
997 OPC_MSUB_S = 0x28 | OPC_CP3,
998 OPC_MSUB_D = 0x29 | OPC_CP3,
999 OPC_MSUB_PS = 0x2E | OPC_CP3,
1000 OPC_NMADD_S = 0x30 | OPC_CP3,
1001 OPC_NMADD_D = 0x31 | OPC_CP3,
1002 OPC_NMADD_PS= 0x36 | OPC_CP3,
1003 OPC_NMSUB_S = 0x38 | OPC_CP3,
1004 OPC_NMSUB_D = 0x39 | OPC_CP3,
1005 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1006 };
1007
1008 /* global register indices */
1009 static TCGv_ptr cpu_env;
1010 static TCGv cpu_gpr[32], cpu_PC;
1011 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
1012 static TCGv cpu_dspctrl, btarget, bcond;
1013 static TCGv_i32 hflags;
1014 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1015 static TCGv_i64 fpu_f64[32];
1016
1017 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1018 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1019
1020 #include "exec/gen-icount.h"
1021
1022 #define gen_helper_0e0i(name, arg) do { \
1023 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1024 gen_helper_##name(cpu_env, helper_tmp); \
1025 tcg_temp_free_i32(helper_tmp); \
1026 } while(0)
1027
1028 #define gen_helper_0e1i(name, arg1, arg2) do { \
1029 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1030 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1031 tcg_temp_free_i32(helper_tmp); \
1032 } while(0)
1033
1034 #define gen_helper_1e0i(name, ret, arg1) do { \
1035 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1036 gen_helper_##name(ret, cpu_env, helper_tmp); \
1037 tcg_temp_free_i32(helper_tmp); \
1038 } while(0)
1039
1040 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1041 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1042 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1043 tcg_temp_free_i32(helper_tmp); \
1044 } while(0)
1045
1046 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1047 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1048 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1049 tcg_temp_free_i32(helper_tmp); \
1050 } while(0)
1051
1052 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1053 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1054 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1055 tcg_temp_free_i32(helper_tmp); \
1056 } while(0)
1057
1058 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1059 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1060 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1061 tcg_temp_free_i32(helper_tmp); \
1062 } while(0)
1063
1064 typedef struct DisasContext {
1065 struct TranslationBlock *tb;
1066 target_ulong pc, saved_pc;
1067 uint32_t opcode;
1068 int singlestep_enabled;
1069 int insn_flags;
1070 /* Routine used to access memory */
1071 int mem_idx;
1072 uint32_t hflags, saved_hflags;
1073 int bstate;
1074 target_ulong btarget;
1075 } DisasContext;
1076
1077 enum {
1078 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1079 * exception condition */
1080 BS_STOP = 1, /* We want to stop translation for any reason */
1081 BS_BRANCH = 2, /* We reached a branch condition */
1082 BS_EXCP = 3, /* We reached an exception condition */
1083 };
1084
1085 static const char * const regnames[] = {
1086 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1087 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1088 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1089 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1090 };
1091
1092 static const char * const regnames_HI[] = {
1093 "HI0", "HI1", "HI2", "HI3",
1094 };
1095
1096 static const char * const regnames_LO[] = {
1097 "LO0", "LO1", "LO2", "LO3",
1098 };
1099
1100 static const char * const regnames_ACX[] = {
1101 "ACX0", "ACX1", "ACX2", "ACX3",
1102 };
1103
1104 static const char * const fregnames[] = {
1105 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1106 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1107 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1108 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1109 };
1110
1111 #define MIPS_DEBUG(fmt, ...) \
1112 do { \
1113 if (MIPS_DEBUG_DISAS) { \
1114 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1115 TARGET_FMT_lx ": %08x " fmt "\n", \
1116 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1117 } \
1118 } while (0)
1119
1120 #define LOG_DISAS(...) \
1121 do { \
1122 if (MIPS_DEBUG_DISAS) { \
1123 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1124 } \
1125 } while (0)
1126
1127 #define MIPS_INVAL(op) \
1128 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1129 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1130
1131 /* General purpose registers moves. */
1132 static inline void gen_load_gpr (TCGv t, int reg)
1133 {
1134 if (reg == 0)
1135 tcg_gen_movi_tl(t, 0);
1136 else
1137 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1138 }
1139
1140 static inline void gen_store_gpr (TCGv t, int reg)
1141 {
1142 if (reg != 0)
1143 tcg_gen_mov_tl(cpu_gpr[reg], t);
1144 }
1145
1146 /* Moves to/from ACX register. */
1147 static inline void gen_load_ACX (TCGv t, int reg)
1148 {
1149 tcg_gen_mov_tl(t, cpu_ACX[reg]);
1150 }
1151
1152 static inline void gen_store_ACX (TCGv t, int reg)
1153 {
1154 tcg_gen_mov_tl(cpu_ACX[reg], t);
1155 }
1156
1157 /* Moves to/from shadow registers. */
1158 static inline void gen_load_srsgpr (int from, int to)
1159 {
1160 TCGv t0 = tcg_temp_new();
1161
1162 if (from == 0)
1163 tcg_gen_movi_tl(t0, 0);
1164 else {
1165 TCGv_i32 t2 = tcg_temp_new_i32();
1166 TCGv_ptr addr = tcg_temp_new_ptr();
1167
1168 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1169 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1170 tcg_gen_andi_i32(t2, t2, 0xf);
1171 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1172 tcg_gen_ext_i32_ptr(addr, t2);
1173 tcg_gen_add_ptr(addr, cpu_env, addr);
1174
1175 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1176 tcg_temp_free_ptr(addr);
1177 tcg_temp_free_i32(t2);
1178 }
1179 gen_store_gpr(t0, to);
1180 tcg_temp_free(t0);
1181 }
1182
1183 static inline void gen_store_srsgpr (int from, int to)
1184 {
1185 if (to != 0) {
1186 TCGv t0 = tcg_temp_new();
1187 TCGv_i32 t2 = tcg_temp_new_i32();
1188 TCGv_ptr addr = tcg_temp_new_ptr();
1189
1190 gen_load_gpr(t0, from);
1191 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1192 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1193 tcg_gen_andi_i32(t2, t2, 0xf);
1194 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1195 tcg_gen_ext_i32_ptr(addr, t2);
1196 tcg_gen_add_ptr(addr, cpu_env, addr);
1197
1198 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1199 tcg_temp_free_ptr(addr);
1200 tcg_temp_free_i32(t2);
1201 tcg_temp_free(t0);
1202 }
1203 }
1204
1205 /* Floating point register moves. */
1206 static void gen_load_fpr32(TCGv_i32 t, int reg)
1207 {
1208 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1209 }
1210
1211 static void gen_store_fpr32(TCGv_i32 t, int reg)
1212 {
1213 TCGv_i64 t64 = tcg_temp_new_i64();
1214 tcg_gen_extu_i32_i64(t64, t);
1215 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1216 tcg_temp_free_i64(t64);
1217 }
1218
1219 static void gen_load_fpr32h(TCGv_i32 t, int reg)
1220 {
1221 TCGv_i64 t64 = tcg_temp_new_i64();
1222 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1223 tcg_gen_trunc_i64_i32(t, t64);
1224 tcg_temp_free_i64(t64);
1225 }
1226
1227 static void gen_store_fpr32h(TCGv_i32 t, int reg)
1228 {
1229 TCGv_i64 t64 = tcg_temp_new_i64();
1230 tcg_gen_extu_i32_i64(t64, t);
1231 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1232 tcg_temp_free_i64(t64);
1233 }
1234
1235 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1236 {
1237 if (ctx->hflags & MIPS_HFLAG_F64) {
1238 tcg_gen_mov_i64(t, fpu_f64[reg]);
1239 } else {
1240 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1241 }
1242 }
1243
1244 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1245 {
1246 if (ctx->hflags & MIPS_HFLAG_F64) {
1247 tcg_gen_mov_i64(fpu_f64[reg], t);
1248 } else {
1249 TCGv_i64 t0;
1250 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1251 t0 = tcg_temp_new_i64();
1252 tcg_gen_shri_i64(t0, t, 32);
1253 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1254 tcg_temp_free_i64(t0);
1255 }
1256 }
1257
1258 static inline int get_fp_bit (int cc)
1259 {
1260 if (cc)
1261 return 24 + cc;
1262 else
1263 return 23;
1264 }
1265
1266 /* Tests */
1267 static inline void gen_save_pc(target_ulong pc)
1268 {
1269 tcg_gen_movi_tl(cpu_PC, pc);
1270 }
1271
1272 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1273 {
1274 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1275 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1276 gen_save_pc(ctx->pc);
1277 ctx->saved_pc = ctx->pc;
1278 }
1279 if (ctx->hflags != ctx->saved_hflags) {
1280 tcg_gen_movi_i32(hflags, ctx->hflags);
1281 ctx->saved_hflags = ctx->hflags;
1282 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1283 case MIPS_HFLAG_BR:
1284 break;
1285 case MIPS_HFLAG_BC:
1286 case MIPS_HFLAG_BL:
1287 case MIPS_HFLAG_B:
1288 tcg_gen_movi_tl(btarget, ctx->btarget);
1289 break;
1290 }
1291 }
1292 }
1293
1294 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1295 {
1296 ctx->saved_hflags = ctx->hflags;
1297 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1298 case MIPS_HFLAG_BR:
1299 break;
1300 case MIPS_HFLAG_BC:
1301 case MIPS_HFLAG_BL:
1302 case MIPS_HFLAG_B:
1303 ctx->btarget = env->btarget;
1304 break;
1305 }
1306 }
1307
1308 static inline void
1309 generate_exception_err (DisasContext *ctx, int excp, int err)
1310 {
1311 TCGv_i32 texcp = tcg_const_i32(excp);
1312 TCGv_i32 terr = tcg_const_i32(err);
1313 save_cpu_state(ctx, 1);
1314 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1315 tcg_temp_free_i32(terr);
1316 tcg_temp_free_i32(texcp);
1317 }
1318
1319 static inline void
1320 generate_exception (DisasContext *ctx, int excp)
1321 {
1322 save_cpu_state(ctx, 1);
1323 gen_helper_0e0i(raise_exception, excp);
1324 }
1325
1326 /* Addresses computation */
1327 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1328 {
1329 tcg_gen_add_tl(ret, arg0, arg1);
1330
1331 #if defined(TARGET_MIPS64)
1332 /* For compatibility with 32-bit code, data reference in user mode
1333 with Status_UX = 0 should be casted to 32-bit and sign extended.
1334 See the MIPS64 PRA manual, section 4.10. */
1335 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
1336 !(ctx->hflags & MIPS_HFLAG_UX)) {
1337 tcg_gen_ext32s_i64(ret, ret);
1338 }
1339 #endif
1340 }
1341
1342 static inline void check_cp0_enabled(DisasContext *ctx)
1343 {
1344 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1345 generate_exception_err(ctx, EXCP_CpU, 0);
1346 }
1347
1348 static inline void check_cp1_enabled(DisasContext *ctx)
1349 {
1350 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1351 generate_exception_err(ctx, EXCP_CpU, 1);
1352 }
1353
1354 /* Verify that the processor is running with COP1X instructions enabled.
1355 This is associated with the nabla symbol in the MIPS32 and MIPS64
1356 opcode tables. */
1357
1358 static inline void check_cop1x(DisasContext *ctx)
1359 {
1360 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1361 generate_exception(ctx, EXCP_RI);
1362 }
1363
1364 /* Verify that the processor is running with 64-bit floating-point
1365 operations enabled. */
1366
1367 static inline void check_cp1_64bitmode(DisasContext *ctx)
1368 {
1369 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1370 generate_exception(ctx, EXCP_RI);
1371 }
1372
1373 /*
1374 * Verify if floating point register is valid; an operation is not defined
1375 * if bit 0 of any register specification is set and the FR bit in the
1376 * Status register equals zero, since the register numbers specify an
1377 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1378 * in the Status register equals one, both even and odd register numbers
1379 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1380 *
1381 * Multiple 64 bit wide registers can be checked by calling
1382 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1383 */
1384 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1385 {
1386 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1387 generate_exception(ctx, EXCP_RI);
1388 }
1389
1390 /* Verify that the processor is running with DSP instructions enabled.
1391 This is enabled by CP0 Status register MX(24) bit.
1392 */
1393
1394 static inline void check_dsp(DisasContext *ctx)
1395 {
1396 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1397 if (ctx->insn_flags & ASE_DSP) {
1398 generate_exception(ctx, EXCP_DSPDIS);
1399 } else {
1400 generate_exception(ctx, EXCP_RI);
1401 }
1402 }
1403 }
1404
1405 static inline void check_dspr2(DisasContext *ctx)
1406 {
1407 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1408 if (ctx->insn_flags & ASE_DSP) {
1409 generate_exception(ctx, EXCP_DSPDIS);
1410 } else {
1411 generate_exception(ctx, EXCP_RI);
1412 }
1413 }
1414 }
1415
1416 /* This code generates a "reserved instruction" exception if the
1417 CPU does not support the instruction set corresponding to flags. */
1418 static inline void check_insn(DisasContext *ctx, int flags)
1419 {
1420 if (unlikely(!(ctx->insn_flags & flags))) {
1421 generate_exception(ctx, EXCP_RI);
1422 }
1423 }
1424
1425 /* This code generates a "reserved instruction" exception if 64-bit
1426 instructions are not enabled. */
1427 static inline void check_mips_64(DisasContext *ctx)
1428 {
1429 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1430 generate_exception(ctx, EXCP_RI);
1431 }
1432
1433 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1434 calling interface for 32 and 64-bit FPRs. No sense in changing
1435 all callers for gen_load_fpr32 when we need the CTX parameter for
1436 this one use. */
1437 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1438 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1439 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1440 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1441 int ft, int fs, int cc) \
1442 { \
1443 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1444 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1445 switch (ifmt) { \
1446 case FMT_PS: \
1447 check_cp1_64bitmode(ctx); \
1448 break; \
1449 case FMT_D: \
1450 if (abs) { \
1451 check_cop1x(ctx); \
1452 } \
1453 check_cp1_registers(ctx, fs | ft); \
1454 break; \
1455 case FMT_S: \
1456 if (abs) { \
1457 check_cop1x(ctx); \
1458 } \
1459 break; \
1460 } \
1461 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1462 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1463 switch (n) { \
1464 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1465 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1466 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1467 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1468 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1469 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1470 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1471 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1472 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1473 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1474 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1475 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1476 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1477 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1478 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1479 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1480 default: abort(); \
1481 } \
1482 tcg_temp_free_i##bits (fp0); \
1483 tcg_temp_free_i##bits (fp1); \
1484 }
1485
1486 FOP_CONDS(, 0, d, FMT_D, 64)
1487 FOP_CONDS(abs, 1, d, FMT_D, 64)
1488 FOP_CONDS(, 0, s, FMT_S, 32)
1489 FOP_CONDS(abs, 1, s, FMT_S, 32)
1490 FOP_CONDS(, 0, ps, FMT_PS, 64)
1491 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1492 #undef FOP_CONDS
1493 #undef gen_ldcmp_fpr32
1494 #undef gen_ldcmp_fpr64
1495
1496 /* load/store instructions. */
1497 #ifdef CONFIG_USER_ONLY
1498 #define OP_LD_ATOMIC(insn,fname) \
1499 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1500 { \
1501 TCGv t0 = tcg_temp_new(); \
1502 tcg_gen_mov_tl(t0, arg1); \
1503 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1504 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1505 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1506 tcg_temp_free(t0); \
1507 }
1508 #else
1509 #define OP_LD_ATOMIC(insn,fname) \
1510 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1511 { \
1512 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1513 }
1514 #endif
1515 OP_LD_ATOMIC(ll,ld32s);
1516 #if defined(TARGET_MIPS64)
1517 OP_LD_ATOMIC(lld,ld64);
1518 #endif
1519 #undef OP_LD_ATOMIC
1520
1521 #ifdef CONFIG_USER_ONLY
1522 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1523 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1524 { \
1525 TCGv t0 = tcg_temp_new(); \
1526 int l1 = gen_new_label(); \
1527 int l2 = gen_new_label(); \
1528 \
1529 tcg_gen_andi_tl(t0, arg2, almask); \
1530 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
1531 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
1532 generate_exception(ctx, EXCP_AdES); \
1533 gen_set_label(l1); \
1534 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1535 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1536 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
1537 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1538 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
1539 gen_helper_0e0i(raise_exception, EXCP_SC); \
1540 gen_set_label(l2); \
1541 tcg_gen_movi_tl(t0, 0); \
1542 gen_store_gpr(t0, rt); \
1543 tcg_temp_free(t0); \
1544 }
1545 #else
1546 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1547 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1548 { \
1549 TCGv t0 = tcg_temp_new(); \
1550 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
1551 gen_store_gpr(t0, rt); \
1552 tcg_temp_free(t0); \
1553 }
1554 #endif
1555 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1556 #if defined(TARGET_MIPS64)
1557 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1558 #endif
1559 #undef OP_ST_ATOMIC
1560
1561 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1562 int base, int16_t offset)
1563 {
1564 if (base == 0) {
1565 tcg_gen_movi_tl(addr, offset);
1566 } else if (offset == 0) {
1567 gen_load_gpr(addr, base);
1568 } else {
1569 tcg_gen_movi_tl(addr, offset);
1570 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1571 }
1572 }
1573
1574 static target_ulong pc_relative_pc (DisasContext *ctx)
1575 {
1576 target_ulong pc = ctx->pc;
1577
1578 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1579 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1580
1581 pc -= branch_bytes;
1582 }
1583
1584 pc &= ~(target_ulong)3;
1585 return pc;
1586 }
1587
1588 /* Load */
1589 static void gen_ld(DisasContext *ctx, uint32_t opc,
1590 int rt, int base, int16_t offset)
1591 {
1592 const char *opn = "ld";
1593 TCGv t0, t1, t2;
1594
1595 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1596 /* Loongson CPU uses a load to zero register for prefetch.
1597 We emulate it as a NOP. On other CPU we must perform the
1598 actual memory access. */
1599 MIPS_DEBUG("NOP");
1600 return;
1601 }
1602
1603 t0 = tcg_temp_new();
1604 gen_base_offset_addr(ctx, t0, base, offset);
1605
1606 switch (opc) {
1607 #if defined(TARGET_MIPS64)
1608 case OPC_LWU:
1609 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1610 gen_store_gpr(t0, rt);
1611 opn = "lwu";
1612 break;
1613 case OPC_LD:
1614 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1615 gen_store_gpr(t0, rt);
1616 opn = "ld";
1617 break;
1618 case OPC_LLD:
1619 save_cpu_state(ctx, 1);
1620 op_ld_lld(t0, t0, ctx);
1621 gen_store_gpr(t0, rt);
1622 opn = "lld";
1623 break;
1624 case OPC_LDL:
1625 t1 = tcg_temp_new();
1626 tcg_gen_andi_tl(t1, t0, 7);
1627 #ifndef TARGET_WORDS_BIGENDIAN
1628 tcg_gen_xori_tl(t1, t1, 7);
1629 #endif
1630 tcg_gen_shli_tl(t1, t1, 3);
1631 tcg_gen_andi_tl(t0, t0, ~7);
1632 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1633 tcg_gen_shl_tl(t0, t0, t1);
1634 tcg_gen_xori_tl(t1, t1, 63);
1635 t2 = tcg_const_tl(0x7fffffffffffffffull);
1636 tcg_gen_shr_tl(t2, t2, t1);
1637 gen_load_gpr(t1, rt);
1638 tcg_gen_and_tl(t1, t1, t2);
1639 tcg_temp_free(t2);
1640 tcg_gen_or_tl(t0, t0, t1);
1641 tcg_temp_free(t1);
1642 gen_store_gpr(t0, rt);
1643 opn = "ldl";
1644 break;
1645 case OPC_LDR:
1646 t1 = tcg_temp_new();
1647 tcg_gen_andi_tl(t1, t0, 7);
1648 #ifdef TARGET_WORDS_BIGENDIAN
1649 tcg_gen_xori_tl(t1, t1, 7);
1650 #endif
1651 tcg_gen_shli_tl(t1, t1, 3);
1652 tcg_gen_andi_tl(t0, t0, ~7);
1653 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1654 tcg_gen_shr_tl(t0, t0, t1);
1655 tcg_gen_xori_tl(t1, t1, 63);
1656 t2 = tcg_const_tl(0xfffffffffffffffeull);
1657 tcg_gen_shl_tl(t2, t2, t1);
1658 gen_load_gpr(t1, rt);
1659 tcg_gen_and_tl(t1, t1, t2);
1660 tcg_temp_free(t2);
1661 tcg_gen_or_tl(t0, t0, t1);
1662 tcg_temp_free(t1);
1663 gen_store_gpr(t0, rt);
1664 opn = "ldr";
1665 break;
1666 case OPC_LDPC:
1667 t1 = tcg_const_tl(pc_relative_pc(ctx));
1668 gen_op_addr_add(ctx, t0, t0, t1);
1669 tcg_temp_free(t1);
1670 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1671 gen_store_gpr(t0, rt);
1672 opn = "ldpc";
1673 break;
1674 #endif
1675 case OPC_LWPC:
1676 t1 = tcg_const_tl(pc_relative_pc(ctx));
1677 gen_op_addr_add(ctx, t0, t0, t1);
1678 tcg_temp_free(t1);
1679 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1680 gen_store_gpr(t0, rt);
1681 opn = "lwpc";
1682 break;
1683 case OPC_LW:
1684 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1685 gen_store_gpr(t0, rt);
1686 opn = "lw";
1687 break;
1688 case OPC_LH:
1689 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
1690 gen_store_gpr(t0, rt);
1691 opn = "lh";
1692 break;
1693 case OPC_LHU:
1694 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
1695 gen_store_gpr(t0, rt);
1696 opn = "lhu";
1697 break;
1698 case OPC_LB:
1699 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
1700 gen_store_gpr(t0, rt);
1701 opn = "lb";
1702 break;
1703 case OPC_LBU:
1704 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
1705 gen_store_gpr(t0, rt);
1706 opn = "lbu";
1707 break;
1708 case OPC_LWL:
1709 t1 = tcg_temp_new();
1710 tcg_gen_andi_tl(t1, t0, 3);
1711 #ifndef TARGET_WORDS_BIGENDIAN
1712 tcg_gen_xori_tl(t1, t1, 3);
1713 #endif
1714 tcg_gen_shli_tl(t1, t1, 3);
1715 tcg_gen_andi_tl(t0, t0, ~3);
1716 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1717 tcg_gen_shl_tl(t0, t0, t1);
1718 tcg_gen_xori_tl(t1, t1, 31);
1719 t2 = tcg_const_tl(0x7fffffffull);
1720 tcg_gen_shr_tl(t2, t2, t1);
1721 gen_load_gpr(t1, rt);
1722 tcg_gen_and_tl(t1, t1, t2);
1723 tcg_temp_free(t2);
1724 tcg_gen_or_tl(t0, t0, t1);
1725 tcg_temp_free(t1);
1726 tcg_gen_ext32s_tl(t0, t0);
1727 gen_store_gpr(t0, rt);
1728 opn = "lwl";
1729 break;
1730 case OPC_LWR:
1731 t1 = tcg_temp_new();
1732 tcg_gen_andi_tl(t1, t0, 3);
1733 #ifdef TARGET_WORDS_BIGENDIAN
1734 tcg_gen_xori_tl(t1, t1, 3);
1735 #endif
1736 tcg_gen_shli_tl(t1, t1, 3);
1737 tcg_gen_andi_tl(t0, t0, ~3);
1738 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1739 tcg_gen_shr_tl(t0, t0, t1);
1740 tcg_gen_xori_tl(t1, t1, 31);
1741 t2 = tcg_const_tl(0xfffffffeull);
1742 tcg_gen_shl_tl(t2, t2, t1);
1743 gen_load_gpr(t1, rt);
1744 tcg_gen_and_tl(t1, t1, t2);
1745 tcg_temp_free(t2);
1746 tcg_gen_or_tl(t0, t0, t1);
1747 tcg_temp_free(t1);
1748 tcg_gen_ext32s_tl(t0, t0);
1749 gen_store_gpr(t0, rt);
1750 opn = "lwr";
1751 break;
1752 case OPC_LL:
1753 save_cpu_state(ctx, 1);
1754 op_ld_ll(t0, t0, ctx);
1755 gen_store_gpr(t0, rt);
1756 opn = "ll";
1757 break;
1758 }
1759 (void)opn; /* avoid a compiler warning */
1760 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1761 tcg_temp_free(t0);
1762 }
1763
1764 /* Store */
1765 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1766 int base, int16_t offset)
1767 {
1768 const char *opn = "st";
1769 TCGv t0 = tcg_temp_new();
1770 TCGv t1 = tcg_temp_new();
1771
1772 gen_base_offset_addr(ctx, t0, base, offset);
1773 gen_load_gpr(t1, rt);
1774 switch (opc) {
1775 #if defined(TARGET_MIPS64)
1776 case OPC_SD:
1777 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
1778 opn = "sd";
1779 break;
1780 case OPC_SDL:
1781 save_cpu_state(ctx, 1);
1782 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
1783 opn = "sdl";
1784 break;
1785 case OPC_SDR:
1786 save_cpu_state(ctx, 1);
1787 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
1788 opn = "sdr";
1789 break;
1790 #endif
1791 case OPC_SW:
1792 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
1793 opn = "sw";
1794 break;
1795 case OPC_SH:
1796 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
1797 opn = "sh";
1798 break;
1799 case OPC_SB:
1800 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
1801 opn = "sb";
1802 break;
1803 case OPC_SWL:
1804 save_cpu_state(ctx, 1);
1805 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
1806 opn = "swl";
1807 break;
1808 case OPC_SWR:
1809 save_cpu_state(ctx, 1);
1810 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
1811 opn = "swr";
1812 break;
1813 }
1814 (void)opn; /* avoid a compiler warning */
1815 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1816 tcg_temp_free(t0);
1817 tcg_temp_free(t1);
1818 }
1819
1820
1821 /* Store conditional */
1822 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1823 int base, int16_t offset)
1824 {
1825 const char *opn = "st_cond";
1826 TCGv t0, t1;
1827
1828 #ifdef CONFIG_USER_ONLY
1829 t0 = tcg_temp_local_new();
1830 t1 = tcg_temp_local_new();
1831 #else
1832 t0 = tcg_temp_new();
1833 t1 = tcg_temp_new();
1834 #endif
1835 gen_base_offset_addr(ctx, t0, base, offset);
1836 gen_load_gpr(t1, rt);
1837 switch (opc) {
1838 #if defined(TARGET_MIPS64)
1839 case OPC_SCD:
1840 save_cpu_state(ctx, 1);
1841 op_st_scd(t1, t0, rt, ctx);
1842 opn = "scd";
1843 break;
1844 #endif
1845 case OPC_SC:
1846 save_cpu_state(ctx, 1);
1847 op_st_sc(t1, t0, rt, ctx);
1848 opn = "sc";
1849 break;
1850 }
1851 (void)opn; /* avoid a compiler warning */
1852 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1853 tcg_temp_free(t1);
1854 tcg_temp_free(t0);
1855 }
1856
1857 /* Load and store */
1858 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1859 int base, int16_t offset)
1860 {
1861 const char *opn = "flt_ldst";
1862 TCGv t0 = tcg_temp_new();
1863
1864 gen_base_offset_addr(ctx, t0, base, offset);
1865 /* Don't do NOP if destination is zero: we must perform the actual
1866 memory access. */
1867 switch (opc) {
1868 case OPC_LWC1:
1869 {
1870 TCGv_i32 fp0 = tcg_temp_new_i32();
1871 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
1872 gen_store_fpr32(fp0, ft);
1873 tcg_temp_free_i32(fp0);
1874 }
1875 opn = "lwc1";
1876 break;
1877 case OPC_SWC1:
1878 {
1879 TCGv_i32 fp0 = tcg_temp_new_i32();
1880 gen_load_fpr32(fp0, ft);
1881 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
1882 tcg_temp_free_i32(fp0);
1883 }
1884 opn = "swc1";
1885 break;
1886 case OPC_LDC1:
1887 {
1888 TCGv_i64 fp0 = tcg_temp_new_i64();
1889 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
1890 gen_store_fpr64(ctx, fp0, ft);
1891 tcg_temp_free_i64(fp0);
1892 }
1893 opn = "ldc1";
1894 break;
1895 case OPC_SDC1:
1896 {
1897 TCGv_i64 fp0 = tcg_temp_new_i64();
1898 gen_load_fpr64(ctx, fp0, ft);
1899 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
1900 tcg_temp_free_i64(fp0);
1901 }
1902 opn = "sdc1";
1903 break;
1904 default:
1905 MIPS_INVAL(opn);
1906 generate_exception(ctx, EXCP_RI);
1907 goto out;
1908 }
1909 (void)opn; /* avoid a compiler warning */
1910 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1911 out:
1912 tcg_temp_free(t0);
1913 }
1914
1915 static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
1916 uint32_t op, int rt, int rs, int16_t imm)
1917 {
1918 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1919 check_cp1_enabled(ctx);
1920 gen_flt_ldst(ctx, op, rt, rs, imm);
1921 } else {
1922 generate_exception_err(ctx, EXCP_CpU, 1);
1923 }
1924 }
1925
1926 /* Arithmetic with immediate operand */
1927 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
1928 int rt, int rs, int16_t imm)
1929 {
1930 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1931 const char *opn = "imm arith";
1932
1933 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1934 /* If no destination, treat it as a NOP.
1935 For addi, we must generate the overflow exception when needed. */
1936 MIPS_DEBUG("NOP");
1937 return;
1938 }
1939 switch (opc) {
1940 case OPC_ADDI:
1941 {
1942 TCGv t0 = tcg_temp_local_new();
1943 TCGv t1 = tcg_temp_new();
1944 TCGv t2 = tcg_temp_new();
1945 int l1 = gen_new_label();
1946
1947 gen_load_gpr(t1, rs);
1948 tcg_gen_addi_tl(t0, t1, uimm);
1949 tcg_gen_ext32s_tl(t0, t0);
1950
1951 tcg_gen_xori_tl(t1, t1, ~uimm);
1952 tcg_gen_xori_tl(t2, t0, uimm);
1953 tcg_gen_and_tl(t1, t1, t2);
1954 tcg_temp_free(t2);
1955 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1956 tcg_temp_free(t1);
1957 /* operands of same sign, result different sign */
1958 generate_exception(ctx, EXCP_OVERFLOW);
1959 gen_set_label(l1);
1960 tcg_gen_ext32s_tl(t0, t0);
1961 gen_store_gpr(t0, rt);
1962 tcg_temp_free(t0);
1963 }
1964 opn = "addi";
1965 break;
1966 case OPC_ADDIU:
1967 if (rs != 0) {
1968 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1969 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1970 } else {
1971 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1972 }
1973 opn = "addiu";
1974 break;
1975 #if defined(TARGET_MIPS64)
1976 case OPC_DADDI:
1977 {
1978 TCGv t0 = tcg_temp_local_new();
1979 TCGv t1 = tcg_temp_new();
1980 TCGv t2 = tcg_temp_new();
1981 int l1 = gen_new_label();
1982
1983 gen_load_gpr(t1, rs);
1984 tcg_gen_addi_tl(t0, t1, uimm);
1985
1986 tcg_gen_xori_tl(t1, t1, ~uimm);
1987 tcg_gen_xori_tl(t2, t0, uimm);
1988 tcg_gen_and_tl(t1, t1, t2);
1989 tcg_temp_free(t2);
1990 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1991 tcg_temp_free(t1);
1992 /* operands of same sign, result different sign */
1993 generate_exception(ctx, EXCP_OVERFLOW);
1994 gen_set_label(l1);
1995 gen_store_gpr(t0, rt);
1996 tcg_temp_free(t0);
1997 }
1998 opn = "daddi";
1999 break;
2000 case OPC_DADDIU:
2001 if (rs != 0) {
2002 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2003 } else {
2004 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2005 }
2006 opn = "daddiu";
2007 break;
2008 #endif
2009 }
2010 (void)opn; /* avoid a compiler warning */
2011 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2012 }
2013
2014 /* Logic with immediate operand */
2015 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2016 int rt, int rs, int16_t imm)
2017 {
2018 target_ulong uimm;
2019
2020 if (rt == 0) {
2021 /* If no destination, treat it as a NOP. */
2022 MIPS_DEBUG("NOP");
2023 return;
2024 }
2025 uimm = (uint16_t)imm;
2026 switch (opc) {
2027 case OPC_ANDI:
2028 if (likely(rs != 0))
2029 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2030 else
2031 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2032 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2033 regnames[rs], uimm);
2034 break;
2035 case OPC_ORI:
2036 if (rs != 0)
2037 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2038 else
2039 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2040 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2041 regnames[rs], uimm);
2042 break;
2043 case OPC_XORI:
2044 if (likely(rs != 0))
2045 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2046 else
2047 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2048 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2049 regnames[rs], uimm);
2050 break;
2051 case OPC_LUI:
2052 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2053 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2054 break;
2055
2056 default:
2057 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2058 break;
2059 }
2060 }
2061
2062 /* Set on less than with immediate operand */
2063 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2064 int rt, int rs, int16_t imm)
2065 {
2066 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2067 const char *opn = "imm arith";
2068 TCGv t0;
2069
2070 if (rt == 0) {
2071 /* If no destination, treat it as a NOP. */
2072 MIPS_DEBUG("NOP");
2073 return;
2074 }
2075 t0 = tcg_temp_new();
2076 gen_load_gpr(t0, rs);
2077 switch (opc) {
2078 case OPC_SLTI:
2079 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2080 opn = "slti";
2081 break;
2082 case OPC_SLTIU:
2083 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2084 opn = "sltiu";
2085 break;
2086 }
2087 (void)opn; /* avoid a compiler warning */
2088 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2089 tcg_temp_free(t0);
2090 }
2091
2092 /* Shifts with immediate operand */
2093 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2094 int rt, int rs, int16_t imm)
2095 {
2096 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2097 const char *opn = "imm shift";
2098 TCGv t0;
2099
2100 if (rt == 0) {
2101 /* If no destination, treat it as a NOP. */
2102 MIPS_DEBUG("NOP");
2103 return;
2104 }
2105
2106 t0 = tcg_temp_new();
2107 gen_load_gpr(t0, rs);
2108 switch (opc) {
2109 case OPC_SLL:
2110 tcg_gen_shli_tl(t0, t0, uimm);
2111 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2112 opn = "sll";
2113 break;
2114 case OPC_SRA:
2115 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2116 opn = "sra";
2117 break;
2118 case OPC_SRL:
2119 if (uimm != 0) {
2120 tcg_gen_ext32u_tl(t0, t0);
2121 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2122 } else {
2123 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2124 }
2125 opn = "srl";
2126 break;
2127 case OPC_ROTR:
2128 if (uimm != 0) {
2129 TCGv_i32 t1 = tcg_temp_new_i32();
2130
2131 tcg_gen_trunc_tl_i32(t1, t0);
2132 tcg_gen_rotri_i32(t1, t1, uimm);
2133 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2134 tcg_temp_free_i32(t1);
2135 } else {
2136 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2137 }
2138 opn = "rotr";
2139 break;
2140 #if defined(TARGET_MIPS64)
2141 case OPC_DSLL:
2142 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2143 opn = "dsll";
2144 break;
2145 case OPC_DSRA:
2146 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2147 opn = "dsra";
2148 break;
2149 case OPC_DSRL:
2150 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2151 opn = "dsrl";
2152 break;
2153 case OPC_DROTR:
2154 if (uimm != 0) {
2155 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2156 } else {
2157 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2158 }
2159 opn = "drotr";
2160 break;
2161 case OPC_DSLL32:
2162 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2163 opn = "dsll32";
2164 break;
2165 case OPC_DSRA32:
2166 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2167 opn = "dsra32";
2168 break;
2169 case OPC_DSRL32:
2170 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2171 opn = "dsrl32";
2172 break;
2173 case OPC_DROTR32:
2174 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2175 opn = "drotr32";
2176 break;
2177 #endif
2178 }
2179 (void)opn; /* avoid a compiler warning */
2180 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2181 tcg_temp_free(t0);
2182 }
2183
2184 /* Arithmetic */
2185 static void gen_arith(DisasContext *ctx, uint32_t opc,
2186 int rd, int rs, int rt)
2187 {
2188 const char *opn = "arith";
2189
2190 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2191 && opc != OPC_DADD && opc != OPC_DSUB) {
2192 /* If no destination, treat it as a NOP.
2193 For add & sub, we must generate the overflow exception when needed. */
2194 MIPS_DEBUG("NOP");
2195 return;
2196 }
2197
2198 switch (opc) {
2199 case OPC_ADD:
2200 {
2201 TCGv t0 = tcg_temp_local_new();
2202 TCGv t1 = tcg_temp_new();
2203 TCGv t2 = tcg_temp_new();
2204 int l1 = gen_new_label();
2205
2206 gen_load_gpr(t1, rs);
2207 gen_load_gpr(t2, rt);
2208 tcg_gen_add_tl(t0, t1, t2);
2209 tcg_gen_ext32s_tl(t0, t0);
2210 tcg_gen_xor_tl(t1, t1, t2);
2211 tcg_gen_xor_tl(t2, t0, t2);
2212 tcg_gen_andc_tl(t1, t2, t1);
2213 tcg_temp_free(t2);
2214 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2215 tcg_temp_free(t1);
2216 /* operands of same sign, result different sign */
2217 generate_exception(ctx, EXCP_OVERFLOW);
2218 gen_set_label(l1);
2219 gen_store_gpr(t0, rd);
2220 tcg_temp_free(t0);
2221 }
2222 opn = "add";
2223 break;
2224 case OPC_ADDU:
2225 if (rs != 0 && rt != 0) {
2226 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2227 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2228 } else if (rs == 0 && rt != 0) {
2229 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2230 } else if (rs != 0 && rt == 0) {
2231 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2232 } else {
2233 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2234 }
2235 opn = "addu";
2236 break;
2237 case OPC_SUB:
2238 {
2239 TCGv t0 = tcg_temp_local_new();
2240 TCGv t1 = tcg_temp_new();
2241 TCGv t2 = tcg_temp_new();
2242 int l1 = gen_new_label();
2243
2244 gen_load_gpr(t1, rs);
2245 gen_load_gpr(t2, rt);
2246 tcg_gen_sub_tl(t0, t1, t2);
2247 tcg_gen_ext32s_tl(t0, t0);
2248 tcg_gen_xor_tl(t2, t1, t2);
2249 tcg_gen_xor_tl(t1, t0, t1);
2250 tcg_gen_and_tl(t1, t1, t2);
2251 tcg_temp_free(t2);
2252 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2253 tcg_temp_free(t1);
2254 /* operands of different sign, first operand and result different sign */
2255 generate_exception(ctx, EXCP_OVERFLOW);
2256 gen_set_label(l1);
2257 gen_store_gpr(t0, rd);
2258 tcg_temp_free(t0);
2259 }
2260 opn = "sub";
2261 break;
2262 case OPC_SUBU:
2263 if (rs != 0 && rt != 0) {
2264 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2265 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2266 } else if (rs == 0 && rt != 0) {
2267 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2268 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2269 } else if (rs != 0 && rt == 0) {
2270 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2271 } else {
2272 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2273 }
2274 opn = "subu";
2275 break;
2276 #if defined(TARGET_MIPS64)
2277 case OPC_DADD:
2278 {
2279 TCGv t0 = tcg_temp_local_new();
2280 TCGv t1 = tcg_temp_new();
2281 TCGv t2 = tcg_temp_new();
2282 int l1 = gen_new_label();
2283
2284 gen_load_gpr(t1, rs);
2285 gen_load_gpr(t2, rt);
2286 tcg_gen_add_tl(t0, t1, t2);
2287 tcg_gen_xor_tl(t1, t1, t2);
2288 tcg_gen_xor_tl(t2, t0, t2);
2289 tcg_gen_andc_tl(t1, t2, t1);
2290 tcg_temp_free(t2);
2291 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2292 tcg_temp_free(t1);
2293 /* operands of same sign, result different sign */
2294 generate_exception(ctx, EXCP_OVERFLOW);
2295 gen_set_label(l1);
2296 gen_store_gpr(t0, rd);
2297 tcg_temp_free(t0);
2298 }
2299 opn = "dadd";
2300 break;
2301 case OPC_DADDU:
2302 if (rs != 0 && rt != 0) {
2303 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2304 } else if (rs == 0 && rt != 0) {
2305 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2306 } else if (rs != 0 && rt == 0) {
2307 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2308 } else {
2309 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2310 }
2311 opn = "daddu";
2312 break;
2313 case OPC_DSUB:
2314 {
2315 TCGv t0 = tcg_temp_local_new();
2316 TCGv t1 = tcg_temp_new();
2317 TCGv t2 = tcg_temp_new();
2318 int l1 = gen_new_label();
2319
2320 gen_load_gpr(t1, rs);
2321 gen_load_gpr(t2, rt);
2322 tcg_gen_sub_tl(t0, t1, t2);
2323 tcg_gen_xor_tl(t2, t1, t2);
2324 tcg_gen_xor_tl(t1, t0, t1);
2325 tcg_gen_and_tl(t1, t1, t2);
2326 tcg_temp_free(t2);
2327 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2328 tcg_temp_free(t1);
2329 /* operands of different sign, first operand and result different sign */
2330 generate_exception(ctx, EXCP_OVERFLOW);
2331 gen_set_label(l1);
2332 gen_store_gpr(t0, rd);
2333 tcg_temp_free(t0);
2334 }
2335 opn = "dsub";
2336 break;
2337 case OPC_DSUBU:
2338 if (rs != 0 && rt != 0) {
2339 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2340 } else if (rs == 0 && rt != 0) {
2341 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2342 } else if (rs != 0 && rt == 0) {
2343 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2344 } else {
2345 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2346 }
2347 opn = "dsubu";
2348 break;
2349 #endif
2350 case OPC_MUL:
2351 if (likely(rs != 0 && rt != 0)) {
2352 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2353 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2354 } else {
2355 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2356 }
2357 opn = "mul";
2358 break;
2359 }
2360 (void)opn; /* avoid a compiler warning */
2361 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2362 }
2363
2364 /* Conditional move */
2365 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2366 int rd, int rs, int rt)
2367 {
2368 const char *opn = "cond move";
2369 TCGv t0, t1, t2;
2370
2371 if (rd == 0) {
2372 /* If no destination, treat it as a NOP. */
2373 MIPS_DEBUG("NOP");
2374 return;
2375 }
2376
2377 t0 = tcg_temp_new();
2378 gen_load_gpr(t0, rt);
2379 t1 = tcg_const_tl(0);
2380 t2 = tcg_temp_new();
2381 gen_load_gpr(t2, rs);
2382 switch (opc) {
2383 case OPC_MOVN:
2384 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2385 opn = "movn";
2386 break;
2387 case OPC_MOVZ:
2388 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2389 opn = "movz";
2390 break;
2391 }
2392 tcg_temp_free(t2);
2393 tcg_temp_free(t1);
2394 tcg_temp_free(t0);
2395
2396 (void)opn; /* avoid a compiler warning */
2397 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2398 }
2399
2400 /* Logic */
2401 static void gen_logic(DisasContext *ctx, uint32_t opc,
2402 int rd, int rs, int rt)
2403 {
2404 const char *opn = "logic";
2405
2406 if (rd == 0) {
2407 /* If no destination, treat it as a NOP. */
2408 MIPS_DEBUG("NOP");
2409 return;
2410 }
2411
2412 switch (opc) {
2413 case OPC_AND:
2414 if (likely(rs != 0 && rt != 0)) {
2415 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2416 } else {
2417 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2418 }
2419 opn = "and";
2420 break;
2421 case OPC_NOR:
2422 if (rs != 0 && rt != 0) {
2423 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2424 } else if (rs == 0 && rt != 0) {
2425 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2426 } else if (rs != 0 && rt == 0) {
2427 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2428 } else {
2429 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2430 }
2431 opn = "nor";
2432 break;
2433 case OPC_OR:
2434 if (likely(rs != 0 && rt != 0)) {
2435 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2436 } else if (rs == 0 && rt != 0) {
2437 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2438 } else if (rs != 0 && rt == 0) {
2439 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2440 } else {
2441 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2442 }
2443 opn = "or";
2444 break;
2445 case OPC_XOR:
2446 if (likely(rs != 0 && rt != 0)) {
2447 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2448 } else if (rs == 0 && rt != 0) {
2449 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2450 } else if (rs != 0 && rt == 0) {
2451 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2452 } else {
2453 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2454 }
2455 opn = "xor";
2456 break;
2457 }
2458 (void)opn; /* avoid a compiler warning */
2459 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2460 }
2461
2462 /* Set on lower than */
2463 static void gen_slt(DisasContext *ctx, uint32_t opc,
2464 int rd, int rs, int rt)
2465 {
2466 const char *opn = "slt";
2467 TCGv t0, t1;
2468
2469 if (rd == 0) {
2470 /* If no destination, treat it as a NOP. */
2471 MIPS_DEBUG("NOP");
2472 return;
2473 }
2474
2475 t0 = tcg_temp_new();
2476 t1 = tcg_temp_new();
2477 gen_load_gpr(t0, rs);
2478 gen_load_gpr(t1, rt);
2479 switch (opc) {
2480 case OPC_SLT:
2481 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2482 opn = "slt";
2483 break;
2484 case OPC_SLTU:
2485 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2486 opn = "sltu";
2487 break;
2488 }
2489 (void)opn; /* avoid a compiler warning */
2490 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2491 tcg_temp_free(t0);
2492 tcg_temp_free(t1);
2493 }
2494
2495 /* Shifts */
2496 static void gen_shift(DisasContext *ctx, uint32_t opc,
2497 int rd, int rs, int rt)
2498 {
2499 const char *opn = "shifts";
2500 TCGv t0, t1;
2501
2502 if (rd == 0) {
2503 /* If no destination, treat it as a NOP.
2504 For add & sub, we must generate the overflow exception when needed. */
2505 MIPS_DEBUG("NOP");
2506 return;
2507 }
2508
2509 t0 = tcg_temp_new();
2510 t1 = tcg_temp_new();
2511 gen_load_gpr(t0, rs);
2512 gen_load_gpr(t1, rt);
2513 switch (opc) {
2514 case OPC_SLLV:
2515 tcg_gen_andi_tl(t0, t0, 0x1f);
2516 tcg_gen_shl_tl(t0, t1, t0);
2517 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2518 opn = "sllv";
2519 break;
2520 case OPC_SRAV:
2521 tcg_gen_andi_tl(t0, t0, 0x1f);
2522 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2523 opn = "srav";
2524 break;
2525 case OPC_SRLV:
2526 tcg_gen_ext32u_tl(t1, t1);
2527 tcg_gen_andi_tl(t0, t0, 0x1f);
2528 tcg_gen_shr_tl(t0, t1, t0);
2529 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2530 opn = "srlv";
2531 break;
2532 case OPC_ROTRV:
2533 {
2534 TCGv_i32 t2 = tcg_temp_new_i32();
2535 TCGv_i32 t3 = tcg_temp_new_i32();
2536
2537 tcg_gen_trunc_tl_i32(t2, t0);
2538 tcg_gen_trunc_tl_i32(t3, t1);
2539 tcg_gen_andi_i32(t2, t2, 0x1f);
2540 tcg_gen_rotr_i32(t2, t3, t2);
2541 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2542 tcg_temp_free_i32(t2);
2543 tcg_temp_free_i32(t3);
2544 opn = "rotrv";
2545 }
2546 break;
2547 #if defined(TARGET_MIPS64)
2548 case OPC_DSLLV:
2549 tcg_gen_andi_tl(t0, t0, 0x3f);
2550 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2551 opn = "dsllv";
2552 break;
2553 case OPC_DSRAV:
2554 tcg_gen_andi_tl(t0, t0, 0x3f);
2555 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2556 opn = "dsrav";
2557 break;
2558 case OPC_DSRLV:
2559 tcg_gen_andi_tl(t0, t0, 0x3f);
2560 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2561 opn = "dsrlv";
2562 break;
2563 case OPC_DROTRV:
2564 tcg_gen_andi_tl(t0, t0, 0x3f);
2565 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2566 opn = "drotrv";
2567 break;
2568 #endif
2569 }
2570 (void)opn; /* avoid a compiler warning */
2571 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2572 tcg_temp_free(t0);
2573 tcg_temp_free(t1);
2574 }
2575
2576 /* Arithmetic on HI/LO registers */
2577 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2578 {
2579 const char *opn = "hilo";
2580
2581 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2582 /* Treat as NOP. */
2583 MIPS_DEBUG("NOP");
2584 return;
2585 }
2586
2587 if (acc != 0) {
2588 check_dsp(ctx);
2589 }
2590
2591 switch (opc) {
2592 case OPC_MFHI:
2593 #if defined(TARGET_MIPS64)
2594 if (acc != 0) {
2595 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2596 } else
2597 #endif
2598 {
2599 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2600 }
2601 opn = "mfhi";
2602 break;
2603 case OPC_MFLO:
2604 #if defined(TARGET_MIPS64)
2605 if (acc != 0) {
2606 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2607 } else
2608 #endif
2609 {
2610 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2611 }
2612 opn = "mflo";
2613 break;
2614 case OPC_MTHI:
2615 if (reg != 0) {
2616 #if defined(TARGET_MIPS64)
2617 if (acc != 0) {
2618 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2619 } else
2620 #endif
2621 {
2622 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2623 }
2624 } else {
2625 tcg_gen_movi_tl(cpu_HI[acc], 0);
2626 }
2627 opn = "mthi";
2628 break;
2629 case OPC_MTLO:
2630 if (reg != 0) {
2631 #if defined(TARGET_MIPS64)
2632 if (acc != 0) {
2633 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2634 } else
2635 #endif
2636 {
2637 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2638 }
2639 } else {
2640 tcg_gen_movi_tl(cpu_LO[acc], 0);
2641 }
2642 opn = "mtlo";
2643 break;
2644 }
2645 (void)opn; /* avoid a compiler warning */
2646 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2647 }
2648
2649 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
2650 int acc, int rs, int rt)
2651 {
2652 const char *opn = "mul/div";
2653 TCGv t0, t1;
2654
2655 t0 = tcg_temp_new();
2656 t1 = tcg_temp_new();
2657
2658 gen_load_gpr(t0, rs);
2659 gen_load_gpr(t1, rt);
2660
2661 if (acc != 0) {
2662 check_dsp(ctx);
2663 }
2664
2665 switch (opc) {
2666 case OPC_DIV:
2667 {
2668 TCGv t2 = tcg_temp_new();
2669 TCGv t3 = tcg_temp_new();
2670 tcg_gen_ext32s_tl(t0, t0);
2671 tcg_gen_ext32s_tl(t1, t1);
2672 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2673 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2674 tcg_gen_and_tl(t2, t2, t3);
2675 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2676 tcg_gen_or_tl(t2, t2, t3);
2677 tcg_gen_movi_tl(t3, 0);
2678 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2679 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
2680 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
2681 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
2682 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
2683 tcg_temp_free(t3);
2684 tcg_temp_free(t2);
2685 }
2686 opn = "div";
2687 break;
2688 case OPC_DIVU:
2689 {
2690 TCGv t2 = tcg_const_tl(0);
2691 TCGv t3 = tcg_const_tl(1);
2692 tcg_gen_ext32u_tl(t0, t0);
2693 tcg_gen_ext32u_tl(t1, t1);
2694 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
2695 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
2696 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
2697 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
2698 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
2699 tcg_temp_free(t3);
2700 tcg_temp_free(t2);
2701 }
2702 opn = "divu";
2703 break;
2704 case OPC_MULT:
2705 {
2706 TCGv_i32 t2 = tcg_temp_new_i32();
2707 TCGv_i32 t3 = tcg_temp_new_i32();
2708 tcg_gen_trunc_tl_i32(t2, t0);
2709 tcg_gen_trunc_tl_i32(t3, t1);
2710 tcg_gen_muls2_i32(t2, t3, t2, t3);
2711 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2712 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2713 tcg_temp_free_i32(t2);
2714 tcg_temp_free_i32(t3);
2715 }
2716 opn = "mult";
2717 break;
2718 case OPC_MULTU:
2719 {
2720 TCGv_i32 t2 = tcg_temp_new_i32();
2721 TCGv_i32 t3 = tcg_temp_new_i32();
2722 tcg_gen_trunc_tl_i32(t2, t0);
2723 tcg_gen_trunc_tl_i32(t3, t1);
2724 tcg_gen_mulu2_i32(t2, t3, t2, t3);
2725 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2726 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2727 tcg_temp_free_i32(t2);
2728 tcg_temp_free_i32(t3);
2729 }
2730 opn = "multu";
2731 break;
2732 #if defined(TARGET_MIPS64)
2733 case OPC_DDIV:
2734 {
2735 TCGv t2 = tcg_temp_new();
2736 TCGv t3 = tcg_temp_new();
2737 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
2738 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
2739 tcg_gen_and_tl(t2, t2, t3);
2740 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2741 tcg_gen_or_tl(t2, t2, t3);
2742 tcg_gen_movi_tl(t3, 0);
2743 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2744 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
2745 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
2746 tcg_temp_free(t3);
2747 tcg_temp_free(t2);
2748 }
2749 opn = "ddiv";
2750 break;
2751 case OPC_DDIVU:
2752 {
2753 TCGv t2 = tcg_const_tl(0);
2754 TCGv t3 = tcg_const_tl(1);
2755 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
2756 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
2757 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
2758 tcg_temp_free(t3);
2759 tcg_temp_free(t2);
2760 }
2761 opn = "ddivu";
2762 break;
2763 case OPC_DMULT:
2764 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
2765 opn = "dmult";
2766 break;
2767 case OPC_DMULTU:
2768 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
2769 opn = "dmultu";
2770 break;
2771 #endif
2772 case OPC_MADD:
2773 {
2774 TCGv_i64 t2 = tcg_temp_new_i64();
2775 TCGv_i64 t3 = tcg_temp_new_i64();
2776
2777 tcg_gen_ext_tl_i64(t2, t0);
2778 tcg_gen_ext_tl_i64(t3, t1);
2779 tcg_gen_mul_i64(t2, t2, t3);
2780 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2781 tcg_gen_add_i64(t2, t2, t3);
2782 tcg_temp_free_i64(t3);
2783 tcg_gen_trunc_i64_tl(t0, t2);
2784 tcg_gen_shri_i64(t2, t2, 32);
2785 tcg_gen_trunc_i64_tl(t1, t2);
2786 tcg_temp_free_i64(t2);
2787 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2788 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2789 }
2790 opn = "madd";
2791 break;
2792 case OPC_MADDU:
2793 {
2794 TCGv_i64 t2 = tcg_temp_new_i64();
2795 TCGv_i64 t3 = tcg_temp_new_i64();
2796
2797 tcg_gen_ext32u_tl(t0, t0);
2798 tcg_gen_ext32u_tl(t1, t1);
2799 tcg_gen_extu_tl_i64(t2, t0);
2800 tcg_gen_extu_tl_i64(t3, t1);
2801 tcg_gen_mul_i64(t2, t2, t3);
2802 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2803 tcg_gen_add_i64(t2, t2, t3);
2804 tcg_temp_free_i64(t3);
2805 tcg_gen_trunc_i64_tl(t0, t2);
2806 tcg_gen_shri_i64(t2, t2, 32);
2807 tcg_gen_trunc_i64_tl(t1, t2);
2808 tcg_temp_free_i64(t2);
2809 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2810 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2811 }
2812 opn = "maddu";
2813 break;
2814 case OPC_MSUB:
2815 {
2816 TCGv_i64 t2 = tcg_temp_new_i64();
2817 TCGv_i64 t3 = tcg_temp_new_i64();
2818
2819 tcg_gen_ext_tl_i64(t2, t0);
2820 tcg_gen_ext_tl_i64(t3, t1);
2821 tcg_gen_mul_i64(t2, t2, t3);
2822 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2823 tcg_gen_sub_i64(t2, t3, t2);
2824 tcg_temp_free_i64(t3);
2825 tcg_gen_trunc_i64_tl(t0, t2);
2826 tcg_gen_shri_i64(t2, t2, 32);
2827 tcg_gen_trunc_i64_tl(t1, t2);
2828 tcg_temp_free_i64(t2);
2829 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2830 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2831 }
2832 opn = "msub";
2833 break;
2834 case OPC_MSUBU:
2835 {
2836 TCGv_i64 t2 = tcg_temp_new_i64();
2837 TCGv_i64 t3 = tcg_temp_new_i64();
2838
2839 tcg_gen_ext32u_tl(t0, t0);
2840 tcg_gen_ext32u_tl(t1, t1);
2841 tcg_gen_extu_tl_i64(t2, t0);
2842 tcg_gen_extu_tl_i64(t3, t1);
2843 tcg_gen_mul_i64(t2, t2, t3);
2844 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2845 tcg_gen_sub_i64(t2, t3, t2);
2846 tcg_temp_free_i64(t3);
2847 tcg_gen_trunc_i64_tl(t0, t2);
2848 tcg_gen_shri_i64(t2, t2, 32);
2849 tcg_gen_trunc_i64_tl(t1, t2);
2850 tcg_temp_free_i64(t2);
2851 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2852 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2853 }
2854 opn = "msubu";
2855 break;
2856 default:
2857 MIPS_INVAL(opn);
2858 generate_exception(ctx, EXCP_RI);
2859 goto out;
2860 }
2861 (void)opn; /* avoid a compiler warning */
2862 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2863 out:
2864 tcg_temp_free(t0);
2865 tcg_temp_free(t1);
2866 }
2867
2868 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2869 int rd, int rs, int rt)
2870 {
2871 const char *opn = "mul vr54xx";
2872 TCGv t0 = tcg_temp_new();
2873 TCGv t1 = tcg_temp_new();
2874
2875 gen_load_gpr(t0, rs);
2876 gen_load_gpr(t1, rt);
2877
2878 switch (opc) {
2879 case OPC_VR54XX_MULS:
2880 gen_helper_muls(t0, cpu_env, t0, t1);
2881 opn = "muls";
2882 break;
2883 case OPC_VR54XX_MULSU:
2884 gen_helper_mulsu(t0, cpu_env, t0, t1);
2885 opn = "mulsu";
2886 break;
2887 case OPC_VR54XX_MACC:
2888 gen_helper_macc(t0, cpu_env, t0, t1);
2889 opn = "macc";
2890 break;
2891 case OPC_VR54XX_MACCU:
2892 gen_helper_maccu(t0, cpu_env, t0, t1);
2893 opn = "maccu";
2894 break;
2895 case OPC_VR54XX_MSAC:
2896 gen_helper_msac(t0, cpu_env, t0, t1);
2897 opn = "msac";
2898 break;
2899 case OPC_VR54XX_MSACU:
2900 gen_helper_msacu(t0, cpu_env, t0, t1);
2901 opn = "msacu";
2902 break;
2903 case OPC_VR54XX_MULHI:
2904 gen_helper_mulhi(t0, cpu_env, t0, t1);
2905 opn = "mulhi";
2906 break;
2907 case OPC_VR54XX_MULHIU:
2908 gen_helper_mulhiu(t0, cpu_env, t0, t1);
2909 opn = "mulhiu";
2910 break;
2911 case OPC_VR54XX_MULSHI:
2912 gen_helper_mulshi(t0, cpu_env, t0, t1);
2913 opn = "mulshi";
2914 break;
2915 case OPC_VR54XX_MULSHIU:
2916 gen_helper_mulshiu(t0, cpu_env, t0, t1);
2917 opn = "mulshiu";
2918 break;
2919 case OPC_VR54XX_MACCHI:
2920 gen_helper_macchi(t0, cpu_env, t0, t1);
2921 opn = "macchi";
2922 break;
2923 case OPC_VR54XX_MACCHIU:
2924 gen_helper_macchiu(t0, cpu_env, t0, t1);
2925 opn = "macchiu";
2926 break;
2927 case OPC_VR54XX_MSACHI:
2928 gen_helper_msachi(t0, cpu_env, t0, t1);
2929 opn = "msachi";
2930 break;
2931 case OPC_VR54XX_MSACHIU:
2932 gen_helper_msachiu(t0, cpu_env, t0, t1);
2933 opn = "msachiu";
2934 break;
2935 default:
2936 MIPS_INVAL("mul vr54xx");
2937 generate_exception(ctx, EXCP_RI);
2938 goto out;
2939 }
2940 gen_store_gpr(t0, rd);
2941 (void)opn; /* avoid a compiler warning */
2942 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2943
2944 out:
2945 tcg_temp_free(t0);
2946 tcg_temp_free(t1);
2947 }
2948
2949 static void gen_cl (DisasContext *ctx, uint32_t opc,
2950 int rd, int rs)
2951 {
2952 const char *opn = "CLx";
2953 TCGv t0;
2954
2955 if (rd == 0) {
2956 /* Treat as NOP. */
2957 MIPS_DEBUG("NOP");
2958 return;
2959 }
2960 t0 = tcg_temp_new();
2961 gen_load_gpr(t0, rs);
2962 switch (opc) {
2963 case OPC_CLO:
2964 gen_helper_clo(cpu_gpr[rd], t0);
2965 opn = "clo";
2966 break;
2967 case OPC_CLZ:
2968 gen_helper_clz(cpu_gpr[rd], t0);
2969 opn = "clz";
2970 break;
2971 #if defined(TARGET_MIPS64)
2972 case OPC_DCLO:
2973 gen_helper_dclo(cpu_gpr[rd], t0);
2974 opn = "dclo";
2975 break;
2976 case OPC_DCLZ:
2977 gen_helper_dclz(cpu_gpr[rd], t0);
2978 opn = "dclz";
2979 break;
2980 #endif
2981 }
2982 (void)opn; /* avoid a compiler warning */
2983 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2984 tcg_temp_free(t0);
2985 }
2986
2987 /* Godson integer instructions */
2988 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
2989 int rd, int rs, int rt)
2990 {
2991 const char *opn = "loongson";
2992 TCGv t0, t1;
2993
2994 if (rd == 0) {
2995 /* Treat as NOP. */
2996 MIPS_DEBUG("NOP");
2997 return;
2998 }
2999
3000 switch (opc) {
3001 case OPC_MULT_G_2E:
3002 case OPC_MULT_G_2F:
3003 case OPC_MULTU_G_2E:
3004 case OPC_MULTU_G_2F:
3005 #if defined(TARGET_MIPS64)
3006 case OPC_DMULT_G_2E:
3007 case OPC_DMULT_G_2F:
3008 case OPC_DMULTU_G_2E:
3009 case OPC_DMULTU_G_2F:
3010 #endif
3011 t0 = tcg_temp_new();
3012 t1 = tcg_temp_new();
3013 break;
3014 default:
3015 t0 = tcg_temp_local_new();
3016 t1 = tcg_temp_local_new();
3017 break;
3018 }
3019
3020 gen_load_gpr(t0, rs);
3021 gen_load_gpr(t1, rt);
3022
3023 switch (opc) {
3024 case OPC_MULT_G_2E:
3025 case OPC_MULT_G_2F:
3026 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3027 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3028 opn = "mult.g";
3029 break;
3030 case OPC_MULTU_G_2E:
3031 case OPC_MULTU_G_2F:
3032 tcg_gen_ext32u_tl(t0, t0);
3033 tcg_gen_ext32u_tl(t1, t1);
3034 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3035 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3036 opn = "multu.g";
3037 break;
3038 case OPC_DIV_G_2E:
3039 case OPC_DIV_G_2F:
3040 {