target/mips: Add declarations for generic TCG helpers
[qemu/ar7.git] / target / mips / tcg / translate.c
blob3e9945540fc1711a2cce8eacba005cb014d0e069
1 /*
2 * MIPS emulation for QEMU - main translation routines
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 * Copyright (c) 2020 Philippe Mathieu-Daudé
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
25 #include "qemu/osdep.h"
26 #include "cpu.h"
27 #include "internal.h"
28 #include "tcg/tcg-op.h"
29 #include "exec/translator.h"
30 #include "exec/helper-proto.h"
31 #include "exec/helper-gen.h"
32 #include "semihosting/semihost.h"
34 #include "trace.h"
35 #include "trace-tcg.h"
36 #include "exec/translator.h"
37 #include "exec/log.h"
38 #include "qemu/qemu-print.h"
39 #include "fpu_helper.h"
40 #include "translate.h"
43 * Many sysemu-only helpers are not reachable for user-only.
44 * Define stub generators here, so that we need not either sprinkle
45 * ifdefs through the translator, nor provide the helper function.
47 #define STUB_HELPER(NAME, ...) \
48 static inline void gen_helper_##NAME(__VA_ARGS__) \
49 { g_assert_not_reached(); }
51 #ifdef CONFIG_USER_ONLY
52 STUB_HELPER(cache, TCGv_env env, TCGv val, TCGv_i32 reg)
53 #endif
55 enum {
56 /* indirect opcode tables */
57 OPC_SPECIAL = (0x00 << 26),
58 OPC_REGIMM = (0x01 << 26),
59 OPC_CP0 = (0x10 << 26),
60 OPC_CP2 = (0x12 << 26),
61 OPC_CP3 = (0x13 << 26),
62 OPC_SPECIAL2 = (0x1C << 26),
63 OPC_SPECIAL3 = (0x1F << 26),
64 /* arithmetic with immediate */
65 OPC_ADDI = (0x08 << 26),
66 OPC_ADDIU = (0x09 << 26),
67 OPC_SLTI = (0x0A << 26),
68 OPC_SLTIU = (0x0B << 26),
69 /* logic with immediate */
70 OPC_ANDI = (0x0C << 26),
71 OPC_ORI = (0x0D << 26),
72 OPC_XORI = (0x0E << 26),
73 OPC_LUI = (0x0F << 26),
74 /* arithmetic with immediate */
75 OPC_DADDI = (0x18 << 26),
76 OPC_DADDIU = (0x19 << 26),
77 /* Jump and branches */
78 OPC_J = (0x02 << 26),
79 OPC_JAL = (0x03 << 26),
80 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
81 OPC_BEQL = (0x14 << 26),
82 OPC_BNE = (0x05 << 26),
83 OPC_BNEL = (0x15 << 26),
84 OPC_BLEZ = (0x06 << 26),
85 OPC_BLEZL = (0x16 << 26),
86 OPC_BGTZ = (0x07 << 26),
87 OPC_BGTZL = (0x17 << 26),
88 OPC_JALX = (0x1D << 26),
89 OPC_DAUI = (0x1D << 26),
90 /* Load and stores */
91 OPC_LDL = (0x1A << 26),
92 OPC_LDR = (0x1B << 26),
93 OPC_LB = (0x20 << 26),
94 OPC_LH = (0x21 << 26),
95 OPC_LWL = (0x22 << 26),
96 OPC_LW = (0x23 << 26),
97 OPC_LWPC = OPC_LW | 0x5,
98 OPC_LBU = (0x24 << 26),
99 OPC_LHU = (0x25 << 26),
100 OPC_LWR = (0x26 << 26),
101 OPC_LWU = (0x27 << 26),
102 OPC_SB = (0x28 << 26),
103 OPC_SH = (0x29 << 26),
104 OPC_SWL = (0x2A << 26),
105 OPC_SW = (0x2B << 26),
106 OPC_SDL = (0x2C << 26),
107 OPC_SDR = (0x2D << 26),
108 OPC_SWR = (0x2E << 26),
109 OPC_LL = (0x30 << 26),
110 OPC_LLD = (0x34 << 26),
111 OPC_LD = (0x37 << 26),
112 OPC_LDPC = OPC_LD | 0x5,
113 OPC_SC = (0x38 << 26),
114 OPC_SCD = (0x3C << 26),
115 OPC_SD = (0x3F << 26),
116 /* Floating point load/store */
117 OPC_LWC1 = (0x31 << 26),
118 OPC_LWC2 = (0x32 << 26),
119 OPC_LDC1 = (0x35 << 26),
120 OPC_LDC2 = (0x36 << 26),
121 OPC_SWC1 = (0x39 << 26),
122 OPC_SWC2 = (0x3A << 26),
123 OPC_SDC1 = (0x3D << 26),
124 OPC_SDC2 = (0x3E << 26),
125 /* Compact Branches */
126 OPC_BLEZALC = (0x06 << 26),
127 OPC_BGEZALC = (0x06 << 26),
128 OPC_BGEUC = (0x06 << 26),
129 OPC_BGTZALC = (0x07 << 26),
130 OPC_BLTZALC = (0x07 << 26),
131 OPC_BLTUC = (0x07 << 26),
132 OPC_BOVC = (0x08 << 26),
133 OPC_BEQZALC = (0x08 << 26),
134 OPC_BEQC = (0x08 << 26),
135 OPC_BLEZC = (0x16 << 26),
136 OPC_BGEZC = (0x16 << 26),
137 OPC_BGEC = (0x16 << 26),
138 OPC_BGTZC = (0x17 << 26),
139 OPC_BLTZC = (0x17 << 26),
140 OPC_BLTC = (0x17 << 26),
141 OPC_BNVC = (0x18 << 26),
142 OPC_BNEZALC = (0x18 << 26),
143 OPC_BNEC = (0x18 << 26),
144 OPC_BC = (0x32 << 26),
145 OPC_BEQZC = (0x36 << 26),
146 OPC_JIC = (0x36 << 26),
147 OPC_BALC = (0x3A << 26),
148 OPC_BNEZC = (0x3E << 26),
149 OPC_JIALC = (0x3E << 26),
150 /* MDMX ASE specific */
151 OPC_MDMX = (0x1E << 26),
152 /* Cache and prefetch */
153 OPC_CACHE = (0x2F << 26),
154 OPC_PREF = (0x33 << 26),
155 /* PC-relative address computation / loads */
156 OPC_PCREL = (0x3B << 26),
159 /* PC-relative address computation / loads */
160 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
161 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
162 enum {
163 /* Instructions determined by bits 19 and 20 */
164 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
165 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
166 OPC_LWUPC = OPC_PCREL | (2 << 19),
168 /* Instructions determined by bits 16 ... 20 */
169 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
170 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
172 /* Other */
173 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
176 /* MIPS special opcodes */
177 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
179 enum {
180 /* Shifts */
181 OPC_SLL = 0x00 | OPC_SPECIAL,
182 /* NOP is SLL r0, r0, 0 */
183 /* SSNOP is SLL r0, r0, 1 */
184 /* EHB is SLL r0, r0, 3 */
185 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
186 OPC_ROTR = OPC_SRL | (1 << 21),
187 OPC_SRA = 0x03 | OPC_SPECIAL,
188 OPC_SLLV = 0x04 | OPC_SPECIAL,
189 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
190 OPC_ROTRV = OPC_SRLV | (1 << 6),
191 OPC_SRAV = 0x07 | OPC_SPECIAL,
192 OPC_DSLLV = 0x14 | OPC_SPECIAL,
193 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
194 OPC_DROTRV = OPC_DSRLV | (1 << 6),
195 OPC_DSRAV = 0x17 | OPC_SPECIAL,
196 OPC_DSLL = 0x38 | OPC_SPECIAL,
197 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
198 OPC_DROTR = OPC_DSRL | (1 << 21),
199 OPC_DSRA = 0x3B | OPC_SPECIAL,
200 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
201 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
202 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
203 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
204 /* Multiplication / division */
205 OPC_MULT = 0x18 | OPC_SPECIAL,
206 OPC_MULTU = 0x19 | OPC_SPECIAL,
207 OPC_DIV = 0x1A | OPC_SPECIAL,
208 OPC_DIVU = 0x1B | OPC_SPECIAL,
209 OPC_DMULT = 0x1C | OPC_SPECIAL,
210 OPC_DMULTU = 0x1D | OPC_SPECIAL,
211 OPC_DDIV = 0x1E | OPC_SPECIAL,
212 OPC_DDIVU = 0x1F | OPC_SPECIAL,
214 /* 2 registers arithmetic / logic */
215 OPC_ADD = 0x20 | OPC_SPECIAL,
216 OPC_ADDU = 0x21 | OPC_SPECIAL,
217 OPC_SUB = 0x22 | OPC_SPECIAL,
218 OPC_SUBU = 0x23 | OPC_SPECIAL,
219 OPC_AND = 0x24 | OPC_SPECIAL,
220 OPC_OR = 0x25 | OPC_SPECIAL,
221 OPC_XOR = 0x26 | OPC_SPECIAL,
222 OPC_NOR = 0x27 | OPC_SPECIAL,
223 OPC_SLT = 0x2A | OPC_SPECIAL,
224 OPC_SLTU = 0x2B | OPC_SPECIAL,
225 OPC_DADD = 0x2C | OPC_SPECIAL,
226 OPC_DADDU = 0x2D | OPC_SPECIAL,
227 OPC_DSUB = 0x2E | OPC_SPECIAL,
228 OPC_DSUBU = 0x2F | OPC_SPECIAL,
229 /* Jumps */
230 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
231 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
232 /* Traps */
233 OPC_TGE = 0x30 | OPC_SPECIAL,
234 OPC_TGEU = 0x31 | OPC_SPECIAL,
235 OPC_TLT = 0x32 | OPC_SPECIAL,
236 OPC_TLTU = 0x33 | OPC_SPECIAL,
237 OPC_TEQ = 0x34 | OPC_SPECIAL,
238 OPC_TNE = 0x36 | OPC_SPECIAL,
239 /* HI / LO registers load & stores */
240 OPC_MFHI = 0x10 | OPC_SPECIAL,
241 OPC_MTHI = 0x11 | OPC_SPECIAL,
242 OPC_MFLO = 0x12 | OPC_SPECIAL,
243 OPC_MTLO = 0x13 | OPC_SPECIAL,
244 /* Conditional moves */
245 OPC_MOVZ = 0x0A | OPC_SPECIAL,
246 OPC_MOVN = 0x0B | OPC_SPECIAL,
248 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
249 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
251 OPC_MOVCI = 0x01 | OPC_SPECIAL,
253 /* Special */
254 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
255 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
256 OPC_BREAK = 0x0D | OPC_SPECIAL,
257 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
258 OPC_SYNC = 0x0F | OPC_SPECIAL,
260 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
261 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
262 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
263 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
267 * R6 Multiply and Divide instructions have the same opcode
268 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
270 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
272 enum {
273 R6_OPC_MUL = OPC_MULT | (2 << 6),
274 R6_OPC_MUH = OPC_MULT | (3 << 6),
275 R6_OPC_MULU = OPC_MULTU | (2 << 6),
276 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
277 R6_OPC_DIV = OPC_DIV | (2 << 6),
278 R6_OPC_MOD = OPC_DIV | (3 << 6),
279 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
280 R6_OPC_MODU = OPC_DIVU | (3 << 6),
282 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
283 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
284 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
285 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
286 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
287 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
288 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
289 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
291 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
292 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
293 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
294 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
295 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
298 /* Multiplication variants of the vr54xx. */
299 #define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6)))
301 enum {
302 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
303 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
304 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
305 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
306 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
307 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
308 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
309 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
310 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
311 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
312 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
313 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
314 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
315 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
318 /* REGIMM (rt field) opcodes */
319 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
321 enum {
322 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
323 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
324 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
325 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
326 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
327 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
328 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
329 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
330 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
331 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
332 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
333 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
334 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
335 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
336 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
337 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
339 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
340 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
343 /* Special2 opcodes */
344 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
346 enum {
347 /* Multiply & xxx operations */
348 OPC_MADD = 0x00 | OPC_SPECIAL2,
349 OPC_MADDU = 0x01 | OPC_SPECIAL2,
350 OPC_MUL = 0x02 | OPC_SPECIAL2,
351 OPC_MSUB = 0x04 | OPC_SPECIAL2,
352 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
353 /* Loongson 2F */
354 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
355 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
356 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
357 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
358 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
359 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
360 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
361 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
362 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
363 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
364 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
365 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
366 /* Misc */
367 OPC_CLZ = 0x20 | OPC_SPECIAL2,
368 OPC_CLO = 0x21 | OPC_SPECIAL2,
369 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
370 OPC_DCLO = 0x25 | OPC_SPECIAL2,
371 /* Special */
372 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
375 /* Special3 opcodes */
376 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
378 enum {
379 OPC_EXT = 0x00 | OPC_SPECIAL3,
380 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
381 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
382 OPC_DEXT = 0x03 | OPC_SPECIAL3,
383 OPC_INS = 0x04 | OPC_SPECIAL3,
384 OPC_DINSM = 0x05 | OPC_SPECIAL3,
385 OPC_DINSU = 0x06 | OPC_SPECIAL3,
386 OPC_DINS = 0x07 | OPC_SPECIAL3,
387 OPC_FORK = 0x08 | OPC_SPECIAL3,
388 OPC_YIELD = 0x09 | OPC_SPECIAL3,
389 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
390 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
391 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
392 OPC_GINV = 0x3D | OPC_SPECIAL3,
394 /* Loongson 2E */
395 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
396 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
397 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
398 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
399 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
400 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
401 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
402 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
403 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
404 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
405 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
406 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
408 /* MIPS DSP Load */
409 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
410 /* MIPS DSP Arithmetic */
411 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
412 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
413 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
414 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
415 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
416 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
417 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
418 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
419 /* MIPS DSP GPR-Based Shift Sub-class */
420 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
421 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
422 /* MIPS DSP Multiply Sub-class insns */
423 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
424 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
425 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
426 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
427 /* DSP Bit/Manipulation Sub-class */
428 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
429 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
430 /* MIPS DSP Append Sub-class */
431 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
432 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
433 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
434 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
435 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
437 /* EVA */
438 OPC_LWLE = 0x19 | OPC_SPECIAL3,
439 OPC_LWRE = 0x1A | OPC_SPECIAL3,
440 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
441 OPC_SBE = 0x1C | OPC_SPECIAL3,
442 OPC_SHE = 0x1D | OPC_SPECIAL3,
443 OPC_SCE = 0x1E | OPC_SPECIAL3,
444 OPC_SWE = 0x1F | OPC_SPECIAL3,
445 OPC_SWLE = 0x21 | OPC_SPECIAL3,
446 OPC_SWRE = 0x22 | OPC_SPECIAL3,
447 OPC_PREFE = 0x23 | OPC_SPECIAL3,
448 OPC_LBUE = 0x28 | OPC_SPECIAL3,
449 OPC_LHUE = 0x29 | OPC_SPECIAL3,
450 OPC_LBE = 0x2C | OPC_SPECIAL3,
451 OPC_LHE = 0x2D | OPC_SPECIAL3,
452 OPC_LLE = 0x2E | OPC_SPECIAL3,
453 OPC_LWE = 0x2F | OPC_SPECIAL3,
455 /* R6 */
456 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
457 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
458 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
459 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
460 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
461 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
464 /* Loongson EXT load/store quad word opcodes */
465 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
466 enum {
467 OPC_GSLQ = 0x0020 | OPC_LWC2,
468 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
469 OPC_GSSHFL = OPC_LWC2,
470 OPC_GSSQ = 0x0020 | OPC_SWC2,
471 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
472 OPC_GSSHFS = OPC_SWC2,
475 /* Loongson EXT shifted load/store opcodes */
476 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
477 enum {
478 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
479 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
480 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
481 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
482 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
483 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
484 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
485 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
488 /* Loongson EXT LDC2/SDC2 opcodes */
489 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
491 enum {
492 OPC_GSLBX = 0x0 | OPC_LDC2,
493 OPC_GSLHX = 0x1 | OPC_LDC2,
494 OPC_GSLWX = 0x2 | OPC_LDC2,
495 OPC_GSLDX = 0x3 | OPC_LDC2,
496 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
497 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
498 OPC_GSSBX = 0x0 | OPC_SDC2,
499 OPC_GSSHX = 0x1 | OPC_SDC2,
500 OPC_GSSWX = 0x2 | OPC_SDC2,
501 OPC_GSSDX = 0x3 | OPC_SDC2,
502 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
503 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
506 /* BSHFL opcodes */
507 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
509 enum {
510 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
511 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
512 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
513 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
514 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
515 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
516 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
517 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
520 /* DBSHFL opcodes */
521 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
523 enum {
524 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
525 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
526 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
527 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
528 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
529 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
530 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
531 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
532 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
533 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
534 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
537 /* MIPS DSP REGIMM opcodes */
538 enum {
539 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
540 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
543 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
544 /* MIPS DSP Load */
545 enum {
546 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
547 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
548 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
549 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
552 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553 enum {
554 /* MIPS DSP Arithmetic Sub-class */
555 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
556 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
557 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
558 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
559 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
560 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
561 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
562 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
563 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
564 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
565 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
566 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
567 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
568 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
569 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
570 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
571 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
572 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
573 /* MIPS DSP Multiply Sub-class insns */
574 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
575 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
576 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
577 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
578 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
579 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
582 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
583 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
584 enum {
585 /* MIPS DSP Arithmetic Sub-class */
586 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
587 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
588 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
589 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
590 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
591 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
592 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
593 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
594 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
595 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
596 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
597 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
598 /* MIPS DSP Multiply Sub-class insns */
599 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
600 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
601 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
602 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
605 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
606 enum {
607 /* MIPS DSP Arithmetic Sub-class */
608 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
609 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
610 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
611 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
612 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
613 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
614 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
615 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
616 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
617 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
618 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
619 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
620 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
621 /* DSP Bit/Manipulation Sub-class */
622 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
623 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
624 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
625 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
626 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
629 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
630 enum {
631 /* MIPS DSP Arithmetic Sub-class */
632 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
633 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
634 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
635 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
636 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
637 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
638 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
639 /* DSP Compare-Pick Sub-class */
640 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
641 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
642 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
643 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
644 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
645 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
646 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
647 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
648 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
649 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
650 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
651 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
652 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
653 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
654 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
657 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
658 enum {
659 /* MIPS DSP GPR-Based Shift Sub-class */
660 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
661 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
662 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
663 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
664 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
665 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
666 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
667 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
668 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
669 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
670 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
671 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
672 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
673 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
674 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
675 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
676 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
677 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
678 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
679 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
680 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
681 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
684 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
685 enum {
686 /* MIPS DSP Multiply Sub-class insns */
687 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
688 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
689 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
690 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
691 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
692 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
693 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
694 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
695 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
696 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
697 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
698 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
699 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
700 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
701 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
702 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
703 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
704 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
705 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
706 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
707 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
708 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
711 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
712 enum {
713 /* DSP Bit/Manipulation Sub-class */
714 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
717 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
718 enum {
719 /* MIPS DSP Append Sub-class */
720 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
721 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
722 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
725 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
726 enum {
727 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
728 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
729 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
730 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
731 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
732 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
733 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
734 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
735 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
736 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
737 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
738 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
739 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
740 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
741 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
742 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
743 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
744 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
747 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
748 enum {
749 /* MIPS DSP Arithmetic Sub-class */
750 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
751 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
752 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
753 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
754 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
755 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
756 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
757 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
758 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
759 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
760 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
761 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
762 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
763 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
764 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
765 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
766 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
767 /* DSP Bit/Manipulation Sub-class */
768 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
769 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
770 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
771 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
772 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
773 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
776 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
777 enum {
778 /* MIPS DSP Multiply Sub-class insns */
779 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
780 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
781 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
782 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
783 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
784 /* MIPS DSP Arithmetic Sub-class */
785 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
786 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
787 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
788 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
789 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
790 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
791 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
792 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
793 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
794 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
795 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
796 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
797 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
798 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
799 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
800 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
801 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
802 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
803 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
804 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
805 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
808 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
809 enum {
810 /* DSP Compare-Pick Sub-class */
811 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
812 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
813 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
814 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
815 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
816 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
817 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
818 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
819 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
820 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
821 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
822 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
823 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
824 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
825 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
826 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
827 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
828 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
829 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
830 /* MIPS DSP Arithmetic Sub-class */
831 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
832 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
833 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
834 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
835 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
836 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
837 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
838 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
841 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
842 enum {
843 /* DSP Append Sub-class */
844 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
845 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
846 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
847 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
850 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
851 enum {
852 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
853 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
854 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
855 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
856 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
857 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
858 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
859 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
860 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
861 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
862 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
863 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
864 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
865 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
866 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
867 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
868 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
869 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
870 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
871 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
872 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
873 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
876 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
877 enum {
878 /* DSP Bit/Manipulation Sub-class */
879 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
882 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
883 enum {
884 /* MIPS DSP Multiply Sub-class insns */
885 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
886 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
887 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
888 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
889 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
890 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
891 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
892 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
893 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
894 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
895 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
896 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
897 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
898 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
899 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
900 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
901 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
902 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
903 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
904 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
905 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
906 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
907 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
908 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
909 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
910 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
913 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
914 enum {
915 /* MIPS DSP GPR-Based Shift Sub-class */
916 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
917 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
918 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
919 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
920 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
921 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
922 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
923 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
924 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
925 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
926 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
927 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
928 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
929 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
930 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
931 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
932 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
933 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
934 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
935 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
936 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
937 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
938 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
939 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
940 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
941 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
944 /* Coprocessor 0 (rs field) */
945 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
947 enum {
948 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
949 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
950 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
951 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
952 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
953 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
954 OPC_MFTR = (0x08 << 21) | OPC_CP0,
955 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
956 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
957 OPC_MTTR = (0x0C << 21) | OPC_CP0,
958 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
959 OPC_C0 = (0x10 << 21) | OPC_CP0,
960 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
961 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
962 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
963 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
964 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
965 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
966 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
967 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
968 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
969 OPC_C0_A = (0x1A << 21) | OPC_CP0,
970 OPC_C0_B = (0x1B << 21) | OPC_CP0,
971 OPC_C0_C = (0x1C << 21) | OPC_CP0,
972 OPC_C0_D = (0x1D << 21) | OPC_CP0,
973 OPC_C0_E = (0x1E << 21) | OPC_CP0,
974 OPC_C0_F = (0x1F << 21) | OPC_CP0,
977 /* MFMC0 opcodes */
978 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
980 enum {
981 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
982 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
983 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
984 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
985 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
986 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
987 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
988 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
991 /* Coprocessor 0 (with rs == C0) */
992 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
994 enum {
995 OPC_TLBR = 0x01 | OPC_C0,
996 OPC_TLBWI = 0x02 | OPC_C0,
997 OPC_TLBINV = 0x03 | OPC_C0,
998 OPC_TLBINVF = 0x04 | OPC_C0,
999 OPC_TLBWR = 0x06 | OPC_C0,
1000 OPC_TLBP = 0x08 | OPC_C0,
1001 OPC_RFE = 0x10 | OPC_C0,
1002 OPC_ERET = 0x18 | OPC_C0,
1003 OPC_DERET = 0x1F | OPC_C0,
1004 OPC_WAIT = 0x20 | OPC_C0,
1007 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
1009 enum {
1010 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
1011 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
1012 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
1013 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
1014 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
1015 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
1016 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
1017 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
1018 OPC_BC2 = (0x08 << 21) | OPC_CP2,
1019 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
1020 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
1023 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
1025 enum {
1026 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
1027 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
1028 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
1029 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
1030 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
1031 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
1032 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
1033 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
1035 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
1036 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
1037 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
1038 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1039 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1040 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1041 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1042 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1044 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1045 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1046 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1047 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1048 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1049 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1050 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1051 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1053 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1054 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1055 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1056 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1057 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1058 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1059 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1060 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1062 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1063 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1064 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1065 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1066 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1067 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1069 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1070 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1071 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1072 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1073 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1074 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1076 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1077 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1078 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1079 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1080 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1081 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1083 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1084 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1085 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1086 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1087 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1088 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1090 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1091 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1092 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1093 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1094 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1095 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1097 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1098 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1099 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1100 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1101 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1102 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1104 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1105 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1106 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1107 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1108 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1109 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1111 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1112 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1113 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1114 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1115 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1116 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1120 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1122 enum {
1123 OPC_LWXC1 = 0x00 | OPC_CP3,
1124 OPC_LDXC1 = 0x01 | OPC_CP3,
1125 OPC_LUXC1 = 0x05 | OPC_CP3,
1126 OPC_SWXC1 = 0x08 | OPC_CP3,
1127 OPC_SDXC1 = 0x09 | OPC_CP3,
1128 OPC_SUXC1 = 0x0D | OPC_CP3,
1129 OPC_PREFX = 0x0F | OPC_CP3,
1130 OPC_ALNV_PS = 0x1E | OPC_CP3,
1131 OPC_MADD_S = 0x20 | OPC_CP3,
1132 OPC_MADD_D = 0x21 | OPC_CP3,
1133 OPC_MADD_PS = 0x26 | OPC_CP3,
1134 OPC_MSUB_S = 0x28 | OPC_CP3,
1135 OPC_MSUB_D = 0x29 | OPC_CP3,
1136 OPC_MSUB_PS = 0x2E | OPC_CP3,
1137 OPC_NMADD_S = 0x30 | OPC_CP3,
1138 OPC_NMADD_D = 0x31 | OPC_CP3,
1139 OPC_NMADD_PS = 0x36 | OPC_CP3,
1140 OPC_NMSUB_S = 0x38 | OPC_CP3,
1141 OPC_NMSUB_D = 0x39 | OPC_CP3,
1142 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1146 * MMI (MultiMedia Instruction) encodings
1147 * ======================================
1149 * MMI instructions encoding table keys:
1151 * * This code is reserved for future use. An attempt to execute it
1152 * causes a Reserved Instruction exception.
1153 * % This code indicates an instruction class. The instruction word
1154 * must be further decoded by examining additional tables that show
1155 * the values for other instruction fields.
1156 * # This code is reserved for the unsupported instructions DMULT,
1157 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1158 * to execute it causes a Reserved Instruction exception.
1160 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1162 * 31 26 0
1163 * +--------+----------------------------------------+
1164 * | opcode | |
1165 * +--------+----------------------------------------+
1167 * opcode bits 28..26
1168 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1169 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1170 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1171 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1172 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1173 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1174 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1175 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1176 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1177 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1178 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1181 enum {
1182 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1183 MMI_OPC_LQ = 0x1E << 26, /* Same as OPC_MSA */
1184 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1188 * MMI instructions with opcode field = MMI:
1190 * 31 26 5 0
1191 * +--------+-------------------------------+--------+
1192 * | MMI | |function|
1193 * +--------+-------------------------------+--------+
1195 * function bits 2..0
1196 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1197 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1198 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1199 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1200 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1201 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1202 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1203 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1204 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1205 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1206 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1209 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1210 enum {
1211 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1212 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1213 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1214 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1215 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1216 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1217 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1218 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1221 /* global register indices */
1222 TCGv cpu_gpr[32], cpu_PC;
1224 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1225 * and the upper halves in cpu_gpr_hi[].
1227 TCGv_i64 cpu_gpr_hi[32];
1228 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1229 static TCGv cpu_dspctrl, btarget;
1230 TCGv bcond;
1231 static TCGv cpu_lladdr, cpu_llval;
1232 static TCGv_i32 hflags;
1233 TCGv_i32 fpu_fcr0, fpu_fcr31;
1234 TCGv_i64 fpu_f64[32];
1236 #include "exec/gen-icount.h"
1238 #define gen_helper_0e0i(name, arg) do { \
1239 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1240 gen_helper_##name(cpu_env, helper_tmp); \
1241 tcg_temp_free_i32(helper_tmp); \
1242 } while (0)
1244 #define gen_helper_0e1i(name, arg1, arg2) do { \
1245 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1246 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1247 tcg_temp_free_i32(helper_tmp); \
1248 } while (0)
1250 #define gen_helper_1e0i(name, ret, arg1) do { \
1251 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1252 gen_helper_##name(ret, cpu_env, helper_tmp); \
1253 tcg_temp_free_i32(helper_tmp); \
1254 } while (0)
1256 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1257 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1258 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1259 tcg_temp_free_i32(helper_tmp); \
1260 } while (0)
1262 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1263 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1264 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1265 tcg_temp_free_i32(helper_tmp); \
1266 } while (0)
1268 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1269 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1270 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1271 tcg_temp_free_i32(helper_tmp); \
1272 } while (0)
1274 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1275 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1276 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1277 tcg_temp_free_i32(helper_tmp); \
1278 } while (0)
1280 #define DISAS_STOP DISAS_TARGET_0
1281 #define DISAS_EXIT DISAS_TARGET_1
1283 static const char regnames_HI[][4] = {
1284 "HI0", "HI1", "HI2", "HI3",
1287 static const char regnames_LO[][4] = {
1288 "LO0", "LO1", "LO2", "LO3",
1291 /* General purpose registers moves. */
1292 void gen_load_gpr(TCGv t, int reg)
1294 if (reg == 0) {
1295 tcg_gen_movi_tl(t, 0);
1296 } else {
1297 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1301 void gen_store_gpr(TCGv t, int reg)
1303 if (reg != 0) {
1304 tcg_gen_mov_tl(cpu_gpr[reg], t);
1308 #if defined(TARGET_MIPS64)
1309 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1311 if (reg == 0) {
1312 tcg_gen_movi_i64(t, 0);
1313 } else {
1314 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1318 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1320 if (reg != 0) {
1321 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1324 #endif /* TARGET_MIPS64 */
1326 /* Moves to/from shadow registers. */
1327 static inline void gen_load_srsgpr(int from, int to)
1329 TCGv t0 = tcg_temp_new();
1331 if (from == 0) {
1332 tcg_gen_movi_tl(t0, 0);
1333 } else {
1334 TCGv_i32 t2 = tcg_temp_new_i32();
1335 TCGv_ptr addr = tcg_temp_new_ptr();
1337 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1338 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1339 tcg_gen_andi_i32(t2, t2, 0xf);
1340 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1341 tcg_gen_ext_i32_ptr(addr, t2);
1342 tcg_gen_add_ptr(addr, cpu_env, addr);
1344 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1345 tcg_temp_free_ptr(addr);
1346 tcg_temp_free_i32(t2);
1348 gen_store_gpr(t0, to);
1349 tcg_temp_free(t0);
1352 static inline void gen_store_srsgpr(int from, int to)
1354 if (to != 0) {
1355 TCGv t0 = tcg_temp_new();
1356 TCGv_i32 t2 = tcg_temp_new_i32();
1357 TCGv_ptr addr = tcg_temp_new_ptr();
1359 gen_load_gpr(t0, from);
1360 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1361 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1362 tcg_gen_andi_i32(t2, t2, 0xf);
1363 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1364 tcg_gen_ext_i32_ptr(addr, t2);
1365 tcg_gen_add_ptr(addr, cpu_env, addr);
1367 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1368 tcg_temp_free_ptr(addr);
1369 tcg_temp_free_i32(t2);
1370 tcg_temp_free(t0);
1374 /* Tests */
1375 static inline void gen_save_pc(target_ulong pc)
1377 tcg_gen_movi_tl(cpu_PC, pc);
1380 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1382 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1383 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1384 gen_save_pc(ctx->base.pc_next);
1385 ctx->saved_pc = ctx->base.pc_next;
1387 if (ctx->hflags != ctx->saved_hflags) {
1388 tcg_gen_movi_i32(hflags, ctx->hflags);
1389 ctx->saved_hflags = ctx->hflags;
1390 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1391 case MIPS_HFLAG_BR:
1392 break;
1393 case MIPS_HFLAG_BC:
1394 case MIPS_HFLAG_BL:
1395 case MIPS_HFLAG_B:
1396 tcg_gen_movi_tl(btarget, ctx->btarget);
1397 break;
1402 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1404 ctx->saved_hflags = ctx->hflags;
1405 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1406 case MIPS_HFLAG_BR:
1407 break;
1408 case MIPS_HFLAG_BC:
1409 case MIPS_HFLAG_BL:
1410 case MIPS_HFLAG_B:
1411 ctx->btarget = env->btarget;
1412 break;
1416 void generate_exception_err(DisasContext *ctx, int excp, int err)
1418 TCGv_i32 texcp = tcg_const_i32(excp);
1419 TCGv_i32 terr = tcg_const_i32(err);
1420 save_cpu_state(ctx, 1);
1421 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1422 tcg_temp_free_i32(terr);
1423 tcg_temp_free_i32(texcp);
1424 ctx->base.is_jmp = DISAS_NORETURN;
1427 void generate_exception(DisasContext *ctx, int excp)
1429 gen_helper_0e0i(raise_exception, excp);
1432 void generate_exception_end(DisasContext *ctx, int excp)
1434 generate_exception_err(ctx, excp, 0);
1437 void gen_reserved_instruction(DisasContext *ctx)
1439 generate_exception_end(ctx, EXCP_RI);
1442 /* Floating point register moves. */
1443 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1445 if (ctx->hflags & MIPS_HFLAG_FRE) {
1446 generate_exception(ctx, EXCP_RI);
1448 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1451 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1453 TCGv_i64 t64;
1454 if (ctx->hflags & MIPS_HFLAG_FRE) {
1455 generate_exception(ctx, EXCP_RI);
1457 t64 = tcg_temp_new_i64();
1458 tcg_gen_extu_i32_i64(t64, t);
1459 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1460 tcg_temp_free_i64(t64);
1463 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1465 if (ctx->hflags & MIPS_HFLAG_F64) {
1466 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1467 } else {
1468 gen_load_fpr32(ctx, t, reg | 1);
1472 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1474 if (ctx->hflags & MIPS_HFLAG_F64) {
1475 TCGv_i64 t64 = tcg_temp_new_i64();
1476 tcg_gen_extu_i32_i64(t64, t);
1477 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1478 tcg_temp_free_i64(t64);
1479 } else {
1480 gen_store_fpr32(ctx, t, reg | 1);
1484 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1486 if (ctx->hflags & MIPS_HFLAG_F64) {
1487 tcg_gen_mov_i64(t, fpu_f64[reg]);
1488 } else {
1489 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1493 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1495 if (ctx->hflags & MIPS_HFLAG_F64) {
1496 tcg_gen_mov_i64(fpu_f64[reg], t);
1497 } else {
1498 TCGv_i64 t0;
1499 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1500 t0 = tcg_temp_new_i64();
1501 tcg_gen_shri_i64(t0, t, 32);
1502 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1503 tcg_temp_free_i64(t0);
1507 int get_fp_bit(int cc)
1509 if (cc) {
1510 return 24 + cc;
1511 } else {
1512 return 23;
1516 /* Addresses computation */
1517 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1519 tcg_gen_add_tl(ret, arg0, arg1);
1521 #if defined(TARGET_MIPS64)
1522 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1523 tcg_gen_ext32s_i64(ret, ret);
1525 #endif
1528 static inline void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base,
1529 target_long ofs)
1531 tcg_gen_addi_tl(ret, base, ofs);
1533 #if defined(TARGET_MIPS64)
1534 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1535 tcg_gen_ext32s_i64(ret, ret);
1537 #endif
1540 /* Addresses computation (translation time) */
1541 static target_long addr_add(DisasContext *ctx, target_long base,
1542 target_long offset)
1544 target_long sum = base + offset;
1546 #if defined(TARGET_MIPS64)
1547 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1548 sum = (int32_t)sum;
1550 #endif
1551 return sum;
1554 /* Sign-extract the low 32-bits to a target_long. */
1555 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1557 #if defined(TARGET_MIPS64)
1558 tcg_gen_ext32s_i64(ret, arg);
1559 #else
1560 tcg_gen_extrl_i64_i32(ret, arg);
1561 #endif
1564 /* Sign-extract the high 32-bits to a target_long. */
1565 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1567 #if defined(TARGET_MIPS64)
1568 tcg_gen_sari_i64(ret, arg, 32);
1569 #else
1570 tcg_gen_extrh_i64_i32(ret, arg);
1571 #endif
1574 bool check_cp0_enabled(DisasContext *ctx)
1576 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1577 generate_exception_end(ctx, EXCP_CpU);
1578 return false;
1580 return true;
1583 void check_cp1_enabled(DisasContext *ctx)
1585 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1586 generate_exception_err(ctx, EXCP_CpU, 1);
1591 * Verify that the processor is running with COP1X instructions enabled.
1592 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1593 * opcode tables.
1595 void check_cop1x(DisasContext *ctx)
1597 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1598 gen_reserved_instruction(ctx);
1603 * Verify that the processor is running with 64-bit floating-point
1604 * operations enabled.
1606 void check_cp1_64bitmode(DisasContext *ctx)
1608 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X))) {
1609 gen_reserved_instruction(ctx);
1614 * Verify if floating point register is valid; an operation is not defined
1615 * if bit 0 of any register specification is set and the FR bit in the
1616 * Status register equals zero, since the register numbers specify an
1617 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1618 * in the Status register equals one, both even and odd register numbers
1619 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1621 * Multiple 64 bit wide registers can be checked by calling
1622 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1624 void check_cp1_registers(DisasContext *ctx, int regs)
1626 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1627 gen_reserved_instruction(ctx);
1632 * Verify that the processor is running with DSP instructions enabled.
1633 * This is enabled by CP0 Status register MX(24) bit.
1635 static inline void check_dsp(DisasContext *ctx)
1637 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1638 if (ctx->insn_flags & ASE_DSP) {
1639 generate_exception_end(ctx, EXCP_DSPDIS);
1640 } else {
1641 gen_reserved_instruction(ctx);
1646 static inline void check_dsp_r2(DisasContext *ctx)
1648 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1649 if (ctx->insn_flags & ASE_DSP) {
1650 generate_exception_end(ctx, EXCP_DSPDIS);
1651 } else {
1652 gen_reserved_instruction(ctx);
1657 static inline void check_dsp_r3(DisasContext *ctx)
1659 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1660 if (ctx->insn_flags & ASE_DSP) {
1661 generate_exception_end(ctx, EXCP_DSPDIS);
1662 } else {
1663 gen_reserved_instruction(ctx);
1669 * This code generates a "reserved instruction" exception if the
1670 * CPU does not support the instruction set corresponding to flags.
1672 void check_insn(DisasContext *ctx, uint64_t flags)
1674 if (unlikely(!(ctx->insn_flags & flags))) {
1675 gen_reserved_instruction(ctx);
1680 * This code generates a "reserved instruction" exception if the
1681 * CPU has corresponding flag set which indicates that the instruction
1682 * has been removed.
1684 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1686 if (unlikely(ctx->insn_flags & flags)) {
1687 gen_reserved_instruction(ctx);
1692 * The Linux kernel traps certain reserved instruction exceptions to
1693 * emulate the corresponding instructions. QEMU is the kernel in user
1694 * mode, so those traps are emulated by accepting the instructions.
1696 * A reserved instruction exception is generated for flagged CPUs if
1697 * QEMU runs in system mode.
1699 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1701 #ifndef CONFIG_USER_ONLY
1702 check_insn_opc_removed(ctx, flags);
1703 #endif
1707 * This code generates a "reserved instruction" exception if the
1708 * CPU does not support 64-bit paired-single (PS) floating point data type.
1710 static inline void check_ps(DisasContext *ctx)
1712 if (unlikely(!ctx->ps)) {
1713 generate_exception(ctx, EXCP_RI);
1715 check_cp1_64bitmode(ctx);
1719 * This code generates a "reserved instruction" exception if cpu is not
1720 * 64-bit or 64-bit instructions are not enabled.
1722 void check_mips_64(DisasContext *ctx)
1724 if (unlikely((TARGET_LONG_BITS != 64) || !(ctx->hflags & MIPS_HFLAG_64))) {
1725 gen_reserved_instruction(ctx);
1729 #ifndef CONFIG_USER_ONLY
1730 static inline void check_mvh(DisasContext *ctx)
1732 if (unlikely(!ctx->mvh)) {
1733 generate_exception(ctx, EXCP_RI);
1736 #endif
1739 * This code generates a "reserved instruction" exception if the
1740 * Config5 XNP bit is set.
1742 static inline void check_xnp(DisasContext *ctx)
1744 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1745 gen_reserved_instruction(ctx);
1749 #ifndef CONFIG_USER_ONLY
1751 * This code generates a "reserved instruction" exception if the
1752 * Config3 PW bit is NOT set.
1754 static inline void check_pw(DisasContext *ctx)
1756 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1757 gen_reserved_instruction(ctx);
1760 #endif
1763 * This code generates a "reserved instruction" exception if the
1764 * Config3 MT bit is NOT set.
1766 static inline void check_mt(DisasContext *ctx)
1768 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1769 gen_reserved_instruction(ctx);
1773 #ifndef CONFIG_USER_ONLY
1775 * This code generates a "coprocessor unusable" exception if CP0 is not
1776 * available, and, if that is not the case, generates a "reserved instruction"
1777 * exception if the Config5 MT bit is NOT set. This is needed for availability
1778 * control of some of MT ASE instructions.
1780 static inline void check_cp0_mt(DisasContext *ctx)
1782 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1783 generate_exception_end(ctx, EXCP_CpU);
1784 } else {
1785 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1786 gen_reserved_instruction(ctx);
1790 #endif
1793 * This code generates a "reserved instruction" exception if the
1794 * Config5 NMS bit is set.
1796 static inline void check_nms(DisasContext *ctx)
1798 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1799 gen_reserved_instruction(ctx);
1804 * This code generates a "reserved instruction" exception if the
1805 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1806 * Config2 TL, and Config5 L2C are unset.
1808 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1810 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1811 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1812 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1813 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1814 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1815 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1816 gen_reserved_instruction(ctx);
1821 * This code generates a "reserved instruction" exception if the
1822 * Config5 EVA bit is NOT set.
1824 static inline void check_eva(DisasContext *ctx)
1826 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1827 gen_reserved_instruction(ctx);
1833 * Define small wrappers for gen_load_fpr* so that we have a uniform
1834 * calling interface for 32 and 64-bit FPRs. No sense in changing
1835 * all callers for gen_load_fpr32 when we need the CTX parameter for
1836 * this one use.
1838 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1839 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1840 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1841 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1842 int ft, int fs, int cc) \
1844 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1845 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
1846 switch (ifmt) { \
1847 case FMT_PS: \
1848 check_ps(ctx); \
1849 break; \
1850 case FMT_D: \
1851 if (abs) { \
1852 check_cop1x(ctx); \
1854 check_cp1_registers(ctx, fs | ft); \
1855 break; \
1856 case FMT_S: \
1857 if (abs) { \
1858 check_cop1x(ctx); \
1860 break; \
1862 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1863 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
1864 switch (n) { \
1865 case 0: \
1866 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1867 break; \
1868 case 1: \
1869 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1870 break; \
1871 case 2: \
1872 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1873 break; \
1874 case 3: \
1875 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1876 break; \
1877 case 4: \
1878 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1879 break; \
1880 case 5: \
1881 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1882 break; \
1883 case 6: \
1884 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1885 break; \
1886 case 7: \
1887 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1888 break; \
1889 case 8: \
1890 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1891 break; \
1892 case 9: \
1893 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1894 break; \
1895 case 10: \
1896 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1897 break; \
1898 case 11: \
1899 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1900 break; \
1901 case 12: \
1902 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1903 break; \
1904 case 13: \
1905 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1906 break; \
1907 case 14: \
1908 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1909 break; \
1910 case 15: \
1911 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1912 break; \
1913 default: \
1914 abort(); \
1916 tcg_temp_free_i##bits(fp0); \
1917 tcg_temp_free_i##bits(fp1); \
1920 FOP_CONDS(, 0, d, FMT_D, 64)
1921 FOP_CONDS(abs, 1, d, FMT_D, 64)
1922 FOP_CONDS(, 0, s, FMT_S, 32)
1923 FOP_CONDS(abs, 1, s, FMT_S, 32)
1924 FOP_CONDS(, 0, ps, FMT_PS, 64)
1925 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1926 #undef FOP_CONDS
1928 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1929 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
1930 int ft, int fs, int fd) \
1932 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1933 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1934 if (ifmt == FMT_D) { \
1935 check_cp1_registers(ctx, fs | ft | fd); \
1937 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1938 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1939 switch (n) { \
1940 case 0: \
1941 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1942 break; \
1943 case 1: \
1944 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1945 break; \
1946 case 2: \
1947 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1948 break; \
1949 case 3: \
1950 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1951 break; \
1952 case 4: \
1953 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1954 break; \
1955 case 5: \
1956 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1957 break; \
1958 case 6: \
1959 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1960 break; \
1961 case 7: \
1962 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1963 break; \
1964 case 8: \
1965 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1966 break; \
1967 case 9: \
1968 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1969 break; \
1970 case 10: \
1971 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1972 break; \
1973 case 11: \
1974 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1975 break; \
1976 case 12: \
1977 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1978 break; \
1979 case 13: \
1980 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1981 break; \
1982 case 14: \
1983 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1984 break; \
1985 case 15: \
1986 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1987 break; \
1988 case 17: \
1989 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1990 break; \
1991 case 18: \
1992 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1993 break; \
1994 case 19: \
1995 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1996 break; \
1997 case 25: \
1998 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1999 break; \
2000 case 26: \
2001 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
2002 break; \
2003 case 27: \
2004 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
2005 break; \
2006 default: \
2007 abort(); \
2009 STORE; \
2010 tcg_temp_free_i ## bits(fp0); \
2011 tcg_temp_free_i ## bits(fp1); \
2014 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
2015 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
2016 #undef FOP_CONDNS
2017 #undef gen_ldcmp_fpr32
2018 #undef gen_ldcmp_fpr64
2020 /* load/store instructions. */
2021 #ifdef CONFIG_USER_ONLY
2022 #define OP_LD_ATOMIC(insn, fname) \
2023 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2024 DisasContext *ctx) \
2026 TCGv t0 = tcg_temp_new(); \
2027 tcg_gen_mov_tl(t0, arg1); \
2028 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
2029 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
2030 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
2031 tcg_temp_free(t0); \
2033 #else
2034 #define OP_LD_ATOMIC(insn, fname) \
2035 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
2036 DisasContext *ctx) \
2038 gen_helper_1e1i(insn, ret, arg1, mem_idx); \
2040 #endif
2041 OP_LD_ATOMIC(ll, ld32s);
2042 #if defined(TARGET_MIPS64)
2043 OP_LD_ATOMIC(lld, ld64);
2044 #endif
2045 #undef OP_LD_ATOMIC
2047 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
2049 if (base == 0) {
2050 tcg_gen_movi_tl(addr, offset);
2051 } else if (offset == 0) {
2052 gen_load_gpr(addr, base);
2053 } else {
2054 tcg_gen_movi_tl(addr, offset);
2055 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
2059 static target_ulong pc_relative_pc(DisasContext *ctx)
2061 target_ulong pc = ctx->base.pc_next;
2063 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2064 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
2066 pc -= branch_bytes;
2069 pc &= ~(target_ulong)3;
2070 return pc;
2073 /* Load */
2074 static void gen_ld(DisasContext *ctx, uint32_t opc,
2075 int rt, int base, int offset)
2077 TCGv t0, t1, t2;
2078 int mem_idx = ctx->mem_idx;
2080 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2081 INSN_LOONGSON3A)) {
2083 * Loongson CPU uses a load to zero register for prefetch.
2084 * We emulate it as a NOP. On other CPU we must perform the
2085 * actual memory access.
2087 return;
2090 t0 = tcg_temp_new();
2091 gen_base_offset_addr(ctx, t0, base, offset);
2093 switch (opc) {
2094 #if defined(TARGET_MIPS64)
2095 case OPC_LWU:
2096 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL |
2097 ctx->default_tcg_memop_mask);
2098 gen_store_gpr(t0, rt);
2099 break;
2100 case OPC_LD:
2101 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ |
2102 ctx->default_tcg_memop_mask);
2103 gen_store_gpr(t0, rt);
2104 break;
2105 case OPC_LLD:
2106 case R6_OPC_LLD:
2107 op_ld_lld(t0, t0, mem_idx, ctx);
2108 gen_store_gpr(t0, rt);
2109 break;
2110 case OPC_LDL:
2111 t1 = tcg_temp_new();
2113 * Do a byte access to possibly trigger a page
2114 * fault with the unaligned address.
2116 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2117 tcg_gen_andi_tl(t1, t0, 7);
2118 #ifndef TARGET_WORDS_BIGENDIAN
2119 tcg_gen_xori_tl(t1, t1, 7);
2120 #endif
2121 tcg_gen_shli_tl(t1, t1, 3);
2122 tcg_gen_andi_tl(t0, t0, ~7);
2123 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2124 tcg_gen_shl_tl(t0, t0, t1);
2125 t2 = tcg_const_tl(-1);
2126 tcg_gen_shl_tl(t2, t2, t1);
2127 gen_load_gpr(t1, rt);
2128 tcg_gen_andc_tl(t1, t1, t2);
2129 tcg_temp_free(t2);
2130 tcg_gen_or_tl(t0, t0, t1);
2131 tcg_temp_free(t1);
2132 gen_store_gpr(t0, rt);
2133 break;
2134 case OPC_LDR:
2135 t1 = tcg_temp_new();
2137 * Do a byte access to possibly trigger a page
2138 * fault with the unaligned address.
2140 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2141 tcg_gen_andi_tl(t1, t0, 7);
2142 #ifdef TARGET_WORDS_BIGENDIAN
2143 tcg_gen_xori_tl(t1, t1, 7);
2144 #endif
2145 tcg_gen_shli_tl(t1, t1, 3);
2146 tcg_gen_andi_tl(t0, t0, ~7);
2147 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2148 tcg_gen_shr_tl(t0, t0, t1);
2149 tcg_gen_xori_tl(t1, t1, 63);
2150 t2 = tcg_const_tl(0xfffffffffffffffeull);
2151 tcg_gen_shl_tl(t2, t2, t1);
2152 gen_load_gpr(t1, rt);
2153 tcg_gen_and_tl(t1, t1, t2);
2154 tcg_temp_free(t2);
2155 tcg_gen_or_tl(t0, t0, t1);
2156 tcg_temp_free(t1);
2157 gen_store_gpr(t0, rt);
2158 break;
2159 case OPC_LDPC:
2160 t1 = tcg_const_tl(pc_relative_pc(ctx));
2161 gen_op_addr_add(ctx, t0, t0, t1);
2162 tcg_temp_free(t1);
2163 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEQ);
2164 gen_store_gpr(t0, rt);
2165 break;
2166 #endif
2167 case OPC_LWPC:
2168 t1 = tcg_const_tl(pc_relative_pc(ctx));
2169 gen_op_addr_add(ctx, t0, t0, t1);
2170 tcg_temp_free(t1);
2171 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL);
2172 gen_store_gpr(t0, rt);
2173 break;
2174 case OPC_LWE:
2175 mem_idx = MIPS_HFLAG_UM;
2176 /* fall through */
2177 case OPC_LW:
2178 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESL |
2179 ctx->default_tcg_memop_mask);
2180 gen_store_gpr(t0, rt);
2181 break;
2182 case OPC_LHE:
2183 mem_idx = MIPS_HFLAG_UM;
2184 /* fall through */
2185 case OPC_LH:
2186 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TESW |
2187 ctx->default_tcg_memop_mask);
2188 gen_store_gpr(t0, rt);
2189 break;
2190 case OPC_LHUE:
2191 mem_idx = MIPS_HFLAG_UM;
2192 /* fall through */
2193 case OPC_LHU:
2194 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUW |
2195 ctx->default_tcg_memop_mask);
2196 gen_store_gpr(t0, rt);
2197 break;
2198 case OPC_LBE:
2199 mem_idx = MIPS_HFLAG_UM;
2200 /* fall through */
2201 case OPC_LB:
2202 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2203 gen_store_gpr(t0, rt);
2204 break;
2205 case OPC_LBUE:
2206 mem_idx = MIPS_HFLAG_UM;
2207 /* fall through */
2208 case OPC_LBU:
2209 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2210 gen_store_gpr(t0, rt);
2211 break;
2212 case OPC_LWLE:
2213 mem_idx = MIPS_HFLAG_UM;
2214 /* fall through */
2215 case OPC_LWL:
2216 t1 = tcg_temp_new();
2218 * Do a byte access to possibly trigger a page
2219 * fault with the unaligned address.
2221 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2222 tcg_gen_andi_tl(t1, t0, 3);
2223 #ifndef TARGET_WORDS_BIGENDIAN
2224 tcg_gen_xori_tl(t1, t1, 3);
2225 #endif
2226 tcg_gen_shli_tl(t1, t1, 3);
2227 tcg_gen_andi_tl(t0, t0, ~3);
2228 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2229 tcg_gen_shl_tl(t0, t0, t1);
2230 t2 = tcg_const_tl(-1);
2231 tcg_gen_shl_tl(t2, t2, t1);
2232 gen_load_gpr(t1, rt);
2233 tcg_gen_andc_tl(t1, t1, t2);
2234 tcg_temp_free(t2);
2235 tcg_gen_or_tl(t0, t0, t1);
2236 tcg_temp_free(t1);
2237 tcg_gen_ext32s_tl(t0, t0);
2238 gen_store_gpr(t0, rt);
2239 break;
2240 case OPC_LWRE:
2241 mem_idx = MIPS_HFLAG_UM;
2242 /* fall through */
2243 case OPC_LWR:
2244 t1 = tcg_temp_new();
2246 * Do a byte access to possibly trigger a page
2247 * fault with the unaligned address.
2249 tcg_gen_qemu_ld_tl(t1, t0, mem_idx, MO_UB);
2250 tcg_gen_andi_tl(t1, t0, 3);
2251 #ifdef TARGET_WORDS_BIGENDIAN
2252 tcg_gen_xori_tl(t1, t1, 3);
2253 #endif
2254 tcg_gen_shli_tl(t1, t1, 3);
2255 tcg_gen_andi_tl(t0, t0, ~3);
2256 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_TEUL);
2257 tcg_gen_shr_tl(t0, t0, t1);
2258 tcg_gen_xori_tl(t1, t1, 31);
2259 t2 = tcg_const_tl(0xfffffffeull);
2260 tcg_gen_shl_tl(t2, t2, t1);
2261 gen_load_gpr(t1, rt);
2262 tcg_gen_and_tl(t1, t1, t2);
2263 tcg_temp_free(t2);
2264 tcg_gen_or_tl(t0, t0, t1);
2265 tcg_temp_free(t1);
2266 tcg_gen_ext32s_tl(t0, t0);
2267 gen_store_gpr(t0, rt);
2268 break;
2269 case OPC_LLE:
2270 mem_idx = MIPS_HFLAG_UM;
2271 /* fall through */
2272 case OPC_LL:
2273 case R6_OPC_LL:
2274 op_ld_ll(t0, t0, mem_idx, ctx);
2275 gen_store_gpr(t0, rt);
2276 break;
2278 tcg_temp_free(t0);
2281 static void gen_llwp(DisasContext *ctx, uint32_t base, int16_t offset,
2282 uint32_t reg1, uint32_t reg2)
2284 TCGv taddr = tcg_temp_new();
2285 TCGv_i64 tval = tcg_temp_new_i64();
2286 TCGv tmp1 = tcg_temp_new();
2287 TCGv tmp2 = tcg_temp_new();
2289 gen_base_offset_addr(ctx, taddr, base, offset);
2290 tcg_gen_qemu_ld64(tval, taddr, ctx->mem_idx);
2291 #ifdef TARGET_WORDS_BIGENDIAN
2292 tcg_gen_extr_i64_tl(tmp2, tmp1, tval);
2293 #else
2294 tcg_gen_extr_i64_tl(tmp1, tmp2, tval);
2295 #endif
2296 gen_store_gpr(tmp1, reg1);
2297 tcg_temp_free(tmp1);
2298 gen_store_gpr(tmp2, reg2);
2299 tcg_temp_free(tmp2);
2300 tcg_gen_st_i64(tval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2301 tcg_temp_free_i64(tval);
2302 tcg_gen_st_tl(taddr, cpu_env, offsetof(CPUMIPSState, lladdr));
2303 tcg_temp_free(taddr);
2306 /* Store */
2307 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2308 int base, int offset)
2310 TCGv t0 = tcg_temp_new();
2311 TCGv t1 = tcg_temp_new();
2312 int mem_idx = ctx->mem_idx;
2314 gen_base_offset_addr(ctx, t0, base, offset);
2315 gen_load_gpr(t1, rt);
2316 switch (opc) {
2317 #if defined(TARGET_MIPS64)
2318 case OPC_SD:
2319 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEQ |
2320 ctx->default_tcg_memop_mask);
2321 break;
2322 case OPC_SDL:
2323 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2324 break;
2325 case OPC_SDR:
2326 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2327 break;
2328 #endif
2329 case OPC_SWE:
2330 mem_idx = MIPS_HFLAG_UM;
2331 /* fall through */
2332 case OPC_SW:
2333 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUL |
2334 ctx->default_tcg_memop_mask);
2335 break;
2336 case OPC_SHE:
2337 mem_idx = MIPS_HFLAG_UM;
2338 /* fall through */
2339 case OPC_SH:
2340 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_TEUW |
2341 ctx->default_tcg_memop_mask);
2342 break;
2343 case OPC_SBE:
2344 mem_idx = MIPS_HFLAG_UM;
2345 /* fall through */
2346 case OPC_SB:
2347 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2348 break;
2349 case OPC_SWLE:
2350 mem_idx = MIPS_HFLAG_UM;
2351 /* fall through */
2352 case OPC_SWL:
2353 gen_helper_0e2i(swl, t1, t0, mem_idx);
2354 break;
2355 case OPC_SWRE:
2356 mem_idx = MIPS_HFLAG_UM;
2357 /* fall through */
2358 case OPC_SWR:
2359 gen_helper_0e2i(swr, t1, t0, mem_idx);
2360 break;
2362 tcg_temp_free(t0);
2363 tcg_temp_free(t1);
2367 /* Store conditional */
2368 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2369 MemOp tcg_mo, bool eva)
2371 TCGv addr, t0, val;
2372 TCGLabel *l1 = gen_new_label();
2373 TCGLabel *done = gen_new_label();
2375 t0 = tcg_temp_new();
2376 addr = tcg_temp_new();
2377 /* compare the address against that of the preceding LL */
2378 gen_base_offset_addr(ctx, addr, base, offset);
2379 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2380 tcg_temp_free(addr);
2381 tcg_gen_movi_tl(t0, 0);
2382 gen_store_gpr(t0, rt);
2383 tcg_gen_br(done);
2385 gen_set_label(l1);
2386 /* generate cmpxchg */
2387 val = tcg_temp_new();
2388 gen_load_gpr(val, rt);
2389 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2390 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2391 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2392 gen_store_gpr(t0, rt);
2393 tcg_temp_free(val);
2395 gen_set_label(done);
2396 tcg_temp_free(t0);
2400 static void gen_scwp(DisasContext *ctx, uint32_t base, int16_t offset,
2401 uint32_t reg1, uint32_t reg2, bool eva)
2403 TCGv taddr = tcg_temp_local_new();
2404 TCGv lladdr = tcg_temp_local_new();
2405 TCGv_i64 tval = tcg_temp_new_i64();
2406 TCGv_i64 llval = tcg_temp_new_i64();
2407 TCGv_i64 val = tcg_temp_new_i64();
2408 TCGv tmp1 = tcg_temp_new();
2409 TCGv tmp2 = tcg_temp_new();
2410 TCGLabel *lab_fail = gen_new_label();
2411 TCGLabel *lab_done = gen_new_label();
2413 gen_base_offset_addr(ctx, taddr, base, offset);
2415 tcg_gen_ld_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2416 tcg_gen_brcond_tl(TCG_COND_NE, taddr, lladdr, lab_fail);
2418 gen_load_gpr(tmp1, reg1);
2419 gen_load_gpr(tmp2, reg2);
2421 #ifdef TARGET_WORDS_BIGENDIAN
2422 tcg_gen_concat_tl_i64(tval, tmp2, tmp1);
2423 #else
2424 tcg_gen_concat_tl_i64(tval, tmp1, tmp2);
2425 #endif
2427 tcg_gen_ld_i64(llval, cpu_env, offsetof(CPUMIPSState, llval_wp));
2428 tcg_gen_atomic_cmpxchg_i64(val, taddr, llval, tval,
2429 eva ? MIPS_HFLAG_UM : ctx->mem_idx, MO_64);
2430 if (reg1 != 0) {
2431 tcg_gen_movi_tl(cpu_gpr[reg1], 1);
2433 tcg_gen_brcond_i64(TCG_COND_EQ, val, llval, lab_done);
2435 gen_set_label(lab_fail);
2437 if (reg1 != 0) {
2438 tcg_gen_movi_tl(cpu_gpr[reg1], 0);
2440 gen_set_label(lab_done);
2441 tcg_gen_movi_tl(lladdr, -1);
2442 tcg_gen_st_tl(lladdr, cpu_env, offsetof(CPUMIPSState, lladdr));
2445 /* Load and store */
2446 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2447 TCGv t0)
2450 * Don't do NOP if destination is zero: we must perform the actual
2451 * memory access.
2453 switch (opc) {
2454 case OPC_LWC1:
2456 TCGv_i32 fp0 = tcg_temp_new_i32();
2457 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
2458 ctx->default_tcg_memop_mask);
2459 gen_store_fpr32(ctx, fp0, ft);
2460 tcg_temp_free_i32(fp0);
2462 break;
2463 case OPC_SWC1:
2465 TCGv_i32 fp0 = tcg_temp_new_i32();
2466 gen_load_fpr32(ctx, fp0, ft);
2467 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
2468 ctx->default_tcg_memop_mask);
2469 tcg_temp_free_i32(fp0);
2471 break;
2472 case OPC_LDC1:
2474 TCGv_i64 fp0 = tcg_temp_new_i64();
2475 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2476 ctx->default_tcg_memop_mask);
2477 gen_store_fpr64(ctx, fp0, ft);
2478 tcg_temp_free_i64(fp0);
2480 break;
2481 case OPC_SDC1:
2483 TCGv_i64 fp0 = tcg_temp_new_i64();
2484 gen_load_fpr64(ctx, fp0, ft);
2485 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ |
2486 ctx->default_tcg_memop_mask);
2487 tcg_temp_free_i64(fp0);
2489 break;
2490 default:
2491 MIPS_INVAL("flt_ldst");
2492 gen_reserved_instruction(ctx);
2493 break;
2497 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2498 int rs, int16_t imm)
2500 TCGv t0 = tcg_temp_new();
2502 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2503 check_cp1_enabled(ctx);
2504 switch (op) {
2505 case OPC_LDC1:
2506 case OPC_SDC1:
2507 check_insn(ctx, ISA_MIPS2);
2508 /* Fallthrough */
2509 default:
2510 gen_base_offset_addr(ctx, t0, rs, imm);
2511 gen_flt_ldst(ctx, op, rt, t0);
2513 } else {
2514 generate_exception_err(ctx, EXCP_CpU, 1);
2516 tcg_temp_free(t0);
2519 /* Arithmetic with immediate operand */
2520 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2521 int rt, int rs, int imm)
2523 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2525 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2527 * If no destination, treat it as a NOP.
2528 * For addi, we must generate the overflow exception when needed.
2530 return;
2532 switch (opc) {
2533 case OPC_ADDI:
2535 TCGv t0 = tcg_temp_local_new();
2536 TCGv t1 = tcg_temp_new();
2537 TCGv t2 = tcg_temp_new();
2538 TCGLabel *l1 = gen_new_label();
2540 gen_load_gpr(t1, rs);
2541 tcg_gen_addi_tl(t0, t1, uimm);
2542 tcg_gen_ext32s_tl(t0, t0);
2544 tcg_gen_xori_tl(t1, t1, ~uimm);
2545 tcg_gen_xori_tl(t2, t0, uimm);
2546 tcg_gen_and_tl(t1, t1, t2);
2547 tcg_temp_free(t2);
2548 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2549 tcg_temp_free(t1);
2550 /* operands of same sign, result different sign */
2551 generate_exception(ctx, EXCP_OVERFLOW);
2552 gen_set_label(l1);
2553 tcg_gen_ext32s_tl(t0, t0);
2554 gen_store_gpr(t0, rt);
2555 tcg_temp_free(t0);
2557 break;
2558 case OPC_ADDIU:
2559 if (rs != 0) {
2560 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2561 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2562 } else {
2563 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2565 break;
2566 #if defined(TARGET_MIPS64)
2567 case OPC_DADDI:
2569 TCGv t0 = tcg_temp_local_new();
2570 TCGv t1 = tcg_temp_new();
2571 TCGv t2 = tcg_temp_new();
2572 TCGLabel *l1 = gen_new_label();
2574 gen_load_gpr(t1, rs);
2575 tcg_gen_addi_tl(t0, t1, uimm);
2577 tcg_gen_xori_tl(t1, t1, ~uimm);
2578 tcg_gen_xori_tl(t2, t0, uimm);
2579 tcg_gen_and_tl(t1, t1, t2);
2580 tcg_temp_free(t2);
2581 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2582 tcg_temp_free(t1);
2583 /* operands of same sign, result different sign */
2584 generate_exception(ctx, EXCP_OVERFLOW);
2585 gen_set_label(l1);
2586 gen_store_gpr(t0, rt);
2587 tcg_temp_free(t0);
2589 break;
2590 case OPC_DADDIU:
2591 if (rs != 0) {
2592 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2593 } else {
2594 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2596 break;
2597 #endif
2601 /* Logic with immediate operand */
2602 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2603 int rt, int rs, int16_t imm)
2605 target_ulong uimm;
2607 if (rt == 0) {
2608 /* If no destination, treat it as a NOP. */
2609 return;
2611 uimm = (uint16_t)imm;
2612 switch (opc) {
2613 case OPC_ANDI:
2614 if (likely(rs != 0)) {
2615 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2616 } else {
2617 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2619 break;
2620 case OPC_ORI:
2621 if (rs != 0) {
2622 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2623 } else {
2624 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2626 break;
2627 case OPC_XORI:
2628 if (likely(rs != 0)) {
2629 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2630 } else {
2631 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2633 break;
2634 case OPC_LUI:
2635 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2636 /* OPC_AUI */
2637 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2638 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2639 } else {
2640 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2642 break;
2644 default:
2645 break;
2649 /* Set on less than with immediate operand */
2650 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2651 int rt, int rs, int16_t imm)
2653 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2654 TCGv t0;
2656 if (rt == 0) {
2657 /* If no destination, treat it as a NOP. */
2658 return;
2660 t0 = tcg_temp_new();
2661 gen_load_gpr(t0, rs);
2662 switch (opc) {
2663 case OPC_SLTI:
2664 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2665 break;
2666 case OPC_SLTIU:
2667 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2668 break;
2670 tcg_temp_free(t0);
2673 /* Shifts with immediate operand */
2674 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2675 int rt, int rs, int16_t imm)
2677 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2678 TCGv t0;
2680 if (rt == 0) {
2681 /* If no destination, treat it as a NOP. */
2682 return;
2685 t0 = tcg_temp_new();
2686 gen_load_gpr(t0, rs);
2687 switch (opc) {
2688 case OPC_SLL:
2689 tcg_gen_shli_tl(t0, t0, uimm);
2690 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2691 break;
2692 case OPC_SRA:
2693 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2694 break;
2695 case OPC_SRL:
2696 if (uimm != 0) {
2697 tcg_gen_ext32u_tl(t0, t0);
2698 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2699 } else {
2700 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2702 break;
2703 case OPC_ROTR:
2704 if (uimm != 0) {
2705 TCGv_i32 t1 = tcg_temp_new_i32();
2707 tcg_gen_trunc_tl_i32(t1, t0);
2708 tcg_gen_rotri_i32(t1, t1, uimm);
2709 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2710 tcg_temp_free_i32(t1);
2711 } else {
2712 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2714 break;
2715 #if defined(TARGET_MIPS64)
2716 case OPC_DSLL:
2717 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2718 break;
2719 case OPC_DSRA:
2720 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2721 break;
2722 case OPC_DSRL:
2723 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2724 break;
2725 case OPC_DROTR:
2726 if (uimm != 0) {
2727 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2728 } else {
2729 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2731 break;
2732 case OPC_DSLL32:
2733 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2734 break;
2735 case OPC_DSRA32:
2736 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2737 break;
2738 case OPC_DSRL32:
2739 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2740 break;
2741 case OPC_DROTR32:
2742 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2743 break;
2744 #endif
2746 tcg_temp_free(t0);
2749 /* Arithmetic */
2750 static void gen_arith(DisasContext *ctx, uint32_t opc,
2751 int rd, int rs, int rt)
2753 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2754 && opc != OPC_DADD && opc != OPC_DSUB) {
2756 * If no destination, treat it as a NOP.
2757 * For add & sub, we must generate the overflow exception when needed.
2759 return;
2762 switch (opc) {
2763 case OPC_ADD:
2765 TCGv t0 = tcg_temp_local_new();
2766 TCGv t1 = tcg_temp_new();
2767 TCGv t2 = tcg_temp_new();
2768 TCGLabel *l1 = gen_new_label();
2770 gen_load_gpr(t1, rs);
2771 gen_load_gpr(t2, rt);
2772 tcg_gen_add_tl(t0, t1, t2);
2773 tcg_gen_ext32s_tl(t0, t0);
2774 tcg_gen_xor_tl(t1, t1, t2);
2775 tcg_gen_xor_tl(t2, t0, t2);
2776 tcg_gen_andc_tl(t1, t2, t1);
2777 tcg_temp_free(t2);
2778 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2779 tcg_temp_free(t1);
2780 /* operands of same sign, result different sign */
2781 generate_exception(ctx, EXCP_OVERFLOW);
2782 gen_set_label(l1);
2783 gen_store_gpr(t0, rd);
2784 tcg_temp_free(t0);
2786 break;
2787 case OPC_ADDU:
2788 if (rs != 0 && rt != 0) {
2789 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2790 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2791 } else if (rs == 0 && rt != 0) {
2792 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2793 } else if (rs != 0 && rt == 0) {
2794 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2795 } else {
2796 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2798 break;
2799 case OPC_SUB:
2801 TCGv t0 = tcg_temp_local_new();
2802 TCGv t1 = tcg_temp_new();
2803 TCGv t2 = tcg_temp_new();
2804 TCGLabel *l1 = gen_new_label();
2806 gen_load_gpr(t1, rs);
2807 gen_load_gpr(t2, rt);
2808 tcg_gen_sub_tl(t0, t1, t2);
2809 tcg_gen_ext32s_tl(t0, t0);
2810 tcg_gen_xor_tl(t2, t1, t2);
2811 tcg_gen_xor_tl(t1, t0, t1);
2812 tcg_gen_and_tl(t1, t1, t2);
2813 tcg_temp_free(t2);
2814 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2815 tcg_temp_free(t1);
2817 * operands of different sign, first operand and the result
2818 * of different sign
2820 generate_exception(ctx, EXCP_OVERFLOW);
2821 gen_set_label(l1);
2822 gen_store_gpr(t0, rd);
2823 tcg_temp_free(t0);
2825 break;
2826 case OPC_SUBU:
2827 if (rs != 0 && rt != 0) {
2828 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2829 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2830 } else if (rs == 0 && rt != 0) {
2831 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2832 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2833 } else if (rs != 0 && rt == 0) {
2834 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2835 } else {
2836 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2838 break;
2839 #if defined(TARGET_MIPS64)
2840 case OPC_DADD:
2842 TCGv t0 = tcg_temp_local_new();
2843 TCGv t1 = tcg_temp_new();
2844 TCGv t2 = tcg_temp_new();
2845 TCGLabel *l1 = gen_new_label();
2847 gen_load_gpr(t1, rs);
2848 gen_load_gpr(t2, rt);
2849 tcg_gen_add_tl(t0, t1, t2);
2850 tcg_gen_xor_tl(t1, t1, t2);
2851 tcg_gen_xor_tl(t2, t0, t2);
2852 tcg_gen_andc_tl(t1, t2, t1);
2853 tcg_temp_free(t2);
2854 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2855 tcg_temp_free(t1);
2856 /* operands of same sign, result different sign */
2857 generate_exception(ctx, EXCP_OVERFLOW);
2858 gen_set_label(l1);
2859 gen_store_gpr(t0, rd);
2860 tcg_temp_free(t0);
2862 break;
2863 case OPC_DADDU:
2864 if (rs != 0 && rt != 0) {
2865 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2866 } else if (rs == 0 && rt != 0) {
2867 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2868 } else if (rs != 0 && rt == 0) {
2869 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2870 } else {
2871 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2873 break;
2874 case OPC_DSUB:
2876 TCGv t0 = tcg_temp_local_new();
2877 TCGv t1 = tcg_temp_new();
2878 TCGv t2 = tcg_temp_new();
2879 TCGLabel *l1 = gen_new_label();
2881 gen_load_gpr(t1, rs);
2882 gen_load_gpr(t2, rt);
2883 tcg_gen_sub_tl(t0, t1, t2);
2884 tcg_gen_xor_tl(t2, t1, t2);
2885 tcg_gen_xor_tl(t1, t0, t1);
2886 tcg_gen_and_tl(t1, t1, t2);
2887 tcg_temp_free(t2);
2888 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2889 tcg_temp_free(t1);
2891 * Operands of different sign, first operand and result different
2892 * sign.
2894 generate_exception(ctx, EXCP_OVERFLOW);
2895 gen_set_label(l1);
2896 gen_store_gpr(t0, rd);
2897 tcg_temp_free(t0);
2899 break;
2900 case OPC_DSUBU:
2901 if (rs != 0 && rt != 0) {
2902 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2903 } else if (rs == 0 && rt != 0) {
2904 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2905 } else if (rs != 0 && rt == 0) {
2906 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2907 } else {
2908 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2910 break;
2911 #endif
2912 case OPC_MUL:
2913 if (likely(rs != 0 && rt != 0)) {
2914 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2915 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2916 } else {
2917 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2919 break;
2923 /* Conditional move */
2924 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2925 int rd, int rs, int rt)
2927 TCGv t0, t1, t2;
2929 if (rd == 0) {
2930 /* If no destination, treat it as a NOP. */
2931 return;
2934 t0 = tcg_temp_new();
2935 gen_load_gpr(t0, rt);
2936 t1 = tcg_const_tl(0);
2937 t2 = tcg_temp_new();
2938 gen_load_gpr(t2, rs);
2939 switch (opc) {
2940 case OPC_MOVN:
2941 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2942 break;
2943 case OPC_MOVZ:
2944 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2945 break;
2946 case OPC_SELNEZ:
2947 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2948 break;
2949 case OPC_SELEQZ:
2950 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2951 break;
2953 tcg_temp_free(t2);
2954 tcg_temp_free(t1);
2955 tcg_temp_free(t0);
2958 /* Logic */
2959 static void gen_logic(DisasContext *ctx, uint32_t opc,
2960 int rd, int rs, int rt)
2962 if (rd == 0) {
2963 /* If no destination, treat it as a NOP. */
2964 return;
2967 switch (opc) {
2968 case OPC_AND:
2969 if (likely(rs != 0 && rt != 0)) {
2970 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2971 } else {
2972 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2974 break;
2975 case OPC_NOR:
2976 if (rs != 0 && rt != 0) {
2977 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2978 } else if (rs == 0 && rt != 0) {
2979 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2980 } else if (rs != 0 && rt == 0) {
2981 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2982 } else {
2983 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2985 break;
2986 case OPC_OR:
2987 if (likely(rs != 0 && rt != 0)) {
2988 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2989 } else if (rs == 0 && rt != 0) {
2990 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2991 } else if (rs != 0 && rt == 0) {
2992 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2993 } else {
2994 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2996 break;
2997 case OPC_XOR:
2998 if (likely(rs != 0 && rt != 0)) {
2999 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
3000 } else if (rs == 0 && rt != 0) {
3001 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
3002 } else if (rs != 0 && rt == 0) {
3003 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
3004 } else {
3005 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3007 break;
3011 /* Set on lower than */
3012 static void gen_slt(DisasContext *ctx, uint32_t opc,
3013 int rd, int rs, int rt)
3015 TCGv t0, t1;
3017 if (rd == 0) {
3018 /* If no destination, treat it as a NOP. */
3019 return;
3022 t0 = tcg_temp_new();
3023 t1 = tcg_temp_new();
3024 gen_load_gpr(t0, rs);
3025 gen_load_gpr(t1, rt);
3026 switch (opc) {
3027 case OPC_SLT:
3028 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
3029 break;
3030 case OPC_SLTU:
3031 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
3032 break;
3034 tcg_temp_free(t0);
3035 tcg_temp_free(t1);
3038 /* Shifts */
3039 static void gen_shift(DisasContext *ctx, uint32_t opc,
3040 int rd, int rs, int rt)
3042 TCGv t0, t1;
3044 if (rd == 0) {
3046 * If no destination, treat it as a NOP.
3047 * For add & sub, we must generate the overflow exception when needed.
3049 return;
3052 t0 = tcg_temp_new();
3053 t1 = tcg_temp_new();
3054 gen_load_gpr(t0, rs);
3055 gen_load_gpr(t1, rt);
3056 switch (opc) {
3057 case OPC_SLLV:
3058 tcg_gen_andi_tl(t0, t0, 0x1f);
3059 tcg_gen_shl_tl(t0, t1, t0);
3060 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3061 break;
3062 case OPC_SRAV:
3063 tcg_gen_andi_tl(t0, t0, 0x1f);
3064 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3065 break;
3066 case OPC_SRLV:
3067 tcg_gen_ext32u_tl(t1, t1);
3068 tcg_gen_andi_tl(t0, t0, 0x1f);
3069 tcg_gen_shr_tl(t0, t1, t0);
3070 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3071 break;
3072 case OPC_ROTRV:
3074 TCGv_i32 t2 = tcg_temp_new_i32();
3075 TCGv_i32 t3 = tcg_temp_new_i32();
3077 tcg_gen_trunc_tl_i32(t2, t0);
3078 tcg_gen_trunc_tl_i32(t3, t1);
3079 tcg_gen_andi_i32(t2, t2, 0x1f);
3080 tcg_gen_rotr_i32(t2, t3, t2);
3081 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3082 tcg_temp_free_i32(t2);
3083 tcg_temp_free_i32(t3);
3085 break;
3086 #if defined(TARGET_MIPS64)
3087 case OPC_DSLLV:
3088 tcg_gen_andi_tl(t0, t0, 0x3f);
3089 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
3090 break;
3091 case OPC_DSRAV:
3092 tcg_gen_andi_tl(t0, t0, 0x3f);
3093 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
3094 break;
3095 case OPC_DSRLV:
3096 tcg_gen_andi_tl(t0, t0, 0x3f);
3097 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
3098 break;
3099 case OPC_DROTRV:
3100 tcg_gen_andi_tl(t0, t0, 0x3f);
3101 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
3102 break;
3103 #endif
3105 tcg_temp_free(t0);
3106 tcg_temp_free(t1);
3109 /* Arithmetic on HI/LO registers */
3110 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
3112 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
3113 /* Treat as NOP. */
3114 return;
3117 if (acc != 0) {
3118 check_dsp(ctx);
3121 switch (opc) {
3122 case OPC_MFHI:
3123 #if defined(TARGET_MIPS64)
3124 if (acc != 0) {
3125 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
3126 } else
3127 #endif
3129 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
3131 break;
3132 case OPC_MFLO:
3133 #if defined(TARGET_MIPS64)
3134 if (acc != 0) {
3135 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
3136 } else
3137 #endif
3139 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
3141 break;
3142 case OPC_MTHI:
3143 if (reg != 0) {
3144 #if defined(TARGET_MIPS64)
3145 if (acc != 0) {
3146 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
3147 } else
3148 #endif
3150 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
3152 } else {
3153 tcg_gen_movi_tl(cpu_HI[acc], 0);
3155 break;
3156 case OPC_MTLO:
3157 if (reg != 0) {
3158 #if defined(TARGET_MIPS64)
3159 if (acc != 0) {
3160 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
3161 } else
3162 #endif
3164 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
3166 } else {
3167 tcg_gen_movi_tl(cpu_LO[acc], 0);
3169 break;
3173 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
3174 MemOp memop)
3176 TCGv t0 = tcg_const_tl(addr);
3177 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
3178 gen_store_gpr(t0, reg);
3179 tcg_temp_free(t0);
3182 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
3183 int rs)
3185 target_long offset;
3186 target_long addr;
3188 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
3189 case OPC_ADDIUPC:
3190 if (rs != 0) {
3191 offset = sextract32(ctx->opcode << 2, 0, 21);
3192 addr = addr_add(ctx, pc, offset);
3193 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3195 break;
3196 case R6_OPC_LWPC:
3197 offset = sextract32(ctx->opcode << 2, 0, 21);
3198 addr = addr_add(ctx, pc, offset);
3199 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
3200 break;
3201 #if defined(TARGET_MIPS64)
3202 case OPC_LWUPC:
3203 check_mips_64(ctx);
3204 offset = sextract32(ctx->opcode << 2, 0, 21);
3205 addr = addr_add(ctx, pc, offset);
3206 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
3207 break;
3208 #endif
3209 default:
3210 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
3211 case OPC_AUIPC:
3212 if (rs != 0) {
3213 offset = sextract32(ctx->opcode, 0, 16) << 16;
3214 addr = addr_add(ctx, pc, offset);
3215 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3217 break;
3218 case OPC_ALUIPC:
3219 if (rs != 0) {
3220 offset = sextract32(ctx->opcode, 0, 16) << 16;
3221 addr = ~0xFFFF & addr_add(ctx, pc, offset);
3222 tcg_gen_movi_tl(cpu_gpr[rs], addr);
3224 break;
3225 #if defined(TARGET_MIPS64)
3226 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
3227 case R6_OPC_LDPC + (1 << 16):
3228 case R6_OPC_LDPC + (2 << 16):
3229 case R6_OPC_LDPC + (3 << 16):
3230 check_mips_64(ctx);
3231 offset = sextract32(ctx->opcode << 3, 0, 21);
3232 addr = addr_add(ctx, (pc & ~0x7), offset);
3233 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
3234 break;
3235 #endif
3236 default:
3237 MIPS_INVAL("OPC_PCREL");
3238 gen_reserved_instruction(ctx);
3239 break;
3241 break;
3245 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3247 TCGv t0, t1;
3249 if (rd == 0) {
3250 /* Treat as NOP. */
3251 return;
3254 t0 = tcg_temp_new();
3255 t1 = tcg_temp_new();
3257 gen_load_gpr(t0, rs);
3258 gen_load_gpr(t1, rt);
3260 switch (opc) {
3261 case R6_OPC_DIV:
3263 TCGv t2 = tcg_temp_new();
3264 TCGv t3 = tcg_temp_new();
3265 tcg_gen_ext32s_tl(t0, t0);
3266 tcg_gen_ext32s_tl(t1, t1);
3267 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3268 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3269 tcg_gen_and_tl(t2, t2, t3);
3270 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3271 tcg_gen_or_tl(t2, t2, t3);
3272 tcg_gen_movi_tl(t3, 0);
3273 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3274 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3275 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3276 tcg_temp_free(t3);
3277 tcg_temp_free(t2);
3279 break;
3280 case R6_OPC_MOD:
3282 TCGv t2 = tcg_temp_new();
3283 TCGv t3 = tcg_temp_new();
3284 tcg_gen_ext32s_tl(t0, t0);
3285 tcg_gen_ext32s_tl(t1, t1);
3286 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3287 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3288 tcg_gen_and_tl(t2, t2, t3);
3289 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3290 tcg_gen_or_tl(t2, t2, t3);
3291 tcg_gen_movi_tl(t3, 0);
3292 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3293 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3294 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3295 tcg_temp_free(t3);
3296 tcg_temp_free(t2);
3298 break;
3299 case R6_OPC_DIVU:
3301 TCGv t2 = tcg_const_tl(0);
3302 TCGv t3 = tcg_const_tl(1);
3303 tcg_gen_ext32u_tl(t0, t0);
3304 tcg_gen_ext32u_tl(t1, t1);
3305 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3306 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3307 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3308 tcg_temp_free(t3);
3309 tcg_temp_free(t2);
3311 break;
3312 case R6_OPC_MODU:
3314 TCGv t2 = tcg_const_tl(0);
3315 TCGv t3 = tcg_const_tl(1);
3316 tcg_gen_ext32u_tl(t0, t0);
3317 tcg_gen_ext32u_tl(t1, t1);
3318 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3319 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3320 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3321 tcg_temp_free(t3);
3322 tcg_temp_free(t2);
3324 break;
3325 case R6_OPC_MUL:
3327 TCGv_i32 t2 = tcg_temp_new_i32();
3328 TCGv_i32 t3 = tcg_temp_new_i32();
3329 tcg_gen_trunc_tl_i32(t2, t0);
3330 tcg_gen_trunc_tl_i32(t3, t1);
3331 tcg_gen_mul_i32(t2, t2, t3);
3332 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3333 tcg_temp_free_i32(t2);
3334 tcg_temp_free_i32(t3);
3336 break;
3337 case R6_OPC_MUH:
3339 TCGv_i32 t2 = tcg_temp_new_i32();
3340 TCGv_i32 t3 = tcg_temp_new_i32();
3341 tcg_gen_trunc_tl_i32(t2, t0);
3342 tcg_gen_trunc_tl_i32(t3, t1);
3343 tcg_gen_muls2_i32(t2, t3, t2, t3);
3344 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3345 tcg_temp_free_i32(t2);
3346 tcg_temp_free_i32(t3);
3348 break;
3349 case R6_OPC_MULU:
3351 TCGv_i32 t2 = tcg_temp_new_i32();
3352 TCGv_i32 t3 = tcg_temp_new_i32();
3353 tcg_gen_trunc_tl_i32(t2, t0);
3354 tcg_gen_trunc_tl_i32(t3, t1);
3355 tcg_gen_mul_i32(t2, t2, t3);
3356 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3357 tcg_temp_free_i32(t2);
3358 tcg_temp_free_i32(t3);
3360 break;
3361 case R6_OPC_MUHU:
3363 TCGv_i32 t2 = tcg_temp_new_i32();
3364 TCGv_i32 t3 = tcg_temp_new_i32();
3365 tcg_gen_trunc_tl_i32(t2, t0);
3366 tcg_gen_trunc_tl_i32(t3, t1);
3367 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3368 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3369 tcg_temp_free_i32(t2);
3370 tcg_temp_free_i32(t3);
3372 break;
3373 #if defined(TARGET_MIPS64)
3374 case R6_OPC_DDIV:
3376 TCGv t2 = tcg_temp_new();
3377 TCGv t3 = tcg_temp_new();
3378 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3379 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3380 tcg_gen_and_tl(t2, t2, t3);
3381 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3382 tcg_gen_or_tl(t2, t2, t3);
3383 tcg_gen_movi_tl(t3, 0);
3384 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3385 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3386 tcg_temp_free(t3);
3387 tcg_temp_free(t2);
3389 break;
3390 case R6_OPC_DMOD:
3392 TCGv t2 = tcg_temp_new();
3393 TCGv t3 = tcg_temp_new();
3394 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3395 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3396 tcg_gen_and_tl(t2, t2, t3);
3397 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3398 tcg_gen_or_tl(t2, t2, t3);
3399 tcg_gen_movi_tl(t3, 0);
3400 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3401 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3402 tcg_temp_free(t3);
3403 tcg_temp_free(t2);
3405 break;
3406 case R6_OPC_DDIVU:
3408 TCGv t2 = tcg_const_tl(0);
3409 TCGv t3 = tcg_const_tl(1);
3410 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3411 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3412 tcg_temp_free(t3);
3413 tcg_temp_free(t2);
3415 break;
3416 case R6_OPC_DMODU:
3418 TCGv t2 = tcg_const_tl(0);
3419 TCGv t3 = tcg_const_tl(1);
3420 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3421 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3422 tcg_temp_free(t3);
3423 tcg_temp_free(t2);
3425 break;
3426 case R6_OPC_DMUL:
3427 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3428 break;
3429 case R6_OPC_DMUH:
3431 TCGv t2 = tcg_temp_new();
3432 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3433 tcg_temp_free(t2);
3435 break;
3436 case R6_OPC_DMULU:
3437 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3438 break;
3439 case R6_OPC_DMUHU:
3441 TCGv t2 = tcg_temp_new();
3442 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3443 tcg_temp_free(t2);
3445 break;
3446 #endif
3447 default:
3448 MIPS_INVAL("r6 mul/div");
3449 gen_reserved_instruction(ctx);
3450 goto out;
3452 out:
3453 tcg_temp_free(t0);
3454 tcg_temp_free(t1);
3457 #if defined(TARGET_MIPS64)
3458 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3460 TCGv t0, t1;
3462 t0 = tcg_temp_new();
3463 t1 = tcg_temp_new();
3465 gen_load_gpr(t0, rs);
3466 gen_load_gpr(t1, rt);
3468 switch (opc) {
3469 case MMI_OPC_DIV1:
3471 TCGv t2 = tcg_temp_new();
3472 TCGv t3 = tcg_temp_new();
3473 tcg_gen_ext32s_tl(t0, t0);
3474 tcg_gen_ext32s_tl(t1, t1);
3475 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3476 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3477 tcg_gen_and_tl(t2, t2, t3);
3478 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3479 tcg_gen_or_tl(t2, t2, t3);
3480 tcg_gen_movi_tl(t3, 0);
3481 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3482 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3483 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3484 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3485 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3486 tcg_temp_free(t3);
3487 tcg_temp_free(t2);
3489 break;
3490 case MMI_OPC_DIVU1:
3492 TCGv t2 = tcg_const_tl(0);
3493 TCGv t3 = tcg_const_tl(1);
3494 tcg_gen_ext32u_tl(t0, t0);
3495 tcg_gen_ext32u_tl(t1, t1);
3496 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3497 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3498 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3499 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3500 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3501 tcg_temp_free(t3);
3502 tcg_temp_free(t2);
3504 break;
3505 default:
3506 MIPS_INVAL("div1 TX79");
3507 gen_reserved_instruction(ctx);
3508 goto out;
3510 out:
3511 tcg_temp_free(t0);
3512 tcg_temp_free(t1);
3514 #endif
3516 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3517 int acc, int rs, int rt)
3519 TCGv t0, t1;
3521 t0 = tcg_temp_new();
3522 t1 = tcg_temp_new();
3524 gen_load_gpr(t0, rs);
3525 gen_load_gpr(t1, rt);
3527 if (acc != 0) {
3528 check_dsp(ctx);
3531 switch (opc) {
3532 case OPC_DIV:
3534 TCGv t2 = tcg_temp_new();
3535 TCGv t3 = tcg_temp_new();
3536 tcg_gen_ext32s_tl(t0, t0);
3537 tcg_gen_ext32s_tl(t1, t1);
3538 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3539 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3540 tcg_gen_and_tl(t2, t2, t3);
3541 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3542 tcg_gen_or_tl(t2, t2, t3);
3543 tcg_gen_movi_tl(t3, 0);
3544 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3545 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3546 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3547 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3548 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3549 tcg_temp_free(t3);
3550 tcg_temp_free(t2);
3552 break;
3553 case OPC_DIVU:
3555 TCGv t2 = tcg_const_tl(0);
3556 TCGv t3 = tcg_const_tl(1);
3557 tcg_gen_ext32u_tl(t0, t0);
3558 tcg_gen_ext32u_tl(t1, t1);
3559 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3560 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3561 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3562 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3563 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3564 tcg_temp_free(t3);
3565 tcg_temp_free(t2);
3567 break;
3568 case OPC_MULT:
3570 TCGv_i32 t2 = tcg_temp_new_i32();
3571 TCGv_i32 t3 = tcg_temp_new_i32();
3572 tcg_gen_trunc_tl_i32(t2, t0);
3573 tcg_gen_trunc_tl_i32(t3, t1);
3574 tcg_gen_muls2_i32(t2, t3, t2, t3);
3575 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3576 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3577 tcg_temp_free_i32(t2);
3578 tcg_temp_free_i32(t3);
3580 break;
3581 case OPC_MULTU:
3583 TCGv_i32 t2 = tcg_temp_new_i32();
3584 TCGv_i32 t3 = tcg_temp_new_i32();
3585 tcg_gen_trunc_tl_i32(t2, t0);
3586 tcg_gen_trunc_tl_i32(t3, t1);
3587 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3588 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3589 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3590 tcg_temp_free_i32(t2);
3591 tcg_temp_free_i32(t3);
3593 break;
3594 #if defined(TARGET_MIPS64)
3595 case OPC_DDIV:
3597 TCGv t2 = tcg_temp_new();
3598 TCGv t3 = tcg_temp_new();
3599 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3600 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3601 tcg_gen_and_tl(t2, t2, t3);
3602 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3603 tcg_gen_or_tl(t2, t2, t3);
3604 tcg_gen_movi_tl(t3, 0);
3605 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3606 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3607 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3608 tcg_temp_free(t3);
3609 tcg_temp_free(t2);
3611 break;
3612 case OPC_DDIVU:
3614 TCGv t2 = tcg_const_tl(0);
3615 TCGv t3 = tcg_const_tl(1);
3616 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3617 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3618 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3619 tcg_temp_free(t3);
3620 tcg_temp_free(t2);
3622 break;
3623 case OPC_DMULT:
3624 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3625 break;
3626 case OPC_DMULTU:
3627 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3628 break;
3629 #endif
3630 case OPC_MADD:
3632 TCGv_i64 t2 = tcg_temp_new_i64();
3633 TCGv_i64 t3 = tcg_temp_new_i64();
3635 tcg_gen_ext_tl_i64(t2, t0);
3636 tcg_gen_ext_tl_i64(t3, t1);
3637 tcg_gen_mul_i64(t2, t2, t3);
3638 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3639 tcg_gen_add_i64(t2, t2, t3);
3640 tcg_temp_free_i64(t3);
3641 gen_move_low32(cpu_LO[acc], t2);
3642 gen_move_high32(cpu_HI[acc], t2);
3643 tcg_temp_free_i64(t2);
3645 break;
3646 case OPC_MADDU:
3648 TCGv_i64 t2 = tcg_temp_new_i64();
3649 TCGv_i64 t3 = tcg_temp_new_i64();
3651 tcg_gen_ext32u_tl(t0, t0);
3652 tcg_gen_ext32u_tl(t1, t1);
3653 tcg_gen_extu_tl_i64(t2, t0);
3654 tcg_gen_extu_tl_i64(t3, t1);
3655 tcg_gen_mul_i64(t2, t2, t3);
3656 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3657 tcg_gen_add_i64(t2, t2, t3);
3658 tcg_temp_free_i64(t3);
3659 gen_move_low32(cpu_LO[acc], t2);
3660 gen_move_high32(cpu_HI[acc], t2);
3661 tcg_temp_free_i64(t2);
3663 break;
3664 case OPC_MSUB:
3666 TCGv_i64 t2 = tcg_temp_new_i64();
3667 TCGv_i64 t3 = tcg_temp_new_i64();
3669 tcg_gen_ext_tl_i64(t2, t0);
3670 tcg_gen_ext_tl_i64(t3, t1);
3671 tcg_gen_mul_i64(t2, t2, t3);
3672 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3673 tcg_gen_sub_i64(t2, t3, t2);
3674 tcg_temp_free_i64(t3);
3675 gen_move_low32(cpu_LO[acc], t2);
3676 gen_move_high32(cpu_HI[acc], t2);
3677 tcg_temp_free_i64(t2);
3679 break;
3680 case OPC_MSUBU:
3682 TCGv_i64 t2 = tcg_temp_new_i64();
3683 TCGv_i64 t3 = tcg_temp_new_i64();
3685 tcg_gen_ext32u_tl(t0, t0);
3686 tcg_gen_ext32u_tl(t1, t1);
3687 tcg_gen_extu_tl_i64(t2, t0);
3688 tcg_gen_extu_tl_i64(t3, t1);
3689 tcg_gen_mul_i64(t2, t2, t3);
3690 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3691 tcg_gen_sub_i64(t2, t3, t2);
3692 tcg_temp_free_i64(t3);
3693 gen_move_low32(cpu_LO[acc], t2);
3694 gen_move_high32(cpu_HI[acc], t2);
3695 tcg_temp_free_i64(t2);
3697 break;
3698 default:
3699 MIPS_INVAL("mul/div");
3700 gen_reserved_instruction(ctx);
3701 goto out;
3703 out:
3704 tcg_temp_free(t0);
3705 tcg_temp_free(t1);
3709 * These MULT[U] and MADD[U] instructions implemented in for example
3710 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3711 * architectures are special three-operand variants with the syntax
3713 * MULT[U][1] rd, rs, rt
3715 * such that
3717 * (rd, LO, HI) <- rs * rt
3719 * and
3721 * MADD[U][1] rd, rs, rt
3723 * such that
3725 * (rd, LO, HI) <- (LO, HI) + rs * rt
3727 * where the low-order 32-bits of the result is placed into both the
3728 * GPR rd and the special register LO. The high-order 32-bits of the
3729 * result is placed into the special register HI.
3731 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3732 * which is the zero register that always reads as 0.
3734 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3735 int rd, int rs, int rt)
3737 TCGv t0 = tcg_temp_new();
3738 TCGv t1 = tcg_temp_new();
3739 int acc = 0;
3741 gen_load_gpr(t0, rs);
3742 gen_load_gpr(t1, rt);
3744 switch (opc) {
3745 case MMI_OPC_MULT1:
3746 acc = 1;
3747 /* Fall through */
3748 case OPC_MULT:
3750 TCGv_i32 t2 = tcg_temp_new_i32();
3751 TCGv_i32 t3 = tcg_temp_new_i32();
3752 tcg_gen_trunc_tl_i32(t2, t0);
3753 tcg_gen_trunc_tl_i32(t3, t1);
3754 tcg_gen_muls2_i32(t2, t3, t2, t3);
3755 if (rd) {
3756 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3758 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3759 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3760 tcg_temp_free_i32(t2);
3761 tcg_temp_free_i32(t3);
3763 break;
3764 case MMI_OPC_MULTU1:
3765 acc = 1;
3766 /* Fall through */
3767 case OPC_MULTU:
3769 TCGv_i32 t2 = tcg_temp_new_i32();
3770 TCGv_i32 t3 = tcg_temp_new_i32();
3771 tcg_gen_trunc_tl_i32(t2, t0);
3772 tcg_gen_trunc_tl_i32(t3, t1);
3773 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3774 if (rd) {
3775 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3777 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3778 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3779 tcg_temp_free_i32(t2);
3780 tcg_temp_free_i32(t3);
3782 break;
3783 case MMI_OPC_MADD1:
3784 acc = 1;
3785 /* Fall through */
3786 case MMI_OPC_MADD:
3788 TCGv_i64 t2 = tcg_temp_new_i64();
3789 TCGv_i64 t3 = tcg_temp_new_i64();
3791 tcg_gen_ext_tl_i64(t2, t0);
3792 tcg_gen_ext_tl_i64(t3, t1);
3793 tcg_gen_mul_i64(t2, t2, t3);
3794 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3795 tcg_gen_add_i64(t2, t2, t3);
3796 tcg_temp_free_i64(t3);
3797 gen_move_low32(cpu_LO[acc], t2);
3798 gen_move_high32(cpu_HI[acc], t2);
3799 if (rd) {
3800 gen_move_low32(cpu_gpr[rd], t2);
3802 tcg_temp_free_i64(t2);
3804 break;
3805 case MMI_OPC_MADDU1:
3806 acc = 1;
3807 /* Fall through */
3808 case MMI_OPC_MADDU:
3810 TCGv_i64 t2 = tcg_temp_new_i64();
3811 TCGv_i64 t3 = tcg_temp_new_i64();
3813 tcg_gen_ext32u_tl(t0, t0);
3814 tcg_gen_ext32u_tl(t1, t1);
3815 tcg_gen_extu_tl_i64(t2, t0);
3816 tcg_gen_extu_tl_i64(t3, t1);
3817 tcg_gen_mul_i64(t2, t2, t3);
3818 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3819 tcg_gen_add_i64(t2, t2, t3);
3820 tcg_temp_free_i64(t3);
3821 gen_move_low32(cpu_LO[acc], t2);
3822 gen_move_high32(cpu_HI[acc], t2);
3823 if (rd) {
3824 gen_move_low32(cpu_gpr[rd], t2);
3826 tcg_temp_free_i64(t2);
3828 break;
3829 default:
3830 MIPS_INVAL("mul/madd TXx9");
3831 gen_reserved_instruction(ctx);
3832 goto out;
3835 out:
3836 tcg_temp_free(t0);
3837 tcg_temp_free(t1);
3840 static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc,
3841 int rd, int rs, int rt)
3843 TCGv t0 = tcg_temp_new();
3844 TCGv t1 = tcg_temp_new();
3846 gen_load_gpr(t0, rs);
3847 gen_load_gpr(t1, rt);
3849 switch (opc) {
3850 case OPC_VR54XX_MULS:
3851 gen_helper_muls(t0, cpu_env, t0, t1);
3852 break;
3853 case OPC_VR54XX_MULSU:
3854 gen_helper_mulsu(t0, cpu_env, t0, t1);
3855 break;
3856 case OPC_VR54XX_MACC:
3857 gen_helper_macc(t0, cpu_env, t0, t1);
3858 break;
3859 case OPC_VR54XX_MACCU:
3860 gen_helper_maccu(t0, cpu_env, t0, t1);
3861 break;
3862 case OPC_VR54XX_MSAC:
3863 gen_helper_msac(t0, cpu_env, t0, t1);
3864 break;
3865 case OPC_VR54XX_MSACU:
3866 gen_helper_msacu(t0, cpu_env, t0, t1);
3867 break;
3868 case OPC_VR54XX_MULHI:
3869 gen_helper_mulhi(t0, cpu_env, t0, t1);
3870 break;
3871 case OPC_VR54XX_MULHIU:
3872 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3873 break;
3874 case OPC_VR54XX_MULSHI:
3875 gen_helper_mulshi(t0, cpu_env, t0, t1);
3876 break;
3877 case OPC_VR54XX_MULSHIU:
3878 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3879 break;
3880 case OPC_VR54XX_MACCHI:
3881 gen_helper_macchi(t0, cpu_env, t0, t1);
3882 break;
3883 case OPC_VR54XX_MACCHIU:
3884 gen_helper_macchiu(t0, cpu_env, t0, t1);
3885 break;
3886 case OPC_VR54XX_MSACHI:
3887 gen_helper_msachi(t0, cpu_env, t0, t1);
3888 break;
3889 case OPC_VR54XX_MSACHIU:
3890 gen_helper_msachiu(t0, cpu_env, t0, t1);
3891 break;
3892 default:
3893 MIPS_INVAL("mul vr54xx");
3894 gen_reserved_instruction(ctx);
3895 goto out;
3897 gen_store_gpr(t0, rd);
3899 out:
3900 tcg_temp_free(t0);
3901 tcg_temp_free(t1);
3904 static void gen_cl(DisasContext *ctx, uint32_t opc,
3905 int rd, int rs)
3907 TCGv t0;
3909 if (rd == 0) {
3910 /* Treat as NOP. */
3911 return;
3913 t0 = cpu_gpr[rd];
3914 gen_load_gpr(t0, rs);
3916 switch (opc) {
3917 case OPC_CLO:
3918 case R6_OPC_CLO:
3919 #if defined(TARGET_MIPS64)
3920 case OPC_DCLO:
3921 case R6_OPC_DCLO:
3922 #endif
3923 tcg_gen_not_tl(t0, t0);
3924 break;
3927 switch (opc) {
3928 case OPC_CLO:
3929 case R6_OPC_CLO:
3930 case OPC_CLZ:
3931 case R6_OPC_CLZ:
3932 tcg_gen_ext32u_tl(t0, t0);
3933 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3934 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3935 break;
3936 #if defined(TARGET_MIPS64)
3937 case OPC_DCLO:
3938 case R6_OPC_DCLO:
3939 case OPC_DCLZ:
3940 case R6_OPC_DCLZ:
3941 tcg_gen_clzi_i64(t0, t0, 64);
3942 break;
3943 #endif
3947 /* Godson integer instructions */
3948 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3949 int rd, int rs, int rt)
3951 TCGv t0, t1;
3953 if (rd == 0) {
3954 /* Treat as NOP. */
3955 return;
3958 switch (opc) {
3959 case OPC_MULT_G_2E:
3960 case OPC_MULT_G_2F:
3961 case OPC_MULTU_G_2E:
3962 case OPC_MULTU_G_2F:
3963 #if defined(TARGET_MIPS64)
3964 case OPC_DMULT_G_2E:
3965 case OPC_DMULT_G_2F:
3966 case OPC_DMULTU_G_2E:
3967 case OPC_DMULTU_G_2F:
3968 #endif
3969 t0 = tcg_temp_new();
3970 t1 = tcg_temp_new();
3971 break;
3972 default:
3973 t0 = tcg_temp_local_new();
3974 t1 = tcg_temp_local_new();
3975 break;
3978 gen_load_gpr(t0, rs);
3979 gen_load_gpr(t1, rt);
3981 switch (opc) {
3982 case OPC_MULT_G_2E:
3983 case OPC_MULT_G_2F:
3984 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3985 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3986 break;
3987 case OPC_MULTU_G_2E:
3988 case OPC_MULTU_G_2F:
3989 tcg_gen_ext32u_tl(t0, t0);
3990 tcg_gen_ext32u_tl(t1, t1);
3991 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3992 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3993 break;
3994 case OPC_DIV_G_2E:
3995 case OPC_DIV_G_2F:
3997 TCGLabel *l1 = gen_new_label();
3998 TCGLabel *l2 = gen_new_label();
3999 TCGLabel *l3 = gen_new_label();
4000 tcg_gen_ext32s_tl(t0, t0);
4001 tcg_gen_ext32s_tl(t1, t1);
4002 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4003 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4004 tcg_gen_br(l3);
4005 gen_set_label(l1);
4006 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4007 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4008 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4009 tcg_gen_br(l3);
4010 gen_set_label(l2);
4011 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4012 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4013 gen_set_label(l3);
4015 break;
4016 case OPC_DIVU_G_2E:
4017 case OPC_DIVU_G_2F:
4019 TCGLabel *l1 = gen_new_label();
4020 TCGLabel *l2 = gen_new_label();
4021 tcg_gen_ext32u_tl(t0, t0);
4022 tcg_gen_ext32u_tl(t1, t1);
4023 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4024 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4025 tcg_gen_br(l2);
4026 gen_set_label(l1);
4027 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4028 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4029 gen_set_label(l2);
4031 break;
4032 case OPC_MOD_G_2E:
4033 case OPC_MOD_G_2F:
4035 TCGLabel *l1 = gen_new_label();
4036 TCGLabel *l2 = gen_new_label();
4037 TCGLabel *l3 = gen_new_label();
4038 tcg_gen_ext32u_tl(t0, t0);
4039 tcg_gen_ext32u_tl(t1, t1);
4040 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4041 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
4042 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
4043 gen_set_label(l1);
4044 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4045 tcg_gen_br(l3);
4046 gen_set_label(l2);
4047 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4048 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4049 gen_set_label(l3);
4051 break;
4052 case OPC_MODU_G_2E:
4053 case OPC_MODU_G_2F:
4055 TCGLabel *l1 = gen_new_label();
4056 TCGLabel *l2 = gen_new_label();
4057 tcg_gen_ext32u_tl(t0, t0);
4058 tcg_gen_ext32u_tl(t1, t1);
4059 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4060 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4061 tcg_gen_br(l2);
4062 gen_set_label(l1);
4063 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4064 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
4065 gen_set_label(l2);
4067 break;
4068 #if defined(TARGET_MIPS64)
4069 case OPC_DMULT_G_2E:
4070 case OPC_DMULT_G_2F:
4071 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4072 break;
4073 case OPC_DMULTU_G_2E:
4074 case OPC_DMULTU_G_2F:
4075 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
4076 break;
4077 case OPC_DDIV_G_2E:
4078 case OPC_DDIV_G_2F:
4080 TCGLabel *l1 = gen_new_label();
4081 TCGLabel *l2 = gen_new_label();
4082 TCGLabel *l3 = gen_new_label();
4083 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4084 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4085 tcg_gen_br(l3);
4086 gen_set_label(l1);
4087 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4088 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4089 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4090 tcg_gen_br(l3);
4091 gen_set_label(l2);
4092 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
4093 gen_set_label(l3);
4095 break;
4096 case OPC_DDIVU_G_2E:
4097 case OPC_DDIVU_G_2F:
4099 TCGLabel *l1 = gen_new_label();
4100 TCGLabel *l2 = gen_new_label();
4101 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4102 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4103 tcg_gen_br(l2);
4104 gen_set_label(l1);
4105 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
4106 gen_set_label(l2);
4108 break;
4109 case OPC_DMOD_G_2E:
4110 case OPC_DMOD_G_2F:
4112 TCGLabel *l1 = gen_new_label();
4113 TCGLabel *l2 = gen_new_label();
4114 TCGLabel *l3 = gen_new_label();
4115 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4116 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
4117 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
4118 gen_set_label(l1);
4119 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4120 tcg_gen_br(l3);
4121 gen_set_label(l2);
4122 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
4123 gen_set_label(l3);
4125 break;
4126 case OPC_DMODU_G_2E:
4127 case OPC_DMODU_G_2F:
4129 TCGLabel *l1 = gen_new_label();
4130 TCGLabel *l2 = gen_new_label();
4131 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
4132 tcg_gen_movi_tl(cpu_gpr[rd], 0);
4133 tcg_gen_br(l2);
4134 gen_set_label(l1);
4135 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
4136 gen_set_label(l2);
4138 break;
4139 #endif
4142 tcg_temp_free(t0);
4143 tcg_temp_free(t1);
4146 /* Loongson multimedia instructions */
4147 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
4149 uint32_t opc, shift_max;
4150 TCGv_i64 t0, t1;
4151 TCGCond cond;
4153 opc = MASK_LMMI(ctx->opcode);
4154 switch (opc) {
4155 case OPC_ADD_CP2:
4156 case OPC_SUB_CP2:
4157 case OPC_DADD_CP2:
4158 case OPC_DSUB_CP2:
4159 t0 = tcg_temp_local_new_i64();
4160 t1 = tcg_temp_local_new_i64();
4161 break;
4162 default:
4163 t0 = tcg_temp_new_i64();
4164 t1 = tcg_temp_new_i64();
4165 break;
4168 check_cp1_enabled(ctx);
4169 gen_load_fpr64(ctx, t0, rs);
4170 gen_load_fpr64(ctx, t1, rt);
4172 switch (opc) {
4173 case OPC_PADDSH:
4174 gen_helper_paddsh(t0, t0, t1);
4175 break;
4176 case OPC_PADDUSH:
4177 gen_helper_paddush(t0, t0, t1);
4178 break;
4179 case OPC_PADDH:
4180 gen_helper_paddh(t0, t0, t1);
4181 break;
4182 case OPC_PADDW:
4183 gen_helper_paddw(t0, t0, t1);
4184 break;
4185 case OPC_PADDSB:
4186 gen_helper_paddsb(t0, t0, t1);
4187 break;
4188 case OPC_PADDUSB:
4189 gen_helper_paddusb(t0, t0, t1);
4190 break;
4191 case OPC_PADDB:
4192 gen_helper_paddb(t0, t0, t1);
4193 break;
4195 case OPC_PSUBSH:
4196 gen_helper_psubsh(t0, t0, t1);
4197 break;
4198 case OPC_PSUBUSH:
4199 gen_helper_psubush(t0, t0, t1);
4200 break;
4201 case OPC_PSUBH:
4202 gen_helper_psubh(t0, t0, t1);
4203 break;
4204 case OPC_PSUBW:
4205 gen_helper_psubw(t0, t0, t1);
4206 break;
4207 case OPC_PSUBSB:
4208 gen_helper_psubsb(t0, t0, t1);
4209 break;
4210 case OPC_PSUBUSB:
4211 gen_helper_psubusb(t0, t0, t1);
4212 break;
4213 case OPC_PSUBB:
4214 gen_helper_psubb(t0, t0, t1);
4215 break;
4217 case OPC_PSHUFH:
4218 gen_helper_pshufh(t0, t0, t1);
4219 break;
4220 case OPC_PACKSSWH:
4221 gen_helper_packsswh(t0, t0, t1);
4222 break;
4223 case OPC_PACKSSHB:
4224 gen_helper_packsshb(t0, t0, t1);
4225 break;
4226 case OPC_PACKUSHB:
4227 gen_helper_packushb(t0, t0, t1);
4228 break;
4230 case OPC_PUNPCKLHW:
4231 gen_helper_punpcklhw(t0, t0, t1);
4232 break;
4233 case OPC_PUNPCKHHW:
4234 gen_helper_punpckhhw(t0, t0, t1);
4235 break;
4236 case OPC_PUNPCKLBH:
4237 gen_helper_punpcklbh(t0, t0, t1);
4238 break;
4239 case OPC_PUNPCKHBH:
4240 gen_helper_punpckhbh(t0, t0, t1);
4241 break;
4242 case OPC_PUNPCKLWD:
4243 gen_helper_punpcklwd(t0, t0, t1);
4244 break;
4245 case OPC_PUNPCKHWD:
4246 gen_helper_punpckhwd(t0, t0, t1);
4247 break;
4249 case OPC_PAVGH:
4250 gen_helper_pavgh(t0, t0, t1);
4251 break;
4252 case OPC_PAVGB:
4253 gen_helper_pavgb(t0, t0, t1);
4254 break;
4255 case OPC_PMAXSH:
4256 gen_helper_pmaxsh(t0, t0, t1);
4257 break;
4258 case OPC_PMINSH:
4259 gen_helper_pminsh(t0, t0, t1);
4260 break;
4261 case OPC_PMAXUB:
4262 gen_helper_pmaxub(t0, t0, t1);
4263 break;
4264 case OPC_PMINUB:
4265 gen_helper_pminub(t0, t0, t1);
4266 break;
4268 case OPC_PCMPEQW:
4269 gen_helper_pcmpeqw(t0, t0, t1);
4270 break;
4271 case OPC_PCMPGTW:
4272 gen_helper_pcmpgtw(t0, t0, t1);
4273 break;
4274 case OPC_PCMPEQH:
4275 gen_helper_pcmpeqh(t0, t0, t1);
4276 break;
4277 case OPC_PCMPGTH:
4278 gen_helper_pcmpgth(t0, t0, t1);
4279 break;
4280 case OPC_PCMPEQB:
4281 gen_helper_pcmpeqb(t0, t0, t1);
4282 break;
4283 case OPC_PCMPGTB:
4284 gen_helper_pcmpgtb(t0, t0, t1);
4285 break;
4287 case OPC_PSLLW:
4288 gen_helper_psllw(t0, t0, t1);
4289 break;
4290 case OPC_PSLLH:
4291 gen_helper_psllh(t0, t0, t1);
4292 break;
4293 case OPC_PSRLW:
4294 gen_helper_psrlw(t0, t0, t1);
4295 break;
4296 case OPC_PSRLH:
4297 gen_helper_psrlh(t0, t0, t1);
4298 break;
4299 case OPC_PSRAW:
4300 gen_helper_psraw(t0, t0, t1);
4301 break;
4302 case OPC_PSRAH:
4303 gen_helper_psrah(t0, t0, t1);
4304 break;
4306 case OPC_PMULLH:
4307 gen_helper_pmullh(t0, t0, t1);
4308 break;
4309 case OPC_PMULHH:
4310 gen_helper_pmulhh(t0, t0, t1);
4311 break;
4312 case OPC_PMULHUH:
4313 gen_helper_pmulhuh(t0, t0, t1);
4314 break;
4315 case OPC_PMADDHW:
4316 gen_helper_pmaddhw(t0, t0, t1);
4317 break;
4319 case OPC_PASUBUB:
4320 gen_helper_pasubub(t0, t0, t1);
4321 break;
4322 case OPC_BIADD:
4323 gen_helper_biadd(t0, t0);
4324 break;
4325 case OPC_PMOVMSKB:
4326 gen_helper_pmovmskb(t0, t0);
4327 break;
4329 case OPC_PADDD:
4330 tcg_gen_add_i64(t0, t0, t1);
4331 break;
4332 case OPC_PSUBD:
4333 tcg_gen_sub_i64(t0, t0, t1);
4334 break;
4335 case OPC_XOR_CP2:
4336 tcg_gen_xor_i64(t0, t0, t1);
4337 break;
4338 case OPC_NOR_CP2:
4339 tcg_gen_nor_i64(t0, t0, t1);
4340 break;
4341 case OPC_AND_CP2:
4342 tcg_gen_and_i64(t0, t0, t1);
4343 break;
4344 case OPC_OR_CP2:
4345 tcg_gen_or_i64(t0, t0, t1);
4346 break;
4348 case OPC_PANDN:
4349 tcg_gen_andc_i64(t0, t1, t0);
4350 break;
4352 case OPC_PINSRH_0:
4353 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
4354 break;
4355 case OPC_PINSRH_1:
4356 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
4357 break;
4358 case OPC_PINSRH_2:
4359 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
4360 break;
4361 case OPC_PINSRH_3:
4362 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
4363 break;
4365 case OPC_PEXTRH:
4366 tcg_gen_andi_i64(t1, t1, 3);
4367 tcg_gen_shli_i64(t1, t1, 4);
4368 tcg_gen_shr_i64(t0, t0, t1);
4369 tcg_gen_ext16u_i64(t0, t0);
4370 break;
4372 case OPC_ADDU_CP2:
4373 tcg_gen_add_i64(t0, t0, t1);
4374 tcg_gen_ext32s_i64(t0, t0);
4375 break;
4376 case OPC_SUBU_CP2:
4377 tcg_gen_sub_i64(t0, t0, t1);
4378 tcg_gen_ext32s_i64(t0, t0);
4379 break;
4381 case OPC_SLL_CP2:
4382 shift_max = 32;
4383 goto do_shift;
4384 case OPC_SRL_CP2:
4385 shift_max = 32;
4386 goto do_shift;
4387 case OPC_SRA_CP2:
4388 shift_max = 32;
4389 goto do_shift;
4390 case OPC_DSLL_CP2:
4391 shift_max = 64;
4392 goto do_shift;
4393 case OPC_DSRL_CP2:
4394 shift_max = 64;
4395 goto do_shift;
4396 case OPC_DSRA_CP2:
4397 shift_max = 64;
4398 goto do_shift;
4399 do_shift:
4400 /* Make sure shift count isn't TCG undefined behaviour. */
4401 tcg_gen_andi_i64(t1, t1, shift_max - 1);
4403 switch (opc) {
4404 case OPC_SLL_CP2:
4405 case OPC_DSLL_CP2:
4406 tcg_gen_shl_i64(t0, t0, t1);
4407 break;
4408 case OPC_SRA_CP2:
4409 case OPC_DSRA_CP2:
4411 * Since SRA is UndefinedResult without sign-extended inputs,
4412 * we can treat SRA and DSRA the same.
4414 tcg_gen_sar_i64(t0, t0, t1);
4415 break;
4416 case OPC_SRL_CP2:
4417 /* We want to shift in zeros for SRL; zero-extend first. */
4418 tcg_gen_ext32u_i64(t0, t0);
4419 /* FALLTHRU */
4420 case OPC_DSRL_CP2:
4421 tcg_gen_shr_i64(t0, t0, t1);
4422 break;
4425 if (shift_max == 32) {
4426 tcg_gen_ext32s_i64(t0, t0);
4429 /* Shifts larger than MAX produce zero. */
4430 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
4431 tcg_gen_neg_i64(t1, t1);
4432 tcg_gen_and_i64(t0, t0, t1);
4433 break;
4435 case OPC_ADD_CP2:
4436 case OPC_DADD_CP2:
4438 TCGv_i64 t2 = tcg_temp_new_i64();
4439 TCGLabel *lab = gen_new_label();
4441 tcg_gen_mov_i64(t2, t0);
4442 tcg_gen_add_i64(t0, t1, t2);
4443 if (opc == OPC_ADD_CP2) {
4444 tcg_gen_ext32s_i64(t0, t0);
4446 tcg_gen_xor_i64(t1, t1, t2);
4447 tcg_gen_xor_i64(t2, t2, t0);
4448 tcg_gen_andc_i64(t1, t2, t1);
4449 tcg_temp_free_i64(t2);
4450 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4451 generate_exception(ctx, EXCP_OVERFLOW);
4452 gen_set_label(lab);
4453 break;
4456 case OPC_SUB_CP2:
4457 case OPC_DSUB_CP2:
4459 TCGv_i64 t2 = tcg_temp_new_i64();
4460 TCGLabel *lab = gen_new_label();
4462 tcg_gen_mov_i64(t2, t0);
4463 tcg_gen_sub_i64(t0, t1, t2);
4464 if (opc == OPC_SUB_CP2) {
4465 tcg_gen_ext32s_i64(t0, t0);
4467 tcg_gen_xor_i64(t1, t1, t2);
4468 tcg_gen_xor_i64(t2, t2, t0);
4469 tcg_gen_and_i64(t1, t1, t2);
4470 tcg_temp_free_i64(t2);
4471 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
4472 generate_exception(ctx, EXCP_OVERFLOW);
4473 gen_set_label(lab);
4474 break;
4477 case OPC_PMULUW:
4478 tcg_gen_ext32u_i64(t0, t0);
4479 tcg_gen_ext32u_i64(t1, t1);
4480 tcg_gen_mul_i64(t0, t0, t1);
4481 break;
4483 case OPC_SEQU_CP2:
4484 case OPC_SEQ_CP2:
4485 cond = TCG_COND_EQ;
4486 goto do_cc_cond;
4487 break;
4488 case OPC_SLTU_CP2:
4489 cond = TCG_COND_LTU;
4490 goto do_cc_cond;
4491 break;
4492 case OPC_SLT_CP2:
4493 cond = TCG_COND_LT;
4494 goto do_cc_cond;
4495 break;
4496 case OPC_SLEU_CP2:
4497 cond = TCG_COND_LEU;
4498 goto do_cc_cond;
4499 break;
4500 case OPC_SLE_CP2:
4501 cond = TCG_COND_LE;
4502 do_cc_cond:
4504 int cc = (ctx->opcode >> 8) & 0x7;
4505 TCGv_i64 t64 = tcg_temp_new_i64();
4506 TCGv_i32 t32 = tcg_temp_new_i32();
4508 tcg_gen_setcond_i64(cond, t64, t0, t1);
4509 tcg_gen_extrl_i64_i32(t32, t64);
4510 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
4511 get_fp_bit(cc), 1);
4513 tcg_temp_free_i32(t32);
4514 tcg_temp_free_i64(t64);
4516 goto no_rd;
4517 break;
4518 default:
4519 MIPS_INVAL("loongson_cp2");
4520 gen_reserved_instruction(ctx);
4521 return;
4524 gen_store_fpr64(ctx, t0, rd);
4526 no_rd:
4527 tcg_temp_free_i64(t0);
4528 tcg_temp_free_i64(t1);
4531 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
4532 int rs, int rd)
4534 TCGv t0, t1, t2;
4535 TCGv_i32 fp0;
4536 #if defined(TARGET_MIPS64)
4537 int lsq_rt1 = ctx->opcode & 0x1f;
4538 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
4539 #endif
4540 int shf_offset = sextract32(ctx->opcode, 6, 8);
4542 t0 = tcg_temp_new();
4544 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
4545 #if defined(TARGET_MIPS64)
4546 case OPC_GSLQ:
4547 t1 = tcg_temp_new();
4548 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4549 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4550 ctx->default_tcg_memop_mask);
4551 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4552 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4553 ctx->default_tcg_memop_mask);
4554 gen_store_gpr(t1, rt);
4555 gen_store_gpr(t0, lsq_rt1);
4556 tcg_temp_free(t1);
4557 break;
4558 case OPC_GSLQC1:
4559 check_cp1_enabled(ctx);
4560 t1 = tcg_temp_new();
4561 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4562 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4563 ctx->default_tcg_memop_mask);
4564 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4565 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4566 ctx->default_tcg_memop_mask);
4567 gen_store_fpr64(ctx, t1, rt);
4568 gen_store_fpr64(ctx, t0, lsq_rt1);
4569 tcg_temp_free(t1);
4570 break;
4571 case OPC_GSSQ:
4572 t1 = tcg_temp_new();
4573 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4574 gen_load_gpr(t1, rt);
4575 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4576 ctx->default_tcg_memop_mask);
4577 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4578 gen_load_gpr(t1, lsq_rt1);
4579 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4580 ctx->default_tcg_memop_mask);
4581 tcg_temp_free(t1);
4582 break;
4583 case OPC_GSSQC1:
4584 check_cp1_enabled(ctx);
4585 t1 = tcg_temp_new();
4586 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
4587 gen_load_fpr64(ctx, t1, rt);
4588 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4589 ctx->default_tcg_memop_mask);
4590 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
4591 gen_load_fpr64(ctx, t1, lsq_rt1);
4592 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4593 ctx->default_tcg_memop_mask);
4594 tcg_temp_free(t1);
4595 break;
4596 #endif
4597 case OPC_GSSHFL:
4598 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4599 case OPC_GSLWLC1:
4600 check_cp1_enabled(ctx);
4601 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4602 t1 = tcg_temp_new();
4603 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4604 tcg_gen_andi_tl(t1, t0, 3);
4605 #ifndef TARGET_WORDS_BIGENDIAN
4606 tcg_gen_xori_tl(t1, t1, 3);
4607 #endif
4608 tcg_gen_shli_tl(t1, t1, 3);
4609 tcg_gen_andi_tl(t0, t0, ~3);
4610 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4611 tcg_gen_shl_tl(t0, t0, t1);
4612 t2 = tcg_const_tl(-1);
4613 tcg_gen_shl_tl(t2, t2, t1);
4614 fp0 = tcg_temp_new_i32();
4615 gen_load_fpr32(ctx, fp0, rt);
4616 tcg_gen_ext_i32_tl(t1, fp0);
4617 tcg_gen_andc_tl(t1, t1, t2);
4618 tcg_temp_free(t2);
4619 tcg_gen_or_tl(t0, t0, t1);
4620 tcg_temp_free(t1);
4621 #if defined(TARGET_MIPS64)
4622 tcg_gen_extrl_i64_i32(fp0, t0);
4623 #else
4624 tcg_gen_ext32s_tl(fp0, t0);
4625 #endif
4626 gen_store_fpr32(ctx, fp0, rt);
4627 tcg_temp_free_i32(fp0);
4628 break;
4629 case OPC_GSLWRC1:
4630 check_cp1_enabled(ctx);
4631 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4632 t1 = tcg_temp_new();
4633 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4634 tcg_gen_andi_tl(t1, t0, 3);
4635 #ifdef TARGET_WORDS_BIGENDIAN
4636 tcg_gen_xori_tl(t1, t1, 3);
4637 #endif
4638 tcg_gen_shli_tl(t1, t1, 3);
4639 tcg_gen_andi_tl(t0, t0, ~3);
4640 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
4641 tcg_gen_shr_tl(t0, t0, t1);
4642 tcg_gen_xori_tl(t1, t1, 31);
4643 t2 = tcg_const_tl(0xfffffffeull);
4644 tcg_gen_shl_tl(t2, t2, t1);
4645 fp0 = tcg_temp_new_i32();
4646 gen_load_fpr32(ctx, fp0, rt);
4647 tcg_gen_ext_i32_tl(t1, fp0);
4648 tcg_gen_and_tl(t1, t1, t2);
4649 tcg_temp_free(t2);
4650 tcg_gen_or_tl(t0, t0, t1);
4651 tcg_temp_free(t1);
4652 #if defined(TARGET_MIPS64)
4653 tcg_gen_extrl_i64_i32(fp0, t0);
4654 #else
4655 tcg_gen_ext32s_tl(fp0, t0);
4656 #endif
4657 gen_store_fpr32(ctx, fp0, rt);
4658 tcg_temp_free_i32(fp0);
4659 break;
4660 #if defined(TARGET_MIPS64)
4661 case OPC_GSLDLC1:
4662 check_cp1_enabled(ctx);
4663 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4664 t1 = tcg_temp_new();
4665 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4666 tcg_gen_andi_tl(t1, t0, 7);
4667 #ifndef TARGET_WORDS_BIGENDIAN
4668 tcg_gen_xori_tl(t1, t1, 7);
4669 #endif
4670 tcg_gen_shli_tl(t1, t1, 3);
4671 tcg_gen_andi_tl(t0, t0, ~7);
4672 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4673 tcg_gen_shl_tl(t0, t0, t1);
4674 t2 = tcg_const_tl(-1);
4675 tcg_gen_shl_tl(t2, t2, t1);
4676 gen_load_fpr64(ctx, t1, rt);
4677 tcg_gen_andc_tl(t1, t1, t2);
4678 tcg_temp_free(t2);
4679 tcg_gen_or_tl(t0, t0, t1);
4680 tcg_temp_free(t1);
4681 gen_store_fpr64(ctx, t0, rt);
4682 break;
4683 case OPC_GSLDRC1:
4684 check_cp1_enabled(ctx);
4685 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4686 t1 = tcg_temp_new();
4687 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_UB);
4688 tcg_gen_andi_tl(t1, t0, 7);
4689 #ifdef TARGET_WORDS_BIGENDIAN
4690 tcg_gen_xori_tl(t1, t1, 7);
4691 #endif
4692 tcg_gen_shli_tl(t1, t1, 3);
4693 tcg_gen_andi_tl(t0, t0, ~7);
4694 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
4695 tcg_gen_shr_tl(t0, t0, t1);
4696 tcg_gen_xori_tl(t1, t1, 63);
4697 t2 = tcg_const_tl(0xfffffffffffffffeull);
4698 tcg_gen_shl_tl(t2, t2, t1);
4699 gen_load_fpr64(ctx, t1, rt);
4700 tcg_gen_and_tl(t1, t1, t2);
4701 tcg_temp_free(t2);
4702 tcg_gen_or_tl(t0, t0, t1);
4703 tcg_temp_free(t1);
4704 gen_store_fpr64(ctx, t0, rt);
4705 break;
4706 #endif
4707 default:
4708 MIPS_INVAL("loongson_gsshfl");
4709 gen_reserved_instruction(ctx);
4710 break;
4712 break;
4713 case OPC_GSSHFS:
4714 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4715 case OPC_GSSWLC1:
4716 check_cp1_enabled(ctx);
4717 t1 = tcg_temp_new();
4718 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4719 fp0 = tcg_temp_new_i32();
4720 gen_load_fpr32(ctx, fp0, rt);
4721 tcg_gen_ext_i32_tl(t1, fp0);
4722 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4723 tcg_temp_free_i32(fp0);
4724 tcg_temp_free(t1);
4725 break;
4726 case OPC_GSSWRC1:
4727 check_cp1_enabled(ctx);
4728 t1 = tcg_temp_new();
4729 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4730 fp0 = tcg_temp_new_i32();
4731 gen_load_fpr32(ctx, fp0, rt);
4732 tcg_gen_ext_i32_tl(t1, fp0);
4733 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4734 tcg_temp_free_i32(fp0);
4735 tcg_temp_free(t1);
4736 break;
4737 #if defined(TARGET_MIPS64)
4738 case OPC_GSSDLC1:
4739 check_cp1_enabled(ctx);
4740 t1 = tcg_temp_new();
4741 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4742 gen_load_fpr64(ctx, t1, rt);
4743 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4744 tcg_temp_free(t1);
4745 break;
4746 case OPC_GSSDRC1:
4747 check_cp1_enabled(ctx);
4748 t1 = tcg_temp_new();
4749 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4750 gen_load_fpr64(ctx, t1, rt);
4751 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4752 tcg_temp_free(t1);
4753 break;
4754 #endif
4755 default:
4756 MIPS_INVAL("loongson_gsshfs");
4757 gen_reserved_instruction(ctx);
4758 break;
4760 break;
4761 default:
4762 MIPS_INVAL("loongson_gslsq");
4763 gen_reserved_instruction(ctx);
4764 break;
4766 tcg_temp_free(t0);
4769 /* Loongson EXT LDC2/SDC2 */
4770 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4771 int rs, int rd)
4773 int offset = sextract32(ctx->opcode, 3, 8);
4774 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4775 TCGv t0, t1;
4776 TCGv_i32 fp0;
4778 /* Pre-conditions */
4779 switch (opc) {
4780 case OPC_GSLBX:
4781 case OPC_GSLHX:
4782 case OPC_GSLWX:
4783 case OPC_GSLDX:
4784 /* prefetch, implement as NOP */
4785 if (rt == 0) {
4786 return;
4788 break;
4789 case OPC_GSSBX:
4790 case OPC_GSSHX:
4791 case OPC_GSSWX:
4792 case OPC_GSSDX:
4793 break;
4794 case OPC_GSLWXC1:
4795 #if defined(TARGET_MIPS64)
4796 case OPC_GSLDXC1:
4797 #endif
4798 check_cp1_enabled(ctx);
4799 /* prefetch, implement as NOP */
4800 if (rt == 0) {
4801 return;
4803 break;
4804 case OPC_GSSWXC1:
4805 #if defined(TARGET_MIPS64)
4806 case OPC_GSSDXC1:
4807 #endif
4808 check_cp1_enabled(ctx);
4809 break;
4810 default:
4811 MIPS_INVAL("loongson_lsdc2");
4812 gen_reserved_instruction(ctx);
4813 return;
4814 break;
4817 t0 = tcg_temp_new();
4819 gen_base_offset_addr(ctx, t0, rs, offset);
4820 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4822 switch (opc) {
4823 case OPC_GSLBX:
4824 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4825 gen_store_gpr(t0, rt);
4826 break;
4827 case OPC_GSLHX:
4828 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
4829 ctx->default_tcg_memop_mask);
4830 gen_store_gpr(t0, rt);
4831 break;
4832 case OPC_GSLWX:
4833 gen_base_offset_addr(ctx, t0, rs, offset);
4834 if (rd) {
4835 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4837 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL |
4838 ctx->default_tcg_memop_mask);
4839 gen_store_gpr(t0, rt);
4840 break;
4841 #if defined(TARGET_MIPS64)
4842 case OPC_GSLDX:
4843 gen_base_offset_addr(ctx, t0, rs, offset);
4844 if (rd) {
4845 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4847 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4848 ctx->default_tcg_memop_mask);
4849 gen_store_gpr(t0, rt);
4850 break;
4851 #endif
4852 case OPC_GSLWXC1:
4853 check_cp1_enabled(ctx);
4854 gen_base_offset_addr(ctx, t0, rs, offset);
4855 if (rd) {
4856 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4858 fp0 = tcg_temp_new_i32();
4859 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL |
4860 ctx->default_tcg_memop_mask);
4861 gen_store_fpr32(ctx, fp0, rt);
4862 tcg_temp_free_i32(fp0);
4863 break;
4864 #if defined(TARGET_MIPS64)
4865 case OPC_GSLDXC1:
4866 check_cp1_enabled(ctx);
4867 gen_base_offset_addr(ctx, t0, rs, offset);
4868 if (rd) {
4869 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4871 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ |
4872 ctx->default_tcg_memop_mask);
4873 gen_store_fpr64(ctx, t0, rt);
4874 break;
4875 #endif
4876 case OPC_GSSBX:
4877 t1 = tcg_temp_new();
4878 gen_load_gpr(t1, rt);
4879 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4880 tcg_temp_free(t1);
4881 break;
4882 case OPC_GSSHX:
4883 t1 = tcg_temp_new();
4884 gen_load_gpr(t1, rt);
4885 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
4886 ctx->default_tcg_memop_mask);
4887 tcg_temp_free(t1);
4888 break;
4889 case OPC_GSSWX:
4890 t1 = tcg_temp_new();
4891 gen_load_gpr(t1, rt);
4892 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL |
4893 ctx->default_tcg_memop_mask);
4894 tcg_temp_free(t1);
4895 break;
4896 #if defined(TARGET_MIPS64)
4897 case OPC_GSSDX:
4898 t1 = tcg_temp_new();
4899 gen_load_gpr(t1, rt);
4900 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ |
4901 ctx->default_tcg_memop_mask);
4902 tcg_temp_free(t1);
4903 break;
4904 #endif
4905 case OPC_GSSWXC1:
4906 fp0 = tcg_temp_new_i32();
4907 gen_load_fpr32(ctx, fp0, rt);
4908 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL |
4909 ctx->default_tcg_memop_mask);
4910 tcg_temp_free_i32(fp0);
4911 break;
4912 #if defined(TARGET_MIPS64)
4913 case OPC_GSSDXC1:
4914 t1 = tcg_temp_new();
4915 gen_load_fpr64(ctx, t1, rt);
4916 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, MO_TEQ |
4917 ctx->default_tcg_memop_mask);
4918 tcg_temp_free(t1);
4919 break;
4920 #endif
4921 default:
4922 break;
4925 tcg_temp_free(t0);
4928 /* Traps */
4929 static void gen_trap(DisasContext *ctx, uint32_t opc,
4930 int rs, int rt, int16_t imm)
4932 int cond;
4933 TCGv t0 = tcg_temp_new();
4934 TCGv t1 = tcg_temp_new();
4936 cond = 0;
4937 /* Load needed operands */
4938 switch (opc) {
4939 case OPC_TEQ:
4940 case OPC_TGE:
4941 case OPC_TGEU:
4942 case OPC_TLT:
4943 case OPC_TLTU:
4944 case OPC_TNE:
4945 /* Compare two registers */
4946 if (rs != rt) {
4947 gen_load_gpr(t0, rs);
4948 gen_load_gpr(t1, rt);
4949 cond = 1;
4951 break;
4952 case OPC_TEQI:
4953 case OPC_TGEI:
4954 case OPC_TGEIU:
4955 case OPC_TLTI:
4956 case OPC_TLTIU:
4957 case OPC_TNEI:
4958 /* Compare register to immediate */
4959 if (rs != 0 || imm != 0) {
4960 gen_load_gpr(t0, rs);
4961 tcg_gen_movi_tl(t1, (int32_t)imm);
4962 cond = 1;
4964 break;
4966 if (cond == 0) {
4967 switch (opc) {
4968 case OPC_TEQ: /* rs == rs */
4969 case OPC_TEQI: /* r0 == 0 */
4970 case OPC_TGE: /* rs >= rs */
4971 case OPC_TGEI: /* r0 >= 0 */
4972 case OPC_TGEU: /* rs >= rs unsigned */
4973 case OPC_TGEIU: /* r0 >= 0 unsigned */
4974 /* Always trap */
4975 generate_exception_end(ctx, EXCP_TRAP);
4976 break;
4977 case OPC_TLT: /* rs < rs */
4978 case OPC_TLTI: /* r0 < 0 */
4979 case OPC_TLTU: /* rs < rs unsigned */
4980 case OPC_TLTIU: /* r0 < 0 unsigned */
4981 case OPC_TNE: /* rs != rs */
4982 case OPC_TNEI: /* r0 != 0 */
4983 /* Never trap: treat as NOP. */
4984 break;
4986 } else {
4987 TCGLabel *l1 = gen_new_label();
4989 switch (opc) {
4990 case OPC_TEQ:
4991 case OPC_TEQI:
4992 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4993 break;
4994 case OPC_TGE:
4995 case OPC_TGEI:
4996 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4997 break;
4998 case OPC_TGEU:
4999 case OPC_TGEIU:
5000 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
5001 break;
5002 case OPC_TLT:
5003 case OPC_TLTI:
5004 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
5005 break;
5006 case OPC_TLTU:
5007 case OPC_TLTIU:
5008 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
5009 break;
5010 case OPC_TNE:
5011 case OPC_TNEI:
5012 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
5013 break;
5015 generate_exception(ctx, EXCP_TRAP);
5016 gen_set_label(l1);
5018 tcg_temp_free(t0);
5019 tcg_temp_free(t1);
5022 static inline bool use_goto_tb(DisasContext *ctx, target_ulong dest)
5024 if (unlikely(ctx->base.singlestep_enabled)) {
5025 return false;
5028 #ifndef CONFIG_USER_ONLY
5029 return (ctx->base.tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK);
5030 #else
5031 return true;
5032 #endif
5035 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
5037 if (use_goto_tb(ctx, dest)) {
5038 tcg_gen_goto_tb(n);
5039 gen_save_pc(dest);
5040 tcg_gen_exit_tb(ctx->base.tb, n);
5041 } else {
5042 gen_save_pc(dest);
5043 if (ctx->base.singlestep_enabled) {
5044 save_cpu_state(ctx, 0);
5045 gen_helper_raise_exception_debug(cpu_env);
5047 tcg_gen_lookup_and_goto_ptr();
5051 /* Branches (before delay slot) */
5052 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
5053 int insn_bytes,
5054 int rs, int rt, int32_t offset,
5055 int delayslot_size)
5057 target_ulong btgt = -1;
5058 int blink = 0;
5059 int bcond_compute = 0;
5060 TCGv t0 = tcg_temp_new();
5061 TCGv t1 = tcg_temp_new();
5063 if (ctx->hflags & MIPS_HFLAG_BMASK) {
5064 #ifdef MIPS_DEBUG_DISAS
5065 LOG_DISAS("Branch in delay / forbidden slot at PC 0x"
5066 TARGET_FMT_lx "\n", ctx->base.pc_next);
5067 #endif
5068 gen_reserved_instruction(ctx);
5069 goto out;
5072 /* Load needed operands */
5073 switch (opc) {
5074 case OPC_BEQ:
5075 case OPC_BEQL:
5076 case OPC_BNE:
5077 case OPC_BNEL:
5078 /* Compare two registers */
5079 if (rs != rt) {
5080 gen_load_gpr(t0, rs);
5081 gen_load_gpr(t1, rt);
5082 bcond_compute = 1;
5084 btgt = ctx->base.pc_next + insn_bytes + offset;
5085 break;
5086 case OPC_BGEZ:
5087 case OPC_BGEZAL:
5088 case OPC_BGEZALL:
5089 case OPC_BGEZL:
5090 case OPC_BGTZ:
5091 case OPC_BGTZL:
5092 case OPC_BLEZ:
5093 case OPC_BLEZL:
5094 case OPC_BLTZ:
5095 case OPC_BLTZAL:
5096 case OPC_BLTZALL:
5097 case OPC_BLTZL:
5098 /* Compare to zero */
5099 if (rs != 0) {
5100 gen_load_gpr(t0, rs);
5101 bcond_compute = 1;
5103 btgt = ctx->base.pc_next + insn_bytes + offset;
5104 break;
5105 case OPC_BPOSGE32:
5106 #if defined(TARGET_MIPS64)
5107 case OPC_BPOSGE64:
5108 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
5109 #else
5110 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5111 #endif
5112 bcond_compute = 1;
5113 btgt = ctx->base.pc_next + insn_bytes + offset;
5114 break;
5115 case OPC_J:
5116 case OPC_JAL:
5117 case OPC_JALX:
5118 /* Jump to immediate */
5119 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
5120 (uint32_t)offset;
5121 break;
5122 case OPC_JR:
5123 case OPC_JALR:
5124 /* Jump to register */
5125 if (offset != 0 && offset != 16) {
5127 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5128 * others are reserved.
5130 MIPS_INVAL("jump hint");
5131 gen_reserved_instruction(ctx);
5132 goto out;
5134 gen_load_gpr(btarget, rs);
5135 break;
5136 default:
5137 MIPS_INVAL("branch/jump");
5138 gen_reserved_instruction(ctx);
5139 goto out;
5141 if (bcond_compute == 0) {
5142 /* No condition to be computed */
5143 switch (opc) {
5144 case OPC_BEQ: /* rx == rx */
5145 case OPC_BEQL: /* rx == rx likely */
5146 case OPC_BGEZ: /* 0 >= 0 */
5147 case OPC_BGEZL: /* 0 >= 0 likely */
5148 case OPC_BLEZ: /* 0 <= 0 */
5149 case OPC_BLEZL: /* 0 <= 0 likely */
5150 /* Always take */
5151 ctx->hflags |= MIPS_HFLAG_B;
5152 break;
5153 case OPC_BGEZAL: /* 0 >= 0 */
5154 case OPC_BGEZALL: /* 0 >= 0 likely */
5155 /* Always take and link */
5156 blink = 31;
5157 ctx->hflags |= MIPS_HFLAG_B;
5158 break;
5159 case OPC_BNE: /* rx != rx */
5160 case OPC_BGTZ: /* 0 > 0 */
5161 case OPC_BLTZ: /* 0 < 0 */
5162 /* Treat as NOP. */
5163 goto out;
5164 case OPC_BLTZAL: /* 0 < 0 */
5166 * Handle as an unconditional branch to get correct delay
5167 * slot checking.
5169 blink = 31;
5170 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
5171 ctx->hflags |= MIPS_HFLAG_B;
5172 break;
5173 case OPC_BLTZALL: /* 0 < 0 likely */
5174 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5175 /* Skip the instruction in the delay slot */
5176 ctx->base.pc_next += 4;
5177 goto out;
5178 case OPC_BNEL: /* rx != rx likely */
5179 case OPC_BGTZL: /* 0 > 0 likely */
5180 case OPC_BLTZL: /* 0 < 0 likely */
5181 /* Skip the instruction in the delay slot */
5182 ctx->base.pc_next += 4;
5183 goto out;
5184 case OPC_J:
5185 ctx->hflags |= MIPS_HFLAG_B;
5186 break;
5187 case OPC_JALX:
5188 ctx->hflags |= MIPS_HFLAG_BX;
5189 /* Fallthrough */
5190 case OPC_JAL:
5191 blink = 31;
5192 ctx->hflags |= MIPS_HFLAG_B;
5193 break;
5194 case OPC_JR:
5195 ctx->hflags |= MIPS_HFLAG_BR;
5196 break;
5197 case OPC_JALR:
5198 blink = rt;
5199 ctx->hflags |= MIPS_HFLAG_BR;
5200 break;
5201 default:
5202 MIPS_INVAL("branch/jump");
5203 gen_reserved_instruction(ctx);
5204 goto out;
5206 } else {
5207 switch (opc) {
5208 case OPC_BEQ:
5209 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5210 goto not_likely;
5211 case OPC_BEQL:
5212 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5213 goto likely;
5214 case OPC_BNE:
5215 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5216 goto not_likely;
5217 case OPC_BNEL:
5218 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5219 goto likely;
5220 case OPC_BGEZ:
5221 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5222 goto not_likely;
5223 case OPC_BGEZL:
5224 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5225 goto likely;
5226 case OPC_BGEZAL:
5227 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5228 blink = 31;
5229 goto not_likely;
5230 case OPC_BGEZALL:
5231 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5232 blink = 31;
5233 goto likely;
5234 case OPC_BGTZ:
5235 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5236 goto not_likely;
5237 case OPC_BGTZL:
5238 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
5239 goto likely;
5240 case OPC_BLEZ:
5241 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5242 goto not_likely;
5243 case OPC_BLEZL:
5244 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
5245 goto likely;
5246 case OPC_BLTZ:
5247 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5248 goto not_likely;
5249 case OPC_BLTZL:
5250 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5251 goto likely;
5252 case OPC_BPOSGE32:
5253 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5254 goto not_likely;
5255 #if defined(TARGET_MIPS64)
5256 case OPC_BPOSGE64:
5257 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
5258 goto not_likely;
5259 #endif
5260 case OPC_BLTZAL:
5261 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5262 blink = 31;
5263 not_likely:
5264 ctx->hflags |= MIPS_HFLAG_BC;
5265 break;
5266 case OPC_BLTZALL:
5267 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
5268 blink = 31;
5269 likely:
5270 ctx->hflags |= MIPS_HFLAG_BL;
5271 break;
5272 default:
5273 MIPS_INVAL("conditional branch/jump");
5274 gen_reserved_instruction(ctx);
5275 goto out;
5279 ctx->btarget = btgt;
5281 switch (delayslot_size) {
5282 case 2:
5283 ctx->hflags |= MIPS_HFLAG_BDS16;
5284 break;
5285 case 4:
5286 ctx->hflags |= MIPS_HFLAG_BDS32;
5287 break;
5290 if (blink > 0) {
5291 int post_delay = insn_bytes + delayslot_size;
5292 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
5294 tcg_gen_movi_tl(cpu_gpr[blink],
5295 ctx->base.pc_next + post_delay + lowbit);
5298 out:
5299 if (insn_bytes == 2) {
5300 ctx->hflags |= MIPS_HFLAG_B16;
5302 tcg_temp_free(t0);
5303 tcg_temp_free(t1);
5307 /* nanoMIPS Branches */
5308 static void gen_compute_branch_nm(DisasContext *ctx, uint32_t opc,
5309 int insn_bytes,
5310 int rs, int rt, int32_t offset)
5312 target_ulong btgt = -1;
5313 int bcond_compute = 0;
5314 TCGv t0 = tcg_temp_new();
5315 TCGv t1 = tcg_temp_new();
5317 /* Load needed operands */
5318 switch (opc) {
5319 case OPC_BEQ:
5320 case OPC_BNE:
5321 /* Compare two registers */
5322 if (rs != rt) {
5323 gen_load_gpr(t0, rs);
5324 gen_load_gpr(t1, rt);
5325 bcond_compute = 1;
5327 btgt = ctx->base.pc_next + insn_bytes + offset;
5328 break;
5329 case OPC_BGEZAL:
5330 /* Compare to zero */
5331 if (rs != 0) {
5332 gen_load_gpr(t0, rs);
5333 bcond_compute = 1;
5335 btgt = ctx->base.pc_next + insn_bytes + offset;
5336 break;
5337 case OPC_BPOSGE32:
5338 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
5339 bcond_compute = 1;
5340 btgt = ctx->base.pc_next + insn_bytes + offset;
5341 break;
5342 case OPC_JR:
5343 case OPC_JALR:
5344 /* Jump to register */
5345 if (offset != 0 && offset != 16) {
5347 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
5348 * others are reserved.
5350 MIPS_INVAL("jump hint");
5351 gen_reserved_instruction(ctx);
5352 goto out;
5354 gen_load_gpr(btarget, rs);
5355 break;
5356 default:
5357 MIPS_INVAL("branch/jump");
5358 gen_reserved_instruction(ctx);
5359 goto out;
5361 if (bcond_compute == 0) {
5362 /* No condition to be computed */
5363 switch (opc) {
5364 case OPC_BEQ: /* rx == rx */
5365 /* Always take */
5366 ctx->hflags |= MIPS_HFLAG_B;
5367 break;
5368 case OPC_BGEZAL: /* 0 >= 0 */
5369 /* Always take and link */
5370 tcg_gen_movi_tl(cpu_gpr[31],
5371 ctx->base.pc_next + insn_bytes);
5372 ctx->hflags |= MIPS_HFLAG_B;
5373 break;
5374 case OPC_BNE: /* rx != rx */
5375 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
5376 /* Skip the instruction in the delay slot */
5377 ctx->base.pc_next += 4;
5378 goto out;
5379 case OPC_JR:
5380 ctx->hflags |= MIPS_HFLAG_BR;
5381 break;
5382 case OPC_JALR:
5383 if (rt > 0) {
5384 tcg_gen_movi_tl(cpu_gpr[rt],
5385 ctx->base.pc_next + insn_bytes);
5387 ctx->hflags |= MIPS_HFLAG_BR;
5388 break;
5389 default:
5390 MIPS_INVAL("branch/jump");
5391 gen_reserved_instruction(ctx);
5392 goto out;
5394 } else {
5395 switch (opc) {
5396 case OPC_BEQ:
5397 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
5398 goto not_likely;
5399 case OPC_BNE:
5400 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
5401 goto not_likely;
5402 case OPC_BGEZAL:
5403 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
5404 tcg_gen_movi_tl(cpu_gpr[31],
5405 ctx->base.pc_next + insn_bytes);
5406 goto not_likely;
5407 case OPC_BPOSGE32:
5408 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
5409 not_likely:
5410 ctx->hflags |= MIPS_HFLAG_BC;
5411 break;
5412 default:
5413 MIPS_INVAL("conditional branch/jump");
5414 gen_reserved_instruction(ctx);
5415 goto out;
5419 ctx->btarget = btgt;
5421 out:
5422 if (insn_bytes == 2) {
5423 ctx->hflags |= MIPS_HFLAG_B16;
5425 tcg_temp_free(t0);
5426 tcg_temp_free(t1);
5430 /* special3 bitfield operations */
5431 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
5432 int rs, int lsb, int msb)
5434 TCGv t0 = tcg_temp_new();
5435 TCGv t1 = tcg_temp_new();
5437 gen_load_gpr(t1, rs);
5438 switch (opc) {
5439 case OPC_EXT:
5440 if (lsb + msb > 31) {
5441 goto fail;
5443 if (msb != 31) {
5444 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5445 } else {
5447 * The two checks together imply that lsb == 0,
5448 * so this is a simple sign-extension.
5450 tcg_gen_ext32s_tl(t0, t1);
5452 break;
5453 #if defined(TARGET_MIPS64)
5454 case OPC_DEXTU:
5455 lsb += 32;
5456 goto do_dext;
5457 case OPC_DEXTM:
5458 msb += 32;
5459 goto do_dext;
5460 case OPC_DEXT:
5461 do_dext:
5462 if (lsb + msb > 63) {
5463 goto fail;
5465 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
5466 break;
5467 #endif
5468 case OPC_INS:
5469 if (lsb > msb) {
5470 goto fail;
5472 gen_load_gpr(t0, rt);
5473 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5474 tcg_gen_ext32s_tl(t0, t0);
5475 break;
5476 #if defined(TARGET_MIPS64)
5477 case OPC_DINSU:
5478 lsb += 32;
5479 /* FALLTHRU */
5480 case OPC_DINSM:
5481 msb += 32;
5482 /* FALLTHRU */
5483 case OPC_DINS:
5484 if (lsb > msb) {
5485 goto fail;
5487 gen_load_gpr(t0, rt);
5488 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
5489 break;
5490 #endif
5491 default:
5492 fail:
5493 MIPS_INVAL("bitops");
5494 gen_reserved_instruction(ctx);
5495 tcg_temp_free(t0);
5496 tcg_temp_free(t1);
5497 return;
5499 gen_store_gpr(t0, rt);
5500 tcg_temp_free(t0);
5501 tcg_temp_free(t1);
5504 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
5506 TCGv t0;
5508 if (rd == 0) {
5509 /* If no destination, treat it as a NOP. */
5510 return;
5513 t0 = tcg_temp_new();
5514 gen_load_gpr(t0, rt);
5515 switch (op2) {
5516 case OPC_WSBH:
5518 TCGv t1 = tcg_temp_new();
5519 TCGv t2 = tcg_const_tl(0x00FF00FF);
5521 tcg_gen_shri_tl(t1, t0, 8);
5522 tcg_gen_and_tl(t1, t1, t2);
5523 tcg_gen_and_tl(t0, t0, t2);
5524 tcg_gen_shli_tl(t0, t0, 8);
5525 tcg_gen_or_tl(t0, t0, t1);
5526 tcg_temp_free(t2);
5527 tcg_temp_free(t1);
5528 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5530 break;
5531 case OPC_SEB:
5532 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
5533 break;
5534 case OPC_SEH:
5535 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
5536 break;
5537 #if defined(TARGET_MIPS64)
5538 case OPC_DSBH:
5540 TCGv t1 = tcg_temp_new();
5541 TCGv t2 = tcg_const_tl(0x00FF00FF00FF00FFULL);
5543 tcg_gen_shri_tl(t1, t0, 8);
5544 tcg_gen_and_tl(t1, t1, t2);
5545 tcg_gen_and_tl(t0, t0, t2);
5546 tcg_gen_shli_tl(t0, t0, 8);
5547 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5548 tcg_temp_free(t2);
5549 tcg_temp_free(t1);
5551 break;
5552 case OPC_DSHD:
5554 TCGv t1 = tcg_temp_new();
5555 TCGv t2 = tcg_const_tl(0x0000FFFF0000FFFFULL);
5557 tcg_gen_shri_tl(t1, t0, 16);
5558 tcg_gen_and_tl(t1, t1, t2);
5559 tcg_gen_and_tl(t0, t0, t2);
5560 tcg_gen_shli_tl(t0, t0, 16);
5561 tcg_gen_or_tl(t0, t0, t1);
5562 tcg_gen_shri_tl(t1, t0, 32);
5563 tcg_gen_shli_tl(t0, t0, 32);
5564 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
5565 tcg_temp_free(t2);
5566 tcg_temp_free(t1);
5568 break;
5569 #endif
5570 default:
5571 MIPS_INVAL("bsfhl");
5572 gen_reserved_instruction(ctx);
5573 tcg_temp_free(t0);
5574 return;
5576 tcg_temp_free(t0);
5579 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
5580 int rt, int bits)
5582 TCGv t0;
5583 if (rd == 0) {
5584 /* Treat as NOP. */
5585 return;
5587 t0 = tcg_temp_new();
5588 if (bits == 0 || bits == wordsz) {
5589 if (bits == 0) {
5590 gen_load_gpr(t0, rt);
5591 } else {
5592 gen_load_gpr(t0, rs);
5594 switch (wordsz) {
5595 case 32:
5596 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
5597 break;
5598 #if defined(TARGET_MIPS64)
5599 case 64:
5600 tcg_gen_mov_tl(cpu_gpr[rd], t0);
5601 break;
5602 #endif
5604 } else {
5605 TCGv t1 = tcg_temp_new();
5606 gen_load_gpr(t0, rt);
5607 gen_load_gpr(t1, rs);
5608 switch (wordsz) {
5609 case 32:
5611 TCGv_i64 t2 = tcg_temp_new_i64();
5612 tcg_gen_concat_tl_i64(t2, t1, t0);
5613 tcg_gen_shri_i64(t2, t2, 32 - bits);
5614 gen_move_low32(cpu_gpr[rd], t2);
5615 tcg_temp_free_i64(t2);
5617 break;
5618 #if defined(TARGET_MIPS64)
5619 case 64:
5620 tcg_gen_shli_tl(t0, t0, bits);
5621 tcg_gen_shri_tl(t1, t1, 64 - bits);
5622 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
5623 break;
5624 #endif
5626 tcg_temp_free(t1);
5629 tcg_temp_free(t0);
5632 void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp)
5634 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
5637 static void gen_ext(DisasContext *ctx, int wordsz, int rd, int rs, int rt,
5638 int shift)
5640 gen_align_bits(ctx, wordsz, rd, rs, rt, wordsz - shift);
5643 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
5645 TCGv t0;
5646 if (rd == 0) {
5647 /* Treat as NOP. */
5648 return;
5650 t0 = tcg_temp_new();
5651 gen_load_gpr(t0, rt);
5652 switch (opc) {
5653 case OPC_BITSWAP:
5654 gen_helper_bitswap(cpu_gpr[rd], t0);
5655 break;
5656 #if defined(TARGET_MIPS64)
5657 case OPC_DBITSWAP:
5658 gen_helper_dbitswap(cpu_gpr[rd], t0);
5659 break;
5660 #endif
5662 tcg_temp_free(t0);
5665 #ifndef CONFIG_USER_ONLY
5666 /* CP0 (MMU and control) */
5667 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
5669 TCGv_i64 t0 = tcg_temp_new_i64();
5670 TCGv_i64 t1 = tcg_temp_new_i64();
5672 tcg_gen_ext_tl_i64(t0, arg);
5673 tcg_gen_ld_i64(t1, cpu_env, off);
5674 #if defined(TARGET_MIPS64)
5675 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
5676 #else
5677 tcg_gen_concat32_i64(t1, t1, t0);
5678 #endif
5679 tcg_gen_st_i64(t1, cpu_env, off);
5680 tcg_temp_free_i64(t1);
5681 tcg_temp_free_i64(t0);
5684 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
5686 TCGv_i64 t0 = tcg_temp_new_i64();
5687 TCGv_i64 t1 = tcg_temp_new_i64();
5689 tcg_gen_ext_tl_i64(t0, arg);
5690 tcg_gen_ld_i64(t1, cpu_env, off);
5691 tcg_gen_concat32_i64(t1, t1, t0);
5692 tcg_gen_st_i64(t1, cpu_env, off);
5693 tcg_temp_free_i64(t1);
5694 tcg_temp_free_i64(t0);
5697 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
5699 TCGv_i64 t0 = tcg_temp_new_i64();
5701 tcg_gen_ld_i64(t0, cpu_env, off);
5702 #if defined(TARGET_MIPS64)
5703 tcg_gen_shri_i64(t0, t0, 30);
5704 #else
5705 tcg_gen_shri_i64(t0, t0, 32);
5706 #endif
5707 gen_move_low32(arg, t0);
5708 tcg_temp_free_i64(t0);
5711 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
5713 TCGv_i64 t0 = tcg_temp_new_i64();
5715 tcg_gen_ld_i64(t0, cpu_env, off);
5716 tcg_gen_shri_i64(t0, t0, 32 + shift);
5717 gen_move_low32(arg, t0);
5718 tcg_temp_free_i64(t0);
5721 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
5723 TCGv_i32 t0 = tcg_temp_new_i32();
5725 tcg_gen_ld_i32(t0, cpu_env, off);
5726 tcg_gen_ext_i32_tl(arg, t0);
5727 tcg_temp_free_i32(t0);
5730 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
5732 tcg_gen_ld_tl(arg, cpu_env, off);
5733 tcg_gen_ext32s_tl(arg, arg);
5736 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
5738 TCGv_i32 t0 = tcg_temp_new_i32();
5740 tcg_gen_trunc_tl_i32(t0, arg);
5741 tcg_gen_st_i32(t0, cpu_env, off);
5742 tcg_temp_free_i32(t0);
5745 #define CP0_CHECK(c) \
5746 do { \
5747 if (!(c)) { \
5748 goto cp0_unimplemented; \
5750 } while (0)
5752 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5754 const char *register_name = "invalid";
5756 switch (reg) {
5757 case CP0_REGISTER_02:
5758 switch (sel) {
5759 case 0:
5760 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5761 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5762 register_name = "EntryLo0";
5763 break;
5764 default:
5765 goto cp0_unimplemented;
5767 break;
5768 case CP0_REGISTER_03:
5769 switch (sel) {
5770 case CP0_REG03__ENTRYLO1:
5771 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5772 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5773 register_name = "EntryLo1";
5774 break;
5775 default:
5776 goto cp0_unimplemented;
5778 break;
5779 case CP0_REGISTER_09:
5780 switch (sel) {
5781 case CP0_REG09__SAAR:
5782 CP0_CHECK(ctx->saar);
5783 gen_helper_mfhc0_saar(arg, cpu_env);
5784 register_name = "SAAR";
5785 break;
5786 default:
5787 goto cp0_unimplemented;
5789 break;
5790 case CP0_REGISTER_17:
5791 switch (sel) {
5792 case CP0_REG17__LLADDR:
5793 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
5794 ctx->CP0_LLAddr_shift);
5795 register_name = "LLAddr";
5796 break;
5797 case CP0_REG17__MAAR:
5798 CP0_CHECK(ctx->mrp);
5799 gen_helper_mfhc0_maar(arg, cpu_env);
5800 register_name = "MAAR";
5801 break;
5802 default:
5803 goto cp0_unimplemented;
5805 break;
5806 case CP0_REGISTER_19:
5807 switch (sel) {
5808 case CP0_REG19__WATCHHI0:
5809 case CP0_REG19__WATCHHI1:
5810 case CP0_REG19__WATCHHI2:
5811 case CP0_REG19__WATCHHI3:
5812 case CP0_REG19__WATCHHI4:
5813 case CP0_REG19__WATCHHI5:
5814 case CP0_REG19__WATCHHI6:
5815 case CP0_REG19__WATCHHI7:
5816 /* upper 32 bits are only available when Config5MI != 0 */
5817 CP0_CHECK(ctx->mi);
5818 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
5819 register_name = "WatchHi";
5820 break;
5821 default:
5822 goto cp0_unimplemented;
5824 break;
5825 case CP0_REGISTER_28:
5826 switch (sel) {
5827 case 0:
5828 case 2:
5829 case 4:
5830 case 6:
5831 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
5832 register_name = "TagLo";
5833 break;
5834 default:
5835 goto cp0_unimplemented;
5837 break;
5838 default:
5839 goto cp0_unimplemented;
5841 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
5842 return;
5844 cp0_unimplemented:
5845 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
5846 register_name, reg, sel);
5847 tcg_gen_movi_tl(arg, 0);
5850 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5852 const char *register_name = "invalid";
5853 uint64_t mask = ctx->PAMask >> 36;
5855 switch (reg) {
5856 case CP0_REGISTER_02:
5857 switch (sel) {
5858 case 0:
5859 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5860 tcg_gen_andi_tl(arg, arg, mask);
5861 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5862 register_name = "EntryLo0";
5863 break;
5864 default:
5865 goto cp0_unimplemented;
5867 break;
5868 case CP0_REGISTER_03:
5869 switch (sel) {
5870 case CP0_REG03__ENTRYLO1:
5871 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5872 tcg_gen_andi_tl(arg, arg, mask);
5873 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5874 register_name = "EntryLo1";
5875 break;
5876 default:
5877 goto cp0_unimplemented;
5879 break;
5880 case CP0_REGISTER_09:
5881 switch (sel) {
5882 case CP0_REG09__SAAR:
5883 CP0_CHECK(ctx->saar);
5884 gen_helper_mthc0_saar(cpu_env, arg);
5885 register_name = "SAAR";
5886 break;
5887 default:
5888 goto cp0_unimplemented;
5890 break;
5891 case CP0_REGISTER_17:
5892 switch (sel) {
5893 case CP0_REG17__LLADDR:
5895 * LLAddr is read-only (the only exception is bit 0 if LLB is
5896 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5897 * relevant for modern MIPS cores supporting MTHC0, therefore
5898 * treating MTHC0 to LLAddr as NOP.
5900 register_name = "LLAddr";
5901 break;
5902 case CP0_REG17__MAAR:
5903 CP0_CHECK(ctx->mrp);
5904 gen_helper_mthc0_maar(cpu_env, arg);
5905 register_name = "MAAR";
5906 break;
5907 default:
5908 goto cp0_unimplemented;
5910 break;
5911 case CP0_REGISTER_19:
5912 switch (sel) {
5913 case CP0_REG19__WATCHHI0:
5914 case CP0_REG19__WATCHHI1:
5915 case CP0_REG19__WATCHHI2:
5916 case CP0_REG19__WATCHHI3:
5917 case CP0_REG19__WATCHHI4:
5918 case CP0_REG19__WATCHHI5:
5919 case CP0_REG19__WATCHHI6:
5920 case CP0_REG19__WATCHHI7:
5921 /* upper 32 bits are only available when Config5MI != 0 */
5922 CP0_CHECK(ctx->mi);
5923 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5924 register_name = "WatchHi";
5925 break;
5926 default:
5927 goto cp0_unimplemented;
5929 break;
5930 case CP0_REGISTER_28:
5931 switch (sel) {
5932 case 0:
5933 case 2:
5934 case 4:
5935 case 6:
5936 tcg_gen_andi_tl(arg, arg, mask);
5937 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5938 register_name = "TagLo";
5939 break;
5940 default:
5941 goto cp0_unimplemented;
5943 break;
5944 default:
5945 goto cp0_unimplemented;
5947 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5948 return;
5950 cp0_unimplemented:
5951 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5952 register_name, reg, sel);
5955 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5957 if (ctx->insn_flags & ISA_MIPS_R6) {
5958 tcg_gen_movi_tl(arg, 0);
5959 } else {
5960 tcg_gen_movi_tl(arg, ~0);
5964 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5966 const char *register_name = "invalid";
5968 if (sel != 0) {
5969 check_insn(ctx, ISA_MIPS_R1);
5972 switch (reg) {
5973 case CP0_REGISTER_00:
5974 switch (sel) {
5975 case CP0_REG00__INDEX:
5976 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5977 register_name = "Index";
5978 break;
5979 case CP0_REG00__MVPCONTROL:
5980 CP0_CHECK(ctx->insn_flags & ASE_MT);
5981 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5982 register_name = "MVPControl";
5983 break;
5984 case CP0_REG00__MVPCONF0:
5985 CP0_CHECK(ctx->insn_flags & ASE_MT);
5986 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5987 register_name = "MVPConf0";
5988 break;
5989 case CP0_REG00__MVPCONF1:
5990 CP0_CHECK(ctx->insn_flags & ASE_MT);
5991 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5992 register_name = "MVPConf1";
5993 break;
5994 case CP0_REG00__VPCONTROL:
5995 CP0_CHECK(ctx->vp);
5996 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5997 register_name = "VPControl";
5998 break;
5999 default:
6000 goto cp0_unimplemented;
6002 break;
6003 case CP0_REGISTER_01:
6004 switch (sel) {
6005 case CP0_REG01__RANDOM:
6006 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6007 gen_helper_mfc0_random(arg, cpu_env);
6008 register_name = "Random";
6009 break;
6010 case CP0_REG01__VPECONTROL:
6011 CP0_CHECK(ctx->insn_flags & ASE_MT);
6012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6013 register_name = "VPEControl";
6014 break;
6015 case CP0_REG01__VPECONF0:
6016 CP0_CHECK(ctx->insn_flags & ASE_MT);
6017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6018 register_name = "VPEConf0";
6019 break;
6020 case CP0_REG01__VPECONF1:
6021 CP0_CHECK(ctx->insn_flags & ASE_MT);
6022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6023 register_name = "VPEConf1";
6024 break;
6025 case CP0_REG01__YQMASK:
6026 CP0_CHECK(ctx->insn_flags & ASE_MT);
6027 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
6028 register_name = "YQMask";
6029 break;
6030 case CP0_REG01__VPESCHEDULE:
6031 CP0_CHECK(ctx->insn_flags & ASE_MT);
6032 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
6033 register_name = "VPESchedule";
6034 break;
6035 case CP0_REG01__VPESCHEFBACK:
6036 CP0_CHECK(ctx->insn_flags & ASE_MT);
6037 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6038 register_name = "VPEScheFBack";
6039 break;
6040 case CP0_REG01__VPEOPT:
6041 CP0_CHECK(ctx->insn_flags & ASE_MT);
6042 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6043 register_name = "VPEOpt";
6044 break;
6045 default:
6046 goto cp0_unimplemented;
6048 break;
6049 case CP0_REGISTER_02:
6050 switch (sel) {
6051 case CP0_REG02__ENTRYLO0:
6053 TCGv_i64 tmp = tcg_temp_new_i64();
6054 tcg_gen_ld_i64(tmp, cpu_env,
6055 offsetof(CPUMIPSState, CP0_EntryLo0));
6056 #if defined(TARGET_MIPS64)
6057 if (ctx->rxi) {
6058 /* Move RI/XI fields to bits 31:30 */
6059 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6060 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6062 #endif
6063 gen_move_low32(arg, tmp);
6064 tcg_temp_free_i64(tmp);
6066 register_name = "EntryLo0";
6067 break;
6068 case CP0_REG02__TCSTATUS:
6069 CP0_CHECK(ctx->insn_flags & ASE_MT);
6070 gen_helper_mfc0_tcstatus(arg, cpu_env);
6071 register_name = "TCStatus";
6072 break;
6073 case CP0_REG02__TCBIND:
6074 CP0_CHECK(ctx->insn_flags & ASE_MT);
6075 gen_helper_mfc0_tcbind(arg, cpu_env);
6076 register_name = "TCBind";
6077 break;
6078 case CP0_REG02__TCRESTART:
6079 CP0_CHECK(ctx->insn_flags & ASE_MT);
6080 gen_helper_mfc0_tcrestart(arg, cpu_env);
6081 register_name = "TCRestart";
6082 break;
6083 case CP0_REG02__TCHALT:
6084 CP0_CHECK(ctx->insn_flags & ASE_MT);
6085 gen_helper_mfc0_tchalt(arg, cpu_env);
6086 register_name = "TCHalt";
6087 break;
6088 case CP0_REG02__TCCONTEXT:
6089 CP0_CHECK(ctx->insn_flags & ASE_MT);
6090 gen_helper_mfc0_tccontext(arg, cpu_env);
6091 register_name = "TCContext";
6092 break;
6093 case CP0_REG02__TCSCHEDULE:
6094 CP0_CHECK(ctx->insn_flags & ASE_MT);
6095 gen_helper_mfc0_tcschedule(arg, cpu_env);
6096 register_name = "TCSchedule";
6097 break;
6098 case CP0_REG02__TCSCHEFBACK:
6099 CP0_CHECK(ctx->insn_flags & ASE_MT);
6100 gen_helper_mfc0_tcschefback(arg, cpu_env);
6101 register_name = "TCScheFBack";
6102 break;
6103 default:
6104 goto cp0_unimplemented;
6106 break;
6107 case CP0_REGISTER_03:
6108 switch (sel) {
6109 case CP0_REG03__ENTRYLO1:
6111 TCGv_i64 tmp = tcg_temp_new_i64();
6112 tcg_gen_ld_i64(tmp, cpu_env,
6113 offsetof(CPUMIPSState, CP0_EntryLo1));
6114 #if defined(TARGET_MIPS64)
6115 if (ctx->rxi) {
6116 /* Move RI/XI fields to bits 31:30 */
6117 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
6118 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
6120 #endif
6121 gen_move_low32(arg, tmp);
6122 tcg_temp_free_i64(tmp);
6124 register_name = "EntryLo1";
6125 break;
6126 case CP0_REG03__GLOBALNUM:
6127 CP0_CHECK(ctx->vp);
6128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6129 register_name = "GlobalNumber";
6130 break;
6131 default:
6132 goto cp0_unimplemented;
6134 break;
6135 case CP0_REGISTER_04:
6136 switch (sel) {
6137 case CP0_REG04__CONTEXT:
6138 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
6139 tcg_gen_ext32s_tl(arg, arg);
6140 register_name = "Context";
6141 break;
6142 case CP0_REG04__CONTEXTCONFIG:
6143 /* SmartMIPS ASE */
6144 /* gen_helper_mfc0_contextconfig(arg); */
6145 register_name = "ContextConfig";
6146 goto cp0_unimplemented;
6147 case CP0_REG04__USERLOCAL:
6148 CP0_CHECK(ctx->ulri);
6149 tcg_gen_ld_tl(arg, cpu_env,
6150 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6151 tcg_gen_ext32s_tl(arg, arg);
6152 register_name = "UserLocal";
6153 break;
6154 case CP0_REG04__MMID:
6155 CP0_CHECK(ctx->mi);
6156 gen_helper_mtc0_memorymapid(cpu_env, arg);
6157 register_name = "MMID";
6158 break;
6159 default:
6160 goto cp0_unimplemented;
6162 break;
6163 case CP0_REGISTER_05:
6164 switch (sel) {
6165 case CP0_REG05__PAGEMASK:
6166 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6167 register_name = "PageMask";
6168 break;
6169 case CP0_REG05__PAGEGRAIN:
6170 check_insn(ctx, ISA_MIPS_R2);
6171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6172 register_name = "PageGrain";
6173 break;
6174 case CP0_REG05__SEGCTL0:
6175 CP0_CHECK(ctx->sc);
6176 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6177 tcg_gen_ext32s_tl(arg, arg);
6178 register_name = "SegCtl0";
6179 break;
6180 case CP0_REG05__SEGCTL1:
6181 CP0_CHECK(ctx->sc);
6182 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6183 tcg_gen_ext32s_tl(arg, arg);
6184 register_name = "SegCtl1";
6185 break;
6186 case CP0_REG05__SEGCTL2:
6187 CP0_CHECK(ctx->sc);
6188 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6189 tcg_gen_ext32s_tl(arg, arg);
6190 register_name = "SegCtl2";
6191 break;
6192 case CP0_REG05__PWBASE:
6193 check_pw(ctx);
6194 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6195 register_name = "PWBase";
6196 break;
6197 case CP0_REG05__PWFIELD:
6198 check_pw(ctx);
6199 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
6200 register_name = "PWField";
6201 break;
6202 case CP0_REG05__PWSIZE:
6203 check_pw(ctx);
6204 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
6205 register_name = "PWSize";
6206 break;
6207 default:
6208 goto cp0_unimplemented;
6210 break;
6211 case CP0_REGISTER_06:
6212 switch (sel) {
6213 case CP0_REG06__WIRED:
6214 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6215 register_name = "Wired";
6216 break;
6217 case CP0_REG06__SRSCONF0:
6218 check_insn(ctx, ISA_MIPS_R2);
6219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6220 register_name = "SRSConf0";
6221 break;
6222 case CP0_REG06__SRSCONF1:
6223 check_insn(ctx, ISA_MIPS_R2);
6224 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6225 register_name = "SRSConf1";
6226 break;
6227 case CP0_REG06__SRSCONF2:
6228 check_insn(ctx, ISA_MIPS_R2);
6229 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6230 register_name = "SRSConf2";
6231 break;
6232 case CP0_REG06__SRSCONF3:
6233 check_insn(ctx, ISA_MIPS_R2);
6234 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6235 register_name = "SRSConf3";
6236 break;
6237 case CP0_REG06__SRSCONF4:
6238 check_insn(ctx, ISA_MIPS_R2);
6239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6240 register_name = "SRSConf4";
6241 break;
6242 case CP0_REG06__PWCTL:
6243 check_pw(ctx);
6244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6245 register_name = "PWCtl";
6246 break;
6247 default:
6248 goto cp0_unimplemented;
6250 break;
6251 case CP0_REGISTER_07:
6252 switch (sel) {
6253 case CP0_REG07__HWRENA:
6254 check_insn(ctx, ISA_MIPS_R2);
6255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6256 register_name = "HWREna";
6257 break;
6258 default:
6259 goto cp0_unimplemented;
6261 break;
6262 case CP0_REGISTER_08:
6263 switch (sel) {
6264 case CP0_REG08__BADVADDR:
6265 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6266 tcg_gen_ext32s_tl(arg, arg);
6267 register_name = "BadVAddr";
6268 break;
6269 case CP0_REG08__BADINSTR:
6270 CP0_CHECK(ctx->bi);
6271 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6272 register_name = "BadInstr";
6273 break;
6274 case CP0_REG08__BADINSTRP:
6275 CP0_CHECK(ctx->bp);
6276 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6277 register_name = "BadInstrP";
6278 break;
6279 case CP0_REG08__BADINSTRX:
6280 CP0_CHECK(ctx->bi);
6281 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6282 tcg_gen_andi_tl(arg, arg, ~0xffff);
6283 register_name = "BadInstrX";
6284 break;
6285 default:
6286 goto cp0_unimplemented;
6288 break;
6289 case CP0_REGISTER_09:
6290 switch (sel) {
6291 case CP0_REG09__COUNT:
6292 /* Mark as an IO operation because we read the time. */
6293 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6294 gen_io_start();
6296 gen_helper_mfc0_count(arg, cpu_env);
6298 * Break the TB to be able to take timer interrupts immediately
6299 * after reading count. DISAS_STOP isn't sufficient, we need to
6300 * ensure we break completely out of translated code.
6302 gen_save_pc(ctx->base.pc_next + 4);
6303 ctx->base.is_jmp = DISAS_EXIT;
6304 register_name = "Count";
6305 break;
6306 case CP0_REG09__SAARI:
6307 CP0_CHECK(ctx->saar);
6308 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
6309 register_name = "SAARI";
6310 break;
6311 case CP0_REG09__SAAR:
6312 CP0_CHECK(ctx->saar);
6313 gen_helper_mfc0_saar(arg, cpu_env);
6314 register_name = "SAAR";
6315 break;
6316 default:
6317 goto cp0_unimplemented;
6319 break;
6320 case CP0_REGISTER_10:
6321 switch (sel) {
6322 case CP0_REG10__ENTRYHI:
6323 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6324 tcg_gen_ext32s_tl(arg, arg);
6325 register_name = "EntryHi";
6326 break;
6327 default:
6328 goto cp0_unimplemented;
6330 break;
6331 case CP0_REGISTER_11:
6332 switch (sel) {
6333 case CP0_REG11__COMPARE:
6334 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6335 register_name = "Compare";
6336 break;
6337 /* 6,7 are implementation dependent */
6338 default:
6339 goto cp0_unimplemented;
6341 break;
6342 case CP0_REGISTER_12:
6343 switch (sel) {
6344 case CP0_REG12__STATUS:
6345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6346 register_name = "Status";
6347 break;
6348 case CP0_REG12__INTCTL:
6349 check_insn(ctx, ISA_MIPS_R2);
6350 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6351 register_name = "IntCtl";
6352 break;
6353 case CP0_REG12__SRSCTL:
6354 check_insn(ctx, ISA_MIPS_R2);
6355 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6356 register_name = "SRSCtl";
6357 break;
6358 case CP0_REG12__SRSMAP:
6359 check_insn(ctx, ISA_MIPS_R2);
6360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6361 register_name = "SRSMap";
6362 break;
6363 default:
6364 goto cp0_unimplemented;
6366 break;
6367 case CP0_REGISTER_13:
6368 switch (sel) {
6369 case CP0_REG13__CAUSE:
6370 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6371 register_name = "Cause";
6372 break;
6373 default:
6374 goto cp0_unimplemented;
6376 break;
6377 case CP0_REGISTER_14:
6378 switch (sel) {
6379 case CP0_REG14__EPC:
6380 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6381 tcg_gen_ext32s_tl(arg, arg);
6382 register_name = "EPC";
6383 break;
6384 default:
6385 goto cp0_unimplemented;
6387 break;
6388 case CP0_REGISTER_15:
6389 switch (sel) {
6390 case CP0_REG15__PRID:
6391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6392 register_name = "PRid";
6393 break;
6394 case CP0_REG15__EBASE:
6395 check_insn(ctx, ISA_MIPS_R2);
6396 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
6397 tcg_gen_ext32s_tl(arg, arg);
6398 register_name = "EBase";
6399 break;
6400 case CP0_REG15__CMGCRBASE:
6401 check_insn(ctx, ISA_MIPS_R2);
6402 CP0_CHECK(ctx->cmgcr);
6403 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
6404 tcg_gen_ext32s_tl(arg, arg);
6405 register_name = "CMGCRBase";
6406 break;
6407 default:
6408 goto cp0_unimplemented;
6410 break;
6411 case CP0_REGISTER_16:
6412 switch (sel) {
6413 case CP0_REG16__CONFIG:
6414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6415 register_name = "Config";
6416 break;
6417 case CP0_REG16__CONFIG1:
6418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6419 register_name = "Config1";
6420 break;
6421 case CP0_REG16__CONFIG2:
6422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6423 register_name = "Config2";
6424 break;
6425 case CP0_REG16__CONFIG3:
6426 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6427 register_name = "Config3";
6428 break;
6429 case CP0_REG16__CONFIG4:
6430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
6431 register_name = "Config4";
6432 break;
6433 case CP0_REG16__CONFIG5:
6434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
6435 register_name = "Config5";
6436 break;
6437 /* 6,7 are implementation dependent */
6438 case CP0_REG16__CONFIG6:
6439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6440 register_name = "Config6";
6441 break;
6442 case CP0_REG16__CONFIG7:
6443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6444 register_name = "Config7";
6445 break;
6446 default:
6447 goto cp0_unimplemented;
6449 break;
6450 case CP0_REGISTER_17:
6451 switch (sel) {
6452 case CP0_REG17__LLADDR:
6453 gen_helper_mfc0_lladdr(arg, cpu_env);
6454 register_name = "LLAddr";
6455 break;
6456 case CP0_REG17__MAAR:
6457 CP0_CHECK(ctx->mrp);
6458 gen_helper_mfc0_maar(arg, cpu_env);
6459 register_name = "MAAR";
6460 break;
6461 case CP0_REG17__MAARI:
6462 CP0_CHECK(ctx->mrp);
6463 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
6464 register_name = "MAARI";
6465 break;
6466 default:
6467 goto cp0_unimplemented;
6469 break;
6470 case CP0_REGISTER_18:
6471 switch (sel) {
6472 case CP0_REG18__WATCHLO0:
6473 case CP0_REG18__WATCHLO1:
6474 case CP0_REG18__WATCHLO2:
6475 case CP0_REG18__WATCHLO3:
6476 case CP0_REG18__WATCHLO4:
6477 case CP0_REG18__WATCHLO5:
6478 case CP0_REG18__WATCHLO6:
6479 case CP0_REG18__WATCHLO7:
6480 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6481 gen_helper_1e0i(mfc0_watchlo, arg, sel);
6482 register_name = "WatchLo";
6483 break;
6484 default:
6485 goto cp0_unimplemented;
6487 break;
6488 case CP0_REGISTER_19:
6489 switch (sel) {
6490 case CP0_REG19__WATCHHI0:
6491 case CP0_REG19__WATCHHI1:
6492 case CP0_REG19__WATCHHI2:
6493 case CP0_REG19__WATCHHI3:
6494 case CP0_REG19__WATCHHI4:
6495 case CP0_REG19__WATCHHI5:
6496 case CP0_REG19__WATCHHI6:
6497 case CP0_REG19__WATCHHI7:
6498 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6499 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6500 register_name = "WatchHi";
6501 break;
6502 default:
6503 goto cp0_unimplemented;
6505 break;
6506 case CP0_REGISTER_20:
6507 switch (sel) {
6508 case CP0_REG20__XCONTEXT:
6509 #if defined(TARGET_MIPS64)
6510 check_insn(ctx, ISA_MIPS3);
6511 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6512 tcg_gen_ext32s_tl(arg, arg);
6513 register_name = "XContext";
6514 break;
6515 #endif
6516 default:
6517 goto cp0_unimplemented;
6519 break;
6520 case CP0_REGISTER_21:
6521 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6522 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6523 switch (sel) {
6524 case 0:
6525 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6526 register_name = "Framemask";
6527 break;
6528 default:
6529 goto cp0_unimplemented;
6531 break;
6532 case CP0_REGISTER_22:
6533 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6534 register_name = "'Diagnostic"; /* implementation dependent */
6535 break;
6536 case CP0_REGISTER_23:
6537 switch (sel) {
6538 case CP0_REG23__DEBUG:
6539 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6540 register_name = "Debug";
6541 break;
6542 case CP0_REG23__TRACECONTROL:
6543 /* PDtrace support */
6544 /* gen_helper_mfc0_tracecontrol(arg); */
6545 register_name = "TraceControl";
6546 goto cp0_unimplemented;
6547 case CP0_REG23__TRACECONTROL2:
6548 /* PDtrace support */
6549 /* gen_helper_mfc0_tracecontrol2(arg); */
6550 register_name = "TraceControl2";
6551 goto cp0_unimplemented;
6552 case CP0_REG23__USERTRACEDATA1:
6553 /* PDtrace support */
6554 /* gen_helper_mfc0_usertracedata1(arg);*/
6555 register_name = "UserTraceData1";
6556 goto cp0_unimplemented;
6557 case CP0_REG23__TRACEIBPC:
6558 /* PDtrace support */
6559 /* gen_helper_mfc0_traceibpc(arg); */
6560 register_name = "TraceIBPC";
6561 goto cp0_unimplemented;
6562 case CP0_REG23__TRACEDBPC:
6563 /* PDtrace support */
6564 /* gen_helper_mfc0_tracedbpc(arg); */
6565 register_name = "TraceDBPC";
6566 goto cp0_unimplemented;
6567 default:
6568 goto cp0_unimplemented;
6570 break;
6571 case CP0_REGISTER_24:
6572 switch (sel) {
6573 case CP0_REG24__DEPC:
6574 /* EJTAG support */
6575 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6576 tcg_gen_ext32s_tl(arg, arg);
6577 register_name = "DEPC";
6578 break;
6579 default:
6580 goto cp0_unimplemented;
6582 break;
6583 case CP0_REGISTER_25:
6584 switch (sel) {
6585 case CP0_REG25__PERFCTL0:
6586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6587 register_name = "Performance0";
6588 break;
6589 case CP0_REG25__PERFCNT0:
6590 /* gen_helper_mfc0_performance1(arg); */
6591 register_name = "Performance1";
6592 goto cp0_unimplemented;
6593 case CP0_REG25__PERFCTL1:
6594 /* gen_helper_mfc0_performance2(arg); */
6595 register_name = "Performance2";
6596 goto cp0_unimplemented;
6597 case CP0_REG25__PERFCNT1:
6598 /* gen_helper_mfc0_performance3(arg); */
6599 register_name = "Performance3";
6600 goto cp0_unimplemented;
6601 case CP0_REG25__PERFCTL2:
6602 /* gen_helper_mfc0_performance4(arg); */
6603 register_name = "Performance4";
6604 goto cp0_unimplemented;
6605 case CP0_REG25__PERFCNT2:
6606 /* gen_helper_mfc0_performance5(arg); */
6607 register_name = "Performance5";
6608 goto cp0_unimplemented;
6609 case CP0_REG25__PERFCTL3:
6610 /* gen_helper_mfc0_performance6(arg); */
6611 register_name = "Performance6";
6612 goto cp0_unimplemented;
6613 case CP0_REG25__PERFCNT3:
6614 /* gen_helper_mfc0_performance7(arg); */
6615 register_name = "Performance7";
6616 goto cp0_unimplemented;
6617 default:
6618 goto cp0_unimplemented;
6620 break;
6621 case CP0_REGISTER_26:
6622 switch (sel) {
6623 case CP0_REG26__ERRCTL:
6624 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
6625 register_name = "ErrCtl";
6626 break;
6627 default:
6628 goto cp0_unimplemented;
6630 break;
6631 case CP0_REGISTER_27:
6632 switch (sel) {
6633 case CP0_REG27__CACHERR:
6634 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6635 register_name = "CacheErr";
6636 break;
6637 default:
6638 goto cp0_unimplemented;
6640 break;
6641 case CP0_REGISTER_28:
6642 switch (sel) {
6643 case CP0_REG28__TAGLO:
6644 case CP0_REG28__TAGLO1:
6645 case CP0_REG28__TAGLO2:
6646 case CP0_REG28__TAGLO3:
6648 TCGv_i64 tmp = tcg_temp_new_i64();
6649 tcg_gen_ld_i64(tmp, cpu_env, offsetof(CPUMIPSState, CP0_TagLo));
6650 gen_move_low32(arg, tmp);
6651 tcg_temp_free_i64(tmp);
6653 register_name = "TagLo";
6654 break;
6655 case CP0_REG28__DATALO:
6656 case CP0_REG28__DATALO1:
6657 case CP0_REG28__DATALO2:
6658 case CP0_REG28__DATALO3:
6659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6660 register_name = "DataLo";
6661 break;
6662 default:
6663 goto cp0_unimplemented;
6665 break;
6666 case CP0_REGISTER_29:
6667 switch (sel) {
6668 case CP0_REG29__TAGHI:
6669 case CP0_REG29__TAGHI1:
6670 case CP0_REG29__TAGHI2:
6671 case CP0_REG29__TAGHI3:
6672 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6673 register_name = "TagHi";
6674 break;
6675 case CP0_REG29__DATAHI:
6676 case CP0_REG29__DATAHI1:
6677 case CP0_REG29__DATAHI2:
6678 case CP0_REG29__DATAHI3:
6679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6680 register_name = "DataHi";
6681 break;
6682 default:
6683 goto cp0_unimplemented;
6685 break;
6686 case CP0_REGISTER_30:
6687 switch (sel) {
6688 case CP0_REG30__ERROREPC:
6689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6690 tcg_gen_ext32s_tl(arg, arg);
6691 register_name = "ErrorEPC";
6692 break;
6693 default:
6694 goto cp0_unimplemented;
6696 break;
6697 case CP0_REGISTER_31:
6698 switch (sel) {
6699 case CP0_REG31__DESAVE:
6700 /* EJTAG support */
6701 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6702 register_name = "DESAVE";
6703 break;
6704 case CP0_REG31__KSCRATCH1:
6705 case CP0_REG31__KSCRATCH2:
6706 case CP0_REG31__KSCRATCH3:
6707 case CP0_REG31__KSCRATCH4:
6708 case CP0_REG31__KSCRATCH5:
6709 case CP0_REG31__KSCRATCH6:
6710 CP0_CHECK(ctx->kscrexist & (1 << sel));
6711 tcg_gen_ld_tl(arg, cpu_env,
6712 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6713 tcg_gen_ext32s_tl(arg, arg);
6714 register_name = "KScratch";
6715 break;
6716 default:
6717 goto cp0_unimplemented;
6719 break;
6720 default:
6721 goto cp0_unimplemented;
6723 trace_mips_translate_c0("mfc0", register_name, reg, sel);
6724 return;
6726 cp0_unimplemented:
6727 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
6728 register_name, reg, sel);
6729 gen_mfc0_unimplemented(ctx, arg);
6732 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6734 const char *register_name = "invalid";
6736 if (sel != 0) {
6737 check_insn(ctx, ISA_MIPS_R1);
6740 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
6741 gen_io_start();
6744 switch (reg) {
6745 case CP0_REGISTER_00:
6746 switch (sel) {
6747 case CP0_REG00__INDEX:
6748 gen_helper_mtc0_index(cpu_env, arg);
6749 register_name = "Index";
6750 break;
6751 case CP0_REG00__MVPCONTROL:
6752 CP0_CHECK(ctx->insn_flags & ASE_MT);
6753 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6754 register_name = "MVPControl";
6755 break;
6756 case CP0_REG00__MVPCONF0:
6757 CP0_CHECK(ctx->insn_flags & ASE_MT);
6758 /* ignored */
6759 register_name = "MVPConf0";
6760 break;
6761 case CP0_REG00__MVPCONF1:
6762 CP0_CHECK(ctx->insn_flags & ASE_MT);
6763 /* ignored */
6764 register_name = "MVPConf1";
6765 break;
6766 case CP0_REG00__VPCONTROL:
6767 CP0_CHECK(ctx->vp);
6768 /* ignored */
6769 register_name = "VPControl";
6770 break;
6771 default:
6772 goto cp0_unimplemented;
6774 break;
6775 case CP0_REGISTER_01:
6776 switch (sel) {
6777 case CP0_REG01__RANDOM:
6778 /* ignored */
6779 register_name = "Random";
6780 break;
6781 case CP0_REG01__VPECONTROL:
6782 CP0_CHECK(ctx->insn_flags & ASE_MT);
6783 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6784 register_name = "VPEControl";
6785 break;
6786 case CP0_REG01__VPECONF0:
6787 CP0_CHECK(ctx->insn_flags & ASE_MT);
6788 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6789 register_name = "VPEConf0";
6790 break;
6791 case CP0_REG01__VPECONF1:
6792 CP0_CHECK(ctx->insn_flags & ASE_MT);
6793 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6794 register_name = "VPEConf1";
6795 break;
6796 case CP0_REG01__YQMASK:
6797 CP0_CHECK(ctx->insn_flags & ASE_MT);
6798 gen_helper_mtc0_yqmask(cpu_env, arg);
6799 register_name = "YQMask";
6800 break;
6801 case CP0_REG01__VPESCHEDULE:
6802 CP0_CHECK(ctx->insn_flags & ASE_MT);
6803 tcg_gen_st_tl(arg, cpu_env,
6804 offsetof(CPUMIPSState, CP0_VPESchedule));
6805 register_name = "VPESchedule";
6806 break;
6807 case CP0_REG01__VPESCHEFBACK:
6808 CP0_CHECK(ctx->insn_flags & ASE_MT);
6809 tcg_gen_st_tl(arg, cpu_env,
6810 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6811 register_name = "VPEScheFBack";
6812 break;
6813 case CP0_REG01__VPEOPT:
6814 CP0_CHECK(ctx->insn_flags & ASE_MT);
6815 gen_helper_mtc0_vpeopt(cpu_env, arg);
6816 register_name = "VPEOpt";
6817 break;
6818 default:
6819 goto cp0_unimplemented;
6821 break;
6822 case CP0_REGISTER_02:
6823 switch (sel) {
6824 case CP0_REG02__ENTRYLO0:
6825 gen_helper_mtc0_entrylo0(cpu_env, arg);
6826 register_name = "EntryLo0";
6827 break;
6828 case CP0_REG02__TCSTATUS:
6829 CP0_CHECK(ctx->insn_flags & ASE_MT);
6830 gen_helper_mtc0_tcstatus(cpu_env, arg);
6831 register_name = "TCStatus";
6832 break;
6833 case CP0_REG02__TCBIND:
6834 CP0_CHECK(ctx->insn_flags & ASE_MT);
6835 gen_helper_mtc0_tcbind(cpu_env, arg);
6836 register_name = "TCBind";
6837 break;
6838 case CP0_REG02__TCRESTART:
6839 CP0_CHECK(ctx->insn_flags & ASE_MT);
6840 gen_helper_mtc0_tcrestart(cpu_env, arg);
6841 register_name = "TCRestart";
6842 break;
6843 case CP0_REG02__TCHALT:
6844 CP0_CHECK(ctx->insn_flags & ASE_MT);
6845 gen_helper_mtc0_tchalt(cpu_env, arg);
6846 register_name = "TCHalt";
6847 break;
6848 case CP0_REG02__TCCONTEXT:
6849 CP0_CHECK(ctx->insn_flags & ASE_MT);
6850 gen_helper_mtc0_tccontext(cpu_env, arg);
6851 register_name = "TCContext";
6852 break;
6853 case CP0_REG02__TCSCHEDULE:
6854 CP0_CHECK(ctx->insn_flags & ASE_MT);
6855 gen_helper_mtc0_tcschedule(cpu_env, arg);
6856 register_name = "TCSchedule";
6857 break;
6858 case CP0_REG02__TCSCHEFBACK:
6859 CP0_CHECK(ctx->insn_flags & ASE_MT);
6860 gen_helper_mtc0_tcschefback(cpu_env, arg);
6861 register_name = "TCScheFBack";
6862 break;
6863 default:
6864 goto cp0_unimplemented;
6866 break;
6867 case CP0_REGISTER_03:
6868 switch (sel) {
6869 case CP0_REG03__ENTRYLO1:
6870 gen_helper_mtc0_entrylo1(cpu_env, arg);
6871 register_name = "EntryLo1";
6872 break;
6873 case CP0_REG03__GLOBALNUM:
6874 CP0_CHECK(ctx->vp);
6875 /* ignored */
6876 register_name = "GlobalNumber";
6877 break;
6878 default:
6879 goto cp0_unimplemented;
6881 break;
6882 case CP0_REGISTER_04:
6883 switch (sel) {
6884 case CP0_REG04__CONTEXT:
6885 gen_helper_mtc0_context(cpu_env, arg);
6886 register_name = "Context";
6887 break;
6888 case CP0_REG04__CONTEXTCONFIG:
6889 /* SmartMIPS ASE */
6890 /* gen_helper_mtc0_contextconfig(arg); */
6891 register_name = "ContextConfig";
6892 goto cp0_unimplemented;
6893 case CP0_REG04__USERLOCAL:
6894 CP0_CHECK(ctx->ulri);
6895 tcg_gen_st_tl(arg, cpu_env,
6896 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6897 register_name = "UserLocal";
6898 break;
6899 case CP0_REG04__MMID:
6900 CP0_CHECK(ctx->mi);
6901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6902 register_name = "MMID";
6903 break;
6904 default:
6905 goto cp0_unimplemented;
6907 break;
6908 case CP0_REGISTER_05:
6909 switch (sel) {
6910 case CP0_REG05__PAGEMASK:
6911 gen_helper_mtc0_pagemask(cpu_env, arg);
6912 register_name = "PageMask";
6913 break;
6914 case CP0_REG05__PAGEGRAIN:
6915 check_insn(ctx, ISA_MIPS_R2);
6916 gen_helper_mtc0_pagegrain(cpu_env, arg);
6917 register_name = "PageGrain";
6918 ctx->base.is_jmp = DISAS_STOP;
6919 break;
6920 case CP0_REG05__SEGCTL0:
6921 CP0_CHECK(ctx->sc);
6922 gen_helper_mtc0_segctl0(cpu_env, arg);
6923 register_name = "SegCtl0";
6924 break;
6925 case CP0_REG05__SEGCTL1:
6926 CP0_CHECK(ctx->sc);
6927 gen_helper_mtc0_segctl1(cpu_env, arg);
6928 register_name = "SegCtl1";
6929 break;
6930 case CP0_REG05__SEGCTL2:
6931 CP0_CHECK(ctx->sc);
6932 gen_helper_mtc0_segctl2(cpu_env, arg);
6933 register_name = "SegCtl2";
6934 break;
6935 case CP0_REG05__PWBASE:
6936 check_pw(ctx);
6937 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6938 register_name = "PWBase";
6939 break;
6940 case CP0_REG05__PWFIELD:
6941 check_pw(ctx);
6942 gen_helper_mtc0_pwfield(cpu_env, arg);
6943 register_name = "PWField";
6944 break;
6945 case CP0_REG05__PWSIZE:
6946 check_pw(ctx);
6947 gen_helper_mtc0_pwsize(cpu_env, arg);
6948 register_name = "PWSize";
6949 break;
6950 default:
6951 goto cp0_unimplemented;
6953 break;
6954 case CP0_REGISTER_06:
6955 switch (sel) {
6956 case CP0_REG06__WIRED:
6957 gen_helper_mtc0_wired(cpu_env, arg);
6958 register_name = "Wired";
6959 break;
6960 case CP0_REG06__SRSCONF0:
6961 check_insn(ctx, ISA_MIPS_R2);
6962 gen_helper_mtc0_srsconf0(cpu_env, arg);
6963 register_name = "SRSConf0";
6964 break;
6965 case CP0_REG06__SRSCONF1:
6966 check_insn(ctx, ISA_MIPS_R2);
6967 gen_helper_mtc0_srsconf1(cpu_env, arg);
6968 register_name = "SRSConf1";
6969 break;
6970 case CP0_REG06__SRSCONF2:
6971 check_insn(ctx, ISA_MIPS_R2);
6972 gen_helper_mtc0_srsconf2(cpu_env, arg);
6973 register_name = "SRSConf2";
6974 break;
6975 case CP0_REG06__SRSCONF3:
6976 check_insn(ctx, ISA_MIPS_R2);
6977 gen_helper_mtc0_srsconf3(cpu_env, arg);
6978 register_name = "SRSConf3";
6979 break;
6980 case CP0_REG06__SRSCONF4:
6981 check_insn(ctx, ISA_MIPS_R2);
6982 gen_helper_mtc0_srsconf4(cpu_env, arg);
6983 register_name = "SRSConf4";
6984 break;
6985 case CP0_REG06__PWCTL:
6986 check_pw(ctx);
6987 gen_helper_mtc0_pwctl(cpu_env, arg);
6988 register_name = "PWCtl";
6989 break;
6990 default:
6991 goto cp0_unimplemented;
6993 break;
6994 case CP0_REGISTER_07:
6995 switch (sel) {
6996 case CP0_REG07__HWRENA:
6997 check_insn(ctx, ISA_MIPS_R2);
6998 gen_helper_mtc0_hwrena(cpu_env, arg);
6999 ctx->base.is_jmp = DISAS_STOP;
7000 register_name = "HWREna";
7001 break;
7002 default:
7003 goto cp0_unimplemented;
7005 break;
7006 case CP0_REGISTER_08:
7007 switch (sel) {
7008 case CP0_REG08__BADVADDR:
7009 /* ignored */
7010 register_name = "BadVAddr";
7011 break;
7012 case CP0_REG08__BADINSTR:
7013 /* ignored */
7014 register_name = "BadInstr";
7015 break;
7016 case CP0_REG08__BADINSTRP:
7017 /* ignored */
7018 register_name = "BadInstrP";
7019 break;
7020 case CP0_REG08__BADINSTRX:
7021 /* ignored */
7022 register_name = "BadInstrX";
7023 break;
7024 default:
7025 goto cp0_unimplemented;
7027 break;
7028 case CP0_REGISTER_09:
7029 switch (sel) {
7030 case CP0_REG09__COUNT:
7031 gen_helper_mtc0_count(cpu_env, arg);
7032 register_name = "Count";
7033 break;
7034 case CP0_REG09__SAARI:
7035 CP0_CHECK(ctx->saar);
7036 gen_helper_mtc0_saari(cpu_env, arg);
7037 register_name = "SAARI";
7038 break;
7039 case CP0_REG09__SAAR:
7040 CP0_CHECK(ctx->saar);
7041 gen_helper_mtc0_saar(cpu_env, arg);
7042 register_name = "SAAR";
7043 break;
7044 default:
7045 goto cp0_unimplemented;
7047 break;
7048 case CP0_REGISTER_10:
7049 switch (sel) {
7050 case CP0_REG10__ENTRYHI:
7051 gen_helper_mtc0_entryhi(cpu_env, arg);
7052 register_name = "EntryHi";
7053 break;
7054 default:
7055 goto cp0_unimplemented;
7057 break;
7058 case CP0_REGISTER_11:
7059 switch (sel) {
7060 case CP0_REG11__COMPARE:
7061 gen_helper_mtc0_compare(cpu_env, arg);
7062 register_name = "Compare";
7063 break;
7064 /* 6,7 are implementation dependent */
7065 default:
7066 goto cp0_unimplemented;
7068 break;
7069 case CP0_REGISTER_12:
7070 switch (sel) {
7071 case CP0_REG12__STATUS:
7072 save_cpu_state(ctx, 1);
7073 gen_helper_mtc0_status(cpu_env, arg);
7074 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7075 gen_save_pc(ctx->base.pc_next + 4);
7076 ctx->base.is_jmp = DISAS_EXIT;
7077 register_name = "Status";
7078 break;
7079 case CP0_REG12__INTCTL:
7080 check_insn(ctx, ISA_MIPS_R2);
7081 gen_helper_mtc0_intctl(cpu_env, arg);
7082 /* Stop translation as we may have switched the execution mode */
7083 ctx->base.is_jmp = DISAS_STOP;
7084 register_name = "IntCtl";
7085 break;
7086 case CP0_REG12__SRSCTL:
7087 check_insn(ctx, ISA_MIPS_R2);
7088 gen_helper_mtc0_srsctl(cpu_env, arg);
7089 /* Stop translation as we may have switched the execution mode */
7090 ctx->base.is_jmp = DISAS_STOP;
7091 register_name = "SRSCtl";
7092 break;
7093 case CP0_REG12__SRSMAP:
7094 check_insn(ctx, ISA_MIPS_R2);
7095 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7096 /* Stop translation as we may have switched the execution mode */
7097 ctx->base.is_jmp = DISAS_STOP;
7098 register_name = "SRSMap";
7099 break;
7100 default:
7101 goto cp0_unimplemented;
7103 break;
7104 case CP0_REGISTER_13:
7105 switch (sel) {
7106 case CP0_REG13__CAUSE:
7107 save_cpu_state(ctx, 1);
7108 gen_helper_mtc0_cause(cpu_env, arg);
7110 * Stop translation as we may have triggered an interrupt.
7111 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7112 * translated code to check for pending interrupts.
7114 gen_save_pc(ctx->base.pc_next + 4);
7115 ctx->base.is_jmp = DISAS_EXIT;
7116 register_name = "Cause";
7117 break;
7118 default:
7119 goto cp0_unimplemented;
7121 break;
7122 case CP0_REGISTER_14:
7123 switch (sel) {
7124 case CP0_REG14__EPC:
7125 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7126 register_name = "EPC";
7127 break;
7128 default:
7129 goto cp0_unimplemented;
7131 break;
7132 case CP0_REGISTER_15:
7133 switch (sel) {
7134 case CP0_REG15__PRID:
7135 /* ignored */
7136 register_name = "PRid";
7137 break;
7138 case CP0_REG15__EBASE:
7139 check_insn(ctx, ISA_MIPS_R2);
7140 gen_helper_mtc0_ebase(cpu_env, arg);
7141 register_name = "EBase";
7142 break;
7143 default:
7144 goto cp0_unimplemented;
7146 break;
7147 case CP0_REGISTER_16:
7148 switch (sel) {
7149 case CP0_REG16__CONFIG:
7150 gen_helper_mtc0_config0(cpu_env, arg);
7151 register_name = "Config";
7152 /* Stop translation as we may have switched the execution mode */
7153 ctx->base.is_jmp = DISAS_STOP;
7154 break;
7155 case CP0_REG16__CONFIG1:
7156 /* ignored, read only */
7157 register_name = "Config1";
7158 break;
7159 case CP0_REG16__CONFIG2:
7160 gen_helper_mtc0_config2(cpu_env, arg);
7161 register_name = "Config2";
7162 /* Stop translation as we may have switched the execution mode */
7163 ctx->base.is_jmp = DISAS_STOP;
7164 break;
7165 case CP0_REG16__CONFIG3:
7166 gen_helper_mtc0_config3(cpu_env, arg);
7167 register_name = "Config3";
7168 /* Stop translation as we may have switched the execution mode */
7169 ctx->base.is_jmp = DISAS_STOP;
7170 break;
7171 case CP0_REG16__CONFIG4:
7172 gen_helper_mtc0_config4(cpu_env, arg);
7173 register_name = "Config4";
7174 ctx->base.is_jmp = DISAS_STOP;
7175 break;
7176 case CP0_REG16__CONFIG5:
7177 gen_helper_mtc0_config5(cpu_env, arg);
7178 register_name = "Config5";
7179 /* Stop translation as we may have switched the execution mode */
7180 ctx->base.is_jmp = DISAS_STOP;
7181 break;
7182 /* 6,7 are implementation dependent */
7183 case CP0_REG16__CONFIG6:
7184 /* ignored */
7185 register_name = "Config6";
7186 break;
7187 case CP0_REG16__CONFIG7:
7188 /* ignored */
7189 register_name = "Config7";
7190 break;
7191 default:
7192 register_name = "Invalid config selector";
7193 goto cp0_unimplemented;
7195 break;
7196 case CP0_REGISTER_17:
7197 switch (sel) {
7198 case CP0_REG17__LLADDR:
7199 gen_helper_mtc0_lladdr(cpu_env, arg);
7200 register_name = "LLAddr";
7201 break;
7202 case CP0_REG17__MAAR:
7203 CP0_CHECK(ctx->mrp);
7204 gen_helper_mtc0_maar(cpu_env, arg);
7205 register_name = "MAAR";
7206 break;
7207 case CP0_REG17__MAARI:
7208 CP0_CHECK(ctx->mrp);
7209 gen_helper_mtc0_maari(cpu_env, arg);
7210 register_name = "MAARI";
7211 break;
7212 default:
7213 goto cp0_unimplemented;
7215 break;
7216 case CP0_REGISTER_18:
7217 switch (sel) {
7218 case CP0_REG18__WATCHLO0:
7219 case CP0_REG18__WATCHLO1:
7220 case CP0_REG18__WATCHLO2:
7221 case CP0_REG18__WATCHLO3:
7222 case CP0_REG18__WATCHLO4:
7223 case CP0_REG18__WATCHLO5:
7224 case CP0_REG18__WATCHLO6:
7225 case CP0_REG18__WATCHLO7:
7226 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7227 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7228 register_name = "WatchLo";
7229 break;
7230 default:
7231 goto cp0_unimplemented;
7233 break;
7234 case CP0_REGISTER_19:
7235 switch (sel) {
7236 case CP0_REG19__WATCHHI0:
7237 case CP0_REG19__WATCHHI1:
7238 case CP0_REG19__WATCHHI2:
7239 case CP0_REG19__WATCHHI3:
7240 case CP0_REG19__WATCHHI4:
7241 case CP0_REG19__WATCHHI5:
7242 case CP0_REG19__WATCHHI6:
7243 case CP0_REG19__WATCHHI7:
7244 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7245 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7246 register_name = "WatchHi";
7247 break;
7248 default:
7249 goto cp0_unimplemented;
7251 break;
7252 case CP0_REGISTER_20:
7253 switch (sel) {
7254 case CP0_REG20__XCONTEXT:
7255 #if defined(TARGET_MIPS64)
7256 check_insn(ctx, ISA_MIPS3);
7257 gen_helper_mtc0_xcontext(cpu_env, arg);
7258 register_name = "XContext";
7259 break;
7260 #endif
7261 default:
7262 goto cp0_unimplemented;
7264 break;
7265 case CP0_REGISTER_21:
7266 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7267 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7268 switch (sel) {
7269 case 0:
7270 gen_helper_mtc0_framemask(cpu_env, arg);
7271 register_name = "Framemask";
7272 break;
7273 default:
7274 goto cp0_unimplemented;
7276 break;
7277 case CP0_REGISTER_22:
7278 /* ignored */
7279 register_name = "Diagnostic"; /* implementation dependent */
7280 break;
7281 case CP0_REGISTER_23:
7282 switch (sel) {
7283 case CP0_REG23__DEBUG:
7284 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
7285 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7286 gen_save_pc(ctx->base.pc_next + 4);
7287 ctx->base.is_jmp = DISAS_EXIT;
7288 register_name = "Debug";
7289 break;
7290 case CP0_REG23__TRACECONTROL:
7291 /* PDtrace support */
7292 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
7293 register_name = "TraceControl";
7294 /* Stop translation as we may have switched the execution mode */
7295 ctx->base.is_jmp = DISAS_STOP;
7296 goto cp0_unimplemented;
7297 case CP0_REG23__TRACECONTROL2:
7298 /* PDtrace support */
7299 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
7300 register_name = "TraceControl2";
7301 /* Stop translation as we may have switched the execution mode */
7302 ctx->base.is_jmp = DISAS_STOP;
7303 goto cp0_unimplemented;
7304 case CP0_REG23__USERTRACEDATA1:
7305 /* Stop translation as we may have switched the execution mode */
7306 ctx->base.is_jmp = DISAS_STOP;
7307 /* PDtrace support */
7308 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
7309 register_name = "UserTraceData";
7310 /* Stop translation as we may have switched the execution mode */
7311 ctx->base.is_jmp = DISAS_STOP;
7312 goto cp0_unimplemented;
7313 case CP0_REG23__TRACEIBPC:
7314 /* PDtrace support */
7315 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
7316 /* Stop translation as we may have switched the execution mode */
7317 ctx->base.is_jmp = DISAS_STOP;
7318 register_name = "TraceIBPC";
7319 goto cp0_unimplemented;
7320 case CP0_REG23__TRACEDBPC:
7321 /* PDtrace support */
7322 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
7323 /* Stop translation as we may have switched the execution mode */
7324 ctx->base.is_jmp = DISAS_STOP;
7325 register_name = "TraceDBPC";
7326 goto cp0_unimplemented;
7327 default:
7328 goto cp0_unimplemented;
7330 break;
7331 case CP0_REGISTER_24:
7332 switch (sel) {
7333 case CP0_REG24__DEPC:
7334 /* EJTAG support */
7335 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
7336 register_name = "DEPC";
7337 break;
7338 default:
7339 goto cp0_unimplemented;
7341 break;
7342 case CP0_REGISTER_25:
7343 switch (sel) {
7344 case CP0_REG25__PERFCTL0:
7345 gen_helper_mtc0_performance0(cpu_env, arg);
7346 register_name = "Performance0";
7347 break;
7348 case CP0_REG25__PERFCNT0:
7349 /* gen_helper_mtc0_performance1(arg); */
7350 register_name = "Performance1";
7351 goto cp0_unimplemented;
7352 case CP0_REG25__PERFCTL1:
7353 /* gen_helper_mtc0_performance2(arg); */
7354 register_name = "Performance2";
7355 goto cp0_unimplemented;
7356 case CP0_REG25__PERFCNT1:
7357 /* gen_helper_mtc0_performance3(arg); */
7358 register_name = "Performance3";
7359 goto cp0_unimplemented;
7360 case CP0_REG25__PERFCTL2:
7361 /* gen_helper_mtc0_performance4(arg); */
7362 register_name = "Performance4";
7363 goto cp0_unimplemented;
7364 case CP0_REG25__PERFCNT2:
7365 /* gen_helper_mtc0_performance5(arg); */
7366 register_name = "Performance5";
7367 goto cp0_unimplemented;
7368 case CP0_REG25__PERFCTL3:
7369 /* gen_helper_mtc0_performance6(arg); */
7370 register_name = "Performance6";
7371 goto cp0_unimplemented;
7372 case CP0_REG25__PERFCNT3:
7373 /* gen_helper_mtc0_performance7(arg); */
7374 register_name = "Performance7";
7375 goto cp0_unimplemented;
7376 default:
7377 goto cp0_unimplemented;
7379 break;
7380 case CP0_REGISTER_26:
7381 switch (sel) {
7382 case CP0_REG26__ERRCTL:
7383 gen_helper_mtc0_errctl(cpu_env, arg);
7384 ctx->base.is_jmp = DISAS_STOP;
7385 register_name = "ErrCtl";
7386 break;
7387 default:
7388 goto cp0_unimplemented;
7390 break;
7391 case CP0_REGISTER_27:
7392 switch (sel) {
7393 case CP0_REG27__CACHERR:
7394 /* ignored */
7395 register_name = "CacheErr";
7396 break;
7397 default:
7398 goto cp0_unimplemented;
7400 break;
7401 case CP0_REGISTER_28:
7402 switch (sel) {
7403 case CP0_REG28__TAGLO:
7404 case CP0_REG28__TAGLO1:
7405 case CP0_REG28__TAGLO2:
7406 case CP0_REG28__TAGLO3:
7407 gen_helper_mtc0_taglo(cpu_env, arg);
7408 register_name = "TagLo";
7409 break;
7410 case CP0_REG28__DATALO:
7411 case CP0_REG28__DATALO1:
7412 case CP0_REG28__DATALO2:
7413 case CP0_REG28__DATALO3:
7414 gen_helper_mtc0_datalo(cpu_env, arg);
7415 register_name = "DataLo";
7416 break;
7417 default:
7418 goto cp0_unimplemented;
7420 break;
7421 case CP0_REGISTER_29:
7422 switch (sel) {
7423 case CP0_REG29__TAGHI:
7424 case CP0_REG29__TAGHI1:
7425 case CP0_REG29__TAGHI2:
7426 case CP0_REG29__TAGHI3:
7427 gen_helper_mtc0_taghi(cpu_env, arg);
7428 register_name = "TagHi";
7429 break;
7430 case CP0_REG29__DATAHI:
7431 case CP0_REG29__DATAHI1:
7432 case CP0_REG29__DATAHI2:
7433 case CP0_REG29__DATAHI3:
7434 gen_helper_mtc0_datahi(cpu_env, arg);
7435 register_name = "DataHi";
7436 break;
7437 default:
7438 register_name = "invalid sel";
7439 goto cp0_unimplemented;
7441 break;
7442 case CP0_REGISTER_30:
7443 switch (sel) {
7444 case CP0_REG30__ERROREPC:
7445 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7446 register_name = "ErrorEPC";
7447 break;
7448 default:
7449 goto cp0_unimplemented;
7451 break;
7452 case CP0_REGISTER_31:
7453 switch (sel) {
7454 case CP0_REG31__DESAVE:
7455 /* EJTAG support */
7456 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7457 register_name = "DESAVE";
7458 break;
7459 case CP0_REG31__KSCRATCH1:
7460 case CP0_REG31__KSCRATCH2:
7461 case CP0_REG31__KSCRATCH3:
7462 case CP0_REG31__KSCRATCH4:
7463 case CP0_REG31__KSCRATCH5:
7464 case CP0_REG31__KSCRATCH6:
7465 CP0_CHECK(ctx->kscrexist & (1 << sel));
7466 tcg_gen_st_tl(arg, cpu_env,
7467 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7468 register_name = "KScratch";
7469 break;
7470 default:
7471 goto cp0_unimplemented;
7473 break;
7474 default:
7475 goto cp0_unimplemented;
7477 trace_mips_translate_c0("mtc0", register_name, reg, sel);
7479 /* For simplicity assume that all writes can cause interrupts. */
7480 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7482 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7483 * translated code to check for pending interrupts.
7485 gen_save_pc(ctx->base.pc_next + 4);
7486 ctx->base.is_jmp = DISAS_EXIT;
7488 return;
7490 cp0_unimplemented:
7491 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
7492 register_name, reg, sel);
7495 #if defined(TARGET_MIPS64)
7496 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7498 const char *register_name = "invalid";
7500 if (sel != 0) {
7501 check_insn(ctx, ISA_MIPS_R1);
7504 switch (reg) {
7505 case CP0_REGISTER_00:
7506 switch (sel) {
7507 case CP0_REG00__INDEX:
7508 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
7509 register_name = "Index";
7510 break;
7511 case CP0_REG00__MVPCONTROL:
7512 CP0_CHECK(ctx->insn_flags & ASE_MT);
7513 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
7514 register_name = "MVPControl";
7515 break;
7516 case CP0_REG00__MVPCONF0:
7517 CP0_CHECK(ctx->insn_flags & ASE_MT);
7518 gen_helper_mfc0_mvpconf0(arg, cpu_env);
7519 register_name = "MVPConf0";
7520 break;
7521 case CP0_REG00__MVPCONF1:
7522 CP0_CHECK(ctx->insn_flags & ASE_MT);
7523 gen_helper_mfc0_mvpconf1(arg, cpu_env);
7524 register_name = "MVPConf1";
7525 break;
7526 case CP0_REG00__VPCONTROL:
7527 CP0_CHECK(ctx->vp);
7528 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
7529 register_name = "VPControl";
7530 break;
7531 default:
7532 goto cp0_unimplemented;
7534 break;
7535 case CP0_REGISTER_01:
7536 switch (sel) {
7537 case CP0_REG01__RANDOM:
7538 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7539 gen_helper_mfc0_random(arg, cpu_env);
7540 register_name = "Random";
7541 break;
7542 case CP0_REG01__VPECONTROL:
7543 CP0_CHECK(ctx->insn_flags & ASE_MT);
7544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
7545 register_name = "VPEControl";
7546 break;
7547 case CP0_REG01__VPECONF0:
7548 CP0_CHECK(ctx->insn_flags & ASE_MT);
7549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
7550 register_name = "VPEConf0";
7551 break;
7552 case CP0_REG01__VPECONF1:
7553 CP0_CHECK(ctx->insn_flags & ASE_MT);
7554 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
7555 register_name = "VPEConf1";
7556 break;
7557 case CP0_REG01__YQMASK:
7558 CP0_CHECK(ctx->insn_flags & ASE_MT);
7559 tcg_gen_ld_tl(arg, cpu_env,
7560 offsetof(CPUMIPSState, CP0_YQMask));
7561 register_name = "YQMask";
7562 break;
7563 case CP0_REG01__VPESCHEDULE:
7564 CP0_CHECK(ctx->insn_flags & ASE_MT);
7565 tcg_gen_ld_tl(arg, cpu_env,
7566 offsetof(CPUMIPSState, CP0_VPESchedule));
7567 register_name = "VPESchedule";
7568 break;
7569 case CP0_REG01__VPESCHEFBACK:
7570 CP0_CHECK(ctx->insn_flags & ASE_MT);
7571 tcg_gen_ld_tl(arg, cpu_env,
7572 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7573 register_name = "VPEScheFBack";
7574 break;
7575 case CP0_REG01__VPEOPT:
7576 CP0_CHECK(ctx->insn_flags & ASE_MT);
7577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
7578 register_name = "VPEOpt";
7579 break;
7580 default:
7581 goto cp0_unimplemented;
7583 break;
7584 case CP0_REGISTER_02:
7585 switch (sel) {
7586 case CP0_REG02__ENTRYLO0:
7587 tcg_gen_ld_tl(arg, cpu_env,
7588 offsetof(CPUMIPSState, CP0_EntryLo0));
7589 register_name = "EntryLo0";
7590 break;
7591 case CP0_REG02__TCSTATUS:
7592 CP0_CHECK(ctx->insn_flags & ASE_MT);
7593 gen_helper_mfc0_tcstatus(arg, cpu_env);
7594 register_name = "TCStatus";
7595 break;
7596 case CP0_REG02__TCBIND:
7597 CP0_CHECK(ctx->insn_flags & ASE_MT);
7598 gen_helper_mfc0_tcbind(arg, cpu_env);
7599 register_name = "TCBind";
7600 break;
7601 case CP0_REG02__TCRESTART:
7602 CP0_CHECK(ctx->insn_flags & ASE_MT);
7603 gen_helper_dmfc0_tcrestart(arg, cpu_env);
7604 register_name = "TCRestart";
7605 break;
7606 case CP0_REG02__TCHALT:
7607 CP0_CHECK(ctx->insn_flags & ASE_MT);
7608 gen_helper_dmfc0_tchalt(arg, cpu_env);
7609 register_name = "TCHalt";
7610 break;
7611 case CP0_REG02__TCCONTEXT:
7612 CP0_CHECK(ctx->insn_flags & ASE_MT);
7613 gen_helper_dmfc0_tccontext(arg, cpu_env);
7614 register_name = "TCContext";
7615 break;
7616 case CP0_REG02__TCSCHEDULE:
7617 CP0_CHECK(ctx->insn_flags & ASE_MT);
7618 gen_helper_dmfc0_tcschedule(arg, cpu_env);
7619 register_name = "TCSchedule";
7620 break;
7621 case CP0_REG02__TCSCHEFBACK:
7622 CP0_CHECK(ctx->insn_flags & ASE_MT);
7623 gen_helper_dmfc0_tcschefback(arg, cpu_env);
7624 register_name = "TCScheFBack";
7625 break;
7626 default:
7627 goto cp0_unimplemented;
7629 break;
7630 case CP0_REGISTER_03:
7631 switch (sel) {
7632 case CP0_REG03__ENTRYLO1:
7633 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
7634 register_name = "EntryLo1";
7635 break;
7636 case CP0_REG03__GLOBALNUM:
7637 CP0_CHECK(ctx->vp);
7638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
7639 register_name = "GlobalNumber";
7640 break;
7641 default:
7642 goto cp0_unimplemented;
7644 break;
7645 case CP0_REGISTER_04:
7646 switch (sel) {
7647 case CP0_REG04__CONTEXT:
7648 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
7649 register_name = "Context";
7650 break;
7651 case CP0_REG04__CONTEXTCONFIG:
7652 /* SmartMIPS ASE */
7653 /* gen_helper_dmfc0_contextconfig(arg); */
7654 register_name = "ContextConfig";
7655 goto cp0_unimplemented;
7656 case CP0_REG04__USERLOCAL:
7657 CP0_CHECK(ctx->ulri);
7658 tcg_gen_ld_tl(arg, cpu_env,
7659 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7660 register_name = "UserLocal";
7661 break;
7662 case CP0_REG04__MMID:
7663 CP0_CHECK(ctx->mi);
7664 gen_helper_mtc0_memorymapid(cpu_env, arg);
7665 register_name = "MMID";
7666 break;
7667 default:
7668 goto cp0_unimplemented;
7670 break;
7671 case CP0_REGISTER_05:
7672 switch (sel) {
7673 case CP0_REG05__PAGEMASK:
7674 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
7675 register_name = "PageMask";
7676 break;
7677 case CP0_REG05__PAGEGRAIN:
7678 check_insn(ctx, ISA_MIPS_R2);
7679 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
7680 register_name = "PageGrain";
7681 break;
7682 case CP0_REG05__SEGCTL0:
7683 CP0_CHECK(ctx->sc);
7684 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl0));
7685 register_name = "SegCtl0";
7686 break;
7687 case CP0_REG05__SEGCTL1:
7688 CP0_CHECK(ctx->sc);
7689 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl1));
7690 register_name = "SegCtl1";
7691 break;
7692 case CP0_REG05__SEGCTL2:
7693 CP0_CHECK(ctx->sc);
7694 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_SegCtl2));
7695 register_name = "SegCtl2";
7696 break;
7697 case CP0_REG05__PWBASE:
7698 check_pw(ctx);
7699 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
7700 register_name = "PWBase";
7701 break;
7702 case CP0_REG05__PWFIELD:
7703 check_pw(ctx);
7704 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWField));
7705 register_name = "PWField";
7706 break;
7707 case CP0_REG05__PWSIZE:
7708 check_pw(ctx);
7709 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWSize));
7710 register_name = "PWSize";
7711 break;
7712 default:
7713 goto cp0_unimplemented;
7715 break;
7716 case CP0_REGISTER_06:
7717 switch (sel) {
7718 case CP0_REG06__WIRED:
7719 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
7720 register_name = "Wired";
7721 break;
7722 case CP0_REG06__SRSCONF0:
7723 check_insn(ctx, ISA_MIPS_R2);
7724 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
7725 register_name = "SRSConf0";
7726 break;
7727 case CP0_REG06__SRSCONF1:
7728 check_insn(ctx, ISA_MIPS_R2);
7729 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
7730 register_name = "SRSConf1";
7731 break;
7732 case CP0_REG06__SRSCONF2:
7733 check_insn(ctx, ISA_MIPS_R2);
7734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
7735 register_name = "SRSConf2";
7736 break;
7737 case CP0_REG06__SRSCONF3:
7738 check_insn(ctx, ISA_MIPS_R2);
7739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
7740 register_name = "SRSConf3";
7741 break;
7742 case CP0_REG06__SRSCONF4:
7743 check_insn(ctx, ISA_MIPS_R2);
7744 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
7745 register_name = "SRSConf4";
7746 break;
7747 case CP0_REG06__PWCTL:
7748 check_pw(ctx);
7749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
7750 register_name = "PWCtl";
7751 break;
7752 default:
7753 goto cp0_unimplemented;
7755 break;
7756 case CP0_REGISTER_07:
7757 switch (sel) {
7758 case CP0_REG07__HWRENA:
7759 check_insn(ctx, ISA_MIPS_R2);
7760 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
7761 register_name = "HWREna";
7762 break;
7763 default:
7764 goto cp0_unimplemented;
7766 break;
7767 case CP0_REGISTER_08:
7768 switch (sel) {
7769 case CP0_REG08__BADVADDR:
7770 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
7771 register_name = "BadVAddr";
7772 break;
7773 case CP0_REG08__BADINSTR:
7774 CP0_CHECK(ctx->bi);
7775 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
7776 register_name = "BadInstr";
7777 break;
7778 case CP0_REG08__BADINSTRP:
7779 CP0_CHECK(ctx->bp);
7780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
7781 register_name = "BadInstrP";
7782 break;
7783 case CP0_REG08__BADINSTRX:
7784 CP0_CHECK(ctx->bi);
7785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
7786 tcg_gen_andi_tl(arg, arg, ~0xffff);
7787 register_name = "BadInstrX";
7788 break;
7789 default:
7790 goto cp0_unimplemented;
7792 break;
7793 case CP0_REGISTER_09:
7794 switch (sel) {
7795 case CP0_REG09__COUNT:
7796 /* Mark as an IO operation because we read the time. */
7797 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
7798 gen_io_start();
7800 gen_helper_mfc0_count(arg, cpu_env);
7802 * Break the TB to be able to take timer interrupts immediately
7803 * after reading count. DISAS_STOP isn't sufficient, we need to
7804 * ensure we break completely out of translated code.
7806 gen_save_pc(ctx->base.pc_next + 4);
7807 ctx->base.is_jmp = DISAS_EXIT;
7808 register_name = "Count";
7809 break;
7810 case CP0_REG09__SAARI:
7811 CP0_CHECK(ctx->saar);
7812 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SAARI));
7813 register_name = "SAARI";
7814 break;
7815 case CP0_REG09__SAAR:
7816 CP0_CHECK(ctx->saar);
7817 gen_helper_dmfc0_saar(arg, cpu_env);
7818 register_name = "SAAR";
7819 break;
7820 default:
7821 goto cp0_unimplemented;
7823 break;
7824 case CP0_REGISTER_10:
7825 switch (sel) {
7826 case CP0_REG10__ENTRYHI:
7827 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
7828 register_name = "EntryHi";
7829 break;
7830 default:
7831 goto cp0_unimplemented;
7833 break;
7834 case CP0_REGISTER_11:
7835 switch (sel) {
7836 case CP0_REG11__COMPARE:
7837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
7838 register_name = "Compare";
7839 break;
7840 /* 6,7 are implementation dependent */
7841 default:
7842 goto cp0_unimplemented;
7844 break;
7845 case CP0_REGISTER_12:
7846 switch (sel) {
7847 case CP0_REG12__STATUS:
7848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
7849 register_name = "Status";
7850 break;
7851 case CP0_REG12__INTCTL:
7852 check_insn(ctx, ISA_MIPS_R2);
7853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
7854 register_name = "IntCtl";
7855 break;
7856 case CP0_REG12__SRSCTL:
7857 check_insn(ctx, ISA_MIPS_R2);
7858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
7859 register_name = "SRSCtl";
7860 break;
7861 case CP0_REG12__SRSMAP:
7862 check_insn(ctx, ISA_MIPS_R2);
7863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7864 register_name = "SRSMap";
7865 break;
7866 default:
7867 goto cp0_unimplemented;
7869 break;
7870 case CP0_REGISTER_13:
7871 switch (sel) {
7872 case CP0_REG13__CAUSE:
7873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
7874 register_name = "Cause";
7875 break;
7876 default:
7877 goto cp0_unimplemented;
7879 break;
7880 case CP0_REGISTER_14:
7881 switch (sel) {
7882 case CP0_REG14__EPC:
7883 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
7884 register_name = "EPC";
7885 break;
7886 default:
7887 goto cp0_unimplemented;
7889 break;
7890 case CP0_REGISTER_15:
7891 switch (sel) {
7892 case CP0_REG15__PRID:
7893 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
7894 register_name = "PRid";
7895 break;
7896 case CP0_REG15__EBASE:
7897 check_insn(ctx, ISA_MIPS_R2);
7898 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EBase));
7899 register_name = "EBase";
7900 break;
7901 case CP0_REG15__CMGCRBASE:
7902 check_insn(ctx, ISA_MIPS_R2);
7903 CP0_CHECK(ctx->cmgcr);
7904 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7905 register_name = "CMGCRBase";
7906 break;
7907 default:
7908 goto cp0_unimplemented;
7910 break;
7911 case CP0_REGISTER_16:
7912 switch (sel) {
7913 case CP0_REG16__CONFIG:
7914 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7915 register_name = "Config";
7916 break;
7917 case CP0_REG16__CONFIG1:
7918 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7919 register_name = "Config1";
7920 break;
7921 case CP0_REG16__CONFIG2:
7922 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7923 register_name = "Config2";
7924 break;
7925 case CP0_REG16__CONFIG3:
7926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7927 register_name = "Config3";
7928 break;
7929 case CP0_REG16__CONFIG4:
7930 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7931 register_name = "Config4";
7932 break;
7933 case CP0_REG16__CONFIG5:
7934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7935 register_name = "Config5";
7936 break;
7937 /* 6,7 are implementation dependent */
7938 case CP0_REG16__CONFIG6:
7939 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7940 register_name = "Config6";
7941 break;
7942 case CP0_REG16__CONFIG7:
7943 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7944 register_name = "Config7";
7945 break;
7946 default:
7947 goto cp0_unimplemented;
7949 break;
7950 case CP0_REGISTER_17:
7951 switch (sel) {
7952 case CP0_REG17__LLADDR:
7953 gen_helper_dmfc0_lladdr(arg, cpu_env);
7954 register_name = "LLAddr";
7955 break;
7956 case CP0_REG17__MAAR:
7957 CP0_CHECK(ctx->mrp);
7958 gen_helper_dmfc0_maar(arg, cpu_env);
7959 register_name = "MAAR";
7960 break;
7961 case CP0_REG17__MAARI:
7962 CP0_CHECK(ctx->mrp);
7963 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7964 register_name = "MAARI";
7965 break;
7966 default:
7967 goto cp0_unimplemented;
7969 break;
7970 case CP0_REGISTER_18:
7971 switch (sel) {
7972 case CP0_REG18__WATCHLO0:
7973 case CP0_REG18__WATCHLO1:
7974 case CP0_REG18__WATCHLO2:
7975 case CP0_REG18__WATCHLO3:
7976 case CP0_REG18__WATCHLO4:
7977 case CP0_REG18__WATCHLO5:
7978 case CP0_REG18__WATCHLO6:
7979 case CP0_REG18__WATCHLO7:
7980 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7981 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7982 register_name = "WatchLo";
7983 break;
7984 default:
7985 goto cp0_unimplemented;
7987 break;
7988 case CP0_REGISTER_19:
7989 switch (sel) {
7990 case CP0_REG19__WATCHHI0:
7991 case CP0_REG19__WATCHHI1:
7992 case CP0_REG19__WATCHHI2:
7993 case CP0_REG19__WATCHHI3:
7994 case CP0_REG19__WATCHHI4:
7995 case CP0_REG19__WATCHHI5:
7996 case CP0_REG19__WATCHHI6:
7997 case CP0_REG19__WATCHHI7:
7998 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7999 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
8000 register_name = "WatchHi";
8001 break;
8002 default:
8003 goto cp0_unimplemented;
8005 break;
8006 case CP0_REGISTER_20:
8007 switch (sel) {
8008 case CP0_REG20__XCONTEXT:
8009 check_insn(ctx, ISA_MIPS3);
8010 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
8011 register_name = "XContext";
8012 break;
8013 default:
8014 goto cp0_unimplemented;
8016 break;
8017 case CP0_REGISTER_21:
8018 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8019 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8020 switch (sel) {
8021 case 0:
8022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
8023 register_name = "Framemask";
8024 break;
8025 default:
8026 goto cp0_unimplemented;
8028 break;
8029 case CP0_REGISTER_22:
8030 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8031 register_name = "'Diagnostic"; /* implementation dependent */
8032 break;
8033 case CP0_REGISTER_23:
8034 switch (sel) {
8035 case CP0_REG23__DEBUG:
8036 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
8037 register_name = "Debug";
8038 break;
8039 case CP0_REG23__TRACECONTROL:
8040 /* PDtrace support */
8041 /* gen_helper_dmfc0_tracecontrol(arg, cpu_env); */
8042 register_name = "TraceControl";
8043 goto cp0_unimplemented;
8044 case CP0_REG23__TRACECONTROL2:
8045 /* PDtrace support */
8046 /* gen_helper_dmfc0_tracecontrol2(arg, cpu_env); */
8047 register_name = "TraceControl2";
8048 goto cp0_unimplemented;
8049 case CP0_REG23__USERTRACEDATA1:
8050 /* PDtrace support */
8051 /* gen_helper_dmfc0_usertracedata1(arg, cpu_env);*/
8052 register_name = "UserTraceData1";
8053 goto cp0_unimplemented;
8054 case CP0_REG23__TRACEIBPC:
8055 /* PDtrace support */
8056 /* gen_helper_dmfc0_traceibpc(arg, cpu_env); */
8057 register_name = "TraceIBPC";
8058 goto cp0_unimplemented;
8059 case CP0_REG23__TRACEDBPC:
8060 /* PDtrace support */
8061 /* gen_helper_dmfc0_tracedbpc(arg, cpu_env); */
8062 register_name = "TraceDBPC";
8063 goto cp0_unimplemented;
8064 default:
8065 goto cp0_unimplemented;
8067 break;
8068 case CP0_REGISTER_24:
8069 switch (sel) {
8070 case CP0_REG24__DEPC:
8071 /* EJTAG support */
8072 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8073 register_name = "DEPC";
8074 break;
8075 default:
8076 goto cp0_unimplemented;
8078 break;
8079 case CP0_REGISTER_25:
8080 switch (sel) {
8081 case CP0_REG25__PERFCTL0:
8082 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
8083 register_name = "Performance0";
8084 break;
8085 case CP0_REG25__PERFCNT0:
8086 /* gen_helper_dmfc0_performance1(arg); */
8087 register_name = "Performance1";
8088 goto cp0_unimplemented;
8089 case CP0_REG25__PERFCTL1:
8090 /* gen_helper_dmfc0_performance2(arg); */
8091 register_name = "Performance2";
8092 goto cp0_unimplemented;
8093 case CP0_REG25__PERFCNT1:
8094 /* gen_helper_dmfc0_performance3(arg); */
8095 register_name = "Performance3";
8096 goto cp0_unimplemented;
8097 case CP0_REG25__PERFCTL2:
8098 /* gen_helper_dmfc0_performance4(arg); */
8099 register_name = "Performance4";
8100 goto cp0_unimplemented;
8101 case CP0_REG25__PERFCNT2:
8102 /* gen_helper_dmfc0_performance5(arg); */
8103 register_name = "Performance5";
8104 goto cp0_unimplemented;
8105 case CP0_REG25__PERFCTL3:
8106 /* gen_helper_dmfc0_performance6(arg); */
8107 register_name = "Performance6";
8108 goto cp0_unimplemented;
8109 case CP0_REG25__PERFCNT3:
8110 /* gen_helper_dmfc0_performance7(arg); */
8111 register_name = "Performance7";
8112 goto cp0_unimplemented;
8113 default:
8114 goto cp0_unimplemented;
8116 break;
8117 case CP0_REGISTER_26:
8118 switch (sel) {
8119 case CP0_REG26__ERRCTL:
8120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
8121 register_name = "ErrCtl";
8122 break;
8123 default:
8124 goto cp0_unimplemented;
8126 break;
8127 case CP0_REGISTER_27:
8128 switch (sel) {
8129 /* ignored */
8130 case CP0_REG27__CACHERR:
8131 tcg_gen_movi_tl(arg, 0); /* unimplemented */
8132 register_name = "CacheErr";
8133 break;
8134 default:
8135 goto cp0_unimplemented;
8137 break;
8138 case CP0_REGISTER_28:
8139 switch (sel) {
8140 case CP0_REG28__TAGLO:
8141 case CP0_REG28__TAGLO1:
8142 case CP0_REG28__TAGLO2:
8143 case CP0_REG28__TAGLO3:
8144 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
8145 register_name = "TagLo";
8146 break;
8147 case CP0_REG28__DATALO:
8148 case CP0_REG28__DATALO1:
8149 case CP0_REG28__DATALO2:
8150 case CP0_REG28__DATALO3:
8151 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
8152 register_name = "DataLo";
8153 break;
8154 default:
8155 goto cp0_unimplemented;
8157 break;
8158 case CP0_REGISTER_29:
8159 switch (sel) {
8160 case CP0_REG29__TAGHI:
8161 case CP0_REG29__TAGHI1:
8162 case CP0_REG29__TAGHI2:
8163 case CP0_REG29__TAGHI3:
8164 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
8165 register_name = "TagHi";
8166 break;
8167 case CP0_REG29__DATAHI:
8168 case CP0_REG29__DATAHI1:
8169 case CP0_REG29__DATAHI2:
8170 case CP0_REG29__DATAHI3:
8171 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
8172 register_name = "DataHi";
8173 break;
8174 default:
8175 goto cp0_unimplemented;
8177 break;
8178 case CP0_REGISTER_30:
8179 switch (sel) {
8180 case CP0_REG30__ERROREPC:
8181 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8182 register_name = "ErrorEPC";
8183 break;
8184 default:
8185 goto cp0_unimplemented;
8187 break;
8188 case CP0_REGISTER_31:
8189 switch (sel) {
8190 case CP0_REG31__DESAVE:
8191 /* EJTAG support */
8192 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8193 register_name = "DESAVE";
8194 break;
8195 case CP0_REG31__KSCRATCH1:
8196 case CP0_REG31__KSCRATCH2:
8197 case CP0_REG31__KSCRATCH3:
8198 case CP0_REG31__KSCRATCH4:
8199 case CP0_REG31__KSCRATCH5:
8200 case CP0_REG31__KSCRATCH6:
8201 CP0_CHECK(ctx->kscrexist & (1 << sel));
8202 tcg_gen_ld_tl(arg, cpu_env,
8203 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8204 register_name = "KScratch";
8205 break;
8206 default:
8207 goto cp0_unimplemented;
8209 break;
8210 default:
8211 goto cp0_unimplemented;
8213 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
8214 return;
8216 cp0_unimplemented:
8217 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
8218 register_name, reg, sel);
8219 gen_mfc0_unimplemented(ctx, arg);
8222 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
8224 const char *register_name = "invalid";
8226 if (sel != 0) {
8227 check_insn(ctx, ISA_MIPS_R1);
8230 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8231 gen_io_start();
8234 switch (reg) {
8235 case CP0_REGISTER_00:
8236 switch (sel) {
8237 case CP0_REG00__INDEX:
8238 gen_helper_mtc0_index(cpu_env, arg);
8239 register_name = "Index";
8240 break;
8241 case CP0_REG00__MVPCONTROL:
8242 CP0_CHECK(ctx->insn_flags & ASE_MT);
8243 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
8244 register_name = "MVPControl";
8245 break;
8246 case CP0_REG00__MVPCONF0:
8247 CP0_CHECK(ctx->insn_flags & ASE_MT);
8248 /* ignored */
8249 register_name = "MVPConf0";
8250 break;
8251 case CP0_REG00__MVPCONF1:
8252 CP0_CHECK(ctx->insn_flags & ASE_MT);
8253 /* ignored */
8254 register_name = "MVPConf1";
8255 break;
8256 case CP0_REG00__VPCONTROL:
8257 CP0_CHECK(ctx->vp);
8258 /* ignored */
8259 register_name = "VPControl";
8260 break;
8261 default:
8262 goto cp0_unimplemented;
8264 break;
8265 case CP0_REGISTER_01:
8266 switch (sel) {
8267 case CP0_REG01__RANDOM:
8268 /* ignored */
8269 register_name = "Random";
8270 break;
8271 case CP0_REG01__VPECONTROL:
8272 CP0_CHECK(ctx->insn_flags & ASE_MT);
8273 gen_helper_mtc0_vpecontrol(cpu_env, arg);
8274 register_name = "VPEControl";
8275 break;
8276 case CP0_REG01__VPECONF0:
8277 CP0_CHECK(ctx->insn_flags & ASE_MT);
8278 gen_helper_mtc0_vpeconf0(cpu_env, arg);
8279 register_name = "VPEConf0";
8280 break;
8281 case CP0_REG01__VPECONF1:
8282 CP0_CHECK(ctx->insn_flags & ASE_MT);
8283 gen_helper_mtc0_vpeconf1(cpu_env, arg);
8284 register_name = "VPEConf1";
8285 break;
8286 case CP0_REG01__YQMASK:
8287 CP0_CHECK(ctx->insn_flags & ASE_MT);
8288 gen_helper_mtc0_yqmask(cpu_env, arg);
8289 register_name = "YQMask";
8290 break;
8291 case CP0_REG01__VPESCHEDULE:
8292 CP0_CHECK(ctx->insn_flags & ASE_MT);
8293 tcg_gen_st_tl(arg, cpu_env,
8294 offsetof(CPUMIPSState, CP0_VPESchedule));
8295 register_name = "VPESchedule";
8296 break;
8297 case CP0_REG01__VPESCHEFBACK:
8298 CP0_CHECK(ctx->insn_flags & ASE_MT);
8299 tcg_gen_st_tl(arg, cpu_env,
8300 offsetof(CPUMIPSState, CP0_VPEScheFBack));
8301 register_name = "VPEScheFBack";
8302 break;
8303 case CP0_REG01__VPEOPT:
8304 CP0_CHECK(ctx->insn_flags & ASE_MT);
8305 gen_helper_mtc0_vpeopt(cpu_env, arg);
8306 register_name = "VPEOpt";
8307 break;
8308 default:
8309 goto cp0_unimplemented;
8311 break;
8312 case CP0_REGISTER_02:
8313 switch (sel) {
8314 case CP0_REG02__ENTRYLO0:
8315 gen_helper_dmtc0_entrylo0(cpu_env, arg);
8316 register_name = "EntryLo0";
8317 break;
8318 case CP0_REG02__TCSTATUS:
8319 CP0_CHECK(ctx->insn_flags & ASE_MT);
8320 gen_helper_mtc0_tcstatus(cpu_env, arg);
8321 register_name = "TCStatus";
8322 break;
8323 case CP0_REG02__TCBIND:
8324 CP0_CHECK(ctx->insn_flags & ASE_MT);
8325 gen_helper_mtc0_tcbind(cpu_env, arg);
8326 register_name = "TCBind";
8327 break;
8328 case CP0_REG02__TCRESTART:
8329 CP0_CHECK(ctx->insn_flags & ASE_MT);
8330 gen_helper_mtc0_tcrestart(cpu_env, arg);
8331 register_name = "TCRestart";
8332 break;
8333 case CP0_REG02__TCHALT:
8334 CP0_CHECK(ctx->insn_flags & ASE_MT);
8335 gen_helper_mtc0_tchalt(cpu_env, arg);
8336 register_name = "TCHalt";
8337 break;
8338 case CP0_REG02__TCCONTEXT:
8339 CP0_CHECK(ctx->insn_flags & ASE_MT);
8340 gen_helper_mtc0_tccontext(cpu_env, arg);
8341 register_name = "TCContext";
8342 break;
8343 case CP0_REG02__TCSCHEDULE:
8344 CP0_CHECK(ctx->insn_flags & ASE_MT);
8345 gen_helper_mtc0_tcschedule(cpu_env, arg);
8346 register_name = "TCSchedule";
8347 break;
8348 case CP0_REG02__TCSCHEFBACK:
8349 CP0_CHECK(ctx->insn_flags & ASE_MT);
8350 gen_helper_mtc0_tcschefback(cpu_env, arg);
8351 register_name = "TCScheFBack";
8352 break;
8353 default:
8354 goto cp0_unimplemented;
8356 break;
8357 case CP0_REGISTER_03:
8358 switch (sel) {
8359 case CP0_REG03__ENTRYLO1:
8360 gen_helper_dmtc0_entrylo1(cpu_env, arg);
8361 register_name = "EntryLo1";
8362 break;
8363 case CP0_REG03__GLOBALNUM:
8364 CP0_CHECK(ctx->vp);
8365 /* ignored */
8366 register_name = "GlobalNumber";
8367 break;
8368 default:
8369 goto cp0_unimplemented;
8371 break;
8372 case CP0_REGISTER_04:
8373 switch (sel) {
8374 case CP0_REG04__CONTEXT:
8375 gen_helper_mtc0_context(cpu_env, arg);
8376 register_name = "Context";
8377 break;
8378 case CP0_REG04__CONTEXTCONFIG:
8379 /* SmartMIPS ASE */
8380 /* gen_helper_dmtc0_contextconfig(arg); */
8381 register_name = "ContextConfig";
8382 goto cp0_unimplemented;
8383 case CP0_REG04__USERLOCAL:
8384 CP0_CHECK(ctx->ulri);
8385 tcg_gen_st_tl(arg, cpu_env,
8386 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
8387 register_name = "UserLocal";
8388 break;
8389 case CP0_REG04__MMID:
8390 CP0_CHECK(ctx->mi);
8391 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
8392 register_name = "MMID";
8393 break;
8394 default:
8395 goto cp0_unimplemented;
8397 break;
8398 case CP0_REGISTER_05:
8399 switch (sel) {
8400 case CP0_REG05__PAGEMASK:
8401 gen_helper_mtc0_pagemask(cpu_env, arg);
8402 register_name = "PageMask";
8403 break;
8404 case CP0_REG05__PAGEGRAIN:
8405 check_insn(ctx, ISA_MIPS_R2);
8406 gen_helper_mtc0_pagegrain(cpu_env, arg);
8407 register_name = "PageGrain";
8408 break;
8409 case CP0_REG05__SEGCTL0:
8410 CP0_CHECK(ctx->sc);
8411 gen_helper_mtc0_segctl0(cpu_env, arg);
8412 register_name = "SegCtl0";
8413 break;
8414 case CP0_REG05__SEGCTL1:
8415 CP0_CHECK(ctx->sc);
8416 gen_helper_mtc0_segctl1(cpu_env, arg);
8417 register_name = "SegCtl1";
8418 break;
8419 case CP0_REG05__SEGCTL2:
8420 CP0_CHECK(ctx->sc);
8421 gen_helper_mtc0_segctl2(cpu_env, arg);
8422 register_name = "SegCtl2";
8423 break;
8424 case CP0_REG05__PWBASE:
8425 check_pw(ctx);
8426 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_PWBase));
8427 register_name = "PWBase";
8428 break;
8429 case CP0_REG05__PWFIELD:
8430 check_pw(ctx);
8431 gen_helper_mtc0_pwfield(cpu_env, arg);
8432 register_name = "PWField";
8433 break;
8434 case CP0_REG05__PWSIZE:
8435 check_pw(ctx);
8436 gen_helper_mtc0_pwsize(cpu_env, arg);
8437 register_name = "PWSize";
8438 break;
8439 default:
8440 goto cp0_unimplemented;
8442 break;
8443 case CP0_REGISTER_06:
8444 switch (sel) {
8445 case CP0_REG06__WIRED:
8446 gen_helper_mtc0_wired(cpu_env, arg);
8447 register_name = "Wired";
8448 break;
8449 case CP0_REG06__SRSCONF0:
8450 check_insn(ctx, ISA_MIPS_R2);
8451 gen_helper_mtc0_srsconf0(cpu_env, arg);
8452 register_name = "SRSConf0";
8453 break;
8454 case CP0_REG06__SRSCONF1:
8455 check_insn(ctx, ISA_MIPS_R2);
8456 gen_helper_mtc0_srsconf1(cpu_env, arg);
8457 register_name = "SRSConf1";
8458 break;
8459 case CP0_REG06__SRSCONF2:
8460 check_insn(ctx, ISA_MIPS_R2);
8461 gen_helper_mtc0_srsconf2(cpu_env, arg);
8462 register_name = "SRSConf2";
8463 break;
8464 case CP0_REG06__SRSCONF3:
8465 check_insn(ctx, ISA_MIPS_R2);
8466 gen_helper_mtc0_srsconf3(cpu_env, arg);
8467 register_name = "SRSConf3";
8468 break;
8469 case CP0_REG06__SRSCONF4:
8470 check_insn(ctx, ISA_MIPS_R2);
8471 gen_helper_mtc0_srsconf4(cpu_env, arg);
8472 register_name = "SRSConf4";
8473 break;
8474 case CP0_REG06__PWCTL:
8475 check_pw(ctx);
8476 gen_helper_mtc0_pwctl(cpu_env, arg);
8477 register_name = "PWCtl";
8478 break;
8479 default:
8480 goto cp0_unimplemented;
8482 break;
8483 case CP0_REGISTER_07:
8484 switch (sel) {
8485 case CP0_REG07__HWRENA:
8486 check_insn(ctx, ISA_MIPS_R2);
8487 gen_helper_mtc0_hwrena(cpu_env, arg);
8488 ctx->base.is_jmp = DISAS_STOP;
8489 register_name = "HWREna";
8490 break;
8491 default:
8492 goto cp0_unimplemented;
8494 break;
8495 case CP0_REGISTER_08:
8496 switch (sel) {
8497 case CP0_REG08__BADVADDR:
8498 /* ignored */
8499 register_name = "BadVAddr";
8500 break;
8501 case CP0_REG08__BADINSTR:
8502 /* ignored */
8503 register_name = "BadInstr";
8504 break;
8505 case CP0_REG08__BADINSTRP:
8506 /* ignored */
8507 register_name = "BadInstrP";
8508 break;
8509 case CP0_REG08__BADINSTRX:
8510 /* ignored */
8511 register_name = "BadInstrX";
8512 break;
8513 default:
8514 goto cp0_unimplemented;
8516 break;
8517 case CP0_REGISTER_09:
8518 switch (sel) {
8519 case CP0_REG09__COUNT:
8520 gen_helper_mtc0_count(cpu_env, arg);
8521 register_name = "Count";
8522 break;
8523 case CP0_REG09__SAARI:
8524 CP0_CHECK(ctx->saar);
8525 gen_helper_mtc0_saari(cpu_env, arg);
8526 register_name = "SAARI";
8527 break;
8528 case CP0_REG09__SAAR:
8529 CP0_CHECK(ctx->saar);
8530 gen_helper_mtc0_saar(cpu_env, arg);
8531 register_name = "SAAR";
8532 break;
8533 default:
8534 goto cp0_unimplemented;
8536 /* Stop translation as we may have switched the execution mode */
8537 ctx->base.is_jmp = DISAS_STOP;
8538 break;
8539 case CP0_REGISTER_10:
8540 switch (sel) {
8541 case CP0_REG10__ENTRYHI:
8542 gen_helper_mtc0_entryhi(cpu_env, arg);
8543 register_name = "EntryHi";
8544 break;
8545 default:
8546 goto cp0_unimplemented;
8548 break;
8549 case CP0_REGISTER_11:
8550 switch (sel) {
8551 case CP0_REG11__COMPARE:
8552 gen_helper_mtc0_compare(cpu_env, arg);
8553 register_name = "Compare";
8554 break;
8555 /* 6,7 are implementation dependent */
8556 default:
8557 goto cp0_unimplemented;
8559 /* Stop translation as we may have switched the execution mode */
8560 ctx->base.is_jmp = DISAS_STOP;
8561 break;
8562 case CP0_REGISTER_12:
8563 switch (sel) {
8564 case CP0_REG12__STATUS:
8565 save_cpu_state(ctx, 1);
8566 gen_helper_mtc0_status(cpu_env, arg);
8567 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8568 gen_save_pc(ctx->base.pc_next + 4);
8569 ctx->base.is_jmp = DISAS_EXIT;
8570 register_name = "Status";
8571 break;
8572 case CP0_REG12__INTCTL:
8573 check_insn(ctx, ISA_MIPS_R2);
8574 gen_helper_mtc0_intctl(cpu_env, arg);
8575 /* Stop translation as we may have switched the execution mode */
8576 ctx->base.is_jmp = DISAS_STOP;
8577 register_name = "IntCtl";
8578 break;
8579 case CP0_REG12__SRSCTL:
8580 check_insn(ctx, ISA_MIPS_R2);
8581 gen_helper_mtc0_srsctl(cpu_env, arg);
8582 /* Stop translation as we may have switched the execution mode */
8583 ctx->base.is_jmp = DISAS_STOP;
8584 register_name = "SRSCtl";
8585 break;
8586 case CP0_REG12__SRSMAP:
8587 check_insn(ctx, ISA_MIPS_R2);
8588 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
8589 /* Stop translation as we may have switched the execution mode */
8590 ctx->base.is_jmp = DISAS_STOP;
8591 register_name = "SRSMap";
8592 break;
8593 default:
8594 goto cp0_unimplemented;
8596 break;
8597 case CP0_REGISTER_13:
8598 switch (sel) {
8599 case CP0_REG13__CAUSE:
8600 save_cpu_state(ctx, 1);
8601 gen_helper_mtc0_cause(cpu_env, arg);
8603 * Stop translation as we may have triggered an interrupt.
8604 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8605 * translated code to check for pending interrupts.
8607 gen_save_pc(ctx->base.pc_next + 4);
8608 ctx->base.is_jmp = DISAS_EXIT;
8609 register_name = "Cause";
8610 break;
8611 default:
8612 goto cp0_unimplemented;
8614 break;
8615 case CP0_REGISTER_14:
8616 switch (sel) {
8617 case CP0_REG14__EPC:
8618 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
8619 register_name = "EPC";
8620 break;
8621 default:
8622 goto cp0_unimplemented;
8624 break;
8625 case CP0_REGISTER_15:
8626 switch (sel) {
8627 case CP0_REG15__PRID:
8628 /* ignored */
8629 register_name = "PRid";
8630 break;
8631 case CP0_REG15__EBASE:
8632 check_insn(ctx, ISA_MIPS_R2);
8633 gen_helper_mtc0_ebase(cpu_env, arg);
8634 register_name = "EBase";
8635 break;
8636 default:
8637 goto cp0_unimplemented;
8639 break;
8640 case CP0_REGISTER_16:
8641 switch (sel) {
8642 case CP0_REG16__CONFIG:
8643 gen_helper_mtc0_config0(cpu_env, arg);
8644 register_name = "Config";
8645 /* Stop translation as we may have switched the execution mode */
8646 ctx->base.is_jmp = DISAS_STOP;
8647 break;
8648 case CP0_REG16__CONFIG1:
8649 /* ignored, read only */
8650 register_name = "Config1";
8651 break;
8652 case CP0_REG16__CONFIG2:
8653 gen_helper_mtc0_config2(cpu_env, arg);
8654 register_name = "Config2";
8655 /* Stop translation as we may have switched the execution mode */
8656 ctx->base.is_jmp = DISAS_STOP;
8657 break;
8658 case CP0_REG16__CONFIG3:
8659 gen_helper_mtc0_config3(cpu_env, arg);
8660 register_name = "Config3";
8661 /* Stop translation as we may have switched the execution mode */
8662 ctx->base.is_jmp = DISAS_STOP;
8663 break;
8664 case CP0_REG16__CONFIG4:
8665 /* currently ignored */
8666 register_name = "Config4";
8667 break;
8668 case CP0_REG16__CONFIG5:
8669 gen_helper_mtc0_config5(cpu_env, arg);
8670 register_name = "Config5";
8671 /* Stop translation as we may have switched the execution mode */
8672 ctx->base.is_jmp = DISAS_STOP;
8673 break;
8674 /* 6,7 are implementation dependent */
8675 default:
8676 register_name = "Invalid config selector";
8677 goto cp0_unimplemented;
8679 break;
8680 case CP0_REGISTER_17:
8681 switch (sel) {
8682 case CP0_REG17__LLADDR:
8683 gen_helper_mtc0_lladdr(cpu_env, arg);
8684 register_name = "LLAddr";
8685 break;
8686 case CP0_REG17__MAAR:
8687 CP0_CHECK(ctx->mrp);
8688 gen_helper_mtc0_maar(cpu_env, arg);
8689 register_name = "MAAR";
8690 break;
8691 case CP0_REG17__MAARI:
8692 CP0_CHECK(ctx->mrp);
8693 gen_helper_mtc0_maari(cpu_env, arg);
8694 register_name = "MAARI";
8695 break;
8696 default:
8697 goto cp0_unimplemented;
8699 break;
8700 case CP0_REGISTER_18:
8701 switch (sel) {
8702 case CP0_REG18__WATCHLO0:
8703 case CP0_REG18__WATCHLO1:
8704 case CP0_REG18__WATCHLO2:
8705 case CP0_REG18__WATCHLO3:
8706 case CP0_REG18__WATCHLO4:
8707 case CP0_REG18__WATCHLO5:
8708 case CP0_REG18__WATCHLO6:
8709 case CP0_REG18__WATCHLO7:
8710 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8711 gen_helper_0e1i(mtc0_watchlo, arg, sel);
8712 register_name = "WatchLo";
8713 break;
8714 default:
8715 goto cp0_unimplemented;
8717 break;
8718 case CP0_REGISTER_19:
8719 switch (sel) {
8720 case CP0_REG19__WATCHHI0:
8721 case CP0_REG19__WATCHHI1:
8722 case CP0_REG19__WATCHHI2:
8723 case CP0_REG19__WATCHHI3:
8724 case CP0_REG19__WATCHHI4:
8725 case CP0_REG19__WATCHHI5:
8726 case CP0_REG19__WATCHHI6:
8727 case CP0_REG19__WATCHHI7:
8728 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
8729 gen_helper_0e1i(mtc0_watchhi, arg, sel);
8730 register_name = "WatchHi";
8731 break;
8732 default:
8733 goto cp0_unimplemented;
8735 break;
8736 case CP0_REGISTER_20:
8737 switch (sel) {
8738 case CP0_REG20__XCONTEXT:
8739 check_insn(ctx, ISA_MIPS3);
8740 gen_helper_mtc0_xcontext(cpu_env, arg);
8741 register_name = "XContext";
8742 break;
8743 default:
8744 goto cp0_unimplemented;
8746 break;
8747 case CP0_REGISTER_21:
8748 /* Officially reserved, but sel 0 is used for R1x000 framemask */
8749 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
8750 switch (sel) {
8751 case 0:
8752 gen_helper_mtc0_framemask(cpu_env, arg);
8753 register_name = "Framemask";
8754 break;
8755 default:
8756 goto cp0_unimplemented;
8758 break;
8759 case CP0_REGISTER_22:
8760 /* ignored */
8761 register_name = "Diagnostic"; /* implementation dependent */
8762 break;
8763 case CP0_REGISTER_23:
8764 switch (sel) {
8765 case CP0_REG23__DEBUG:
8766 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
8767 /* DISAS_STOP isn't good enough here, hflags may have changed. */
8768 gen_save_pc(ctx->base.pc_next + 4);
8769 ctx->base.is_jmp = DISAS_EXIT;
8770 register_name = "Debug";
8771 break;
8772 case CP0_REG23__TRACECONTROL:
8773 /* PDtrace support */
8774 /* gen_helper_mtc0_tracecontrol(cpu_env, arg); */
8775 /* Stop translation as we may have switched the execution mode */
8776 ctx->base.is_jmp = DISAS_STOP;
8777 register_name = "TraceControl";
8778 goto cp0_unimplemented;
8779 case CP0_REG23__TRACECONTROL2:
8780 /* PDtrace support */
8781 /* gen_helper_mtc0_tracecontrol2(cpu_env, arg); */
8782 /* Stop translation as we may have switched the execution mode */
8783 ctx->base.is_jmp = DISAS_STOP;
8784 register_name = "TraceControl2";
8785 goto cp0_unimplemented;
8786 case CP0_REG23__USERTRACEDATA1:
8787 /* PDtrace support */
8788 /* gen_helper_mtc0_usertracedata1(cpu_env, arg);*/
8789 /* Stop translation as we may have switched the execution mode */
8790 ctx->base.is_jmp = DISAS_STOP;
8791 register_name = "UserTraceData1";
8792 goto cp0_unimplemented;
8793 case CP0_REG23__TRACEIBPC:
8794 /* PDtrace support */
8795 /* gen_helper_mtc0_traceibpc(cpu_env, arg); */
8796 /* Stop translation as we may have switched the execution mode */
8797 ctx->base.is_jmp = DISAS_STOP;
8798 register_name = "TraceIBPC";
8799 goto cp0_unimplemented;
8800 case CP0_REG23__TRACEDBPC:
8801 /* PDtrace support */
8802 /* gen_helper_mtc0_tracedbpc(cpu_env, arg); */
8803 /* Stop translation as we may have switched the execution mode */
8804 ctx->base.is_jmp = DISAS_STOP;
8805 register_name = "TraceDBPC";
8806 goto cp0_unimplemented;
8807 default:
8808 goto cp0_unimplemented;
8810 break;
8811 case CP0_REGISTER_24:
8812 switch (sel) {
8813 case CP0_REG24__DEPC:
8814 /* EJTAG support */
8815 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
8816 register_name = "DEPC";
8817 break;
8818 default:
8819 goto cp0_unimplemented;
8821 break;
8822 case CP0_REGISTER_25:
8823 switch (sel) {
8824 case CP0_REG25__PERFCTL0:
8825 gen_helper_mtc0_performance0(cpu_env, arg);
8826 register_name = "Performance0";
8827 break;
8828 case CP0_REG25__PERFCNT0:
8829 /* gen_helper_mtc0_performance1(cpu_env, arg); */
8830 register_name = "Performance1";
8831 goto cp0_unimplemented;
8832 case CP0_REG25__PERFCTL1:
8833 /* gen_helper_mtc0_performance2(cpu_env, arg); */
8834 register_name = "Performance2";
8835 goto cp0_unimplemented;
8836 case CP0_REG25__PERFCNT1:
8837 /* gen_helper_mtc0_performance3(cpu_env, arg); */
8838 register_name = "Performance3";
8839 goto cp0_unimplemented;
8840 case CP0_REG25__PERFCTL2:
8841 /* gen_helper_mtc0_performance4(cpu_env, arg); */
8842 register_name = "Performance4";
8843 goto cp0_unimplemented;
8844 case CP0_REG25__PERFCNT2:
8845 /* gen_helper_mtc0_performance5(cpu_env, arg); */
8846 register_name = "Performance5";
8847 goto cp0_unimplemented;
8848 case CP0_REG25__PERFCTL3:
8849 /* gen_helper_mtc0_performance6(cpu_env, arg); */
8850 register_name = "Performance6";
8851 goto cp0_unimplemented;
8852 case CP0_REG25__PERFCNT3:
8853 /* gen_helper_mtc0_performance7(cpu_env, arg); */
8854 register_name = "Performance7";
8855 goto cp0_unimplemented;
8856 default:
8857 goto cp0_unimplemented;
8859 break;
8860 case CP0_REGISTER_26:
8861 switch (sel) {
8862 case CP0_REG26__ERRCTL:
8863 gen_helper_mtc0_errctl(cpu_env, arg);
8864 ctx->base.is_jmp = DISAS_STOP;
8865 register_name = "ErrCtl";
8866 break;
8867 default:
8868 goto cp0_unimplemented;
8870 break;
8871 case CP0_REGISTER_27:
8872 switch (sel) {
8873 case CP0_REG27__CACHERR:
8874 /* ignored */
8875 register_name = "CacheErr";
8876 break;
8877 default:
8878 goto cp0_unimplemented;
8880 break;
8881 case CP0_REGISTER_28:
8882 switch (sel) {
8883 case CP0_REG28__TAGLO:
8884 case CP0_REG28__TAGLO1:
8885 case CP0_REG28__TAGLO2:
8886 case CP0_REG28__TAGLO3:
8887 gen_helper_mtc0_taglo(cpu_env, arg);
8888 register_name = "TagLo";
8889 break;
8890 case CP0_REG28__DATALO:
8891 case CP0_REG28__DATALO1:
8892 case CP0_REG28__DATALO2:
8893 case CP0_REG28__DATALO3:
8894 gen_helper_mtc0_datalo(cpu_env, arg);
8895 register_name = "DataLo";
8896 break;
8897 default:
8898 goto cp0_unimplemented;
8900 break;
8901 case CP0_REGISTER_29:
8902 switch (sel) {
8903 case CP0_REG29__TAGHI:
8904 case CP0_REG29__TAGHI1:
8905 case CP0_REG29__TAGHI2:
8906 case CP0_REG29__TAGHI3:
8907 gen_helper_mtc0_taghi(cpu_env, arg);
8908 register_name = "TagHi";
8909 break;
8910 case CP0_REG29__DATAHI:
8911 case CP0_REG29__DATAHI1:
8912 case CP0_REG29__DATAHI2:
8913 case CP0_REG29__DATAHI3:
8914 gen_helper_mtc0_datahi(cpu_env, arg);
8915 register_name = "DataHi";
8916 break;
8917 default:
8918 register_name = "invalid sel";
8919 goto cp0_unimplemented;
8921 break;
8922 case CP0_REGISTER_30:
8923 switch (sel) {
8924 case CP0_REG30__ERROREPC:
8925 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8926 register_name = "ErrorEPC";
8927 break;
8928 default:
8929 goto cp0_unimplemented;
8931 break;
8932 case CP0_REGISTER_31:
8933 switch (sel) {
8934 case CP0_REG31__DESAVE:
8935 /* EJTAG support */
8936 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8937 register_name = "DESAVE";
8938 break;
8939 case CP0_REG31__KSCRATCH1:
8940 case CP0_REG31__KSCRATCH2:
8941 case CP0_REG31__KSCRATCH3:
8942 case CP0_REG31__KSCRATCH4:
8943 case CP0_REG31__KSCRATCH5:
8944 case CP0_REG31__KSCRATCH6:
8945 CP0_CHECK(ctx->kscrexist & (1 << sel));
8946 tcg_gen_st_tl(arg, cpu_env,
8947 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8948 register_name = "KScratch";
8949 break;
8950 default:
8951 goto cp0_unimplemented;
8953 break;
8954 default:
8955 goto cp0_unimplemented;
8957 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
8959 /* For simplicity assume that all writes can cause interrupts. */
8960 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
8962 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8963 * translated code to check for pending interrupts.
8965 gen_save_pc(ctx->base.pc_next + 4);
8966 ctx->base.is_jmp = DISAS_EXIT;
8968 return;
8970 cp0_unimplemented:
8971 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8972 register_name, reg, sel);
8974 #endif /* TARGET_MIPS64 */
8976 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8977 int u, int sel, int h)
8979 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8980 TCGv t0 = tcg_temp_local_new();
8982 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8983 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8984 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8985 tcg_gen_movi_tl(t0, -1);
8986 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8987 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8988 tcg_gen_movi_tl(t0, -1);
8989 } else if (u == 0) {
8990 switch (rt) {
8991 case 1:
8992 switch (sel) {
8993 case 1:
8994 gen_helper_mftc0_vpecontrol(t0, cpu_env);
8995 break;
8996 case 2:
8997 gen_helper_mftc0_vpeconf0(t0, cpu_env);
8998 break;
8999 default:
9000 goto die;
9001 break;
9003 break;
9004 case 2:
9005 switch (sel) {
9006 case 1:
9007 gen_helper_mftc0_tcstatus(t0, cpu_env);
9008 break;
9009 case 2:
9010 gen_helper_mftc0_tcbind(t0, cpu_env);
9011 break;
9012 case 3:
9013 gen_helper_mftc0_tcrestart(t0, cpu_env);
9014 break;
9015 case 4:
9016 gen_helper_mftc0_tchalt(t0, cpu_env);
9017 break;
9018 case 5:
9019 gen_helper_mftc0_tccontext(t0, cpu_env);
9020 break;
9021 case 6:
9022 gen_helper_mftc0_tcschedule(t0, cpu_env);
9023 break;
9024 case 7:
9025 gen_helper_mftc0_tcschefback(t0, cpu_env);
9026 break;
9027 default:
9028 gen_mfc0(ctx, t0, rt, sel);
9029 break;
9031 break;
9032 case 10:
9033 switch (sel) {
9034 case 0:
9035 gen_helper_mftc0_entryhi(t0, cpu_env);
9036 break;
9037 default:
9038 gen_mfc0(ctx, t0, rt, sel);
9039 break;
9041 break;
9042 case 12:
9043 switch (sel) {
9044 case 0:
9045 gen_helper_mftc0_status(t0, cpu_env);
9046 break;
9047 default:
9048 gen_mfc0(ctx, t0, rt, sel);
9049 break;
9051 break;
9052 case 13:
9053 switch (sel) {
9054 case 0:
9055 gen_helper_mftc0_cause(t0, cpu_env);
9056 break;
9057 default:
9058 goto die;
9059 break;
9061 break;
9062 case 14:
9063 switch (sel) {
9064 case 0:
9065 gen_helper_mftc0_epc(t0, cpu_env);
9066 break;
9067 default:
9068 goto die;
9069 break;
9071 break;
9072 case 15:
9073 switch (sel) {
9074 case 1:
9075 gen_helper_mftc0_ebase(t0, cpu_env);
9076 break;
9077 default:
9078 goto die;
9079 break;
9081 break;
9082 case 16:
9083 switch (sel) {
9084 case 0:
9085 case 1:
9086 case 2:
9087 case 3:
9088 case 4:
9089 case 5:
9090 case 6:
9091 case 7:
9092 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
9093 break;
9094 default:
9095 goto die;
9096 break;
9098 break;
9099 case 23:
9100 switch (sel) {
9101 case 0:
9102 gen_helper_mftc0_debug(t0, cpu_env);
9103 break;
9104 default:
9105 gen_mfc0(ctx, t0, rt, sel);
9106 break;
9108 break;
9109 default:
9110 gen_mfc0(ctx, t0, rt, sel);
9112 } else {
9113 switch (sel) {
9114 /* GPR registers. */
9115 case 0:
9116 gen_helper_1e0i(mftgpr, t0, rt);
9117 break;
9118 /* Auxiliary CPU registers */
9119 case 1:
9120 switch (rt) {
9121 case 0:
9122 gen_helper_1e0i(mftlo, t0, 0);
9123 break;
9124 case 1:
9125 gen_helper_1e0i(mfthi, t0, 0);
9126 break;
9127 case 2:
9128 gen_helper_1e0i(mftacx, t0, 0);
9129 break;
9130 case 4:
9131 gen_helper_1e0i(mftlo, t0, 1);
9132 break;
9133 case 5:
9134 gen_helper_1e0i(mfthi, t0, 1);
9135 break;
9136 case 6:
9137 gen_helper_1e0i(mftacx, t0, 1);
9138 break;
9139 case 8:
9140 gen_helper_1e0i(mftlo, t0, 2);
9141 break;
9142 case 9:
9143 gen_helper_1e0i(mfthi, t0, 2);
9144 break;
9145 case 10:
9146 gen_helper_1e0i(mftacx, t0, 2);
9147 break;
9148 case 12:
9149 gen_helper_1e0i(mftlo, t0, 3);
9150 break;
9151 case 13:
9152 gen_helper_1e0i(mfthi, t0, 3);
9153 break;
9154 case 14:
9155 gen_helper_1e0i(mftacx, t0, 3);
9156 break;
9157 case 16:
9158 gen_helper_mftdsp(t0, cpu_env);
9159 break;
9160 default:
9161 goto die;
9163 break;
9164 /* Floating point (COP1). */
9165 case 2:
9166 /* XXX: For now we support only a single FPU context. */
9167 if (h == 0) {
9168 TCGv_i32 fp0 = tcg_temp_new_i32();
9170 gen_load_fpr32(ctx, fp0, rt);
9171 tcg_gen_ext_i32_tl(t0, fp0);
9172 tcg_temp_free_i32(fp0);
9173 } else {
9174 TCGv_i32 fp0 = tcg_temp_new_i32();
9176 gen_load_fpr32h(ctx, fp0, rt);
9177 tcg_gen_ext_i32_tl(t0, fp0);
9178 tcg_temp_free_i32(fp0);
9180 break;
9181 case 3:
9182 /* XXX: For now we support only a single FPU context. */
9183 gen_helper_1e0i(cfc1, t0, rt);
9184 break;
9185 /* COP2: Not implemented. */
9186 case 4:
9187 case 5:
9188 /* fall through */
9189 default:
9190 goto die;
9193 trace_mips_translate_tr("mftr", rt, u, sel, h);
9194 gen_store_gpr(t0, rd);
9195 tcg_temp_free(t0);
9196 return;
9198 die:
9199 tcg_temp_free(t0);
9200 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
9201 gen_reserved_instruction(ctx);
9204 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
9205 int u, int sel, int h)
9207 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
9208 TCGv t0 = tcg_temp_local_new();
9210 gen_load_gpr(t0, rt);
9211 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
9212 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
9213 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
9214 /* NOP */
9216 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
9217 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
9218 /* NOP */
9220 } else if (u == 0) {
9221 switch (rd) {
9222 case 1:
9223 switch (sel) {
9224 case 1:
9225 gen_helper_mttc0_vpecontrol(cpu_env, t0);
9226 break;
9227 case 2:
9228 gen_helper_mttc0_vpeconf0(cpu_env, t0);
9229 break;
9230 default:
9231 goto die;
9232 break;
9234 break;
9235 case 2:
9236 switch (sel) {
9237 case 1:
9238 gen_helper_mttc0_tcstatus(cpu_env, t0);
9239 break;
9240 case 2:
9241 gen_helper_mttc0_tcbind(cpu_env, t0);
9242 break;
9243 case 3:
9244 gen_helper_mttc0_tcrestart(cpu_env, t0);
9245 break;
9246 case 4:
9247 gen_helper_mttc0_tchalt(cpu_env, t0);
9248 break;
9249 case 5:
9250 gen_helper_mttc0_tccontext(cpu_env, t0);
9251 break;
9252 case 6:
9253 gen_helper_mttc0_tcschedule(cpu_env, t0);
9254 break;
9255 case 7:
9256 gen_helper_mttc0_tcschefback(cpu_env, t0);
9257 break;
9258 default:
9259 gen_mtc0(ctx, t0, rd, sel);
9260 break;
9262 break;
9263 case 10:
9264 switch (sel) {
9265 case 0:
9266 gen_helper_mttc0_entryhi(cpu_env, t0);
9267 break;
9268 default:
9269 gen_mtc0(ctx, t0, rd, sel);
9270 break;
9272 break;
9273 case 12:
9274 switch (sel) {
9275 case 0:
9276 gen_helper_mttc0_status(cpu_env, t0);
9277 break;
9278 default:
9279 gen_mtc0(ctx, t0, rd, sel);
9280 break;
9282 break;
9283 case 13:
9284 switch (sel) {
9285 case 0:
9286 gen_helper_mttc0_cause(cpu_env, t0);
9287 break;
9288 default:
9289 goto die;
9290 break;
9292 break;
9293 case 15:
9294 switch (sel) {
9295 case 1:
9296 gen_helper_mttc0_ebase(cpu_env, t0);
9297 break;
9298 default:
9299 goto die;
9300 break;
9302 break;
9303 case 23:
9304 switch (sel) {
9305 case 0:
9306 gen_helper_mttc0_debug(cpu_env, t0);
9307 break;
9308 default:
9309 gen_mtc0(ctx, t0, rd, sel);
9310 break;
9312 break;
9313 default:
9314 gen_mtc0(ctx, t0, rd, sel);
9316 } else {
9317 switch (sel) {
9318 /* GPR registers. */
9319 case 0:
9320 gen_helper_0e1i(mttgpr, t0, rd);
9321 break;
9322 /* Auxiliary CPU registers */
9323 case 1:
9324 switch (rd) {
9325 case 0:
9326 gen_helper_0e1i(mttlo, t0, 0);
9327 break;
9328 case 1:
9329 gen_helper_0e1i(mtthi, t0, 0);
9330 break;
9331 case 2:
9332 gen_helper_0e1i(mttacx, t0, 0);
9333 break;
9334 case 4:
9335 gen_helper_0e1i(mttlo, t0, 1);
9336 break;
9337 case 5:
9338 gen_helper_0e1i(mtthi, t0, 1);
9339 break;
9340 case 6:
9341 gen_helper_0e1i(mttacx, t0, 1);
9342 break;
9343 case 8:
9344 gen_helper_0e1i(mttlo, t0, 2);
9345 break;
9346 case 9:
9347 gen_helper_0e1i(mtthi, t0, 2);
9348 break;
9349 case 10:
9350 gen_helper_0e1i(mttacx, t0, 2);
9351 break;
9352 case 12:
9353 gen_helper_0e1i(mttlo, t0, 3);
9354 break;
9355 case 13:
9356 gen_helper_0e1i(mtthi, t0, 3);
9357 break;
9358 case 14:
9359 gen_helper_0e1i(mttacx, t0, 3);
9360 break;
9361 case 16:
9362 gen_helper_mttdsp(cpu_env, t0);
9363 break;
9364 default:
9365 goto die;
9367 break;
9368 /* Floating point (COP1). */
9369 case 2:
9370 /* XXX: For now we support only a single FPU context. */
9371 if (h == 0) {
9372 TCGv_i32 fp0 = tcg_temp_new_i32();
9374 tcg_gen_trunc_tl_i32(fp0, t0);
9375 gen_store_fpr32(ctx, fp0, rd);
9376 tcg_temp_free_i32(fp0);
9377 } else {
9378 TCGv_i32 fp0 = tcg_temp_new_i32();
9380 tcg_gen_trunc_tl_i32(fp0, t0);
9381 gen_store_fpr32h(ctx, fp0, rd);
9382 tcg_temp_free_i32(fp0);
9384 break;
9385 case 3:
9386 /* XXX: For now we support only a single FPU context. */
9388 TCGv_i32 fs_tmp = tcg_const_i32(rd);
9390 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
9391 tcg_temp_free_i32(fs_tmp);
9393 /* Stop translation as we may have changed hflags */
9394 ctx->base.is_jmp = DISAS_STOP;
9395 break;
9396 /* COP2: Not implemented. */
9397 case 4:
9398 case 5:
9399 /* fall through */
9400 default:
9401 goto die;
9404 trace_mips_translate_tr("mttr", rd, u, sel, h);
9405 tcg_temp_free(t0);
9406 return;
9408 die:
9409 tcg_temp_free(t0);
9410 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
9411 gen_reserved_instruction(ctx);
9414 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
9415 int rt, int rd)
9417 const char *opn = "ldst";
9419 check_cp0_enabled(ctx);
9420 switch (opc) {
9421 case OPC_MFC0:
9422 if (rt == 0) {
9423 /* Treat as NOP. */
9424 return;
9426 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9427 opn = "mfc0";
9428 break;
9429 case OPC_MTC0:
9431 TCGv t0 = tcg_temp_new();
9433 gen_load_gpr(t0, rt);
9434 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
9435 tcg_temp_free(t0);
9437 opn = "mtc0";
9438 break;
9439 #if defined(TARGET_MIPS64)
9440 case OPC_DMFC0:
9441 check_insn(ctx, ISA_MIPS3);
9442 if (rt == 0) {
9443 /* Treat as NOP. */
9444 return;
9446 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9447 opn = "dmfc0";
9448 break;
9449 case OPC_DMTC0:
9450 check_insn(ctx, ISA_MIPS3);
9452 TCGv t0 = tcg_temp_new();
9454 gen_load_gpr(t0, rt);
9455 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
9456 tcg_temp_free(t0);
9458 opn = "dmtc0";
9459 break;
9460 #endif
9461 case OPC_MFHC0:
9462 check_mvh(ctx);
9463 if (rt == 0) {
9464 /* Treat as NOP. */
9465 return;
9467 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
9468 opn = "mfhc0";
9469 break;
9470 case OPC_MTHC0:
9471 check_mvh(ctx);
9473 TCGv t0 = tcg_temp_new();
9474 gen_load_gpr(t0, rt);
9475 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
9476 tcg_temp_free(t0);
9478 opn = "mthc0";
9479 break;
9480 case OPC_MFTR:
9481 check_cp0_enabled(ctx);
9482 if (rd == 0) {
9483 /* Treat as NOP. */
9484 return;
9486 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
9487 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9488 opn = "mftr";
9489 break;
9490 case OPC_MTTR:
9491 check_cp0_enabled(ctx);
9492 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
9493 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
9494 opn = "mttr";
9495 break;
9496 case OPC_TLBWI:
9497 opn = "tlbwi";
9498 if (!env->tlb->helper_tlbwi) {
9499 goto die;
9501 gen_helper_tlbwi(cpu_env);
9502 break;
9503 case OPC_TLBINV:
9504 opn = "tlbinv";
9505 if (ctx->ie >= 2) {
9506 if (!env->tlb->helper_tlbinv) {
9507 goto die;
9509 gen_helper_tlbinv(cpu_env);
9510 } /* treat as nop if TLBINV not supported */
9511 break;
9512 case OPC_TLBINVF:
9513 opn = "tlbinvf";
9514 if (ctx->ie >= 2) {
9515 if (!env->tlb->helper_tlbinvf) {
9516 goto die;
9518 gen_helper_tlbinvf(cpu_env);
9519 } /* treat as nop if TLBINV not supported */
9520 break;
9521 case OPC_TLBWR:
9522 opn = "tlbwr";
9523 if (!env->tlb->helper_tlbwr) {
9524 goto die;
9526 gen_helper_tlbwr(cpu_env);
9527 break;
9528 case OPC_TLBP:
9529 opn = "tlbp";
9530 if (!env->tlb->helper_tlbp) {
9531 goto die;
9533 gen_helper_tlbp(cpu_env);
9534 break;
9535 case OPC_TLBR:
9536 opn = "tlbr";
9537 if (!env->tlb->helper_tlbr) {
9538 goto die;
9540 gen_helper_tlbr(cpu_env);
9541 break;
9542 case OPC_ERET: /* OPC_ERETNC */
9543 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9544 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9545 goto die;
9546 } else {
9547 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
9548 if (ctx->opcode & (1 << bit_shift)) {
9549 /* OPC_ERETNC */
9550 opn = "eretnc";
9551 check_insn(ctx, ISA_MIPS_R5);
9552 gen_helper_eretnc(cpu_env);
9553 } else {
9554 /* OPC_ERET */
9555 opn = "eret";
9556 check_insn(ctx, ISA_MIPS2);
9557 gen_helper_eret(cpu_env);
9559 ctx->base.is_jmp = DISAS_EXIT;
9561 break;
9562 case OPC_DERET:
9563 opn = "deret";
9564 check_insn(ctx, ISA_MIPS_R1);
9565 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9566 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9567 goto die;
9569 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9570 MIPS_INVAL(opn);
9571 gen_reserved_instruction(ctx);
9572 } else {
9573 gen_helper_deret(cpu_env);
9574 ctx->base.is_jmp = DISAS_EXIT;
9576 break;
9577 case OPC_WAIT:
9578 opn = "wait";
9579 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
9580 if ((ctx->insn_flags & ISA_MIPS_R6) &&
9581 (ctx->hflags & MIPS_HFLAG_BMASK)) {
9582 goto die;
9584 /* If we get an exception, we want to restart at next instruction */
9585 ctx->base.pc_next += 4;
9586 save_cpu_state(ctx, 1);
9587 ctx->base.pc_next -= 4;
9588 gen_helper_wait(cpu_env);
9589 ctx->base.is_jmp = DISAS_NORETURN;
9590 break;
9591 default:
9592 die:
9593 MIPS_INVAL(opn);
9594 gen_reserved_instruction(ctx);
9595 return;
9597 (void)opn; /* avoid a compiler warning */
9599 #endif /* !CONFIG_USER_ONLY */
9601 /* CP1 Branches (before delay slot) */
9602 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
9603 int32_t cc, int32_t offset)
9605 target_ulong btarget;
9606 TCGv_i32 t0 = tcg_temp_new_i32();
9608 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9609 gen_reserved_instruction(ctx);
9610 goto out;
9613 if (cc != 0) {
9614 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
9617 btarget = ctx->base.pc_next + 4 + offset;
9619 switch (op) {
9620 case OPC_BC1F:
9621 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9622 tcg_gen_not_i32(t0, t0);
9623 tcg_gen_andi_i32(t0, t0, 1);
9624 tcg_gen_extu_i32_tl(bcond, t0);
9625 goto not_likely;
9626 case OPC_BC1FL:
9627 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9628 tcg_gen_not_i32(t0, t0);
9629 tcg_gen_andi_i32(t0, t0, 1);
9630 tcg_gen_extu_i32_tl(bcond, t0);
9631 goto likely;
9632 case OPC_BC1T:
9633 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9634 tcg_gen_andi_i32(t0, t0, 1);
9635 tcg_gen_extu_i32_tl(bcond, t0);
9636 goto not_likely;
9637 case OPC_BC1TL:
9638 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9639 tcg_gen_andi_i32(t0, t0, 1);
9640 tcg_gen_extu_i32_tl(bcond, t0);
9641 likely:
9642 ctx->hflags |= MIPS_HFLAG_BL;
9643 break;
9644 case OPC_BC1FANY2:
9646 TCGv_i32 t1 = tcg_temp_new_i32();
9647 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9648 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9649 tcg_gen_nand_i32(t0, t0, t1);
9650 tcg_temp_free_i32(t1);
9651 tcg_gen_andi_i32(t0, t0, 1);
9652 tcg_gen_extu_i32_tl(bcond, t0);
9654 goto not_likely;
9655 case OPC_BC1TANY2:
9657 TCGv_i32 t1 = tcg_temp_new_i32();
9658 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9659 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9660 tcg_gen_or_i32(t0, t0, t1);
9661 tcg_temp_free_i32(t1);
9662 tcg_gen_andi_i32(t0, t0, 1);
9663 tcg_gen_extu_i32_tl(bcond, t0);
9665 goto not_likely;
9666 case OPC_BC1FANY4:
9668 TCGv_i32 t1 = tcg_temp_new_i32();
9669 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9670 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9671 tcg_gen_and_i32(t0, t0, t1);
9672 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9673 tcg_gen_and_i32(t0, t0, t1);
9674 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9675 tcg_gen_nand_i32(t0, t0, t1);
9676 tcg_temp_free_i32(t1);
9677 tcg_gen_andi_i32(t0, t0, 1);
9678 tcg_gen_extu_i32_tl(bcond, t0);
9680 goto not_likely;
9681 case OPC_BC1TANY4:
9683 TCGv_i32 t1 = tcg_temp_new_i32();
9684 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
9685 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
9686 tcg_gen_or_i32(t0, t0, t1);
9687 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
9688 tcg_gen_or_i32(t0, t0, t1);
9689 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
9690 tcg_gen_or_i32(t0, t0, t1);
9691 tcg_temp_free_i32(t1);
9692 tcg_gen_andi_i32(t0, t0, 1);
9693 tcg_gen_extu_i32_tl(bcond, t0);
9695 not_likely:
9696 ctx->hflags |= MIPS_HFLAG_BC;
9697 break;
9698 default:
9699 MIPS_INVAL("cp1 cond branch");
9700 gen_reserved_instruction(ctx);
9701 goto out;
9703 ctx->btarget = btarget;
9704 ctx->hflags |= MIPS_HFLAG_BDS32;
9705 out:
9706 tcg_temp_free_i32(t0);
9709 /* R6 CP1 Branches */
9710 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
9711 int32_t ft, int32_t offset,
9712 int delayslot_size)
9714 target_ulong btarget;
9715 TCGv_i64 t0 = tcg_temp_new_i64();
9717 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9718 #ifdef MIPS_DEBUG_DISAS
9719 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
9720 "\n", ctx->base.pc_next);
9721 #endif
9722 gen_reserved_instruction(ctx);
9723 goto out;
9726 gen_load_fpr64(ctx, t0, ft);
9727 tcg_gen_andi_i64(t0, t0, 1);
9729 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
9731 switch (op) {
9732 case OPC_BC1EQZ:
9733 tcg_gen_xori_i64(t0, t0, 1);
9734 ctx->hflags |= MIPS_HFLAG_BC;
9735 break;
9736 case OPC_BC1NEZ:
9737 /* t0 already set */
9738 ctx->hflags |= MIPS_HFLAG_BC;
9739 break;
9740 default:
9741 MIPS_INVAL("cp1 cond branch");
9742 gen_reserved_instruction(ctx);
9743 goto out;
9746 tcg_gen_trunc_i64_tl(bcond, t0);
9748 ctx->btarget = btarget;
9750 switch (delayslot_size) {
9751 case 2:
9752 ctx->hflags |= MIPS_HFLAG_BDS16;
9753 break;
9754 case 4:
9755 ctx->hflags |= MIPS_HFLAG_BDS32;
9756 break;
9759 out:
9760 tcg_temp_free_i64(t0);
9763 /* Coprocessor 1 (FPU) */
9765 #define FOP(func, fmt) (((fmt) << 21) | (func))
9767 enum fopcode {
9768 OPC_ADD_S = FOP(0, FMT_S),
9769 OPC_SUB_S = FOP(1, FMT_S),
9770 OPC_MUL_S = FOP(2, FMT_S),
9771 OPC_DIV_S = FOP(3, FMT_S),
9772 OPC_SQRT_S = FOP(4, FMT_S),
9773 OPC_ABS_S = FOP(5, FMT_S),
9774 OPC_MOV_S = FOP(6, FMT_S),
9775 OPC_NEG_S = FOP(7, FMT_S),
9776 OPC_ROUND_L_S = FOP(8, FMT_S),
9777 OPC_TRUNC_L_S = FOP(9, FMT_S),
9778 OPC_CEIL_L_S = FOP(10, FMT_S),
9779 OPC_FLOOR_L_S = FOP(11, FMT_S),
9780 OPC_ROUND_W_S = FOP(12, FMT_S),
9781 OPC_TRUNC_W_S = FOP(13, FMT_S),
9782 OPC_CEIL_W_S = FOP(14, FMT_S),
9783 OPC_FLOOR_W_S = FOP(15, FMT_S),
9784 OPC_SEL_S = FOP(16, FMT_S),
9785 OPC_MOVCF_S = FOP(17, FMT_S),
9786 OPC_MOVZ_S = FOP(18, FMT_S),
9787 OPC_MOVN_S = FOP(19, FMT_S),
9788 OPC_SELEQZ_S = FOP(20, FMT_S),
9789 OPC_RECIP_S = FOP(21, FMT_S),
9790 OPC_RSQRT_S = FOP(22, FMT_S),
9791 OPC_SELNEZ_S = FOP(23, FMT_S),
9792 OPC_MADDF_S = FOP(24, FMT_S),
9793 OPC_MSUBF_S = FOP(25, FMT_S),
9794 OPC_RINT_S = FOP(26, FMT_S),
9795 OPC_CLASS_S = FOP(27, FMT_S),
9796 OPC_MIN_S = FOP(28, FMT_S),
9797 OPC_RECIP2_S = FOP(28, FMT_S),
9798 OPC_MINA_S = FOP(29, FMT_S),
9799 OPC_RECIP1_S = FOP(29, FMT_S),
9800 OPC_MAX_S = FOP(30, FMT_S),
9801 OPC_RSQRT1_S = FOP(30, FMT_S),
9802 OPC_MAXA_S = FOP(31, FMT_S),
9803 OPC_RSQRT2_S = FOP(31, FMT_S),
9804 OPC_CVT_D_S = FOP(33, FMT_S),
9805 OPC_CVT_W_S = FOP(36, FMT_S),
9806 OPC_CVT_L_S = FOP(37, FMT_S),
9807 OPC_CVT_PS_S = FOP(38, FMT_S),
9808 OPC_CMP_F_S = FOP(48, FMT_S),
9809 OPC_CMP_UN_S = FOP(49, FMT_S),
9810 OPC_CMP_EQ_S = FOP(50, FMT_S),
9811 OPC_CMP_UEQ_S = FOP(51, FMT_S),
9812 OPC_CMP_OLT_S = FOP(52, FMT_S),
9813 OPC_CMP_ULT_S = FOP(53, FMT_S),
9814 OPC_CMP_OLE_S = FOP(54, FMT_S),
9815 OPC_CMP_ULE_S = FOP(55, FMT_S),
9816 OPC_CMP_SF_S = FOP(56, FMT_S),
9817 OPC_CMP_NGLE_S = FOP(57, FMT_S),
9818 OPC_CMP_SEQ_S = FOP(58, FMT_S),
9819 OPC_CMP_NGL_S = FOP(59, FMT_S),
9820 OPC_CMP_LT_S = FOP(60, FMT_S),
9821 OPC_CMP_NGE_S = FOP(61, FMT_S),
9822 OPC_CMP_LE_S = FOP(62, FMT_S),
9823 OPC_CMP_NGT_S = FOP(63, FMT_S),
9825 OPC_ADD_D = FOP(0, FMT_D),
9826 OPC_SUB_D = FOP(1, FMT_D),
9827 OPC_MUL_D = FOP(2, FMT_D),
9828 OPC_DIV_D = FOP(3, FMT_D),
9829 OPC_SQRT_D = FOP(4, FMT_D),
9830 OPC_ABS_D = FOP(5, FMT_D),
9831 OPC_MOV_D = FOP(6, FMT_D),
9832 OPC_NEG_D = FOP(7, FMT_D),
9833 OPC_ROUND_L_D = FOP(8, FMT_D),
9834 OPC_TRUNC_L_D = FOP(9, FMT_D),
9835 OPC_CEIL_L_D = FOP(10, FMT_D),
9836 OPC_FLOOR_L_D = FOP(11, FMT_D),
9837 OPC_ROUND_W_D = FOP(12, FMT_D),
9838 OPC_TRUNC_W_D = FOP(13, FMT_D),
9839 OPC_CEIL_W_D = FOP(14, FMT_D),
9840 OPC_FLOOR_W_D = FOP(15, FMT_D),
9841 OPC_SEL_D = FOP(16, FMT_D),
9842 OPC_MOVCF_D = FOP(17, FMT_D),
9843 OPC_MOVZ_D = FOP(18, FMT_D),
9844 OPC_MOVN_D = FOP(19, FMT_D),
9845 OPC_SELEQZ_D = FOP(20, FMT_D),
9846 OPC_RECIP_D = FOP(21, FMT_D),
9847 OPC_RSQRT_D = FOP(22, FMT_D),
9848 OPC_SELNEZ_D = FOP(23, FMT_D),
9849 OPC_MADDF_D = FOP(24, FMT_D),
9850 OPC_MSUBF_D = FOP(25, FMT_D),
9851 OPC_RINT_D = FOP(26, FMT_D),
9852 OPC_CLASS_D = FOP(27, FMT_D),
9853 OPC_MIN_D = FOP(28, FMT_D),
9854 OPC_RECIP2_D = FOP(28, FMT_D),
9855 OPC_MINA_D = FOP(29, FMT_D),
9856 OPC_RECIP1_D = FOP(29, FMT_D),
9857 OPC_MAX_D = FOP(30, FMT_D),
9858 OPC_RSQRT1_D = FOP(30, FMT_D),
9859 OPC_MAXA_D = FOP(31, FMT_D),
9860 OPC_RSQRT2_D = FOP(31, FMT_D),
9861 OPC_CVT_S_D = FOP(32, FMT_D),
9862 OPC_CVT_W_D = FOP(36, FMT_D),
9863 OPC_CVT_L_D = FOP(37, FMT_D),
9864 OPC_CMP_F_D = FOP(48, FMT_D),
9865 OPC_CMP_UN_D = FOP(49, FMT_D),
9866 OPC_CMP_EQ_D = FOP(50, FMT_D),
9867 OPC_CMP_UEQ_D = FOP(51, FMT_D),
9868 OPC_CMP_OLT_D = FOP(52, FMT_D),
9869 OPC_CMP_ULT_D = FOP(53, FMT_D),
9870 OPC_CMP_OLE_D = FOP(54, FMT_D),
9871 OPC_CMP_ULE_D = FOP(55, FMT_D),
9872 OPC_CMP_SF_D = FOP(56, FMT_D),
9873 OPC_CMP_NGLE_D = FOP(57, FMT_D),
9874 OPC_CMP_SEQ_D = FOP(58, FMT_D),
9875 OPC_CMP_NGL_D = FOP(59, FMT_D),
9876 OPC_CMP_LT_D = FOP(60, FMT_D),
9877 OPC_CMP_NGE_D = FOP(61, FMT_D),
9878 OPC_CMP_LE_D = FOP(62, FMT_D),
9879 OPC_CMP_NGT_D = FOP(63, FMT_D),
9881 OPC_CVT_S_W = FOP(32, FMT_W),
9882 OPC_CVT_D_W = FOP(33, FMT_W),
9883 OPC_CVT_S_L = FOP(32, FMT_L),
9884 OPC_CVT_D_L = FOP(33, FMT_L),
9885 OPC_CVT_PS_PW = FOP(38, FMT_W),
9887 OPC_ADD_PS = FOP(0, FMT_PS),
9888 OPC_SUB_PS = FOP(1, FMT_PS),
9889 OPC_MUL_PS = FOP(2, FMT_PS),
9890 OPC_DIV_PS = FOP(3, FMT_PS),
9891 OPC_ABS_PS = FOP(5, FMT_PS),
9892 OPC_MOV_PS = FOP(6, FMT_PS),
9893 OPC_NEG_PS = FOP(7, FMT_PS),
9894 OPC_MOVCF_PS = FOP(17, FMT_PS),
9895 OPC_MOVZ_PS = FOP(18, FMT_PS),
9896 OPC_MOVN_PS = FOP(19, FMT_PS),
9897 OPC_ADDR_PS = FOP(24, FMT_PS),
9898 OPC_MULR_PS = FOP(26, FMT_PS),
9899 OPC_RECIP2_PS = FOP(28, FMT_PS),
9900 OPC_RECIP1_PS = FOP(29, FMT_PS),
9901 OPC_RSQRT1_PS = FOP(30, FMT_PS),
9902 OPC_RSQRT2_PS = FOP(31, FMT_PS),
9904 OPC_CVT_S_PU = FOP(32, FMT_PS),
9905 OPC_CVT_PW_PS = FOP(36, FMT_PS),
9906 OPC_CVT_S_PL = FOP(40, FMT_PS),
9907 OPC_PLL_PS = FOP(44, FMT_PS),
9908 OPC_PLU_PS = FOP(45, FMT_PS),
9909 OPC_PUL_PS = FOP(46, FMT_PS),
9910 OPC_PUU_PS = FOP(47, FMT_PS),
9911 OPC_CMP_F_PS = FOP(48, FMT_PS),
9912 OPC_CMP_UN_PS = FOP(49, FMT_PS),
9913 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
9914 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
9915 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
9916 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
9917 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
9918 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
9919 OPC_CMP_SF_PS = FOP(56, FMT_PS),
9920 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
9921 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
9922 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
9923 OPC_CMP_LT_PS = FOP(60, FMT_PS),
9924 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
9925 OPC_CMP_LE_PS = FOP(62, FMT_PS),
9926 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
9929 enum r6_f_cmp_op {
9930 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
9931 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
9932 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
9933 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
9934 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
9935 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
9936 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9937 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9938 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9939 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9940 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9941 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9942 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9943 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9944 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9945 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9946 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9947 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9948 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9949 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9950 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9951 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9953 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9954 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9955 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9956 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9957 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9958 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9959 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9960 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9961 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9962 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9963 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9964 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9965 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9966 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9967 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9968 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9969 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9970 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9971 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9972 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9973 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9974 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9977 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
9979 TCGv t0 = tcg_temp_new();
9981 switch (opc) {
9982 case OPC_MFC1:
9984 TCGv_i32 fp0 = tcg_temp_new_i32();
9986 gen_load_fpr32(ctx, fp0, fs);
9987 tcg_gen_ext_i32_tl(t0, fp0);
9988 tcg_temp_free_i32(fp0);
9990 gen_store_gpr(t0, rt);
9991 break;
9992 case OPC_MTC1:
9993 gen_load_gpr(t0, rt);
9995 TCGv_i32 fp0 = tcg_temp_new_i32();
9997 tcg_gen_trunc_tl_i32(fp0, t0);
9998 gen_store_fpr32(ctx, fp0, fs);
9999 tcg_temp_free_i32(fp0);
10001 break;
10002 case OPC_CFC1:
10003 gen_helper_1e0i(cfc1, t0, fs);
10004 gen_store_gpr(t0, rt);
10005 break;
10006 case OPC_CTC1:
10007 gen_load_gpr(t0, rt);
10008 save_cpu_state(ctx, 0);
10010 TCGv_i32 fs_tmp = tcg_const_i32(fs);
10012 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
10013 tcg_temp_free_i32(fs_tmp);
10015 /* Stop translation as we may have changed hflags */
10016 ctx->base.is_jmp = DISAS_STOP;
10017 break;
10018 #if defined(TARGET_MIPS64)
10019 case OPC_DMFC1:
10020 gen_load_fpr64(ctx, t0, fs);
10021 gen_store_gpr(t0, rt);
10022 break;
10023 case OPC_DMTC1:
10024 gen_load_gpr(t0, rt);
10025 gen_store_fpr64(ctx, t0, fs);
10026 break;
10027 #endif
10028 case OPC_MFHC1:
10030 TCGv_i32 fp0 = tcg_temp_new_i32();
10032 gen_load_fpr32h(ctx, fp0, fs);
10033 tcg_gen_ext_i32_tl(t0, fp0);
10034 tcg_temp_free_i32(fp0);
10036 gen_store_gpr(t0, rt);
10037 break;
10038 case OPC_MTHC1:
10039 gen_load_gpr(t0, rt);
10041 TCGv_i32 fp0 = tcg_temp_new_i32();
10043 tcg_gen_trunc_tl_i32(fp0, t0);
10044 gen_store_fpr32h(ctx, fp0, fs);
10045 tcg_temp_free_i32(fp0);
10047 break;
10048 default:
10049 MIPS_INVAL("cp1 move");
10050 gen_reserved_instruction(ctx);
10051 goto out;
10054 out:
10055 tcg_temp_free(t0);
10058 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
10060 TCGLabel *l1;
10061 TCGCond cond;
10062 TCGv_i32 t0;
10064 if (rd == 0) {
10065 /* Treat as NOP. */
10066 return;
10069 if (tf) {
10070 cond = TCG_COND_EQ;
10071 } else {
10072 cond = TCG_COND_NE;
10075 l1 = gen_new_label();
10076 t0 = tcg_temp_new_i32();
10077 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10078 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10079 tcg_temp_free_i32(t0);
10080 gen_load_gpr(cpu_gpr[rd], rs);
10081 gen_set_label(l1);
10084 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
10085 int tf)
10087 int cond;
10088 TCGv_i32 t0 = tcg_temp_new_i32();
10089 TCGLabel *l1 = gen_new_label();
10091 if (tf) {
10092 cond = TCG_COND_EQ;
10093 } else {
10094 cond = TCG_COND_NE;
10097 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10098 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10099 gen_load_fpr32(ctx, t0, fs);
10100 gen_store_fpr32(ctx, t0, fd);
10101 gen_set_label(l1);
10102 tcg_temp_free_i32(t0);
10105 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
10106 int tf)
10108 int cond;
10109 TCGv_i32 t0 = tcg_temp_new_i32();
10110 TCGv_i64 fp0;
10111 TCGLabel *l1 = gen_new_label();
10113 if (tf) {
10114 cond = TCG_COND_EQ;
10115 } else {
10116 cond = TCG_COND_NE;
10119 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10120 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10121 tcg_temp_free_i32(t0);
10122 fp0 = tcg_temp_new_i64();
10123 gen_load_fpr64(ctx, fp0, fs);
10124 gen_store_fpr64(ctx, fp0, fd);
10125 tcg_temp_free_i64(fp0);
10126 gen_set_label(l1);
10129 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
10130 int cc, int tf)
10132 int cond;
10133 TCGv_i32 t0 = tcg_temp_new_i32();
10134 TCGLabel *l1 = gen_new_label();
10135 TCGLabel *l2 = gen_new_label();
10137 if (tf) {
10138 cond = TCG_COND_EQ;
10139 } else {
10140 cond = TCG_COND_NE;
10143 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
10144 tcg_gen_brcondi_i32(cond, t0, 0, l1);
10145 gen_load_fpr32(ctx, t0, fs);
10146 gen_store_fpr32(ctx, t0, fd);
10147 gen_set_label(l1);
10149 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
10150 tcg_gen_brcondi_i32(cond, t0, 0, l2);
10151 gen_load_fpr32h(ctx, t0, fs);
10152 gen_store_fpr32h(ctx, t0, fd);
10153 tcg_temp_free_i32(t0);
10154 gen_set_label(l2);
10157 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10158 int fs)
10160 TCGv_i32 t1 = tcg_const_i32(0);
10161 TCGv_i32 fp0 = tcg_temp_new_i32();
10162 TCGv_i32 fp1 = tcg_temp_new_i32();
10163 TCGv_i32 fp2 = tcg_temp_new_i32();
10164 gen_load_fpr32(ctx, fp0, fd);
10165 gen_load_fpr32(ctx, fp1, ft);
10166 gen_load_fpr32(ctx, fp2, fs);
10168 switch (op1) {
10169 case OPC_SEL_S:
10170 tcg_gen_andi_i32(fp0, fp0, 1);
10171 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10172 break;
10173 case OPC_SELEQZ_S:
10174 tcg_gen_andi_i32(fp1, fp1, 1);
10175 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10176 break;
10177 case OPC_SELNEZ_S:
10178 tcg_gen_andi_i32(fp1, fp1, 1);
10179 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10180 break;
10181 default:
10182 MIPS_INVAL("gen_sel_s");
10183 gen_reserved_instruction(ctx);
10184 break;
10187 gen_store_fpr32(ctx, fp0, fd);
10188 tcg_temp_free_i32(fp2);
10189 tcg_temp_free_i32(fp1);
10190 tcg_temp_free_i32(fp0);
10191 tcg_temp_free_i32(t1);
10194 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
10195 int fs)
10197 TCGv_i64 t1 = tcg_const_i64(0);
10198 TCGv_i64 fp0 = tcg_temp_new_i64();
10199 TCGv_i64 fp1 = tcg_temp_new_i64();
10200 TCGv_i64 fp2 = tcg_temp_new_i64();
10201 gen_load_fpr64(ctx, fp0, fd);
10202 gen_load_fpr64(ctx, fp1, ft);
10203 gen_load_fpr64(ctx, fp2, fs);
10205 switch (op1) {
10206 case OPC_SEL_D:
10207 tcg_gen_andi_i64(fp0, fp0, 1);
10208 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
10209 break;
10210 case OPC_SELEQZ_D:
10211 tcg_gen_andi_i64(fp1, fp1, 1);
10212 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
10213 break;
10214 case OPC_SELNEZ_D:
10215 tcg_gen_andi_i64(fp1, fp1, 1);
10216 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
10217 break;
10218 default:
10219 MIPS_INVAL("gen_sel_d");
10220 gen_reserved_instruction(ctx);
10221 break;
10224 gen_store_fpr64(ctx, fp0, fd);
10225 tcg_temp_free_i64(fp2);
10226 tcg_temp_free_i64(fp1);
10227 tcg_temp_free_i64(fp0);
10228 tcg_temp_free_i64(t1);
10231 static void gen_farith(DisasContext *ctx, enum fopcode op1,
10232 int ft, int fs, int fd, int cc)
10234 uint32_t func = ctx->opcode & 0x3f;
10235 switch (op1) {
10236 case OPC_ADD_S:
10238 TCGv_i32 fp0 = tcg_temp_new_i32();
10239 TCGv_i32 fp1 = tcg_temp_new_i32();
10241 gen_load_fpr32(ctx, fp0, fs);
10242 gen_load_fpr32(ctx, fp1, ft);
10243 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
10244 tcg_temp_free_i32(fp1);
10245 gen_store_fpr32(ctx, fp0, fd);
10246 tcg_temp_free_i32(fp0);
10248 break;
10249 case OPC_SUB_S:
10251 TCGv_i32 fp0 = tcg_temp_new_i32();
10252 TCGv_i32 fp1 = tcg_temp_new_i32();
10254 gen_load_fpr32(ctx, fp0, fs);
10255 gen_load_fpr32(ctx, fp1, ft);
10256 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
10257 tcg_temp_free_i32(fp1);
10258 gen_store_fpr32(ctx, fp0, fd);
10259 tcg_temp_free_i32(fp0);
10261 break;
10262 case OPC_MUL_S:
10264 TCGv_i32 fp0 = tcg_temp_new_i32();
10265 TCGv_i32 fp1 = tcg_temp_new_i32();
10267 gen_load_fpr32(ctx, fp0, fs);
10268 gen_load_fpr32(ctx, fp1, ft);
10269 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
10270 tcg_temp_free_i32(fp1);
10271 gen_store_fpr32(ctx, fp0, fd);
10272 tcg_temp_free_i32(fp0);
10274 break;
10275 case OPC_DIV_S:
10277 TCGv_i32 fp0 = tcg_temp_new_i32();
10278 TCGv_i32 fp1 = tcg_temp_new_i32();
10280 gen_load_fpr32(ctx, fp0, fs);
10281 gen_load_fpr32(ctx, fp1, ft);
10282 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
10283 tcg_temp_free_i32(fp1);
10284 gen_store_fpr32(ctx, fp0, fd);
10285 tcg_temp_free_i32(fp0);
10287 break;
10288 case OPC_SQRT_S:
10290 TCGv_i32 fp0 = tcg_temp_new_i32();
10292 gen_load_fpr32(ctx, fp0, fs);
10293 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
10294 gen_store_fpr32(ctx, fp0, fd);
10295 tcg_temp_free_i32(fp0);
10297 break;
10298 case OPC_ABS_S:
10300 TCGv_i32 fp0 = tcg_temp_new_i32();
10302 gen_load_fpr32(ctx, fp0, fs);
10303 if (ctx->abs2008) {
10304 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
10305 } else {
10306 gen_helper_float_abs_s(fp0, fp0);
10308 gen_store_fpr32(ctx, fp0, fd);
10309 tcg_temp_free_i32(fp0);
10311 break;
10312 case OPC_MOV_S:
10314 TCGv_i32 fp0 = tcg_temp_new_i32();
10316 gen_load_fpr32(ctx, fp0, fs);
10317 gen_store_fpr32(ctx, fp0, fd);
10318 tcg_temp_free_i32(fp0);
10320 break;
10321 case OPC_NEG_S:
10323 TCGv_i32 fp0 = tcg_temp_new_i32();
10325 gen_load_fpr32(ctx, fp0, fs);
10326 if (ctx->abs2008) {
10327 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
10328 } else {
10329 gen_helper_float_chs_s(fp0, fp0);
10331 gen_store_fpr32(ctx, fp0, fd);
10332 tcg_temp_free_i32(fp0);
10334 break;
10335 case OPC_ROUND_L_S:
10336 check_cp1_64bitmode(ctx);
10338 TCGv_i32 fp32 = tcg_temp_new_i32();
10339 TCGv_i64 fp64 = tcg_temp_new_i64();
10341 gen_load_fpr32(ctx, fp32, fs);
10342 if (ctx->nan2008) {
10343 gen_helper_float_round_2008_l_s(fp64, cpu_env, fp32);
10344 } else {
10345 gen_helper_float_round_l_s(fp64, cpu_env, fp32);
10347 tcg_temp_free_i32(fp32);
10348 gen_store_fpr64(ctx, fp64, fd);
10349 tcg_temp_free_i64(fp64);
10351 break;
10352 case OPC_TRUNC_L_S:
10353 check_cp1_64bitmode(ctx);
10355 TCGv_i32 fp32 = tcg_temp_new_i32();
10356 TCGv_i64 fp64 = tcg_temp_new_i64();
10358 gen_load_fpr32(ctx, fp32, fs);
10359 if (ctx->nan2008) {
10360 gen_helper_float_trunc_2008_l_s(fp64, cpu_env, fp32);
10361 } else {
10362 gen_helper_float_trunc_l_s(fp64, cpu_env, fp32);
10364 tcg_temp_free_i32(fp32);
10365 gen_store_fpr64(ctx, fp64, fd);
10366 tcg_temp_free_i64(fp64);
10368 break;
10369 case OPC_CEIL_L_S:
10370 check_cp1_64bitmode(ctx);
10372 TCGv_i32 fp32 = tcg_temp_new_i32();
10373 TCGv_i64 fp64 = tcg_temp_new_i64();
10375 gen_load_fpr32(ctx, fp32, fs);
10376 if (ctx->nan2008) {
10377 gen_helper_float_ceil_2008_l_s(fp64, cpu_env, fp32);
10378 } else {
10379 gen_helper_float_ceil_l_s(fp64, cpu_env, fp32);
10381 tcg_temp_free_i32(fp32);
10382 gen_store_fpr64(ctx, fp64, fd);
10383 tcg_temp_free_i64(fp64);
10385 break;
10386 case OPC_FLOOR_L_S:
10387 check_cp1_64bitmode(ctx);
10389 TCGv_i32 fp32 = tcg_temp_new_i32();
10390 TCGv_i64 fp64 = tcg_temp_new_i64();
10392 gen_load_fpr32(ctx, fp32, fs);
10393 if (ctx->nan2008) {
10394 gen_helper_float_floor_2008_l_s(fp64, cpu_env, fp32);
10395 } else {
10396 gen_helper_float_floor_l_s(fp64, cpu_env, fp32);
10398 tcg_temp_free_i32(fp32);
10399 gen_store_fpr64(ctx, fp64, fd);
10400 tcg_temp_free_i64(fp64);
10402 break;
10403 case OPC_ROUND_W_S:
10405 TCGv_i32 fp0 = tcg_temp_new_i32();
10407 gen_load_fpr32(ctx, fp0, fs);
10408 if (ctx->nan2008) {
10409 gen_helper_float_round_2008_w_s(fp0, cpu_env, fp0);
10410 } else {
10411 gen_helper_float_round_w_s(fp0, cpu_env, fp0);
10413 gen_store_fpr32(ctx, fp0, fd);
10414 tcg_temp_free_i32(fp0);
10416 break;
10417 case OPC_TRUNC_W_S:
10419 TCGv_i32 fp0 = tcg_temp_new_i32();
10421 gen_load_fpr32(ctx, fp0, fs);
10422 if (ctx->nan2008) {
10423 gen_helper_float_trunc_2008_w_s(fp0, cpu_env, fp0);
10424 } else {
10425 gen_helper_float_trunc_w_s(fp0, cpu_env, fp0);
10427 gen_store_fpr32(ctx, fp0, fd);
10428 tcg_temp_free_i32(fp0);
10430 break;
10431 case OPC_CEIL_W_S:
10433 TCGv_i32 fp0 = tcg_temp_new_i32();
10435 gen_load_fpr32(ctx, fp0, fs);
10436 if (ctx->nan2008) {
10437 gen_helper_float_ceil_2008_w_s(fp0, cpu_env, fp0);
10438 } else {
10439 gen_helper_float_ceil_w_s(fp0, cpu_env, fp0);
10441 gen_store_fpr32(ctx, fp0, fd);
10442 tcg_temp_free_i32(fp0);
10444 break;
10445 case OPC_FLOOR_W_S:
10447 TCGv_i32 fp0 = tcg_temp_new_i32();
10449 gen_load_fpr32(ctx, fp0, fs);
10450 if (ctx->nan2008) {
10451 gen_helper_float_floor_2008_w_s(fp0, cpu_env, fp0);
10452 } else {
10453 gen_helper_float_floor_w_s(fp0, cpu_env, fp0);
10455 gen_store_fpr32(ctx, fp0, fd);
10456 tcg_temp_free_i32(fp0);
10458 break;
10459 case OPC_SEL_S:
10460 check_insn(ctx, ISA_MIPS_R6);
10461 gen_sel_s(ctx, op1, fd, ft, fs);
10462 break;
10463 case OPC_SELEQZ_S:
10464 check_insn(ctx, ISA_MIPS_R6);
10465 gen_sel_s(ctx, op1, fd, ft, fs);
10466 break;
10467 case OPC_SELNEZ_S:
10468 check_insn(ctx, ISA_MIPS_R6);
10469 gen_sel_s(ctx, op1, fd, ft, fs);
10470 break;
10471 case OPC_MOVCF_S:
10472 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10473 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10474 break;
10475 case OPC_MOVZ_S:
10476 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10478 TCGLabel *l1 = gen_new_label();
10479 TCGv_i32 fp0;
10481 if (ft != 0) {
10482 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10484 fp0 = tcg_temp_new_i32();
10485 gen_load_fpr32(ctx, fp0, fs);
10486 gen_store_fpr32(ctx, fp0, fd);
10487 tcg_temp_free_i32(fp0);
10488 gen_set_label(l1);
10490 break;
10491 case OPC_MOVN_S:
10492 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10494 TCGLabel *l1 = gen_new_label();
10495 TCGv_i32 fp0;
10497 if (ft != 0) {
10498 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10499 fp0 = tcg_temp_new_i32();
10500 gen_load_fpr32(ctx, fp0, fs);
10501 gen_store_fpr32(ctx, fp0, fd);
10502 tcg_temp_free_i32(fp0);
10503 gen_set_label(l1);
10506 break;
10507 case OPC_RECIP_S:
10509 TCGv_i32 fp0 = tcg_temp_new_i32();
10511 gen_load_fpr32(ctx, fp0, fs);
10512 gen_helper_float_recip_s(fp0, cpu_env, fp0);
10513 gen_store_fpr32(ctx, fp0, fd);
10514 tcg_temp_free_i32(fp0);
10516 break;
10517 case OPC_RSQRT_S:
10519 TCGv_i32 fp0 = tcg_temp_new_i32();
10521 gen_load_fpr32(ctx, fp0, fs);
10522 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
10523 gen_store_fpr32(ctx, fp0, fd);
10524 tcg_temp_free_i32(fp0);
10526 break;
10527 case OPC_MADDF_S:
10528 check_insn(ctx, ISA_MIPS_R6);
10530 TCGv_i32 fp0 = tcg_temp_new_i32();
10531 TCGv_i32 fp1 = tcg_temp_new_i32();
10532 TCGv_i32 fp2 = tcg_temp_new_i32();
10533 gen_load_fpr32(ctx, fp0, fs);
10534 gen_load_fpr32(ctx, fp1, ft);
10535 gen_load_fpr32(ctx, fp2, fd);
10536 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
10537 gen_store_fpr32(ctx, fp2, fd);
10538 tcg_temp_free_i32(fp2);
10539 tcg_temp_free_i32(fp1);
10540 tcg_temp_free_i32(fp0);
10542 break;
10543 case OPC_MSUBF_S:
10544 check_insn(ctx, ISA_MIPS_R6);
10546 TCGv_i32 fp0 = tcg_temp_new_i32();
10547 TCGv_i32 fp1 = tcg_temp_new_i32();
10548 TCGv_i32 fp2 = tcg_temp_new_i32();
10549 gen_load_fpr32(ctx, fp0, fs);
10550 gen_load_fpr32(ctx, fp1, ft);
10551 gen_load_fpr32(ctx, fp2, fd);
10552 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
10553 gen_store_fpr32(ctx, fp2, fd);
10554 tcg_temp_free_i32(fp2);
10555 tcg_temp_free_i32(fp1);
10556 tcg_temp_free_i32(fp0);
10558 break;
10559 case OPC_RINT_S:
10560 check_insn(ctx, ISA_MIPS_R6);
10562 TCGv_i32 fp0 = tcg_temp_new_i32();
10563 gen_load_fpr32(ctx, fp0, fs);
10564 gen_helper_float_rint_s(fp0, cpu_env, fp0);
10565 gen_store_fpr32(ctx, fp0, fd);
10566 tcg_temp_free_i32(fp0);
10568 break;
10569 case OPC_CLASS_S:
10570 check_insn(ctx, ISA_MIPS_R6);
10572 TCGv_i32 fp0 = tcg_temp_new_i32();
10573 gen_load_fpr32(ctx, fp0, fs);
10574 gen_helper_float_class_s(fp0, cpu_env, fp0);
10575 gen_store_fpr32(ctx, fp0, fd);
10576 tcg_temp_free_i32(fp0);
10578 break;
10579 case OPC_MIN_S: /* OPC_RECIP2_S */
10580 if (ctx->insn_flags & ISA_MIPS_R6) {
10581 /* OPC_MIN_S */
10582 TCGv_i32 fp0 = tcg_temp_new_i32();
10583 TCGv_i32 fp1 = tcg_temp_new_i32();
10584 TCGv_i32 fp2 = tcg_temp_new_i32();
10585 gen_load_fpr32(ctx, fp0, fs);
10586 gen_load_fpr32(ctx, fp1, ft);
10587 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
10588 gen_store_fpr32(ctx, fp2, fd);
10589 tcg_temp_free_i32(fp2);
10590 tcg_temp_free_i32(fp1);
10591 tcg_temp_free_i32(fp0);
10592 } else {
10593 /* OPC_RECIP2_S */
10594 check_cp1_64bitmode(ctx);
10596 TCGv_i32 fp0 = tcg_temp_new_i32();
10597 TCGv_i32 fp1 = tcg_temp_new_i32();
10599 gen_load_fpr32(ctx, fp0, fs);
10600 gen_load_fpr32(ctx, fp1, ft);
10601 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
10602 tcg_temp_free_i32(fp1);
10603 gen_store_fpr32(ctx, fp0, fd);
10604 tcg_temp_free_i32(fp0);
10607 break;
10608 case OPC_MINA_S: /* OPC_RECIP1_S */
10609 if (ctx->insn_flags & ISA_MIPS_R6) {
10610 /* OPC_MINA_S */
10611 TCGv_i32 fp0 = tcg_temp_new_i32();
10612 TCGv_i32 fp1 = tcg_temp_new_i32();
10613 TCGv_i32 fp2 = tcg_temp_new_i32();
10614 gen_load_fpr32(ctx, fp0, fs);
10615 gen_load_fpr32(ctx, fp1, ft);
10616 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
10617 gen_store_fpr32(ctx, fp2, fd);
10618 tcg_temp_free_i32(fp2);
10619 tcg_temp_free_i32(fp1);
10620 tcg_temp_free_i32(fp0);
10621 } else {
10622 /* OPC_RECIP1_S */
10623 check_cp1_64bitmode(ctx);
10625 TCGv_i32 fp0 = tcg_temp_new_i32();
10627 gen_load_fpr32(ctx, fp0, fs);
10628 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
10629 gen_store_fpr32(ctx, fp0, fd);
10630 tcg_temp_free_i32(fp0);
10633 break;
10634 case OPC_MAX_S: /* OPC_RSQRT1_S */
10635 if (ctx->insn_flags & ISA_MIPS_R6) {
10636 /* OPC_MAX_S */
10637 TCGv_i32 fp0 = tcg_temp_new_i32();
10638 TCGv_i32 fp1 = tcg_temp_new_i32();
10639 gen_load_fpr32(ctx, fp0, fs);
10640 gen_load_fpr32(ctx, fp1, ft);
10641 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
10642 gen_store_fpr32(ctx, fp1, fd);
10643 tcg_temp_free_i32(fp1);
10644 tcg_temp_free_i32(fp0);
10645 } else {
10646 /* OPC_RSQRT1_S */
10647 check_cp1_64bitmode(ctx);
10649 TCGv_i32 fp0 = tcg_temp_new_i32();
10651 gen_load_fpr32(ctx, fp0, fs);
10652 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
10653 gen_store_fpr32(ctx, fp0, fd);
10654 tcg_temp_free_i32(fp0);
10657 break;
10658 case OPC_MAXA_S: /* OPC_RSQRT2_S */
10659 if (ctx->insn_flags & ISA_MIPS_R6) {
10660 /* OPC_MAXA_S */
10661 TCGv_i32 fp0 = tcg_temp_new_i32();
10662 TCGv_i32 fp1 = tcg_temp_new_i32();
10663 gen_load_fpr32(ctx, fp0, fs);
10664 gen_load_fpr32(ctx, fp1, ft);
10665 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
10666 gen_store_fpr32(ctx, fp1, fd);
10667 tcg_temp_free_i32(fp1);
10668 tcg_temp_free_i32(fp0);
10669 } else {
10670 /* OPC_RSQRT2_S */
10671 check_cp1_64bitmode(ctx);
10673 TCGv_i32 fp0 = tcg_temp_new_i32();
10674 TCGv_i32 fp1 = tcg_temp_new_i32();
10676 gen_load_fpr32(ctx, fp0, fs);
10677 gen_load_fpr32(ctx, fp1, ft);
10678 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
10679 tcg_temp_free_i32(fp1);
10680 gen_store_fpr32(ctx, fp0, fd);
10681 tcg_temp_free_i32(fp0);
10684 break;
10685 case OPC_CVT_D_S:
10686 check_cp1_registers(ctx, fd);
10688 TCGv_i32 fp32 = tcg_temp_new_i32();
10689 TCGv_i64 fp64 = tcg_temp_new_i64();
10691 gen_load_fpr32(ctx, fp32, fs);
10692 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
10693 tcg_temp_free_i32(fp32);
10694 gen_store_fpr64(ctx, fp64, fd);
10695 tcg_temp_free_i64(fp64);
10697 break;
10698 case OPC_CVT_W_S:
10700 TCGv_i32 fp0 = tcg_temp_new_i32();
10702 gen_load_fpr32(ctx, fp0, fs);
10703 if (ctx->nan2008) {
10704 gen_helper_float_cvt_2008_w_s(fp0, cpu_env, fp0);
10705 } else {
10706 gen_helper_float_cvt_w_s(fp0, cpu_env, fp0);
10708 gen_store_fpr32(ctx, fp0, fd);
10709 tcg_temp_free_i32(fp0);
10711 break;
10712 case OPC_CVT_L_S:
10713 check_cp1_64bitmode(ctx);
10715 TCGv_i32 fp32 = tcg_temp_new_i32();
10716 TCGv_i64 fp64 = tcg_temp_new_i64();
10718 gen_load_fpr32(ctx, fp32, fs);
10719 if (ctx->nan2008) {
10720 gen_helper_float_cvt_2008_l_s(fp64, cpu_env, fp32);
10721 } else {
10722 gen_helper_float_cvt_l_s(fp64, cpu_env, fp32);
10724 tcg_temp_free_i32(fp32);
10725 gen_store_fpr64(ctx, fp64, fd);
10726 tcg_temp_free_i64(fp64);
10728 break;
10729 case OPC_CVT_PS_S:
10730 check_ps(ctx);
10732 TCGv_i64 fp64 = tcg_temp_new_i64();
10733 TCGv_i32 fp32_0 = tcg_temp_new_i32();
10734 TCGv_i32 fp32_1 = tcg_temp_new_i32();
10736 gen_load_fpr32(ctx, fp32_0, fs);
10737 gen_load_fpr32(ctx, fp32_1, ft);
10738 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
10739 tcg_temp_free_i32(fp32_1);
10740 tcg_temp_free_i32(fp32_0);
10741 gen_store_fpr64(ctx, fp64, fd);
10742 tcg_temp_free_i64(fp64);
10744 break;
10745 case OPC_CMP_F_S:
10746 case OPC_CMP_UN_S:
10747 case OPC_CMP_EQ_S:
10748 case OPC_CMP_UEQ_S:
10749 case OPC_CMP_OLT_S:
10750 case OPC_CMP_ULT_S:
10751 case OPC_CMP_OLE_S:
10752 case OPC_CMP_ULE_S:
10753 case OPC_CMP_SF_S:
10754 case OPC_CMP_NGLE_S:
10755 case OPC_CMP_SEQ_S:
10756 case OPC_CMP_NGL_S:
10757 case OPC_CMP_LT_S:
10758 case OPC_CMP_NGE_S:
10759 case OPC_CMP_LE_S:
10760 case OPC_CMP_NGT_S:
10761 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10762 if (ctx->opcode & (1 << 6)) {
10763 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
10764 } else {
10765 gen_cmp_s(ctx, func - 48, ft, fs, cc);
10767 break;
10768 case OPC_ADD_D:
10769 check_cp1_registers(ctx, fs | ft | fd);
10771 TCGv_i64 fp0 = tcg_temp_new_i64();
10772 TCGv_i64 fp1 = tcg_temp_new_i64();
10774 gen_load_fpr64(ctx, fp0, fs);
10775 gen_load_fpr64(ctx, fp1, ft);
10776 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
10777 tcg_temp_free_i64(fp1);
10778 gen_store_fpr64(ctx, fp0, fd);
10779 tcg_temp_free_i64(fp0);
10781 break;
10782 case OPC_SUB_D:
10783 check_cp1_registers(ctx, fs | ft | fd);
10785 TCGv_i64 fp0 = tcg_temp_new_i64();
10786 TCGv_i64 fp1 = tcg_temp_new_i64();
10788 gen_load_fpr64(ctx, fp0, fs);
10789 gen_load_fpr64(ctx, fp1, ft);
10790 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
10791 tcg_temp_free_i64(fp1);
10792 gen_store_fpr64(ctx, fp0, fd);
10793 tcg_temp_free_i64(fp0);
10795 break;
10796 case OPC_MUL_D:
10797 check_cp1_registers(ctx, fs | ft | fd);
10799 TCGv_i64 fp0 = tcg_temp_new_i64();
10800 TCGv_i64 fp1 = tcg_temp_new_i64();
10802 gen_load_fpr64(ctx, fp0, fs);
10803 gen_load_fpr64(ctx, fp1, ft);
10804 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
10805 tcg_temp_free_i64(fp1);
10806 gen_store_fpr64(ctx, fp0, fd);
10807 tcg_temp_free_i64(fp0);
10809 break;
10810 case OPC_DIV_D:
10811 check_cp1_registers(ctx, fs | ft | fd);
10813 TCGv_i64 fp0 = tcg_temp_new_i64();
10814 TCGv_i64 fp1 = tcg_temp_new_i64();
10816 gen_load_fpr64(ctx, fp0, fs);
10817 gen_load_fpr64(ctx, fp1, ft);
10818 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
10819 tcg_temp_free_i64(fp1);
10820 gen_store_fpr64(ctx, fp0, fd);
10821 tcg_temp_free_i64(fp0);
10823 break;
10824 case OPC_SQRT_D:
10825 check_cp1_registers(ctx, fs | fd);
10827 TCGv_i64 fp0 = tcg_temp_new_i64();
10829 gen_load_fpr64(ctx, fp0, fs);
10830 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
10831 gen_store_fpr64(ctx, fp0, fd);
10832 tcg_temp_free_i64(fp0);
10834 break;
10835 case OPC_ABS_D:
10836 check_cp1_registers(ctx, fs | fd);
10838 TCGv_i64 fp0 = tcg_temp_new_i64();
10840 gen_load_fpr64(ctx, fp0, fs);
10841 if (ctx->abs2008) {
10842 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
10843 } else {
10844 gen_helper_float_abs_d(fp0, fp0);
10846 gen_store_fpr64(ctx, fp0, fd);
10847 tcg_temp_free_i64(fp0);
10849 break;
10850 case OPC_MOV_D:
10851 check_cp1_registers(ctx, fs | fd);
10853 TCGv_i64 fp0 = tcg_temp_new_i64();
10855 gen_load_fpr64(ctx, fp0, fs);
10856 gen_store_fpr64(ctx, fp0, fd);
10857 tcg_temp_free_i64(fp0);
10859 break;
10860 case OPC_NEG_D:
10861 check_cp1_registers(ctx, fs | fd);
10863 TCGv_i64 fp0 = tcg_temp_new_i64();
10865 gen_load_fpr64(ctx, fp0, fs);
10866 if (ctx->abs2008) {
10867 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
10868 } else {
10869 gen_helper_float_chs_d(fp0, fp0);
10871 gen_store_fpr64(ctx, fp0, fd);
10872 tcg_temp_free_i64(fp0);
10874 break;
10875 case OPC_ROUND_L_D:
10876 check_cp1_64bitmode(ctx);
10878 TCGv_i64 fp0 = tcg_temp_new_i64();
10880 gen_load_fpr64(ctx, fp0, fs);
10881 if (ctx->nan2008) {
10882 gen_helper_float_round_2008_l_d(fp0, cpu_env, fp0);
10883 } else {
10884 gen_helper_float_round_l_d(fp0, cpu_env, fp0);
10886 gen_store_fpr64(ctx, fp0, fd);
10887 tcg_temp_free_i64(fp0);
10889 break;
10890 case OPC_TRUNC_L_D:
10891 check_cp1_64bitmode(ctx);
10893 TCGv_i64 fp0 = tcg_temp_new_i64();
10895 gen_load_fpr64(ctx, fp0, fs);
10896 if (ctx->nan2008) {
10897 gen_helper_float_trunc_2008_l_d(fp0, cpu_env, fp0);
10898 } else {
10899 gen_helper_float_trunc_l_d(fp0, cpu_env, fp0);
10901 gen_store_fpr64(ctx, fp0, fd);
10902 tcg_temp_free_i64(fp0);
10904 break;
10905 case OPC_CEIL_L_D:
10906 check_cp1_64bitmode(ctx);
10908 TCGv_i64 fp0 = tcg_temp_new_i64();
10910 gen_load_fpr64(ctx, fp0, fs);
10911 if (ctx->nan2008) {
10912 gen_helper_float_ceil_2008_l_d(fp0, cpu_env, fp0);
10913 } else {
10914 gen_helper_float_ceil_l_d(fp0, cpu_env, fp0);
10916 gen_store_fpr64(ctx, fp0, fd);
10917 tcg_temp_free_i64(fp0);
10919 break;
10920 case OPC_FLOOR_L_D:
10921 check_cp1_64bitmode(ctx);
10923 TCGv_i64 fp0 = tcg_temp_new_i64();
10925 gen_load_fpr64(ctx, fp0, fs);
10926 if (ctx->nan2008) {
10927 gen_helper_float_floor_2008_l_d(fp0, cpu_env, fp0);
10928 } else {
10929 gen_helper_float_floor_l_d(fp0, cpu_env, fp0);
10931 gen_store_fpr64(ctx, fp0, fd);
10932 tcg_temp_free_i64(fp0);
10934 break;
10935 case OPC_ROUND_W_D:
10936 check_cp1_registers(ctx, fs);
10938 TCGv_i32 fp32 = tcg_temp_new_i32();
10939 TCGv_i64 fp64 = tcg_temp_new_i64();
10941 gen_load_fpr64(ctx, fp64, fs);
10942 if (ctx->nan2008) {
10943 gen_helper_float_round_2008_w_d(fp32, cpu_env, fp64);
10944 } else {
10945 gen_helper_float_round_w_d(fp32, cpu_env, fp64);
10947 tcg_temp_free_i64(fp64);
10948 gen_store_fpr32(ctx, fp32, fd);
10949 tcg_temp_free_i32(fp32);
10951 break;
10952 case OPC_TRUNC_W_D:
10953 check_cp1_registers(ctx, fs);
10955 TCGv_i32 fp32 = tcg_temp_new_i32();
10956 TCGv_i64 fp64 = tcg_temp_new_i64();
10958 gen_load_fpr64(ctx, fp64, fs);
10959 if (ctx->nan2008) {
10960 gen_helper_float_trunc_2008_w_d(fp32, cpu_env, fp64);
10961 } else {
10962 gen_helper_float_trunc_w_d(fp32, cpu_env, fp64);
10964 tcg_temp_free_i64(fp64);
10965 gen_store_fpr32(ctx, fp32, fd);
10966 tcg_temp_free_i32(fp32);
10968 break;
10969 case OPC_CEIL_W_D:
10970 check_cp1_registers(ctx, fs);
10972 TCGv_i32 fp32 = tcg_temp_new_i32();
10973 TCGv_i64 fp64 = tcg_temp_new_i64();
10975 gen_load_fpr64(ctx, fp64, fs);
10976 if (ctx->nan2008) {
10977 gen_helper_float_ceil_2008_w_d(fp32, cpu_env, fp64);
10978 } else {
10979 gen_helper_float_ceil_w_d(fp32, cpu_env, fp64);
10981 tcg_temp_free_i64(fp64);
10982 gen_store_fpr32(ctx, fp32, fd);
10983 tcg_temp_free_i32(fp32);
10985 break;
10986 case OPC_FLOOR_W_D:
10987 check_cp1_registers(ctx, fs);
10989 TCGv_i32 fp32 = tcg_temp_new_i32();
10990 TCGv_i64 fp64 = tcg_temp_new_i64();
10992 gen_load_fpr64(ctx, fp64, fs);
10993 if (ctx->nan2008) {
10994 gen_helper_float_floor_2008_w_d(fp32, cpu_env, fp64);
10995 } else {
10996 gen_helper_float_floor_w_d(fp32, cpu_env, fp64);
10998 tcg_temp_free_i64(fp64);
10999 gen_store_fpr32(ctx, fp32, fd);
11000 tcg_temp_free_i32(fp32);
11002 break;
11003 case OPC_SEL_D:
11004 check_insn(ctx, ISA_MIPS_R6);
11005 gen_sel_d(ctx, op1, fd, ft, fs);
11006 break;
11007 case OPC_SELEQZ_D:
11008 check_insn(ctx, ISA_MIPS_R6);
11009 gen_sel_d(ctx, op1, fd, ft, fs);
11010 break;
11011 case OPC_SELNEZ_D:
11012 check_insn(ctx, ISA_MIPS_R6);
11013 gen_sel_d(ctx, op1, fd, ft, fs);
11014 break;
11015 case OPC_MOVCF_D:
11016 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11017 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11018 break;
11019 case OPC_MOVZ_D:
11020 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11022 TCGLabel *l1 = gen_new_label();
11023 TCGv_i64 fp0;
11025 if (ft != 0) {
11026 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11028 fp0 = tcg_temp_new_i64();
11029 gen_load_fpr64(ctx, fp0, fs);
11030 gen_store_fpr64(ctx, fp0, fd);
11031 tcg_temp_free_i64(fp0);
11032 gen_set_label(l1);
11034 break;
11035 case OPC_MOVN_D:
11036 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11038 TCGLabel *l1 = gen_new_label();
11039 TCGv_i64 fp0;
11041 if (ft != 0) {
11042 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11043 fp0 = tcg_temp_new_i64();
11044 gen_load_fpr64(ctx, fp0, fs);
11045 gen_store_fpr64(ctx, fp0, fd);
11046 tcg_temp_free_i64(fp0);
11047 gen_set_label(l1);
11050 break;
11051 case OPC_RECIP_D:
11052 check_cp1_registers(ctx, fs | fd);
11054 TCGv_i64 fp0 = tcg_temp_new_i64();
11056 gen_load_fpr64(ctx, fp0, fs);
11057 gen_helper_float_recip_d(fp0, cpu_env, fp0);
11058 gen_store_fpr64(ctx, fp0, fd);
11059 tcg_temp_free_i64(fp0);
11061 break;
11062 case OPC_RSQRT_D:
11063 check_cp1_registers(ctx, fs | fd);
11065 TCGv_i64 fp0 = tcg_temp_new_i64();
11067 gen_load_fpr64(ctx, fp0, fs);
11068 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
11069 gen_store_fpr64(ctx, fp0, fd);
11070 tcg_temp_free_i64(fp0);
11072 break;
11073 case OPC_MADDF_D:
11074 check_insn(ctx, ISA_MIPS_R6);
11076 TCGv_i64 fp0 = tcg_temp_new_i64();
11077 TCGv_i64 fp1 = tcg_temp_new_i64();
11078 TCGv_i64 fp2 = tcg_temp_new_i64();
11079 gen_load_fpr64(ctx, fp0, fs);
11080 gen_load_fpr64(ctx, fp1, ft);
11081 gen_load_fpr64(ctx, fp2, fd);
11082 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
11083 gen_store_fpr64(ctx, fp2, fd);
11084 tcg_temp_free_i64(fp2);
11085 tcg_temp_free_i64(fp1);
11086 tcg_temp_free_i64(fp0);
11088 break;
11089 case OPC_MSUBF_D:
11090 check_insn(ctx, ISA_MIPS_R6);
11092 TCGv_i64 fp0 = tcg_temp_new_i64();
11093 TCGv_i64 fp1 = tcg_temp_new_i64();
11094 TCGv_i64 fp2 = tcg_temp_new_i64();
11095 gen_load_fpr64(ctx, fp0, fs);
11096 gen_load_fpr64(ctx, fp1, ft);
11097 gen_load_fpr64(ctx, fp2, fd);
11098 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
11099 gen_store_fpr64(ctx, fp2, fd);
11100 tcg_temp_free_i64(fp2);
11101 tcg_temp_free_i64(fp1);
11102 tcg_temp_free_i64(fp0);
11104 break;
11105 case OPC_RINT_D:
11106 check_insn(ctx, ISA_MIPS_R6);
11108 TCGv_i64 fp0 = tcg_temp_new_i64();
11109 gen_load_fpr64(ctx, fp0, fs);
11110 gen_helper_float_rint_d(fp0, cpu_env, fp0);
11111 gen_store_fpr64(ctx, fp0, fd);
11112 tcg_temp_free_i64(fp0);
11114 break;
11115 case OPC_CLASS_D:
11116 check_insn(ctx, ISA_MIPS_R6);
11118 TCGv_i64 fp0 = tcg_temp_new_i64();
11119 gen_load_fpr64(ctx, fp0, fs);
11120 gen_helper_float_class_d(fp0, cpu_env, fp0);
11121 gen_store_fpr64(ctx, fp0, fd);
11122 tcg_temp_free_i64(fp0);
11124 break;
11125 case OPC_MIN_D: /* OPC_RECIP2_D */
11126 if (ctx->insn_flags & ISA_MIPS_R6) {
11127 /* OPC_MIN_D */
11128 TCGv_i64 fp0 = tcg_temp_new_i64();
11129 TCGv_i64 fp1 = tcg_temp_new_i64();
11130 gen_load_fpr64(ctx, fp0, fs);
11131 gen_load_fpr64(ctx, fp1, ft);
11132 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
11133 gen_store_fpr64(ctx, fp1, fd);
11134 tcg_temp_free_i64(fp1);
11135 tcg_temp_free_i64(fp0);
11136 } else {
11137 /* OPC_RECIP2_D */
11138 check_cp1_64bitmode(ctx);
11140 TCGv_i64 fp0 = tcg_temp_new_i64();
11141 TCGv_i64 fp1 = tcg_temp_new_i64();
11143 gen_load_fpr64(ctx, fp0, fs);
11144 gen_load_fpr64(ctx, fp1, ft);
11145 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
11146 tcg_temp_free_i64(fp1);
11147 gen_store_fpr64(ctx, fp0, fd);
11148 tcg_temp_free_i64(fp0);
11151 break;
11152 case OPC_MINA_D: /* OPC_RECIP1_D */
11153 if (ctx->insn_flags & ISA_MIPS_R6) {
11154 /* OPC_MINA_D */
11155 TCGv_i64 fp0 = tcg_temp_new_i64();
11156 TCGv_i64 fp1 = tcg_temp_new_i64();
11157 gen_load_fpr64(ctx, fp0, fs);
11158 gen_load_fpr64(ctx, fp1, ft);
11159 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
11160 gen_store_fpr64(ctx, fp1, fd);
11161 tcg_temp_free_i64(fp1);
11162 tcg_temp_free_i64(fp0);
11163 } else {
11164 /* OPC_RECIP1_D */
11165 check_cp1_64bitmode(ctx);
11167 TCGv_i64 fp0 = tcg_temp_new_i64();
11169 gen_load_fpr64(ctx, fp0, fs);
11170 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
11171 gen_store_fpr64(ctx, fp0, fd);
11172 tcg_temp_free_i64(fp0);
11175 break;
11176 case OPC_MAX_D: /* OPC_RSQRT1_D */
11177 if (ctx->insn_flags & ISA_MIPS_R6) {
11178 /* OPC_MAX_D */
11179 TCGv_i64 fp0 = tcg_temp_new_i64();
11180 TCGv_i64 fp1 = tcg_temp_new_i64();
11181 gen_load_fpr64(ctx, fp0, fs);
11182 gen_load_fpr64(ctx, fp1, ft);
11183 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
11184 gen_store_fpr64(ctx, fp1, fd);
11185 tcg_temp_free_i64(fp1);
11186 tcg_temp_free_i64(fp0);
11187 } else {
11188 /* OPC_RSQRT1_D */
11189 check_cp1_64bitmode(ctx);
11191 TCGv_i64 fp0 = tcg_temp_new_i64();
11193 gen_load_fpr64(ctx, fp0, fs);
11194 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
11195 gen_store_fpr64(ctx, fp0, fd);
11196 tcg_temp_free_i64(fp0);
11199 break;
11200 case OPC_MAXA_D: /* OPC_RSQRT2_D */
11201 if (ctx->insn_flags & ISA_MIPS_R6) {
11202 /* OPC_MAXA_D */
11203 TCGv_i64 fp0 = tcg_temp_new_i64();
11204 TCGv_i64 fp1 = tcg_temp_new_i64();
11205 gen_load_fpr64(ctx, fp0, fs);
11206 gen_load_fpr64(ctx, fp1, ft);
11207 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
11208 gen_store_fpr64(ctx, fp1, fd);
11209 tcg_temp_free_i64(fp1);
11210 tcg_temp_free_i64(fp0);
11211 } else {
11212 /* OPC_RSQRT2_D */
11213 check_cp1_64bitmode(ctx);
11215 TCGv_i64 fp0 = tcg_temp_new_i64();
11216 TCGv_i64 fp1 = tcg_temp_new_i64();
11218 gen_load_fpr64(ctx, fp0, fs);
11219 gen_load_fpr64(ctx, fp1, ft);
11220 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
11221 tcg_temp_free_i64(fp1);
11222 gen_store_fpr64(ctx, fp0, fd);
11223 tcg_temp_free_i64(fp0);
11226 break;
11227 case OPC_CMP_F_D:
11228 case OPC_CMP_UN_D:
11229 case OPC_CMP_EQ_D:
11230 case OPC_CMP_UEQ_D:
11231 case OPC_CMP_OLT_D:
11232 case OPC_CMP_ULT_D:
11233 case OPC_CMP_OLE_D:
11234 case OPC_CMP_ULE_D:
11235 case OPC_CMP_SF_D:
11236 case OPC_CMP_NGLE_D:
11237 case OPC_CMP_SEQ_D:
11238 case OPC_CMP_NGL_D:
11239 case OPC_CMP_LT_D:
11240 case OPC_CMP_NGE_D:
11241 case OPC_CMP_LE_D:
11242 case OPC_CMP_NGT_D:
11243 check_insn_opc_removed(ctx, ISA_MIPS_R6);
11244 if (ctx->opcode & (1 << 6)) {
11245 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
11246 } else {
11247 gen_cmp_d(ctx, func - 48, ft, fs, cc);
11249 break;
11250 case OPC_CVT_S_D:
11251 check_cp1_registers(ctx, fs);
11253 TCGv_i32 fp32 = tcg_temp_new_i32();
11254 TCGv_i64 fp64 = tcg_temp_new_i64();
11256 gen_load_fpr64(ctx, fp64, fs);
11257 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
11258 tcg_temp_free_i64(fp64);
11259 gen_store_fpr32(ctx, fp32, fd);
11260 tcg_temp_free_i32(fp32);
11262 break;
11263 case OPC_CVT_W_D:
11264 check_cp1_registers(ctx, fs);
11266 TCGv_i32 fp32 = tcg_temp_new_i32();
11267 TCGv_i64 fp64 = tcg_temp_new_i64();
11269 gen_load_fpr64(ctx, fp64, fs);
11270 if (ctx->nan2008) {
11271 gen_helper_float_cvt_2008_w_d(fp32, cpu_env, fp64);
11272 } else {
11273 gen_helper_float_cvt_w_d(fp32, cpu_env, fp64);
11275 tcg_temp_free_i64(fp64);
11276 gen_store_fpr32(ctx, fp32, fd);
11277 tcg_temp_free_i32(fp32);
11279 break;
11280 case OPC_CVT_L_D:
11281 check_cp1_64bitmode(ctx);
11283 TCGv_i64 fp0 = tcg_temp_new_i64();
11285 gen_load_fpr64(ctx, fp0, fs);
11286 if (ctx->nan2008) {
11287 gen_helper_float_cvt_2008_l_d(fp0, cpu_env, fp0);
11288 } else {
11289 gen_helper_float_cvt_l_d(fp0, cpu_env, fp0);
11291 gen_store_fpr64(ctx, fp0, fd);
11292 tcg_temp_free_i64(fp0);
11294 break;
11295 case OPC_CVT_S_W:
11297 TCGv_i32 fp0 = tcg_temp_new_i32();
11299 gen_load_fpr32(ctx, fp0, fs);
11300 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
11301 gen_store_fpr32(ctx, fp0, fd);
11302 tcg_temp_free_i32(fp0);
11304 break;
11305 case OPC_CVT_D_W:
11306 check_cp1_registers(ctx, fd);
11308 TCGv_i32 fp32 = tcg_temp_new_i32();
11309 TCGv_i64 fp64 = tcg_temp_new_i64();
11311 gen_load_fpr32(ctx, fp32, fs);
11312 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
11313 tcg_temp_free_i32(fp32);
11314 gen_store_fpr64(ctx, fp64, fd);
11315 tcg_temp_free_i64(fp64);
11317 break;
11318 case OPC_CVT_S_L:
11319 check_cp1_64bitmode(ctx);
11321 TCGv_i32 fp32 = tcg_temp_new_i32();
11322 TCGv_i64 fp64 = tcg_temp_new_i64();
11324 gen_load_fpr64(ctx, fp64, fs);
11325 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
11326 tcg_temp_free_i64(fp64);
11327 gen_store_fpr32(ctx, fp32, fd);
11328 tcg_temp_free_i32(fp32);
11330 break;
11331 case OPC_CVT_D_L:
11332 check_cp1_64bitmode(ctx);
11334 TCGv_i64 fp0 = tcg_temp_new_i64();
11336 gen_load_fpr64(ctx, fp0, fs);
11337 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
11338 gen_store_fpr64(ctx, fp0, fd);
11339 tcg_temp_free_i64(fp0);
11341 break;
11342 case OPC_CVT_PS_PW:
11343 check_ps(ctx);
11345 TCGv_i64 fp0 = tcg_temp_new_i64();
11347 gen_load_fpr64(ctx, fp0, fs);
11348 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
11349 gen_store_fpr64(ctx, fp0, fd);
11350 tcg_temp_free_i64(fp0);
11352 break;
11353 case OPC_ADD_PS:
11354 check_ps(ctx);
11356 TCGv_i64 fp0 = tcg_temp_new_i64();
11357 TCGv_i64 fp1 = tcg_temp_new_i64();
11359 gen_load_fpr64(ctx, fp0, fs);
11360 gen_load_fpr64(ctx, fp1, ft);
11361 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
11362 tcg_temp_free_i64(fp1);
11363 gen_store_fpr64(ctx, fp0, fd);
11364 tcg_temp_free_i64(fp0);
11366 break;
11367 case OPC_SUB_PS:
11368 check_ps(ctx);
11370 TCGv_i64 fp0 = tcg_temp_new_i64();
11371 TCGv_i64 fp1 = tcg_temp_new_i64();
11373 gen_load_fpr64(ctx, fp0, fs);
11374 gen_load_fpr64(ctx, fp1, ft);
11375 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
11376 tcg_temp_free_i64(fp1);
11377 gen_store_fpr64(ctx, fp0, fd);
11378 tcg_temp_free_i64(fp0);
11380 break;
11381 case OPC_MUL_PS:
11382 check_ps(ctx);
11384 TCGv_i64 fp0 = tcg_temp_new_i64();
11385 TCGv_i64 fp1 = tcg_temp_new_i64();
11387 gen_load_fpr64(ctx, fp0, fs);
11388 gen_load_fpr64(ctx, fp1, ft);
11389 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
11390 tcg_temp_free_i64(fp1);
11391 gen_store_fpr64(ctx, fp0, fd);
11392 tcg_temp_free_i64(fp0);
11394 break;
11395 case OPC_ABS_PS:
11396 check_ps(ctx);
11398 TCGv_i64 fp0 = tcg_temp_new_i64();
11400 gen_load_fpr64(ctx, fp0, fs);
11401 gen_helper_float_abs_ps(fp0, fp0);
11402 gen_store_fpr64(ctx, fp0, fd);
11403 tcg_temp_free_i64(fp0);
11405 break;
11406 case OPC_MOV_PS:
11407 check_ps(ctx);
11409 TCGv_i64 fp0 = tcg_temp_new_i64();
11411 gen_load_fpr64(ctx, fp0, fs);
11412 gen_store_fpr64(ctx, fp0, fd);
11413 tcg_temp_free_i64(fp0);
11415 break;
11416 case OPC_NEG_PS:
11417 check_ps(ctx);
11419 TCGv_i64 fp0 = tcg_temp_new_i64();
11421 gen_load_fpr64(ctx, fp0, fs);
11422 gen_helper_float_chs_ps(fp0, fp0);
11423 gen_store_fpr64(ctx, fp0, fd);
11424 tcg_temp_free_i64(fp0);
11426 break;
11427 case OPC_MOVCF_PS:
11428 check_ps(ctx);
11429 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
11430 break;
11431 case OPC_MOVZ_PS:
11432 check_ps(ctx);
11434 TCGLabel *l1 = gen_new_label();
11435 TCGv_i64 fp0;
11437 if (ft != 0) {
11438 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
11440 fp0 = tcg_temp_new_i64();
11441 gen_load_fpr64(ctx, fp0, fs);
11442 gen_store_fpr64(ctx, fp0, fd);
11443 tcg_temp_free_i64(fp0);
11444 gen_set_label(l1);
11446 break;
11447 case OPC_MOVN_PS:
11448 check_ps(ctx);
11450 TCGLabel *l1 = gen_new_label();
11451 TCGv_i64 fp0;
11453 if (ft != 0) {
11454 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
11455 fp0 = tcg_temp_new_i64();
11456 gen_load_fpr64(ctx, fp0, fs);
11457 gen_store_fpr64(ctx, fp0, fd);
11458 tcg_temp_free_i64(fp0);
11459 gen_set_label(l1);
11462 break;
11463 case OPC_ADDR_PS:
11464 check_ps(ctx);
11466 TCGv_i64 fp0 = tcg_temp_new_i64();
11467 TCGv_i64 fp1 = tcg_temp_new_i64();
11469 gen_load_fpr64(ctx, fp0, ft);
11470 gen_load_fpr64(ctx, fp1, fs);
11471 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
11472 tcg_temp_free_i64(fp1);
11473 gen_store_fpr64(ctx, fp0, fd);
11474 tcg_temp_free_i64(fp0);
11476 break;
11477 case OPC_MULR_PS:
11478 check_ps(ctx);
11480 TCGv_i64 fp0 = tcg_temp_new_i64();
11481 TCGv_i64 fp1 = tcg_temp_new_i64();
11483 gen_load_fpr64(ctx, fp0, ft);
11484 gen_load_fpr64(ctx, fp1, fs);
11485 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
11486 tcg_temp_free_i64(fp1);
11487 gen_store_fpr64(ctx, fp0, fd);
11488 tcg_temp_free_i64(fp0);
11490 break;
11491 case OPC_RECIP2_PS:
11492 check_ps(ctx);
11494 TCGv_i64 fp0 = tcg_temp_new_i64();
11495 TCGv_i64 fp1 = tcg_temp_new_i64();
11497 gen_load_fpr64(ctx, fp0, fs);
11498 gen_load_fpr64(ctx, fp1, ft);
11499 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
11500 tcg_temp_free_i64(fp1);
11501 gen_store_fpr64(ctx, fp0, fd);
11502 tcg_temp_free_i64(fp0);
11504 break;
11505 case OPC_RECIP1_PS:
11506 check_ps(ctx);
11508 TCGv_i64 fp0 = tcg_temp_new_i64();
11510 gen_load_fpr64(ctx, fp0, fs);
11511 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
11512 gen_store_fpr64(ctx, fp0, fd);
11513 tcg_temp_free_i64(fp0);
11515 break;
11516 case OPC_RSQRT1_PS:
11517 check_ps(ctx);
11519 TCGv_i64 fp0 = tcg_temp_new_i64();
11521 gen_load_fpr64(ctx, fp0, fs);
11522 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
11523 gen_store_fpr64(ctx, fp0, fd);
11524 tcg_temp_free_i64(fp0);
11526 break;
11527 case OPC_RSQRT2_PS:
11528 check_ps(ctx);
11530 TCGv_i64 fp0 = tcg_temp_new_i64();
11531 TCGv_i64 fp1 = tcg_temp_new_i64();
11533 gen_load_fpr64(ctx, fp0, fs);
11534 gen_load_fpr64(ctx, fp1, ft);
11535 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
11536 tcg_temp_free_i64(fp1);
11537 gen_store_fpr64(ctx, fp0, fd);
11538 tcg_temp_free_i64(fp0);
11540 break;
11541 case OPC_CVT_S_PU:
11542 check_cp1_64bitmode(ctx);
11544 TCGv_i32 fp0 = tcg_temp_new_i32();
11546 gen_load_fpr32h(ctx, fp0, fs);
11547 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
11548 gen_store_fpr32(ctx, fp0, fd);
11549 tcg_temp_free_i32(fp0);
11551 break;
11552 case OPC_CVT_PW_PS:
11553 check_ps(ctx);
11555 TCGv_i64 fp0 = tcg_temp_new_i64();
11557 gen_load_fpr64(ctx, fp0, fs);
11558 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
11559 gen_store_fpr64(ctx, fp0, fd);
11560 tcg_temp_free_i64(fp0);
11562 break;
11563 case OPC_CVT_S_PL:
11564 check_cp1_64bitmode(ctx);
11566 TCGv_i32 fp0 = tcg_temp_new_i32();
11568 gen_load_fpr32(ctx, fp0, fs);
11569 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
11570 gen_store_fpr32(ctx, fp0, fd);
11571 tcg_temp_free_i32(fp0);
11573 break;
11574 case OPC_PLL_PS:
11575 check_ps(ctx);
11577 TCGv_i32 fp0 = tcg_temp_new_i32();
11578 TCGv_i32 fp1 = tcg_temp_new_i32();
11580 gen_load_fpr32(ctx, fp0, fs);
11581 gen_load_fpr32(ctx, fp1, ft);
11582 gen_store_fpr32h(ctx, fp0, fd);
11583 gen_store_fpr32(ctx, fp1, fd);
11584 tcg_temp_free_i32(fp0);
11585 tcg_temp_free_i32(fp1);
11587 break;
11588 case OPC_PLU_PS:
11589 check_ps(ctx);
11591 TCGv_i32 fp0 = tcg_temp_new_i32();
11592 TCGv_i32 fp1 = tcg_temp_new_i32();
11594 gen_load_fpr32(ctx, fp0, fs);
11595 gen_load_fpr32h(ctx, fp1, ft);
11596 gen_store_fpr32(ctx, fp1, fd);
11597 gen_store_fpr32h(ctx, fp0, fd);
11598 tcg_temp_free_i32(fp0);
11599 tcg_temp_free_i32(fp1);
11601 break;
11602 case OPC_PUL_PS:
11603 check_ps(ctx);
11605 TCGv_i32 fp0 = tcg_temp_new_i32();
11606 TCGv_i32 fp1 = tcg_temp_new_i32();
11608 gen_load_fpr32h(ctx, fp0, fs);
11609 gen_load_fpr32(ctx, fp1, ft);
11610 gen_store_fpr32(ctx, fp1, fd);
11611 gen_store_fpr32h(ctx, fp0, fd);
11612 tcg_temp_free_i32(fp0);
11613 tcg_temp_free_i32(fp1);
11615 break;
11616 case OPC_PUU_PS:
11617 check_ps(ctx);
11619 TCGv_i32 fp0 = tcg_temp_new_i32();
11620 TCGv_i32 fp1 = tcg_temp_new_i32();
11622 gen_load_fpr32h(ctx, fp0, fs);
11623 gen_load_fpr32h(ctx, fp1, ft);
11624 gen_store_fpr32(ctx, fp1, fd);
11625 gen_store_fpr32h(ctx, fp0, fd);
11626 tcg_temp_free_i32(fp0);
11627 tcg_temp_free_i32(fp1);
11629 break;
11630 case OPC_CMP_F_PS:
11631 case OPC_CMP_UN_PS:
11632 case OPC_CMP_EQ_PS:
11633 case OPC_CMP_UEQ_PS:
11634 case OPC_CMP_OLT_PS:
11635 case OPC_CMP_ULT_PS:
11636 case OPC_CMP_OLE_PS:
11637 case OPC_CMP_ULE_PS:
11638 case OPC_CMP_SF_PS:
11639 case OPC_CMP_NGLE_PS:
11640 case OPC_CMP_SEQ_PS:
11641 case OPC_CMP_NGL_PS:
11642 case OPC_CMP_LT_PS:
11643 case OPC_CMP_NGE_PS:
11644 case OPC_CMP_LE_PS:
11645 case OPC_CMP_NGT_PS:
11646 if (ctx->opcode & (1 << 6)) {
11647 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
11648 } else {
11649 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
11651 break;
11652 default:
11653 MIPS_INVAL("farith");
11654 gen_reserved_instruction(ctx);
11655 return;
11659 /* Coprocessor 3 (FPU) */
11660 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
11661 int fd, int fs, int base, int index)
11663 TCGv t0 = tcg_temp_new();
11665 if (base == 0) {
11666 gen_load_gpr(t0, index);
11667 } else if (index == 0) {
11668 gen_load_gpr(t0, base);
11669 } else {
11670 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
11673 * Don't do NOP if destination is zero: we must perform the actual
11674 * memory access.
11676 switch (opc) {
11677 case OPC_LWXC1:
11678 check_cop1x(ctx);
11680 TCGv_i32 fp0 = tcg_temp_new_i32();
11682 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
11683 tcg_gen_trunc_tl_i32(fp0, t0);
11684 gen_store_fpr32(ctx, fp0, fd);
11685 tcg_temp_free_i32(fp0);
11687 break;
11688 case OPC_LDXC1:
11689 check_cop1x(ctx);
11690 check_cp1_registers(ctx, fd);
11692 TCGv_i64 fp0 = tcg_temp_new_i64();
11693 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11694 gen_store_fpr64(ctx, fp0, fd);
11695 tcg_temp_free_i64(fp0);
11697 break;
11698 case OPC_LUXC1:
11699 check_cp1_64bitmode(ctx);
11700 tcg_gen_andi_tl(t0, t0, ~0x7);
11702 TCGv_i64 fp0 = tcg_temp_new_i64();
11704 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11705 gen_store_fpr64(ctx, fp0, fd);
11706 tcg_temp_free_i64(fp0);
11708 break;
11709 case OPC_SWXC1:
11710 check_cop1x(ctx);
11712 TCGv_i32 fp0 = tcg_temp_new_i32();
11713 gen_load_fpr32(ctx, fp0, fs);
11714 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
11715 tcg_temp_free_i32(fp0);
11717 break;
11718 case OPC_SDXC1:
11719 check_cop1x(ctx);
11720 check_cp1_registers(ctx, fs);
11722 TCGv_i64 fp0 = tcg_temp_new_i64();
11723 gen_load_fpr64(ctx, fp0, fs);
11724 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11725 tcg_temp_free_i64(fp0);
11727 break;
11728 case OPC_SUXC1:
11729 check_cp1_64bitmode(ctx);
11730 tcg_gen_andi_tl(t0, t0, ~0x7);
11732 TCGv_i64 fp0 = tcg_temp_new_i64();
11733 gen_load_fpr64(ctx, fp0, fs);
11734 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
11735 tcg_temp_free_i64(fp0);
11737 break;
11739 tcg_temp_free(t0);
11742 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
11743 int fd, int fr, int fs, int ft)
11745 switch (opc) {
11746 case OPC_ALNV_PS:
11747 check_ps(ctx);
11749 TCGv t0 = tcg_temp_local_new();
11750 TCGv_i32 fp = tcg_temp_new_i32();
11751 TCGv_i32 fph = tcg_temp_new_i32();
11752 TCGLabel *l1 = gen_new_label();
11753 TCGLabel *l2 = gen_new_label();
11755 gen_load_gpr(t0, fr);
11756 tcg_gen_andi_tl(t0, t0, 0x7);
11758 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
11759 gen_load_fpr32(ctx, fp, fs);
11760 gen_load_fpr32h(ctx, fph, fs);
11761 gen_store_fpr32(ctx, fp, fd);
11762 gen_store_fpr32h(ctx, fph, fd);
11763 tcg_gen_br(l2);
11764 gen_set_label(l1);
11765 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
11766 tcg_temp_free(t0);
11767 #ifdef TARGET_WORDS_BIGENDIAN
11768 gen_load_fpr32(ctx, fp, fs);
11769 gen_load_fpr32h(ctx, fph, ft);
11770 gen_store_fpr32h(ctx, fp, fd);
11771 gen_store_fpr32(ctx, fph, fd);
11772 #else
11773 gen_load_fpr32h(ctx, fph, fs);
11774 gen_load_fpr32(ctx, fp, ft);
11775 gen_store_fpr32(ctx, fph, fd);
11776 gen_store_fpr32h(ctx, fp, fd);
11777 #endif
11778 gen_set_label(l2);
11779 tcg_temp_free_i32(fp);
11780 tcg_temp_free_i32(fph);
11782 break;
11783 case OPC_MADD_S:
11784 check_cop1x(ctx);
11786 TCGv_i32 fp0 = tcg_temp_new_i32();
11787 TCGv_i32 fp1 = tcg_temp_new_i32();
11788 TCGv_i32 fp2 = tcg_temp_new_i32();
11790 gen_load_fpr32(ctx, fp0, fs);
11791 gen_load_fpr32(ctx, fp1, ft);
11792 gen_load_fpr32(ctx, fp2, fr);
11793 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
11794 tcg_temp_free_i32(fp0);
11795 tcg_temp_free_i32(fp1);
11796 gen_store_fpr32(ctx, fp2, fd);
11797 tcg_temp_free_i32(fp2);
11799 break;
11800 case OPC_MADD_D:
11801 check_cop1x(ctx);
11802 check_cp1_registers(ctx, fd | fs | ft | fr);
11804 TCGv_i64 fp0 = tcg_temp_new_i64();
11805 TCGv_i64 fp1 = tcg_temp_new_i64();
11806 TCGv_i64 fp2 = tcg_temp_new_i64();
11808 gen_load_fpr64(ctx, fp0, fs);
11809 gen_load_fpr64(ctx, fp1, ft);
11810 gen_load_fpr64(ctx, fp2, fr);
11811 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
11812 tcg_temp_free_i64(fp0);
11813 tcg_temp_free_i64(fp1);
11814 gen_store_fpr64(ctx, fp2, fd);
11815 tcg_temp_free_i64(fp2);
11817 break;
11818 case OPC_MADD_PS:
11819 check_ps(ctx);
11821 TCGv_i64 fp0 = tcg_temp_new_i64();
11822 TCGv_i64 fp1 = tcg_temp_new_i64();
11823 TCGv_i64 fp2 = tcg_temp_new_i64();
11825 gen_load_fpr64(ctx, fp0, fs);
11826 gen_load_fpr64(ctx, fp1, ft);
11827 gen_load_fpr64(ctx, fp2, fr);
11828 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
11829 tcg_temp_free_i64(fp0);
11830 tcg_temp_free_i64(fp1);
11831 gen_store_fpr64(ctx, fp2, fd);
11832 tcg_temp_free_i64(fp2);
11834 break;
11835 case OPC_MSUB_S:
11836 check_cop1x(ctx);
11838 TCGv_i32 fp0 = tcg_temp_new_i32();
11839 TCGv_i32 fp1 = tcg_temp_new_i32();
11840 TCGv_i32 fp2 = tcg_temp_new_i32();
11842 gen_load_fpr32(ctx, fp0, fs);
11843 gen_load_fpr32(ctx, fp1, ft);
11844 gen_load_fpr32(ctx, fp2, fr);
11845 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
11846 tcg_temp_free_i32(fp0);
11847 tcg_temp_free_i32(fp1);
11848 gen_store_fpr32(ctx, fp2, fd);
11849 tcg_temp_free_i32(fp2);
11851 break;
11852 case OPC_MSUB_D:
11853 check_cop1x(ctx);
11854 check_cp1_registers(ctx, fd | fs | ft | fr);
11856 TCGv_i64 fp0 = tcg_temp_new_i64();
11857 TCGv_i64 fp1 = tcg_temp_new_i64();
11858 TCGv_i64 fp2 = tcg_temp_new_i64();
11860 gen_load_fpr64(ctx, fp0, fs);
11861 gen_load_fpr64(ctx, fp1, ft);
11862 gen_load_fpr64(ctx, fp2, fr);
11863 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
11864 tcg_temp_free_i64(fp0);
11865 tcg_temp_free_i64(fp1);
11866 gen_store_fpr64(ctx, fp2, fd);
11867 tcg_temp_free_i64(fp2);
11869 break;
11870 case OPC_MSUB_PS:
11871 check_ps(ctx);
11873 TCGv_i64 fp0 = tcg_temp_new_i64();
11874 TCGv_i64 fp1 = tcg_temp_new_i64();
11875 TCGv_i64 fp2 = tcg_temp_new_i64();
11877 gen_load_fpr64(ctx, fp0, fs);
11878 gen_load_fpr64(ctx, fp1, ft);
11879 gen_load_fpr64(ctx, fp2, fr);
11880 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
11881 tcg_temp_free_i64(fp0);
11882 tcg_temp_free_i64(fp1);
11883 gen_store_fpr64(ctx, fp2, fd);
11884 tcg_temp_free_i64(fp2);
11886 break;
11887 case OPC_NMADD_S:
11888 check_cop1x(ctx);
11890 TCGv_i32 fp0 = tcg_temp_new_i32();
11891 TCGv_i32 fp1 = tcg_temp_new_i32();
11892 TCGv_i32 fp2 = tcg_temp_new_i32();
11894 gen_load_fpr32(ctx, fp0, fs);
11895 gen_load_fpr32(ctx, fp1, ft);
11896 gen_load_fpr32(ctx, fp2, fr);
11897 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
11898 tcg_temp_free_i32(fp0);
11899 tcg_temp_free_i32(fp1);
11900 gen_store_fpr32(ctx, fp2, fd);
11901 tcg_temp_free_i32(fp2);
11903 break;
11904 case OPC_NMADD_D:
11905 check_cop1x(ctx);
11906 check_cp1_registers(ctx, fd | fs | ft | fr);
11908 TCGv_i64 fp0 = tcg_temp_new_i64();
11909 TCGv_i64 fp1 = tcg_temp_new_i64();
11910 TCGv_i64 fp2 = tcg_temp_new_i64();
11912 gen_load_fpr64(ctx, fp0, fs);
11913 gen_load_fpr64(ctx, fp1, ft);
11914 gen_load_fpr64(ctx, fp2, fr);
11915 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
11916 tcg_temp_free_i64(fp0);
11917 tcg_temp_free_i64(fp1);
11918 gen_store_fpr64(ctx, fp2, fd);
11919 tcg_temp_free_i64(fp2);
11921 break;
11922 case OPC_NMADD_PS:
11923 check_ps(ctx);
11925 TCGv_i64 fp0 = tcg_temp_new_i64();
11926 TCGv_i64 fp1 = tcg_temp_new_i64();
11927 TCGv_i64 fp2 = tcg_temp_new_i64();
11929 gen_load_fpr64(ctx, fp0, fs);
11930 gen_load_fpr64(ctx, fp1, ft);
11931 gen_load_fpr64(ctx, fp2, fr);
11932 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
11933 tcg_temp_free_i64(fp0);
11934 tcg_temp_free_i64(fp1);
11935 gen_store_fpr64(ctx, fp2, fd);
11936 tcg_temp_free_i64(fp2);
11938 break;
11939 case OPC_NMSUB_S:
11940 check_cop1x(ctx);
11942 TCGv_i32 fp0 = tcg_temp_new_i32();
11943 TCGv_i32 fp1 = tcg_temp_new_i32();
11944 TCGv_i32 fp2 = tcg_temp_new_i32();
11946 gen_load_fpr32(ctx, fp0, fs);
11947 gen_load_fpr32(ctx, fp1, ft);
11948 gen_load_fpr32(ctx, fp2, fr);
11949 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
11950 tcg_temp_free_i32(fp0);
11951 tcg_temp_free_i32(fp1);
11952 gen_store_fpr32(ctx, fp2, fd);
11953 tcg_temp_free_i32(fp2);
11955 break;
11956 case OPC_NMSUB_D:
11957 check_cop1x(ctx);
11958 check_cp1_registers(ctx, fd | fs | ft | fr);
11960 TCGv_i64 fp0 = tcg_temp_new_i64();
11961 TCGv_i64 fp1 = tcg_temp_new_i64();
11962 TCGv_i64 fp2 = tcg_temp_new_i64();
11964 gen_load_fpr64(ctx, fp0, fs);
11965 gen_load_fpr64(ctx, fp1, ft);
11966 gen_load_fpr64(ctx, fp2, fr);
11967 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
11968 tcg_temp_free_i64(fp0);
11969 tcg_temp_free_i64(fp1);
11970 gen_store_fpr64(ctx, fp2, fd);
11971 tcg_temp_free_i64(fp2);
11973 break;
11974 case OPC_NMSUB_PS:
11975 check_ps(ctx);
11977 TCGv_i64 fp0 = tcg_temp_new_i64();
11978 TCGv_i64 fp1 = tcg_temp_new_i64();
11979 TCGv_i64 fp2 = tcg_temp_new_i64();
11981 gen_load_fpr64(ctx, fp0, fs);
11982 gen_load_fpr64(ctx, fp1, ft);
11983 gen_load_fpr64(ctx, fp2, fr);
11984 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
11985 tcg_temp_free_i64(fp0);
11986 tcg_temp_free_i64(fp1);
11987 gen_store_fpr64(ctx, fp2, fd);
11988 tcg_temp_free_i64(fp2);
11990 break;
11991 default:
11992 MIPS_INVAL("flt3_arith");
11993 gen_reserved_instruction(ctx);
11994 return;
11998 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
12000 TCGv t0;
12002 #if !defined(CONFIG_USER_ONLY)
12004 * The Linux kernel will emulate rdhwr if it's not supported natively.
12005 * Therefore only check the ISA in system mode.
12007 check_insn(ctx, ISA_MIPS_R2);
12008 #endif
12009 t0 = tcg_temp_new();
12011 switch (rd) {
12012 case 0:
12013 gen_helper_rdhwr_cpunum(t0, cpu_env);
12014 gen_store_gpr(t0, rt);
12015 break;
12016 case 1:
12017 gen_helper_rdhwr_synci_step(t0, cpu_env);
12018 gen_store_gpr(t0, rt);
12019 break;
12020 case 2:
12021 if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
12022 gen_io_start();
12024 gen_helper_rdhwr_cc(t0, cpu_env);
12025 gen_store_gpr(t0, rt);
12027 * Break the TB to be able to take timer interrupts immediately
12028 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
12029 * we break completely out of translated code.
12031 gen_save_pc(ctx->base.pc_next + 4);
12032 ctx->base.is_jmp = DISAS_EXIT;
12033 break;
12034 case 3:
12035 gen_helper_rdhwr_ccres(t0, cpu_env);
12036 gen_store_gpr(t0, rt);
12037 break;
12038 case 4:
12039 check_insn(ctx, ISA_MIPS_R6);
12040 if (sel != 0) {
12042 * Performance counter registers are not implemented other than
12043 * control register 0.
12045 generate_exception(ctx, EXCP_RI);
12047 gen_helper_rdhwr_performance(t0, cpu_env);
12048 gen_store_gpr(t0, rt);
12049 break;
12050 case 5:
12051 check_insn(ctx, ISA_MIPS_R6);
12052 gen_helper_rdhwr_xnp(t0, cpu_env);
12053 gen_store_gpr(t0, rt);
12054 break;
12055 case 29:
12056 #if defined(CONFIG_USER_ONLY)
12057 tcg_gen_ld_tl(t0, cpu_env,
12058 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12059 gen_store_gpr(t0, rt);
12060 break;
12061 #else
12062 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
12063 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
12064 tcg_gen_ld_tl(t0, cpu_env,
12065 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
12066 gen_store_gpr(t0, rt);
12067 } else {
12068 gen_reserved_instruction(ctx);
12070 break;
12071 #endif
12072 default: /* Invalid */
12073 MIPS_INVAL("rdhwr");
12074 gen_reserved_instruction(ctx);
12075 break;
12077 tcg_temp_free(t0);
12080 static inline void clear_branch_hflags(DisasContext *ctx)
12082 ctx->hflags &= ~MIPS_HFLAG_BMASK;
12083 if (ctx->base.is_jmp == DISAS_NEXT) {
12084 save_cpu_state(ctx, 0);
12085 } else {
12087 * It is not safe to save ctx->hflags as hflags may be changed
12088 * in execution time by the instruction in delay / forbidden slot.
12090 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
12094 static void gen_branch(DisasContext *ctx, int insn_bytes)
12096 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12097 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
12098 /* Branches completion */
12099 clear_branch_hflags(ctx);
12100 ctx->base.is_jmp = DISAS_NORETURN;
12101 /* FIXME: Need to clear can_do_io. */
12102 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
12103 case MIPS_HFLAG_FBNSLOT:
12104 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
12105 break;
12106 case MIPS_HFLAG_B:
12107 /* unconditional branch */
12108 if (proc_hflags & MIPS_HFLAG_BX) {
12109 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
12111 gen_goto_tb(ctx, 0, ctx->btarget);
12112 break;
12113 case MIPS_HFLAG_BL:
12114 /* blikely taken case */
12115 gen_goto_tb(ctx, 0, ctx->btarget);
12116 break;
12117 case MIPS_HFLAG_BC:
12118 /* Conditional branch */
12120 TCGLabel *l1 = gen_new_label();
12122 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
12123 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
12124 gen_set_label(l1);
12125 gen_goto_tb(ctx, 0, ctx->btarget);
12127 break;
12128 case MIPS_HFLAG_BR:
12129 /* unconditional branch to register */
12130 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
12131 TCGv t0 = tcg_temp_new();
12132 TCGv_i32 t1 = tcg_temp_new_i32();
12134 tcg_gen_andi_tl(t0, btarget, 0x1);
12135 tcg_gen_trunc_tl_i32(t1, t0);
12136 tcg_temp_free(t0);
12137 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
12138 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
12139 tcg_gen_or_i32(hflags, hflags, t1);
12140 tcg_temp_free_i32(t1);
12142 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
12143 } else {
12144 tcg_gen_mov_tl(cpu_PC, btarget);
12146 if (ctx->base.singlestep_enabled) {
12147 save_cpu_state(ctx, 0);
12148 gen_helper_raise_exception_debug(cpu_env);
12150 tcg_gen_lookup_and_goto_ptr();
12151 break;
12152 default:
12153 LOG_DISAS("unknown branch 0x%x\n", proc_hflags);
12154 gen_reserved_instruction(ctx);
12159 /* Compact Branches */
12160 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
12161 int rs, int rt, int32_t offset)
12163 int bcond_compute = 0;
12164 TCGv t0 = tcg_temp_new();
12165 TCGv t1 = tcg_temp_new();
12166 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
12168 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12169 #ifdef MIPS_DEBUG_DISAS
12170 LOG_DISAS("Branch in delay / forbidden slot at PC 0x" TARGET_FMT_lx
12171 "\n", ctx->base.pc_next);
12172 #endif
12173 gen_reserved_instruction(ctx);
12174 goto out;
12177 /* Load needed operands and calculate btarget */
12178 switch (opc) {
12179 /* compact branch */
12180 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12181 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12182 gen_load_gpr(t0, rs);
12183 gen_load_gpr(t1, rt);
12184 bcond_compute = 1;
12185 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12186 if (rs <= rt && rs == 0) {
12187 /* OPC_BEQZALC, OPC_BNEZALC */
12188 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12190 break;
12191 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12192 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12193 gen_load_gpr(t0, rs);
12194 gen_load_gpr(t1, rt);
12195 bcond_compute = 1;
12196 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12197 break;
12198 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12199 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12200 if (rs == 0 || rs == rt) {
12201 /* OPC_BLEZALC, OPC_BGEZALC */
12202 /* OPC_BGTZALC, OPC_BLTZALC */
12203 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12205 gen_load_gpr(t0, rs);
12206 gen_load_gpr(t1, rt);
12207 bcond_compute = 1;
12208 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12209 break;
12210 case OPC_BC:
12211 case OPC_BALC:
12212 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12213 break;
12214 case OPC_BEQZC:
12215 case OPC_BNEZC:
12216 if (rs != 0) {
12217 /* OPC_BEQZC, OPC_BNEZC */
12218 gen_load_gpr(t0, rs);
12219 bcond_compute = 1;
12220 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
12221 } else {
12222 /* OPC_JIC, OPC_JIALC */
12223 TCGv tbase = tcg_temp_new();
12224 TCGv toffset = tcg_temp_new();
12226 gen_load_gpr(tbase, rt);
12227 tcg_gen_movi_tl(toffset, offset);
12228 gen_op_addr_add(ctx, btarget, tbase, toffset);
12229 tcg_temp_free(tbase);
12230 tcg_temp_free(toffset);
12232 break;
12233 default:
12234 MIPS_INVAL("Compact branch/jump");
12235 gen_reserved_instruction(ctx);
12236 goto out;
12239 if (bcond_compute == 0) {
12240 /* Unconditional compact branch */
12241 switch (opc) {
12242 case OPC_JIALC:
12243 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12244 /* Fallthrough */
12245 case OPC_JIC:
12246 ctx->hflags |= MIPS_HFLAG_BR;
12247 break;
12248 case OPC_BALC:
12249 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
12250 /* Fallthrough */
12251 case OPC_BC:
12252 ctx->hflags |= MIPS_HFLAG_B;
12253 break;
12254 default:
12255 MIPS_INVAL("Compact branch/jump");
12256 gen_reserved_instruction(ctx);
12257 goto out;
12260 /* Generating branch here as compact branches don't have delay slot */
12261 gen_branch(ctx, 4);
12262 } else {
12263 /* Conditional compact branch */
12264 TCGLabel *fs = gen_new_label();
12265 save_cpu_state(ctx, 0);
12267 switch (opc) {
12268 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
12269 if (rs == 0 && rt != 0) {
12270 /* OPC_BLEZALC */
12271 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12272 } else if (rs != 0 && rt != 0 && rs == rt) {
12273 /* OPC_BGEZALC */
12274 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12275 } else {
12276 /* OPC_BGEUC */
12277 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
12279 break;
12280 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
12281 if (rs == 0 && rt != 0) {
12282 /* OPC_BGTZALC */
12283 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12284 } else if (rs != 0 && rt != 0 && rs == rt) {
12285 /* OPC_BLTZALC */
12286 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12287 } else {
12288 /* OPC_BLTUC */
12289 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
12291 break;
12292 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
12293 if (rs == 0 && rt != 0) {
12294 /* OPC_BLEZC */
12295 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
12296 } else if (rs != 0 && rt != 0 && rs == rt) {
12297 /* OPC_BGEZC */
12298 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
12299 } else {
12300 /* OPC_BGEC */
12301 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
12303 break;
12304 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
12305 if (rs == 0 && rt != 0) {
12306 /* OPC_BGTZC */
12307 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
12308 } else if (rs != 0 && rt != 0 && rs == rt) {
12309 /* OPC_BLTZC */
12310 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
12311 } else {
12312 /* OPC_BLTC */
12313 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
12315 break;
12316 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
12317 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
12318 if (rs >= rt) {
12319 /* OPC_BOVC, OPC_BNVC */
12320 TCGv t2 = tcg_temp_new();
12321 TCGv t3 = tcg_temp_new();
12322 TCGv t4 = tcg_temp_new();
12323 TCGv input_overflow = tcg_temp_new();
12325 gen_load_gpr(t0, rs);
12326 gen_load_gpr(t1, rt);
12327 tcg_gen_ext32s_tl(t2, t0);
12328 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
12329 tcg_gen_ext32s_tl(t3, t1);
12330 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
12331 tcg_gen_or_tl(input_overflow, input_overflow, t4);
12333 tcg_gen_add_tl(t4, t2, t3);
12334 tcg_gen_ext32s_tl(t4, t4);
12335 tcg_gen_xor_tl(t2, t2, t3);
12336 tcg_gen_xor_tl(t3, t4, t3);
12337 tcg_gen_andc_tl(t2, t3, t2);
12338 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
12339 tcg_gen_or_tl(t4, t4, input_overflow);
12340 if (opc == OPC_BOVC) {
12341 /* OPC_BOVC */
12342 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
12343 } else {
12344 /* OPC_BNVC */
12345 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
12347 tcg_temp_free(input_overflow);
12348 tcg_temp_free(t4);
12349 tcg_temp_free(t3);
12350 tcg_temp_free(t2);
12351 } else if (rs < rt && rs == 0) {
12352 /* OPC_BEQZALC, OPC_BNEZALC */
12353 if (opc == OPC_BEQZALC) {
12354 /* OPC_BEQZALC */
12355 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
12356 } else {
12357 /* OPC_BNEZALC */
12358 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
12360 } else {
12361 /* OPC_BEQC, OPC_BNEC */
12362 if (opc == OPC_BEQC) {
12363 /* OPC_BEQC */
12364 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
12365 } else {
12366 /* OPC_BNEC */
12367 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
12370 break;
12371 case OPC_BEQZC:
12372 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
12373 break;
12374 case OPC_BNEZC:
12375 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
12376 break;
12377 default:
12378 MIPS_INVAL("Compact conditional branch/jump");
12379 gen_reserved_instruction(ctx);
12380 goto out;
12383 /* Generating branch here as compact branches don't have delay slot */
12384 gen_goto_tb(ctx, 1, ctx->btarget);
12385 gen_set_label(fs);
12387 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
12390 out:
12391 tcg_temp_free(t0);
12392 tcg_temp_free(t1);
12395 /* ISA extensions (ASEs) */
12396 /* MIPS16 extension to MIPS32 */
12398 /* MIPS16 major opcodes */
12399 enum {
12400 M16_OPC_ADDIUSP = 0x00,
12401 M16_OPC_ADDIUPC = 0x01,
12402 M16_OPC_B = 0x02,
12403 M16_OPC_JAL = 0x03,
12404 M16_OPC_BEQZ = 0x04,
12405 M16_OPC_BNEQZ = 0x05,
12406 M16_OPC_SHIFT = 0x06,
12407 M16_OPC_LD = 0x07,
12408 M16_OPC_RRIA = 0x08,
12409 M16_OPC_ADDIU8 = 0x09,
12410 M16_OPC_SLTI = 0x0a,
12411 M16_OPC_SLTIU = 0x0b,
12412 M16_OPC_I8 = 0x0c,
12413 M16_OPC_LI = 0x0d,
12414 M16_OPC_CMPI = 0x0e,
12415 M16_OPC_SD = 0x0f,
12416 M16_OPC_LB = 0x10,
12417 M16_OPC_LH = 0x11,
12418 M16_OPC_LWSP = 0x12,
12419 M16_OPC_LW = 0x13,
12420 M16_OPC_LBU = 0x14,
12421 M16_OPC_LHU = 0x15,
12422 M16_OPC_LWPC = 0x16,
12423 M16_OPC_LWU = 0x17,
12424 M16_OPC_SB = 0x18,
12425 M16_OPC_SH = 0x19,
12426 M16_OPC_SWSP = 0x1a,
12427 M16_OPC_SW = 0x1b,
12428 M16_OPC_RRR = 0x1c,
12429 M16_OPC_RR = 0x1d,
12430 M16_OPC_EXTEND = 0x1e,
12431 M16_OPC_I64 = 0x1f
12434 /* I8 funct field */
12435 enum {
12436 I8_BTEQZ = 0x0,
12437 I8_BTNEZ = 0x1,
12438 I8_SWRASP = 0x2,
12439 I8_ADJSP = 0x3,
12440 I8_SVRS = 0x4,
12441 I8_MOV32R = 0x5,
12442 I8_MOVR32 = 0x7
12445 /* RRR f field */
12446 enum {
12447 RRR_DADDU = 0x0,
12448 RRR_ADDU = 0x1,
12449 RRR_DSUBU = 0x2,
12450 RRR_SUBU = 0x3
12453 /* RR funct field */
12454 enum {
12455 RR_JR = 0x00,
12456 RR_SDBBP = 0x01,
12457 RR_SLT = 0x02,
12458 RR_SLTU = 0x03,
12459 RR_SLLV = 0x04,
12460 RR_BREAK = 0x05,
12461 RR_SRLV = 0x06,
12462 RR_SRAV = 0x07,
12463 RR_DSRL = 0x08,
12464 RR_CMP = 0x0a,
12465 RR_NEG = 0x0b,
12466 RR_AND = 0x0c,
12467 RR_OR = 0x0d,
12468 RR_XOR = 0x0e,
12469 RR_NOT = 0x0f,
12470 RR_MFHI = 0x10,
12471 RR_CNVT = 0x11,
12472 RR_MFLO = 0x12,
12473 RR_DSRA = 0x13,
12474 RR_DSLLV = 0x14,
12475 RR_DSRLV = 0x16,
12476 RR_DSRAV = 0x17,
12477 RR_MULT = 0x18,
12478 RR_MULTU = 0x19,
12479 RR_DIV = 0x1a,
12480 RR_DIVU = 0x1b,
12481 RR_DMULT = 0x1c,
12482 RR_DMULTU = 0x1d,
12483 RR_DDIV = 0x1e,
12484 RR_DDIVU = 0x1f
12487 /* I64 funct field */
12488 enum {
12489 I64_LDSP = 0x0,
12490 I64_SDSP = 0x1,
12491 I64_SDRASP = 0x2,
12492 I64_DADJSP = 0x3,
12493 I64_LDPC = 0x4,
12494 I64_DADDIU5 = 0x5,
12495 I64_DADDIUPC = 0x6,
12496 I64_DADDIUSP = 0x7
12499 /* RR ry field for CNVT */
12500 enum {
12501 RR_RY_CNVT_ZEB = 0x0,
12502 RR_RY_CNVT_ZEH = 0x1,
12503 RR_RY_CNVT_ZEW = 0x2,
12504 RR_RY_CNVT_SEB = 0x4,
12505 RR_RY_CNVT_SEH = 0x5,
12506 RR_RY_CNVT_SEW = 0x6,
12509 static int xlat(int r)
12511 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
12513 return map[r];
12516 static void gen_mips16_save(DisasContext *ctx,
12517 int xsregs, int aregs,
12518 int do_ra, int do_s0, int do_s1,
12519 int framesize)
12521 TCGv t0 = tcg_temp_new();
12522 TCGv t1 = tcg_temp_new();
12523 TCGv t2 = tcg_temp_new();
12524 int args, astatic;
12526 switch (aregs) {
12527 case 0:
12528 case 1:
12529 case 2:
12530 case 3:
12531 case 11:
12532 args = 0;
12533 break;
12534 case 4:
12535 case 5:
12536 case 6:
12537 case 7:
12538 args = 1;
12539 break;
12540 case 8:
12541 case 9:
12542 case 10:
12543 args = 2;
12544 break;
12545 case 12:
12546 case 13:
12547 args = 3;
12548 break;
12549 case 14:
12550 args = 4;
12551 break;
12552 default:
12553 gen_reserved_instruction(ctx);
12554 return;
12557 switch (args) {
12558 case 4:
12559 gen_base_offset_addr(ctx, t0, 29, 12);
12560 gen_load_gpr(t1, 7);
12561 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12562 /* Fall through */
12563 case 3:
12564 gen_base_offset_addr(ctx, t0, 29, 8);
12565 gen_load_gpr(t1, 6);
12566 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12567 /* Fall through */
12568 case 2:
12569 gen_base_offset_addr(ctx, t0, 29, 4);
12570 gen_load_gpr(t1, 5);
12571 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12572 /* Fall through */
12573 case 1:
12574 gen_base_offset_addr(ctx, t0, 29, 0);
12575 gen_load_gpr(t1, 4);
12576 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12579 gen_load_gpr(t0, 29);
12581 #define DECR_AND_STORE(reg) do { \
12582 tcg_gen_movi_tl(t2, -4); \
12583 gen_op_addr_add(ctx, t0, t0, t2); \
12584 gen_load_gpr(t1, reg); \
12585 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
12586 } while (0)
12588 if (do_ra) {
12589 DECR_AND_STORE(31);
12592 switch (xsregs) {
12593 case 7:
12594 DECR_AND_STORE(30);
12595 /* Fall through */
12596 case 6:
12597 DECR_AND_STORE(23);
12598 /* Fall through */
12599 case 5:
12600 DECR_AND_STORE(22);
12601 /* Fall through */
12602 case 4:
12603 DECR_AND_STORE(21);
12604 /* Fall through */
12605 case 3:
12606 DECR_AND_STORE(20);
12607 /* Fall through */
12608 case 2:
12609 DECR_AND_STORE(19);
12610 /* Fall through */
12611 case 1:
12612 DECR_AND_STORE(18);
12615 if (do_s1) {
12616 DECR_AND_STORE(17);
12618 if (do_s0) {
12619 DECR_AND_STORE(16);
12622 switch (aregs) {
12623 case 0:
12624 case 4:
12625 case 8:
12626 case 12:
12627 case 14:
12628 astatic = 0;
12629 break;
12630 case 1:
12631 case 5:
12632 case 9:
12633 case 13:
12634 astatic = 1;
12635 break;
12636 case 2:
12637 case 6:
12638 case 10:
12639 astatic = 2;
12640 break;
12641 case 3:
12642 case 7:
12643 astatic = 3;
12644 break;
12645 case 11:
12646 astatic = 4;
12647 break;
12648 default:
12649 gen_reserved_instruction(ctx);
12650 return;
12653 if (astatic > 0) {
12654 DECR_AND_STORE(7);
12655 if (astatic > 1) {
12656 DECR_AND_STORE(6);
12657 if (astatic > 2) {
12658 DECR_AND_STORE(5);
12659 if (astatic > 3) {
12660 DECR_AND_STORE(4);
12665 #undef DECR_AND_STORE
12667 tcg_gen_movi_tl(t2, -framesize);
12668 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12669 tcg_temp_free(t0);
12670 tcg_temp_free(t1);
12671 tcg_temp_free(t2);
12674 static void gen_mips16_restore(DisasContext *ctx,
12675 int xsregs, int aregs,
12676 int do_ra, int do_s0, int do_s1,
12677 int framesize)
12679 int astatic;
12680 TCGv t0 = tcg_temp_new();
12681 TCGv t1 = tcg_temp_new();
12682 TCGv t2 = tcg_temp_new();
12684 tcg_gen_movi_tl(t2, framesize);
12685 gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
12687 #define DECR_AND_LOAD(reg) do { \
12688 tcg_gen_movi_tl(t2, -4); \
12689 gen_op_addr_add(ctx, t0, t0, t2); \
12690 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
12691 gen_store_gpr(t1, reg); \
12692 } while (0)
12694 if (do_ra) {
12695 DECR_AND_LOAD(31);
12698 switch (xsregs) {
12699 case 7:
12700 DECR_AND_LOAD(30);
12701 /* Fall through */
12702 case 6:
12703 DECR_AND_LOAD(23);
12704 /* Fall through */
12705 case 5:
12706 DECR_AND_LOAD(22);
12707 /* Fall through */
12708 case 4:
12709 DECR_AND_LOAD(21);
12710 /* Fall through */
12711 case 3:
12712 DECR_AND_LOAD(20);
12713 /* Fall through */
12714 case 2:
12715 DECR_AND_LOAD(19);
12716 /* Fall through */
12717 case 1:
12718 DECR_AND_LOAD(18);
12721 if (do_s1) {
12722 DECR_AND_LOAD(17);
12724 if (do_s0) {
12725 DECR_AND_LOAD(16);
12728 switch (aregs) {
12729 case 0:
12730 case 4:
12731 case 8:
12732 case 12:
12733 case 14:
12734 astatic = 0;
12735 break;
12736 case 1:
12737 case 5:
12738 case 9:
12739 case 13:
12740 astatic = 1;
12741 break;
12742 case 2:
12743 case 6:
12744 case 10:
12745 astatic = 2;
12746 break;
12747 case 3:
12748 case 7:
12749 astatic = 3;
12750 break;
12751 case 11:
12752 astatic = 4;
12753 break;
12754 default:
12755 gen_reserved_instruction(ctx);
12756 return;
12759 if (astatic > 0) {
12760 DECR_AND_LOAD(7);
12761 if (astatic > 1) {
12762 DECR_AND_LOAD(6);
12763 if (astatic > 2) {
12764 DECR_AND_LOAD(5);
12765 if (astatic > 3) {
12766 DECR_AND_LOAD(4);
12771 #undef DECR_AND_LOAD
12773 tcg_gen_movi_tl(t2, framesize);
12774 gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
12775 tcg_temp_free(t0);
12776 tcg_temp_free(t1);
12777 tcg_temp_free(t2);
12780 void gen_addiupc(DisasContext *ctx, int rx, int imm,
12781 int is_64_bit, int extended)
12783 TCGv t0;
12785 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12786 gen_reserved_instruction(ctx);
12787 return;
12790 t0 = tcg_temp_new();
12792 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
12793 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
12794 if (!is_64_bit) {
12795 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
12798 tcg_temp_free(t0);
12801 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
12802 int16_t offset)
12804 TCGv_i32 t0 = tcg_const_i32(op);
12805 TCGv t1 = tcg_temp_new();
12806 gen_base_offset_addr(ctx, t1, base, offset);
12807 gen_helper_cache(cpu_env, t1, t0);
12808 tcg_temp_free(t1);
12809 tcg_temp_free_i32(t0);
12812 #if defined(TARGET_MIPS64)
12813 static void decode_i64_mips16(DisasContext *ctx,
12814 int ry, int funct, int16_t offset,
12815 int extended)
12817 switch (funct) {
12818 case I64_LDSP:
12819 check_insn(ctx, ISA_MIPS3);
12820 check_mips_64(ctx);
12821 offset = extended ? offset : offset << 3;
12822 gen_ld(ctx, OPC_LD, ry, 29, offset);
12823 break;
12824 case I64_SDSP:
12825 check_insn(ctx, ISA_MIPS3);
12826 check_mips_64(ctx);
12827 offset = extended ? offset : offset << 3;
12828 gen_st(ctx, OPC_SD, ry, 29, offset);
12829 break;
12830 case I64_SDRASP:
12831 check_insn(ctx, ISA_MIPS3);
12832 check_mips_64(ctx);
12833 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
12834 gen_st(ctx, OPC_SD, 31, 29, offset);
12835 break;
12836 case I64_DADJSP:
12837 check_insn(ctx, ISA_MIPS3);
12838 check_mips_64(ctx);
12839 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
12840 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
12841 break;
12842 case I64_LDPC:
12843 check_insn(ctx, ISA_MIPS3);
12844 check_mips_64(ctx);
12845 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
12846 gen_reserved_instruction(ctx);
12847 } else {
12848 offset = extended ? offset : offset << 3;
12849 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
12851 break;
12852 case I64_DADDIU5:
12853 check_insn(ctx, ISA_MIPS3);
12854 check_mips_64(ctx);
12855 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
12856 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
12857 break;
12858 case I64_DADDIUPC:
12859 check_insn(ctx, ISA_MIPS3);
12860 check_mips_64(ctx);
12861 offset = extended ? offset : offset << 2;
12862 gen_addiupc(ctx, ry, offset, 1, extended);
12863 break;
12864 case I64_DADDIUSP:
12865 check_insn(ctx, ISA_MIPS3);
12866 check_mips_64(ctx);
12867 offset = extended ? offset : offset << 2;
12868 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
12869 break;
12872 #endif
12874 static int decode_extended_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
12876 int extend = translator_lduw(env, ctx->base.pc_next + 2);
12877 int op, rx, ry, funct, sa;
12878 int16_t imm, offset;
12880 ctx->opcode = (ctx->opcode << 16) | extend;
12881 op = (ctx->opcode >> 11) & 0x1f;
12882 sa = (ctx->opcode >> 22) & 0x1f;
12883 funct = (ctx->opcode >> 8) & 0x7;
12884 rx = xlat((ctx->opcode >> 8) & 0x7);
12885 ry = xlat((ctx->opcode >> 5) & 0x7);
12886 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
12887 | ((ctx->opcode >> 21) & 0x3f) << 5
12888 | (ctx->opcode & 0x1f));
12891 * The extended opcodes cleverly reuse the opcodes from their 16-bit
12892 * counterparts.
12894 switch (op) {
12895 case M16_OPC_ADDIUSP:
12896 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
12897 break;
12898 case M16_OPC_ADDIUPC:
12899 gen_addiupc(ctx, rx, imm, 0, 1);
12900 break;
12901 case M16_OPC_B:
12902 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
12903 /* No delay slot, so just process as a normal instruction */
12904 break;
12905 case M16_OPC_BEQZ:
12906 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
12907 /* No delay slot, so just process as a normal instruction */
12908 break;
12909 case M16_OPC_BNEQZ:
12910 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
12911 /* No delay slot, so just process as a normal instruction */
12912 break;
12913 case M16_OPC_SHIFT:
12914 switch (ctx->opcode & 0x3) {
12915 case 0x0:
12916 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
12917 break;
12918 case 0x1:
12919 #if defined(TARGET_MIPS64)
12920 check_mips_64(ctx);
12921 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
12922 #else
12923 gen_reserved_instruction(ctx);
12924 #endif
12925 break;
12926 case 0x2:
12927 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
12928 break;
12929 case 0x3:
12930 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
12931 break;
12933 break;
12934 #if defined(TARGET_MIPS64)
12935 case M16_OPC_LD:
12936 check_insn(ctx, ISA_MIPS3);
12937 check_mips_64(ctx);
12938 gen_ld(ctx, OPC_LD, ry, rx, offset);
12939 break;
12940 #endif
12941 case M16_OPC_RRIA:
12942 imm = ctx->opcode & 0xf;
12943 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
12944 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
12945 imm = (int16_t) (imm << 1) >> 1;
12946 if ((ctx->opcode >> 4) & 0x1) {
12947 #if defined(TARGET_MIPS64)
12948 check_mips_64(ctx);
12949 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
12950 #else
12951 gen_reserved_instruction(ctx);
12952 #endif
12953 } else {
12954 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
12956 break;
12957 case M16_OPC_ADDIU8:
12958 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
12959 break;
12960 case M16_OPC_SLTI:
12961 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
12962 break;
12963 case M16_OPC_SLTIU:
12964 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
12965 break;
12966 case M16_OPC_I8:
12967 switch (funct) {
12968 case I8_BTEQZ:
12969 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
12970 break;
12971 case I8_BTNEZ:
12972 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
12973 break;
12974 case I8_SWRASP:
12975 gen_st(ctx, OPC_SW, 31, 29, imm);
12976 break;
12977 case I8_ADJSP:
12978 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
12979 break;
12980 case I8_SVRS:
12981 check_insn(ctx, ISA_MIPS_R1);
12983 int xsregs = (ctx->opcode >> 24) & 0x7;
12984 int aregs = (ctx->opcode >> 16) & 0xf;
12985 int do_ra = (ctx->opcode >> 6) & 0x1;
12986 int do_s0 = (ctx->opcode >> 5) & 0x1;
12987 int do_s1 = (ctx->opcode >> 4) & 0x1;
12988 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
12989 | (ctx->opcode & 0xf)) << 3;
12991 if (ctx->opcode & (1 << 7)) {
12992 gen_mips16_save(ctx, xsregs, aregs,
12993 do_ra, do_s0, do_s1,
12994 framesize);
12995 } else {
12996 gen_mips16_restore(ctx, xsregs, aregs,
12997 do_ra, do_s0, do_s1,
12998 framesize);
13001 break;
13002 default:
13003 gen_reserved_instruction(ctx);
13004 break;
13006 break;
13007 case M16_OPC_LI:
13008 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
13009 break;
13010 case M16_OPC_CMPI:
13011 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
13012 break;
13013 #if defined(TARGET_MIPS64)
13014 case M16_OPC_SD:
13015 check_insn(ctx, ISA_MIPS3);
13016 check_mips_64(ctx);
13017 gen_st(ctx, OPC_SD, ry, rx, offset);
13018 break;
13019 #endif
13020 case M16_OPC_LB:
13021 gen_ld(ctx, OPC_LB, ry, rx, offset);
13022 break;
13023 case M16_OPC_LH:
13024 gen_ld(ctx, OPC_LH, ry, rx, offset);
13025 break;
13026 case M16_OPC_LWSP:
13027 gen_ld(ctx, OPC_LW, rx, 29, offset);
13028 break;
13029 case M16_OPC_LW:
13030 gen_ld(ctx, OPC_LW, ry, rx, offset);
13031 break;
13032 case M16_OPC_LBU:
13033 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13034 break;
13035 case M16_OPC_LHU:
13036 gen_ld(ctx, OPC_LHU, ry, rx, offset);
13037 break;
13038 case M16_OPC_LWPC:
13039 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
13040 break;
13041 #if defined(TARGET_MIPS64)
13042 case M16_OPC_LWU:
13043 check_insn(ctx, ISA_MIPS3);
13044 check_mips_64(ctx);
13045 gen_ld(ctx, OPC_LWU, ry, rx, offset);
13046 break;
13047 #endif
13048 case M16_OPC_SB:
13049 gen_st(ctx, OPC_SB, ry, rx, offset);
13050 break;
13051 case M16_OPC_SH:
13052 gen_st(ctx, OPC_SH, ry, rx, offset);
13053 break;
13054 case M16_OPC_SWSP:
13055 gen_st(ctx, OPC_SW, rx, 29, offset);
13056 break;
13057 case M16_OPC_SW:
13058 gen_st(ctx, OPC_SW, ry, rx, offset);
13059 break;
13060 #if defined(TARGET_MIPS64)
13061 case M16_OPC_I64:
13062 decode_i64_mips16(ctx, ry, funct, offset, 1);
13063 break;
13064 #endif
13065 default:
13066 gen_reserved_instruction(ctx);
13067 break;
13070 return 4;
13073 static inline bool is_uhi(int sdbbp_code)
13075 #ifdef CONFIG_USER_ONLY
13076 return false;
13077 #else
13078 return semihosting_enabled() && sdbbp_code == 1;
13079 #endif
13082 #ifdef CONFIG_USER_ONLY
13083 /* The above should dead-code away any calls to this..*/
13084 static inline void gen_helper_do_semihosting(void *env)
13086 g_assert_not_reached();
13088 #endif
13090 static int decode_mips16_opc(CPUMIPSState *env, DisasContext *ctx)
13092 int rx, ry;
13093 int sa;
13094 int op, cnvt_op, op1, offset;
13095 int funct;
13096 int n_bytes;
13098 op = (ctx->opcode >> 11) & 0x1f;
13099 sa = (ctx->opcode >> 2) & 0x7;
13100 sa = sa == 0 ? 8 : sa;
13101 rx = xlat((ctx->opcode >> 8) & 0x7);
13102 cnvt_op = (ctx->opcode >> 5) & 0x7;
13103 ry = xlat((ctx->opcode >> 5) & 0x7);
13104 op1 = offset = ctx->opcode & 0x1f;
13106 n_bytes = 2;
13108 switch (op) {
13109 case M16_OPC_ADDIUSP:
13111 int16_t imm = ((uint8_t) ctx->opcode) << 2;
13113 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
13115 break;
13116 case M16_OPC_ADDIUPC:
13117 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
13118 break;
13119 case M16_OPC_B:
13120 offset = (ctx->opcode & 0x7ff) << 1;
13121 offset = (int16_t)(offset << 4) >> 4;
13122 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
13123 /* No delay slot, so just process as a normal instruction */
13124 break;
13125 case M16_OPC_JAL:
13126 offset = translator_lduw(env, ctx->base.pc_next + 2);
13127 offset = (((ctx->opcode & 0x1f) << 21)
13128 | ((ctx->opcode >> 5) & 0x1f) << 16
13129 | offset) << 2;
13130 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
13131 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
13132 n_bytes = 4;
13133 break;
13134 case M16_OPC_BEQZ:
13135 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
13136 ((int8_t)ctx->opcode) << 1, 0);
13137 /* No delay slot, so just process as a normal instruction */
13138 break;
13139 case M16_OPC_BNEQZ:
13140 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
13141 ((int8_t)ctx->opcode) << 1, 0);
13142 /* No delay slot, so just process as a normal instruction */
13143 break;
13144 case M16_OPC_SHIFT:
13145 switch (ctx->opcode & 0x3) {
13146 case 0x0:
13147 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
13148 break;
13149 case 0x1:
13150 #if defined(TARGET_MIPS64)
13151 check_insn(ctx, ISA_MIPS3);
13152 check_mips_64(ctx);
13153 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
13154 #else
13155 gen_reserved_instruction(ctx);
13156 #endif
13157 break;
13158 case 0x2:
13159 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
13160 break;
13161 case 0x3:
13162 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
13163 break;
13165 break;
13166 #if defined(TARGET_MIPS64)
13167 case M16_OPC_LD:
13168 check_insn(ctx, ISA_MIPS3);
13169 check_mips_64(ctx);
13170 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
13171 break;
13172 #endif
13173 case M16_OPC_RRIA:
13175 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
13177 if ((ctx->opcode >> 4) & 1) {
13178 #if defined(TARGET_MIPS64)
13179 check_insn(ctx, ISA_MIPS3);
13180 check_mips_64(ctx);
13181 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
13182 #else
13183 gen_reserved_instruction(ctx);
13184 #endif
13185 } else {
13186 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
13189 break;
13190 case M16_OPC_ADDIU8:
13192 int16_t imm = (int8_t) ctx->opcode;
13194 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
13196 break;
13197 case M16_OPC_SLTI:
13199 int16_t imm = (uint8_t) ctx->opcode;
13200 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
13202 break;
13203 case M16_OPC_SLTIU:
13205 int16_t imm = (uint8_t) ctx->opcode;
13206 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
13208 break;
13209 case M16_OPC_I8:
13211 int reg32;
13213 funct = (ctx->opcode >> 8) & 0x7;
13214 switch (funct) {
13215 case I8_BTEQZ:
13216 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
13217 ((int8_t)ctx->opcode) << 1, 0);
13218 break;
13219 case I8_BTNEZ:
13220 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
13221 ((int8_t)ctx->opcode) << 1, 0);
13222 break;
13223 case I8_SWRASP:
13224 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
13225 break;
13226 case I8_ADJSP:
13227 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
13228 ((int8_t)ctx->opcode) << 3);
13229 break;
13230 case I8_SVRS:
13231 check_insn(ctx, ISA_MIPS_R1);
13233 int do_ra = ctx->opcode & (1 << 6);
13234 int do_s0 = ctx->opcode & (1 << 5);
13235 int do_s1 = ctx->opcode & (1 << 4);
13236 int framesize = ctx->opcode & 0xf;
13238 if (framesize == 0) {
13239 framesize = 128;
13240 } else {
13241 framesize = framesize << 3;
13244 if (ctx->opcode & (1 << 7)) {
13245 gen_mips16_save(ctx, 0, 0,
13246 do_ra, do_s0, do_s1, framesize);
13247 } else {
13248 gen_mips16_restore(ctx, 0, 0,
13249 do_ra, do_s0, do_s1, framesize);
13252 break;
13253 case I8_MOV32R:
13255 int rz = xlat(ctx->opcode & 0x7);
13257 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
13258 ((ctx->opcode >> 5) & 0x7);
13259 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
13261 break;
13262 case I8_MOVR32:
13263 reg32 = ctx->opcode & 0x1f;
13264 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
13265 break;
13266 default:
13267 gen_reserved_instruction(ctx);
13268 break;
13271 break;
13272 case M16_OPC_LI:
13274 int16_t imm = (uint8_t) ctx->opcode;
13276 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
13278 break;
13279 case M16_OPC_CMPI:
13281 int16_t imm = (uint8_t) ctx->opcode;
13282 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
13284 break;
13285 #if defined(TARGET_MIPS64)
13286 case M16_OPC_SD:
13287 check_insn(ctx, ISA_MIPS3);
13288 check_mips_64(ctx);
13289 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
13290 break;
13291 #endif
13292 case M16_OPC_LB:
13293 gen_ld(ctx, OPC_LB, ry, rx, offset);
13294 break;
13295 case M16_OPC_LH:
13296 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
13297 break;
13298 case M16_OPC_LWSP:
13299 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13300 break;
13301 case M16_OPC_LW:
13302 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
13303 break;
13304 case M16_OPC_LBU:
13305 gen_ld(ctx, OPC_LBU, ry, rx, offset);
13306 break;
13307 case M16_OPC_LHU:
13308 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
13309 break;
13310 case M16_OPC_LWPC:
13311 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
13312 break;
13313 #if defined(TARGET_MIPS64)
13314 case M16_OPC_LWU:
13315 check_insn(ctx, ISA_MIPS3);
13316 check_mips_64(ctx);
13317 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
13318 break;
13319 #endif
13320 case M16_OPC_SB:
13321 gen_st(ctx, OPC_SB, ry, rx, offset);
13322 break;
13323 case M16_OPC_SH:
13324 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
13325 break;
13326 case M16_OPC_SWSP:
13327 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
13328 break;
13329 case M16_OPC_SW:
13330 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
13331 break;
13332 case M16_OPC_RRR:
13334 int rz = xlat((ctx->opcode >> 2) & 0x7);
13335 int mips32_op;
13337 switch (ctx->opcode & 0x3) {
13338 case RRR_ADDU:
13339 mips32_op = OPC_ADDU;
13340 break;
13341 case RRR_SUBU:
13342 mips32_op = OPC_SUBU;
13343 break;
13344 #if defined(TARGET_MIPS64)
13345 case RRR_DADDU:
13346 mips32_op = OPC_DADDU;
13347 check_insn(ctx, ISA_MIPS3);
13348 check_mips_64(ctx);
13349 break;
13350 case RRR_DSUBU:
13351 mips32_op = OPC_DSUBU;
13352 check_insn(ctx, ISA_MIPS3);
13353 check_mips_64(ctx);
13354 break;
13355 #endif
13356 default:
13357 gen_reserved_instruction(ctx);
13358 goto done;
13361 gen_arith(ctx, mips32_op, rz, rx, ry);
13362 done:
13365 break;
13366 case M16_OPC_RR:
13367 switch (op1) {
13368 case RR_JR:
13370 int nd = (ctx->opcode >> 7) & 0x1;
13371 int link = (ctx->opcode >> 6) & 0x1;
13372 int ra = (ctx->opcode >> 5) & 0x1;
13374 if (nd) {
13375 check_insn(ctx, ISA_MIPS_R1);
13378 if (link) {
13379 op = OPC_JALR;
13380 } else {
13381 op = OPC_JR;
13384 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
13385 (nd ? 0 : 2));
13387 break;
13388 case RR_SDBBP:
13389 if (is_uhi(extract32(ctx->opcode, 5, 6))) {
13390 gen_helper_do_semihosting(cpu_env);
13391 } else {
13393 * XXX: not clear which exception should be raised
13394 * when in debug mode...
13396 check_insn(ctx, ISA_MIPS_R1);
13397 generate_exception_end(ctx, EXCP_DBp);
13399 break;
13400 case RR_SLT:
13401 gen_slt(ctx, OPC_SLT, 24, rx, ry);
13402 break;
13403 case RR_SLTU:
13404 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
13405 break;
13406 case RR_BREAK:
13407 generate_exception_end(ctx, EXCP_BREAK);
13408 break;
13409 case RR_SLLV:
13410 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
13411 break;
13412 case RR_SRLV:
13413 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
13414 break;
13415 case RR_SRAV:
13416 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
13417 break;
13418 #if defined(TARGET_MIPS64)
13419 case RR_DSRL:
13420 check_insn(ctx, ISA_MIPS3);
13421 check_mips_64(ctx);
13422 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
13423 break;
13424 #endif
13425 case RR_CMP:
13426 gen_logic(ctx, OPC_XOR, 24, rx, ry);
13427 break;
13428 case RR_NEG:
13429 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
13430 break;
13431 case RR_AND:
13432 gen_logic(ctx, OPC_AND, rx, rx, ry);
13433 break;
13434 case RR_OR:
13435 gen_logic(ctx, OPC_OR, rx, rx, ry);
13436 break;
13437 case RR_XOR:
13438 gen_logic(ctx, OPC_XOR, rx, rx, ry);
13439 break;
13440 case RR_NOT:
13441 gen_logic(ctx, OPC_NOR, rx, ry, 0);
13442 break;
13443 case RR_MFHI:
13444 gen_HILO(ctx, OPC_MFHI, 0, rx);
13445 break;
13446 case RR_CNVT:
13447 check_insn(ctx, ISA_MIPS_R1);
13448 switch (cnvt_op) {
13449 case RR_RY_CNVT_ZEB:
13450 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13451 break;
13452 case RR_RY_CNVT_ZEH:
13453 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13454 break;
13455 case RR_RY_CNVT_SEB:
13456 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13457 break;
13458 case RR_RY_CNVT_SEH:
13459 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13460 break;
13461 #if defined(TARGET_MIPS64)
13462 case RR_RY_CNVT_ZEW:
13463 check_insn(ctx, ISA_MIPS_R1);
13464 check_mips_64(ctx);
13465 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
13466 break;
13467 case RR_RY_CNVT_SEW:
13468 check_insn(ctx, ISA_MIPS_R1);
13469 check_mips_64(ctx);
13470 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
13471 break;
13472 #endif
13473 default:
13474 gen_reserved_instruction(ctx);
13475 break;
13477 break;
13478 case RR_MFLO:
13479 gen_HILO(ctx, OPC_MFLO, 0, rx);
13480 break;
13481 #if defined(TARGET_MIPS64)
13482 case RR_DSRA:
13483 check_insn(ctx, ISA_MIPS3);
13484 check_mips_64(ctx);
13485 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
13486 break;
13487 case RR_DSLLV:
13488 check_insn(ctx, ISA_MIPS3);
13489 check_mips_64(ctx);
13490 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
13491 break;
13492 case RR_DSRLV:
13493 check_insn(ctx, ISA_MIPS3);
13494 check_mips_64(ctx);
13495 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
13496 break;
13497 case RR_DSRAV:
13498 check_insn(ctx, ISA_MIPS3);
13499 check_mips_64(ctx);
13500 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
13501 break;
13502 #endif
13503 case RR_MULT:
13504 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
13505 break;
13506 case RR_MULTU:
13507 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
13508 break;
13509 case RR_DIV:
13510 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
13511 break;
13512 case RR_DIVU:
13513 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
13514 break;
13515 #if defined(TARGET_MIPS64)
13516 case RR_DMULT:
13517 check_insn(ctx, ISA_MIPS3);
13518 check_mips_64(ctx);
13519 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
13520 break;
13521 case RR_DMULTU:
13522 check_insn(ctx, ISA_MIPS3);
13523 check_mips_64(ctx);
13524 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
13525 break;
13526 case RR_DDIV:
13527 check_insn(ctx, ISA_MIPS3);
13528 check_mips_64(ctx);
13529 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
13530 break;
13531 case RR_DDIVU:
13532 check_insn(ctx, ISA_MIPS3);
13533 check_mips_64(ctx);
13534 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
13535 break;
13536 #endif
13537 default:
13538 gen_reserved_instruction(ctx);
13539 break;
13541 break;
13542 case M16_OPC_EXTEND:
13543 decode_extended_mips16_opc(env, ctx);
13544 n_bytes = 4;
13545 break;
13546 #if defined(TARGET_MIPS64)
13547 case M16_OPC_I64:
13548 funct = (ctx->opcode >> 8) & 0x7;
13549 decode_i64_mips16(ctx, ry, funct, offset, 0);
13550 break;
13551 #endif
13552 default:
13553 gen_reserved_instruction(ctx);
13554 break;
13557 return n_bytes;
13560 /* microMIPS extension to MIPS32/MIPS64 */
13563 * microMIPS32/microMIPS64 major opcodes
13565 * 1. MIPS Architecture for Programmers Volume II-B:
13566 * The microMIPS32 Instruction Set (Revision 3.05)
13568 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
13570 * 2. MIPS Architecture For Programmers Volume II-A:
13571 * The MIPS64 Instruction Set (Revision 3.51)
13574 enum {
13575 POOL32A = 0x00,
13576 POOL16A = 0x01,
13577 LBU16 = 0x02,
13578 MOVE16 = 0x03,
13579 ADDI32 = 0x04,
13580 R6_LUI = 0x04,
13581 AUI = 0x04,
13582 LBU32 = 0x05,
13583 SB32 = 0x06,
13584 LB32 = 0x07,
13586 POOL32B = 0x08,
13587 POOL16B = 0x09,
13588 LHU16 = 0x0a,
13589 ANDI16 = 0x0b,
13590 ADDIU32 = 0x0c,
13591 LHU32 = 0x0d,
13592 SH32 = 0x0e,
13593 LH32 = 0x0f,
13595 POOL32I = 0x10,
13596 POOL16C = 0x11,
13597 LWSP16 = 0x12,
13598 POOL16D = 0x13,
13599 ORI32 = 0x14,
13600 POOL32F = 0x15,
13601 POOL32S = 0x16, /* MIPS64 */
13602 DADDIU32 = 0x17, /* MIPS64 */
13604 POOL32C = 0x18,
13605 LWGP16 = 0x19,
13606 LW16 = 0x1a,
13607 POOL16E = 0x1b,
13608 XORI32 = 0x1c,
13609 JALS32 = 0x1d,
13610 BOVC = 0x1d,
13611 BEQC = 0x1d,
13612 BEQZALC = 0x1d,
13613 ADDIUPC = 0x1e,
13614 PCREL = 0x1e,
13615 BNVC = 0x1f,
13616 BNEC = 0x1f,
13617 BNEZALC = 0x1f,
13619 R6_BEQZC = 0x20,
13620 JIC = 0x20,
13621 POOL16F = 0x21,
13622 SB16 = 0x22,
13623 BEQZ16 = 0x23,
13624 BEQZC16 = 0x23,
13625 SLTI32 = 0x24,
13626 BEQ32 = 0x25,
13627 BC = 0x25,
13628 SWC132 = 0x26,
13629 LWC132 = 0x27,
13631 /* 0x29 is reserved */
13632 RES_29 = 0x29,
13633 R6_BNEZC = 0x28,
13634 JIALC = 0x28,
13635 SH16 = 0x2a,
13636 BNEZ16 = 0x2b,
13637 BNEZC16 = 0x2b,
13638 SLTIU32 = 0x2c,
13639 BNE32 = 0x2d,
13640 BALC = 0x2d,
13641 SDC132 = 0x2e,
13642 LDC132 = 0x2f,
13644 /* 0x31 is reserved */
13645 RES_31 = 0x31,
13646 BLEZALC = 0x30,
13647 BGEZALC = 0x30,
13648 BGEUC = 0x30,
13649 SWSP16 = 0x32,
13650 B16 = 0x33,
13651 BC16 = 0x33,
13652 ANDI32 = 0x34,
13653 J32 = 0x35,
13654 BGTZC = 0x35,
13655 BLTZC = 0x35,
13656 BLTC = 0x35,
13657 SD32 = 0x36, /* MIPS64 */
13658 LD32 = 0x37, /* MIPS64 */
13660 /* 0x39 is reserved */
13661 RES_39 = 0x39,
13662 BGTZALC = 0x38,
13663 BLTZALC = 0x38,
13664 BLTUC = 0x38,
13665 SW16 = 0x3a,
13666 LI16 = 0x3b,
13667 JALX32 = 0x3c,
13668 JAL32 = 0x3d,
13669 BLEZC = 0x3d,
13670 BGEZC = 0x3d,
13671 BGEC = 0x3d,
13672 SW32 = 0x3e,
13673 LW32 = 0x3f
13676 /* PCREL Instructions perform PC-Relative address calculation. bits 20..16 */
13677 enum {
13678 ADDIUPC_00 = 0x00,
13679 ADDIUPC_01 = 0x01,
13680 ADDIUPC_02 = 0x02,
13681 ADDIUPC_03 = 0x03,
13682 ADDIUPC_04 = 0x04,
13683 ADDIUPC_05 = 0x05,
13684 ADDIUPC_06 = 0x06,
13685 ADDIUPC_07 = 0x07,
13686 AUIPC = 0x1e,
13687 ALUIPC = 0x1f,
13688 LWPC_08 = 0x08,
13689 LWPC_09 = 0x09,
13690 LWPC_0A = 0x0A,
13691 LWPC_0B = 0x0B,
13692 LWPC_0C = 0x0C,
13693 LWPC_0D = 0x0D,
13694 LWPC_0E = 0x0E,
13695 LWPC_0F = 0x0F,
13698 /* POOL32A encoding of minor opcode field */
13700 enum {
13702 * These opcodes are distinguished only by bits 9..6; those bits are
13703 * what are recorded below.
13705 SLL32 = 0x0,
13706 SRL32 = 0x1,
13707 SRA = 0x2,
13708 ROTR = 0x3,
13709 SELEQZ = 0x5,
13710 SELNEZ = 0x6,
13711 R6_RDHWR = 0x7,
13713 SLLV = 0x0,
13714 SRLV = 0x1,
13715 SRAV = 0x2,
13716 ROTRV = 0x3,
13717 ADD = 0x4,
13718 ADDU32 = 0x5,
13719 SUB = 0x6,
13720 SUBU32 = 0x7,
13721 MUL = 0x8,
13722 AND = 0x9,
13723 OR32 = 0xa,
13724 NOR = 0xb,
13725 XOR32 = 0xc,
13726 SLT = 0xd,
13727 SLTU = 0xe,
13729 MOVN = 0x0,
13730 R6_MUL = 0x0,
13731 MOVZ = 0x1,
13732 MUH = 0x1,
13733 MULU = 0x2,
13734 MUHU = 0x3,
13735 LWXS = 0x4,
13736 R6_DIV = 0x4,
13737 MOD = 0x5,
13738 R6_DIVU = 0x6,
13739 MODU = 0x7,
13741 /* The following can be distinguished by their lower 6 bits. */
13742 BREAK32 = 0x07,
13743 INS = 0x0c,
13744 LSA = 0x0f,
13745 ALIGN = 0x1f,
13746 EXT = 0x2c,
13747 POOL32AXF = 0x3c,
13748 SIGRIE = 0x3f
13751 /* POOL32AXF encoding of minor opcode field extension */
13754 * 1. MIPS Architecture for Programmers Volume II-B:
13755 * The microMIPS32 Instruction Set (Revision 3.05)
13757 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
13759 * 2. MIPS Architecture for Programmers VolumeIV-e:
13760 * The MIPS DSP Application-Specific Extension
13761 * to the microMIPS32 Architecture (Revision 2.34)
13763 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
13766 enum {
13767 /* bits 11..6 */
13768 TEQ = 0x00,
13769 TGE = 0x08,
13770 TGEU = 0x10,
13771 TLT = 0x20,
13772 TLTU = 0x28,
13773 TNE = 0x30,
13775 MFC0 = 0x03,
13776 MTC0 = 0x0b,
13778 /* begin of microMIPS32 DSP */
13780 /* bits 13..12 for 0x01 */
13781 MFHI_ACC = 0x0,
13782 MFLO_ACC = 0x1,
13783 MTHI_ACC = 0x2,
13784 MTLO_ACC = 0x3,
13786 /* bits 13..12 for 0x2a */
13787 MADD_ACC = 0x0,
13788 MADDU_ACC = 0x1,
13789 MSUB_ACC = 0x2,
13790 MSUBU_ACC = 0x3,
13792 /* bits 13..12 for 0x32 */
13793 MULT_ACC = 0x0,
13794 MULTU_ACC = 0x1,
13796 /* end of microMIPS32 DSP */
13798 /* bits 15..12 for 0x2c */
13799 BITSWAP = 0x0,
13800 SEB = 0x2,
13801 SEH = 0x3,
13802 CLO = 0x4,
13803 CLZ = 0x5,
13804 RDHWR = 0x6,
13805 WSBH = 0x7,
13806 MULT = 0x8,
13807 MULTU = 0x9,
13808 DIV = 0xa,
13809 DIVU = 0xb,
13810 MADD = 0xc,
13811 MADDU = 0xd,
13812 MSUB = 0xe,
13813 MSUBU = 0xf,
13815 /* bits 15..12 for 0x34 */
13816 MFC2 = 0x4,
13817 MTC2 = 0x5,
13818 MFHC2 = 0x8,
13819 MTHC2 = 0x9,
13820 CFC2 = 0xc,
13821 CTC2 = 0xd,
13823 /* bits 15..12 for 0x3c */
13824 JALR = 0x0,
13825 JR = 0x0, /* alias */
13826 JALRC = 0x0,
13827 JRC = 0x0,
13828 JALR_HB = 0x1,
13829 JALRC_HB = 0x1,
13830 JALRS = 0x4,
13831 JALRS_HB = 0x5,
13833 /* bits 15..12 for 0x05 */
13834 RDPGPR = 0xe,
13835 WRPGPR = 0xf,
13837 /* bits 15..12 for 0x0d */
13838 TLBP = 0x0,
13839 TLBR = 0x1,
13840 TLBWI = 0x2,
13841 TLBWR = 0x3,
13842 TLBINV = 0x4,
13843 TLBINVF = 0x5,
13844 WAIT = 0x9,
13845 IRET = 0xd,
13846 DERET = 0xe,
13847 ERET = 0xf,
13849 /* bits 15..12 for 0x15 */
13850 DMT = 0x0,
13851 DVPE = 0x1,
13852 EMT = 0x2,
13853 EVPE = 0x3,
13855 /* bits 15..12 for 0x1d */
13856 DI = 0x4,
13857 EI = 0x5,
13859 /* bits 15..12 for 0x2d */
13860 SYNC = 0x6,
13861 SYSCALL = 0x8,
13862 SDBBP = 0xd,
13864 /* bits 15..12 for 0x35 */
13865 MFHI32 = 0x0,
13866 MFLO32 = 0x1,
13867 MTHI32 = 0x2,
13868 MTLO32 = 0x3,
13871 /* POOL32B encoding of minor opcode field (bits 15..12) */
13873 enum {
13874 LWC2 = 0x0,
13875 LWP = 0x1,
13876 LDP = 0x4,
13877 LWM32 = 0x5,
13878 CACHE = 0x6,
13879 LDM = 0x7,
13880 SWC2 = 0x8,
13881 SWP = 0x9,
13882 SDP = 0xc,
13883 SWM32 = 0xd,
13884 SDM = 0xf
13887 /* POOL32C encoding of minor opcode field (bits 15..12) */
13889 enum {
13890 LWL = 0x0,
13891 SWL = 0x8,
13892 LWR = 0x1,
13893 SWR = 0x9,
13894 PREF = 0x2,
13895 ST_EVA = 0xa,
13896 LL = 0x3,
13897 SC = 0xb,
13898 LDL = 0x4,
13899 SDL = 0xc,
13900 LDR = 0x5,
13901 SDR = 0xd,
13902 LD_EVA = 0x6,
13903 LWU = 0xe,
13904 LLD = 0x7,
13905 SCD = 0xf
13908 /* POOL32C LD-EVA encoding of minor opcode field (bits 11..9) */
13910 enum {
13911 LBUE = 0x0,
13912 LHUE = 0x1,
13913 LWLE = 0x2,
13914 LWRE = 0x3,
13915 LBE = 0x4,
13916 LHE = 0x5,
13917 LLE = 0x6,
13918 LWE = 0x7,
13921 /* POOL32C ST-EVA encoding of minor opcode field (bits 11..9) */
13923 enum {
13924 SWLE = 0x0,
13925 SWRE = 0x1,
13926 PREFE = 0x2,
13927 CACHEE = 0x3,
13928 SBE = 0x4,
13929 SHE = 0x5,
13930 SCE = 0x6,
13931 SWE = 0x7,
13934 /* POOL32F encoding of minor opcode field (bits 5..0) */
13936 enum {
13937 /* These are the bit 7..6 values */
13938 ADD_FMT = 0x0,
13940 SUB_FMT = 0x1,
13942 MUL_FMT = 0x2,
13944 DIV_FMT = 0x3,
13946 /* These are the bit 8..6 values */
13947 MOVN_FMT = 0x0,
13948 RSQRT2_FMT = 0x0,
13949 MOVF_FMT = 0x0,
13950 RINT_FMT = 0x0,
13951 SELNEZ_FMT = 0x0,
13953 MOVZ_FMT = 0x1,
13954 LWXC1 = 0x1,
13955 MOVT_FMT = 0x1,
13956 CLASS_FMT = 0x1,
13957 SELEQZ_FMT = 0x1,
13959 PLL_PS = 0x2,
13960 SWXC1 = 0x2,
13961 SEL_FMT = 0x2,
13963 PLU_PS = 0x3,
13964 LDXC1 = 0x3,
13966 MOVN_FMT_04 = 0x4,
13967 PUL_PS = 0x4,
13968 SDXC1 = 0x4,
13969 RECIP2_FMT = 0x4,
13971 MOVZ_FMT_05 = 0x05,
13972 PUU_PS = 0x5,
13973 LUXC1 = 0x5,
13975 CVT_PS_S = 0x6,
13976 SUXC1 = 0x6,
13977 ADDR_PS = 0x6,
13978 PREFX = 0x6,
13979 MADDF_FMT = 0x6,
13981 MULR_PS = 0x7,
13982 MSUBF_FMT = 0x7,
13984 MADD_S = 0x01,
13985 MADD_D = 0x09,
13986 MADD_PS = 0x11,
13987 ALNV_PS = 0x19,
13988 MSUB_S = 0x21,
13989 MSUB_D = 0x29,
13990 MSUB_PS = 0x31,
13992 NMADD_S = 0x02,
13993 NMADD_D = 0x0a,
13994 NMADD_PS = 0x12,
13995 NMSUB_S = 0x22,
13996 NMSUB_D = 0x2a,
13997 NMSUB_PS = 0x32,
13999 MIN_FMT = 0x3,
14000 MAX_FMT = 0xb,
14001 MINA_FMT = 0x23,
14002 MAXA_FMT = 0x2b,
14003 POOL32FXF = 0x3b,
14005 CABS_COND_FMT = 0x1c, /* MIPS3D */
14006 C_COND_FMT = 0x3c,
14008 CMP_CONDN_S = 0x5,
14009 CMP_CONDN_D = 0x15
14012 /* POOL32Fxf encoding of minor opcode extension field */
14014 enum {
14015 CVT_L = 0x04,
14016 RSQRT_FMT = 0x08,
14017 FLOOR_L = 0x0c,
14018 CVT_PW_PS = 0x1c,
14019 CVT_W = 0x24,
14020 SQRT_FMT = 0x28,
14021 FLOOR_W = 0x2c,
14022 CVT_PS_PW = 0x3c,
14023 CFC1 = 0x40,
14024 RECIP_FMT = 0x48,
14025 CEIL_L = 0x4c,
14026 CTC1 = 0x60,
14027 CEIL_W = 0x6c,
14028 MFC1 = 0x80,
14029 CVT_S_PL = 0x84,
14030 TRUNC_L = 0x8c,
14031 MTC1 = 0xa0,
14032 CVT_S_PU = 0xa4,
14033 TRUNC_W = 0xac,
14034 MFHC1 = 0xc0,
14035 ROUND_L = 0xcc,
14036 MTHC1 = 0xe0,
14037 ROUND_W = 0xec,
14039 MOV_FMT = 0x01,
14040 MOVF = 0x05,
14041 ABS_FMT = 0x0d,
14042 RSQRT1_FMT = 0x1d,
14043 MOVT = 0x25,
14044 NEG_FMT = 0x2d,
14045 CVT_D = 0x4d,
14046 RECIP1_FMT = 0x5d,
14047 CVT_S = 0x6d
14050 /* POOL32I encoding of minor opcode field (bits 25..21) */
14052 enum {
14053 BLTZ = 0x00,
14054 BLTZAL = 0x01,
14055 BGEZ = 0x02,
14056 BGEZAL = 0x03,
14057 BLEZ = 0x04,
14058 BNEZC = 0x05,
14059 BGTZ = 0x06,
14060 BEQZC = 0x07,
14061 TLTI = 0x08,
14062 BC1EQZC = 0x08,
14063 TGEI = 0x09,
14064 BC1NEZC = 0x09,
14065 TLTIU = 0x0a,
14066 BC2EQZC = 0x0a,
14067 TGEIU = 0x0b,
14068 BC2NEZC = 0x0a,
14069 TNEI = 0x0c,
14070 R6_SYNCI = 0x0c,
14071 LUI = 0x0d,
14072 TEQI = 0x0e,
14073 SYNCI = 0x10,
14074 BLTZALS = 0x11,
14075 BGEZALS = 0x13,
14076 BC2F = 0x14,
14077 BC2T = 0x15,
14078 /* These overlap and are distinguished by bit16 of the instruction */
14079 BC1F = 0x1c,
14080 BC1T = 0x1d,
14081 BC1ANY2F = 0x1c,
14082 BC1ANY2T = 0x1d,
14083 BC1ANY4F = 0x1e,
14084 BC1ANY4T = 0x1f
14087 /* POOL16A encoding of minor opcode field */
14089 enum {
14090 ADDU16 = 0x0,
14091 SUBU16 = 0x1
14094 /* POOL16B encoding of minor opcode field */
14096 enum {
14097 SLL16 = 0x0,
14098 SRL16 = 0x1
14101 /* POOL16C encoding of minor opcode field */
14103 enum {
14104 NOT16 = 0x00,
14105 XOR16 = 0x04,
14106 AND16 = 0x08,
14107 OR16 = 0x0c,
14108 LWM16 = 0x10,
14109 SWM16 = 0x14,
14110 JR16 = 0x18,
14111 JRC16 = 0x1a,
14112 JALR16 = 0x1c,
14113 JALR16S = 0x1e,
14114 MFHI16 = 0x20,
14115 MFLO16 = 0x24,
14116 BREAK16 = 0x28,
14117 SDBBP16 = 0x2c,
14118 JRADDIUSP = 0x30
14121 /* R6 POOL16C encoding of minor opcode field (bits 0..5) */
14123 enum {
14124 R6_NOT16 = 0x00,
14125 R6_AND16 = 0x01,
14126 R6_LWM16 = 0x02,
14127 R6_JRC16 = 0x03,
14128 MOVEP = 0x04,
14129 MOVEP_05 = 0x05,
14130 MOVEP_06 = 0x06,
14131 MOVEP_07 = 0x07,
14132 R6_XOR16 = 0x08,
14133 R6_OR16 = 0x09,
14134 R6_SWM16 = 0x0a,
14135 JALRC16 = 0x0b,
14136 MOVEP_0C = 0x0c,
14137 MOVEP_0D = 0x0d,
14138 MOVEP_0E = 0x0e,
14139 MOVEP_0F = 0x0f,
14140 JRCADDIUSP = 0x13,
14141 R6_BREAK16 = 0x1b,
14142 R6_SDBBP16 = 0x3b
14145 /* POOL16D encoding of minor opcode field */
14147 enum {
14148 ADDIUS5 = 0x0,
14149 ADDIUSP = 0x1
14152 /* POOL16E encoding of minor opcode field */
14154 enum {
14155 ADDIUR2 = 0x0,
14156 ADDIUR1SP = 0x1
14159 static int mmreg(int r)
14161 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
14163 return map[r];
14166 /* Used for 16-bit store instructions. */
14167 static int mmreg2(int r)
14169 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
14171 return map[r];
14174 #define uMIPS_RD(op) ((op >> 7) & 0x7)
14175 #define uMIPS_RS(op) ((op >> 4) & 0x7)
14176 #define uMIPS_RS2(op) uMIPS_RS(op)
14177 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
14178 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
14179 #define uMIPS_RS5(op) (op & 0x1f)
14181 /* Signed immediate */
14182 #define SIMM(op, start, width) \
14183 ((int32_t)(((op >> start) & ((~0U) >> (32 - width))) \
14184 << (32 - width)) \
14185 >> (32 - width))
14186 /* Zero-extended immediate */
14187 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32 - width)))
14189 static void gen_addiur1sp(DisasContext *ctx)
14191 int rd = mmreg(uMIPS_RD(ctx->opcode));
14193 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
14196 static void gen_addiur2(DisasContext *ctx)
14198 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
14199 int rd = mmreg(uMIPS_RD(ctx->opcode));
14200 int rs = mmreg(uMIPS_RS(ctx->opcode));
14202 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
14205 static void gen_addiusp(DisasContext *ctx)
14207 int encoded = ZIMM(ctx->opcode, 1, 9);
14208 int decoded;
14210 if (encoded <= 1) {
14211 decoded = 256 + encoded;
14212 } else if (encoded <= 255) {
14213 decoded = encoded;
14214 } else if (encoded <= 509) {
14215 decoded = encoded - 512;
14216 } else {
14217 decoded = encoded - 768;
14220 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
14223 static void gen_addius5(DisasContext *ctx)
14225 int imm = SIMM(ctx->opcode, 1, 4);
14226 int rd = (ctx->opcode >> 5) & 0x1f;
14228 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
14231 static void gen_andi16(DisasContext *ctx)
14233 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
14234 31, 32, 63, 64, 255, 32768, 65535 };
14235 int rd = mmreg(uMIPS_RD(ctx->opcode));
14236 int rs = mmreg(uMIPS_RS(ctx->opcode));
14237 int encoded = ZIMM(ctx->opcode, 0, 4);
14239 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
14242 static void gen_ldst_multiple(DisasContext *ctx, uint32_t opc, int reglist,
14243 int base, int16_t offset)
14245 TCGv t0, t1;
14246 TCGv_i32 t2;
14248 if (ctx->hflags & MIPS_HFLAG_BMASK) {
14249 gen_reserved_instruction(ctx);
14250 return;
14253 t0 = tcg_temp_new();
14255 gen_base_offset_addr(ctx, t0, base, offset);
14257 t1 = tcg_const_tl(reglist);
14258 t2 = tcg_const_i32(ctx->mem_idx);
14260 save_cpu_state(ctx, 1);
14261 switch (opc) {
14262 case LWM32:
14263 gen_helper_lwm(cpu_env, t0, t1, t2);
14264 break;
14265 case SWM32:
14266 gen_helper_swm(cpu_env, t0, t1, t2);
14267 break;
14268 #ifdef TARGET_MIPS64
14269 case LDM:
14270 gen_helper_ldm(cpu_env, t0, t1, t2);
14271 break;
14272 case SDM:
14273 gen_helper_sdm(cpu_env, t0, t1, t2);
14274 break;
14275 #endif
14277 tcg_temp_free(t0);
14278 tcg_temp_free(t1);
14279 tcg_temp_free_i32(t2);
14283 static void gen_pool16c_insn(DisasContext *ctx)
14285 int rd = mmreg((ctx->opcode >> 3) & 0x7);
14286 int rs = mmreg(ctx->opcode & 0x7);
14288 switch (((ctx->opcode) >> 4) & 0x3f) {
14289 case NOT16 + 0:
14290 case NOT16 + 1:
14291 case NOT16 + 2:
14292 case NOT16 + 3:
14293 gen_logic(ctx, OPC_NOR, rd, rs, 0);
14294 break;
14295 case XOR16 + 0:
14296 case XOR16 + 1:
14297 case XOR16 + 2:
14298 case XOR16 + 3:
14299 gen_logic(ctx, OPC_XOR, rd, rd, rs);
14300 break;
14301 case AND16 + 0:
14302 case AND16 + 1:
14303 case AND16 + 2:
14304 case AND16 + 3:
14305 gen_logic(ctx, OPC_AND, rd, rd, rs);
14306 break;
14307 case OR16 + 0:
14308 case OR16 + 1:
14309 case OR16 + 2:
14310 case OR16 + 3:
14311 gen_logic(ctx, OPC_OR, rd, rd, rs);
14312 break;
14313 case LWM16 + 0:
14314 case LWM16 + 1:
14315 case LWM16 + 2:
14316 case LWM16 + 3:
14318 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14319 int offset = ZIMM(ctx->opcode, 0, 4);
14321 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
14322 29, offset << 2);
14324 break;
14325 case SWM16 + 0:
14326 case SWM16 + 1:
14327 case SWM16 + 2:
14328 case SWM16 + 3:
14330 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
14331 int offset = ZIMM(ctx->opcode, 0, 4);
14333 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
14334 29, offset << 2);
14336 break;
14337 case JR16 + 0:
14338 case JR16 + 1:
14340 int reg = ctx->opcode & 0x1f;
14342 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
14344 break;
14345 case JRC16 + 0:
14346 case JRC16 + 1:
14348 int reg = ctx->opcode & 0x1f;
14349 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
14351 * Let normal delay slot handling in our caller take us
14352 * to the branch target.
14355 break;
14356 case JALR16 + 0:
14357 case JALR16 + 1:
14358 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
14359 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14360 break;
14361 case JALR16S + 0:
14362 case JALR16S + 1:
14363 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
14364 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14365 break;
14366 case MFHI16 + 0:
14367 case MFHI16 + 1:
14368 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
14369 break;
14370 case MFLO16 + 0:
14371 case MFLO16 + 1:
14372 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
14373 break;
14374 case BREAK16:
14375 generate_exception_end(ctx, EXCP_BREAK);
14376 break;
14377 case SDBBP16:
14378 if (is_uhi(extract32(ctx->opcode, 0, 4))) {
14379 gen_helper_do_semihosting(cpu_env);
14380 } else {
14382 * XXX: not clear which exception should be raised
14383 * when in debug mode...
14385 check_insn(ctx, ISA_MIPS_R1);
14386 generate_exception_end(ctx, EXCP_DBp);
14388 break;
14389 case JRADDIUSP + 0:
14390 case JRADDIUSP + 1:
14392 int imm = ZIMM(ctx->opcode, 0, 5);
14393 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14394 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14396 * Let normal delay slot handling in our caller take us
14397 * to the branch target.
14400 break;
14401 default:
14402 gen_reserved_instruction(ctx);
14403 break;
14407 static inline void gen_movep(DisasContext *ctx, int enc_dest, int enc_rt,
14408 int enc_rs)
14410 int rd, re;
14411 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
14412 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
14413 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
14415 rd = rd_enc[enc_dest];
14416 re = re_enc[enc_dest];
14417 gen_load_gpr(cpu_gpr[rd], rs_rt_enc[enc_rs]);
14418 gen_load_gpr(cpu_gpr[re], rs_rt_enc[enc_rt]);
14421 static void gen_pool16c_r6_insn(DisasContext *ctx)
14423 int rt = mmreg((ctx->opcode >> 7) & 0x7);
14424 int rs = mmreg((ctx->opcode >> 4) & 0x7);
14426 switch (ctx->opcode & 0xf) {
14427 case R6_NOT16:
14428 gen_logic(ctx, OPC_NOR, rt, rs, 0);
14429 break;
14430 case R6_AND16:
14431 gen_logic(ctx, OPC_AND, rt, rt, rs);
14432 break;
14433 case R6_LWM16:
14435 int lwm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14436 int offset = extract32(ctx->opcode, 4, 4);
14437 gen_ldst_multiple(ctx, LWM32, lwm_converted, 29, offset << 2);
14439 break;
14440 case R6_JRC16: /* JRCADDIUSP */
14441 if ((ctx->opcode >> 4) & 1) {
14442 /* JRCADDIUSP */
14443 int imm = extract32(ctx->opcode, 5, 5);
14444 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
14445 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
14446 } else {
14447 /* JRC16 */
14448 rs = extract32(ctx->opcode, 5, 5);
14449 gen_compute_branch(ctx, OPC_JR, 2, rs, 0, 0, 0);
14451 break;
14452 case MOVEP:
14453 case MOVEP_05:
14454 case MOVEP_06:
14455 case MOVEP_07:
14456 case MOVEP_0C:
14457 case MOVEP_0D:
14458 case MOVEP_0E:
14459 case MOVEP_0F:
14461 int enc_dest = uMIPS_RD(ctx->opcode);
14462 int enc_rt = uMIPS_RS2(ctx->opcode);
14463 int enc_rs = (ctx->opcode & 3) | ((ctx->opcode >> 1) & 4);
14464 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
14466 break;
14467 case R6_XOR16:
14468 gen_logic(ctx, OPC_XOR, rt, rt, rs);
14469 break;
14470 case R6_OR16:
14471 gen_logic(ctx, OPC_OR, rt, rt, rs);
14472 break;
14473 case R6_SWM16:
14475 int swm_converted = 0x11 + extract32(ctx->opcode, 8, 2);
14476 int offset = extract32(ctx->opcode, 4, 4);
14477 gen_ldst_multiple(ctx, SWM32, swm_converted, 29, offset << 2);
14479 break;
14480 case JALRC16: /* BREAK16, SDBBP16 */
14481 switch (ctx->opcode & 0x3f) {
14482 case JALRC16:
14483 case JALRC16 + 0x20:
14484 /* JALRC16 */
14485 gen_compute_branch(ctx, OPC_JALR, 2, (ctx->opcode >> 5) & 0x1f,
14486 31, 0, 0);
14487 break;
14488 case R6_BREAK16:
14489 /* BREAK16 */
14490 generate_exception(ctx, EXCP_BREAK);
14491 break;
14492 case R6_SDBBP16:
14493 /* SDBBP16 */
14494 if (is_uhi(extract32(ctx->opcode, 6, 4))) {
14495 gen_helper_do_semihosting(cpu_env);
14496 } else {
14497 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14498 generate_exception(ctx, EXCP_RI);
14499 } else {
14500 generate_exception(ctx, EXCP_DBp);
14503 break;
14505 break;
14506 default:
14507 generate_exception(ctx, EXCP_RI);
14508 break;
14512 void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
14514 TCGv t0 = tcg_temp_new();
14515 TCGv t1 = tcg_temp_new();
14517 gen_load_gpr(t0, base);
14519 if (index != 0) {
14520 gen_load_gpr(t1, index);
14521 tcg_gen_shli_tl(t1, t1, 2);
14522 gen_op_addr_add(ctx, t0, t1, t0);
14525 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14526 gen_store_gpr(t1, rd);
14528 tcg_temp_free(t0);
14529 tcg_temp_free(t1);
14532 static void gen_ldst_pair(DisasContext *ctx, uint32_t opc, int rd,
14533 int base, int16_t offset)
14535 TCGv t0, t1;
14537 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
14538 gen_reserved_instruction(ctx);
14539 return;
14542 t0 = tcg_temp_new();
14543 t1 = tcg_temp_new();
14545 gen_base_offset_addr(ctx, t0, base, offset);
14547 switch (opc) {
14548 case LWP:
14549 if (rd == base) {
14550 gen_reserved_instruction(ctx);
14551 return;
14553 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14554 gen_store_gpr(t1, rd);
14555 tcg_gen_movi_tl(t1, 4);
14556 gen_op_addr_add(ctx, t0, t0, t1);
14557 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
14558 gen_store_gpr(t1, rd + 1);
14559 break;
14560 case SWP:
14561 gen_load_gpr(t1, rd);
14562 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14563 tcg_gen_movi_tl(t1, 4);
14564 gen_op_addr_add(ctx, t0, t0, t1);
14565 gen_load_gpr(t1, rd + 1);
14566 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
14567 break;
14568 #ifdef TARGET_MIPS64
14569 case LDP:
14570 if (rd == base) {
14571 gen_reserved_instruction(ctx);
14572 return;
14574 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14575 gen_store_gpr(t1, rd);
14576 tcg_gen_movi_tl(t1, 8);
14577 gen_op_addr_add(ctx, t0, t0, t1);
14578 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14579 gen_store_gpr(t1, rd + 1);
14580 break;
14581 case SDP:
14582 gen_load_gpr(t1, rd);
14583 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14584 tcg_gen_movi_tl(t1, 8);
14585 gen_op_addr_add(ctx, t0, t0, t1);
14586 gen_load_gpr(t1, rd + 1);
14587 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
14588 break;
14589 #endif
14591 tcg_temp_free(t0);
14592 tcg_temp_free(t1);
14595 static void gen_sync(int stype)
14597 TCGBar tcg_mo = TCG_BAR_SC;
14599 switch (stype) {
14600 case 0x4: /* SYNC_WMB */
14601 tcg_mo |= TCG_MO_ST_ST;
14602 break;
14603 case 0x10: /* SYNC_MB */
14604 tcg_mo |= TCG_MO_ALL;
14605 break;
14606 case 0x11: /* SYNC_ACQUIRE */
14607 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
14608 break;
14609 case 0x12: /* SYNC_RELEASE */
14610 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
14611 break;
14612 case 0x13: /* SYNC_RMB */
14613 tcg_mo |= TCG_MO_LD_LD;
14614 break;
14615 default:
14616 tcg_mo |= TCG_MO_ALL;
14617 break;
14620 tcg_gen_mb(tcg_mo);
14623 static void gen_pool32axf(CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
14625 int extension = (ctx->opcode >> 6) & 0x3f;
14626 int minor = (ctx->opcode >> 12) & 0xf;
14627 uint32_t mips32_op;
14629 switch (extension) {
14630 case TEQ:
14631 mips32_op = OPC_TEQ;
14632 goto do_trap;
14633 case TGE:
14634 mips32_op = OPC_TGE;
14635 goto do_trap;
14636 case TGEU:
14637 mips32_op = OPC_TGEU;
14638 goto do_trap;
14639 case TLT:
14640 mips32_op = OPC_TLT;
14641 goto do_trap;
14642 case TLTU:
14643 mips32_op = OPC_TLTU;
14644 goto do_trap;
14645 case TNE:
14646 mips32_op = OPC_TNE;
14647 do_trap:
14648 gen_trap(ctx, mips32_op, rs, rt, -1);
14649 break;
14650 #ifndef CONFIG_USER_ONLY
14651 case MFC0:
14652 case MFC0 + 32:
14653 check_cp0_enabled(ctx);
14654 if (rt == 0) {
14655 /* Treat as NOP. */
14656 break;
14658 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
14659 break;
14660 case MTC0:
14661 case MTC0 + 32:
14662 check_cp0_enabled(ctx);
14664 TCGv t0 = tcg_temp_new();
14666 gen_load_gpr(t0, rt);
14667 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
14668 tcg_temp_free(t0);
14670 break;
14671 #endif
14672 case 0x2a:
14673 switch (minor & 3) {
14674 case MADD_ACC:
14675 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
14676 break;
14677 case MADDU_ACC:
14678 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
14679 break;
14680 case MSUB_ACC:
14681 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
14682 break;
14683 case MSUBU_ACC:
14684 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
14685 break;
14686 default:
14687 goto pool32axf_invalid;
14689 break;
14690 case 0x32:
14691 switch (minor & 3) {
14692 case MULT_ACC:
14693 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
14694 break;
14695 case MULTU_ACC:
14696 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
14697 break;
14698 default:
14699 goto pool32axf_invalid;
14701 break;
14702 case 0x2c:
14703 switch (minor) {
14704 case BITSWAP:
14705 check_insn(ctx, ISA_MIPS_R6);
14706 gen_bitswap(ctx, OPC_BITSWAP, rs, rt);
14707 break;
14708 case SEB:
14709 gen_bshfl(ctx, OPC_SEB, rs, rt);
14710 break;
14711 case SEH:
14712 gen_bshfl(ctx, OPC_SEH, rs, rt);
14713 break;
14714 case CLO:
14715 mips32_op = OPC_CLO;
14716 goto do_cl;
14717 case CLZ:
14718 mips32_op = OPC_CLZ;
14719 do_cl:
14720 check_insn(ctx, ISA_MIPS_R1);
14721 gen_cl(ctx, mips32_op, rt, rs);
14722 break;
14723 case RDHWR:
14724 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14725 gen_rdhwr(ctx, rt, rs, 0);
14726 break;
14727 case WSBH:
14728 gen_bshfl(ctx, OPC_WSBH, rs, rt);
14729 break;
14730 case MULT:
14731 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14732 mips32_op = OPC_MULT;
14733 goto do_mul;
14734 case MULTU:
14735 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14736 mips32_op = OPC_MULTU;
14737 goto do_mul;
14738 case DIV:
14739 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14740 mips32_op = OPC_DIV;
14741 goto do_div;
14742 case DIVU:
14743 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14744 mips32_op = OPC_DIVU;
14745 goto do_div;
14746 do_div:
14747 check_insn(ctx, ISA_MIPS_R1);
14748 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14749 break;
14750 case MADD:
14751 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14752 mips32_op = OPC_MADD;
14753 goto do_mul;
14754 case MADDU:
14755 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14756 mips32_op = OPC_MADDU;
14757 goto do_mul;
14758 case MSUB:
14759 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14760 mips32_op = OPC_MSUB;
14761 goto do_mul;
14762 case MSUBU:
14763 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14764 mips32_op = OPC_MSUBU;
14765 do_mul:
14766 check_insn(ctx, ISA_MIPS_R1);
14767 gen_muldiv(ctx, mips32_op, 0, rs, rt);
14768 break;
14769 default:
14770 goto pool32axf_invalid;
14772 break;
14773 case 0x34:
14774 switch (minor) {
14775 case MFC2:
14776 case MTC2:
14777 case MFHC2:
14778 case MTHC2:
14779 case CFC2:
14780 case CTC2:
14781 generate_exception_err(ctx, EXCP_CpU, 2);
14782 break;
14783 default:
14784 goto pool32axf_invalid;
14786 break;
14787 case 0x3c:
14788 switch (minor) {
14789 case JALR: /* JALRC */
14790 case JALR_HB: /* JALRC_HB */
14791 if (ctx->insn_flags & ISA_MIPS_R6) {
14792 /* JALRC, JALRC_HB */
14793 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 0);
14794 } else {
14795 /* JALR, JALR_HB */
14796 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
14797 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14799 break;
14800 case JALRS:
14801 case JALRS_HB:
14802 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14803 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
14804 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
14805 break;
14806 default:
14807 goto pool32axf_invalid;
14809 break;
14810 case 0x05:
14811 switch (minor) {
14812 case RDPGPR:
14813 check_cp0_enabled(ctx);
14814 check_insn(ctx, ISA_MIPS_R2);
14815 gen_load_srsgpr(rs, rt);
14816 break;
14817 case WRPGPR:
14818 check_cp0_enabled(ctx);
14819 check_insn(ctx, ISA_MIPS_R2);
14820 gen_store_srsgpr(rs, rt);
14821 break;
14822 default:
14823 goto pool32axf_invalid;
14825 break;
14826 #ifndef CONFIG_USER_ONLY
14827 case 0x0d:
14828 switch (minor) {
14829 case TLBP:
14830 mips32_op = OPC_TLBP;
14831 goto do_cp0;
14832 case TLBR:
14833 mips32_op = OPC_TLBR;
14834 goto do_cp0;
14835 case TLBWI:
14836 mips32_op = OPC_TLBWI;
14837 goto do_cp0;
14838 case TLBWR:
14839 mips32_op = OPC_TLBWR;
14840 goto do_cp0;
14841 case TLBINV:
14842 mips32_op = OPC_TLBINV;
14843 goto do_cp0;
14844 case TLBINVF:
14845 mips32_op = OPC_TLBINVF;
14846 goto do_cp0;
14847 case WAIT:
14848 mips32_op = OPC_WAIT;
14849 goto do_cp0;
14850 case DERET:
14851 mips32_op = OPC_DERET;
14852 goto do_cp0;
14853 case ERET:
14854 mips32_op = OPC_ERET;
14855 do_cp0:
14856 gen_cp0(env, ctx, mips32_op, rt, rs);
14857 break;
14858 default:
14859 goto pool32axf_invalid;
14861 break;
14862 case 0x1d:
14863 switch (minor) {
14864 case DI:
14865 check_cp0_enabled(ctx);
14867 TCGv t0 = tcg_temp_new();
14869 save_cpu_state(ctx, 1);
14870 gen_helper_di(t0, cpu_env);
14871 gen_store_gpr(t0, rs);
14873 * Stop translation as we may have switched the execution
14874 * mode.
14876 ctx->base.is_jmp = DISAS_STOP;
14877 tcg_temp_free(t0);
14879 break;
14880 case EI:
14881 check_cp0_enabled(ctx);
14883 TCGv t0 = tcg_temp_new();
14885 save_cpu_state(ctx, 1);
14886 gen_helper_ei(t0, cpu_env);
14887 gen_store_gpr(t0, rs);
14889 * DISAS_STOP isn't sufficient, we need to ensure we break out
14890 * of translated code to check for pending interrupts.
14892 gen_save_pc(ctx->base.pc_next + 4);
14893 ctx->base.is_jmp = DISAS_EXIT;
14894 tcg_temp_free(t0);
14896 break;
14897 default:
14898 goto pool32axf_invalid;
14900 break;
14901 #endif
14902 case 0x2d:
14903 switch (minor) {
14904 case SYNC:
14905 gen_sync(extract32(ctx->opcode, 16, 5));
14906 break;
14907 case SYSCALL:
14908 generate_exception_end(ctx, EXCP_SYSCALL);
14909 break;
14910 case SDBBP:
14911 if (is_uhi(extract32(ctx->opcode, 16, 10))) {
14912 gen_helper_do_semihosting(cpu_env);
14913 } else {
14914 check_insn(ctx, ISA_MIPS_R1);
14915 if (ctx->hflags & MIPS_HFLAG_SBRI) {
14916 gen_reserved_instruction(ctx);
14917 } else {
14918 generate_exception_end(ctx, EXCP_DBp);
14921 break;
14922 default:
14923 goto pool32axf_invalid;
14925 break;
14926 case 0x01:
14927 switch (minor & 3) {
14928 case MFHI_ACC:
14929 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
14930 break;
14931 case MFLO_ACC:
14932 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
14933 break;
14934 case MTHI_ACC:
14935 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
14936 break;
14937 case MTLO_ACC:
14938 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
14939 break;
14940 default:
14941 goto pool32axf_invalid;
14943 break;
14944 case 0x35:
14945 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14946 switch (minor) {
14947 case MFHI32:
14948 gen_HILO(ctx, OPC_MFHI, 0, rs);
14949 break;
14950 case MFLO32:
14951 gen_HILO(ctx, OPC_MFLO, 0, rs);
14952 break;
14953 case MTHI32:
14954 gen_HILO(ctx, OPC_MTHI, 0, rs);
14955 break;
14956 case MTLO32:
14957 gen_HILO(ctx, OPC_MTLO, 0, rs);
14958 break;
14959 default:
14960 goto pool32axf_invalid;
14962 break;
14963 default:
14964 pool32axf_invalid:
14965 MIPS_INVAL("pool32axf");
14966 gen_reserved_instruction(ctx);
14967 break;
14972 * Values for microMIPS fmt field. Variable-width, depending on which
14973 * formats the instruction supports.
14975 enum {
14976 FMT_SD_S = 0,
14977 FMT_SD_D = 1,
14979 FMT_SDPS_S = 0,
14980 FMT_SDPS_D = 1,
14981 FMT_SDPS_PS = 2,
14983 FMT_SWL_S = 0,
14984 FMT_SWL_W = 1,
14985 FMT_SWL_L = 2,
14987 FMT_DWL_D = 0,
14988 FMT_DWL_W = 1,
14989 FMT_DWL_L = 2
14992 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
14994 int extension = (ctx->opcode >> 6) & 0x3ff;
14995 uint32_t mips32_op;
14997 #define FLOAT_1BIT_FMT(opc, fmt) ((fmt << 8) | opc)
14998 #define FLOAT_2BIT_FMT(opc, fmt) ((fmt << 7) | opc)
14999 #define COND_FLOAT_MOV(opc, cond) ((cond << 7) | opc)
15001 switch (extension) {
15002 case FLOAT_1BIT_FMT(CFC1, 0):
15003 mips32_op = OPC_CFC1;
15004 goto do_cp1;
15005 case FLOAT_1BIT_FMT(CTC1, 0):
15006 mips32_op = OPC_CTC1;
15007 goto do_cp1;
15008 case FLOAT_1BIT_FMT(MFC1, 0):
15009 mips32_op = OPC_MFC1;
15010 goto do_cp1;
15011 case FLOAT_1BIT_FMT(MTC1, 0):
15012 mips32_op = OPC_MTC1;
15013 goto do_cp1;
15014 case FLOAT_1BIT_FMT(MFHC1, 0):
15015 mips32_op = OPC_MFHC1;
15016 goto do_cp1;
15017 case FLOAT_1BIT_FMT(MTHC1, 0):
15018 mips32_op = OPC_MTHC1;
15019 do_cp1:
15020 gen_cp1(ctx, mips32_op, rt, rs);
15021 break;
15023 /* Reciprocal square root */
15024 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
15025 mips32_op = OPC_RSQRT_S;
15026 goto do_unaryfp;
15027 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
15028 mips32_op = OPC_RSQRT_D;
15029 goto do_unaryfp;
15031 /* Square root */
15032 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
15033 mips32_op = OPC_SQRT_S;
15034 goto do_unaryfp;
15035 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
15036 mips32_op = OPC_SQRT_D;
15037 goto do_unaryfp;
15039 /* Reciprocal */
15040 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
15041 mips32_op = OPC_RECIP_S;
15042 goto do_unaryfp;
15043 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
15044 mips32_op = OPC_RECIP_D;
15045 goto do_unaryfp;
15047 /* Floor */
15048 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
15049 mips32_op = OPC_FLOOR_L_S;
15050 goto do_unaryfp;
15051 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
15052 mips32_op = OPC_FLOOR_L_D;
15053 goto do_unaryfp;
15054 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
15055 mips32_op = OPC_FLOOR_W_S;
15056 goto do_unaryfp;
15057 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
15058 mips32_op = OPC_FLOOR_W_D;
15059 goto do_unaryfp;
15061 /* Ceiling */
15062 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
15063 mips32_op = OPC_CEIL_L_S;
15064 goto do_unaryfp;
15065 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
15066 mips32_op = OPC_CEIL_L_D;
15067 goto do_unaryfp;
15068 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
15069 mips32_op = OPC_CEIL_W_S;
15070 goto do_unaryfp;
15071 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
15072 mips32_op = OPC_CEIL_W_D;
15073 goto do_unaryfp;
15075 /* Truncation */
15076 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
15077 mips32_op = OPC_TRUNC_L_S;
15078 goto do_unaryfp;
15079 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
15080 mips32_op = OPC_TRUNC_L_D;
15081 goto do_unaryfp;
15082 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
15083 mips32_op = OPC_TRUNC_W_S;
15084 goto do_unaryfp;
15085 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
15086 mips32_op = OPC_TRUNC_W_D;
15087 goto do_unaryfp;
15089 /* Round */
15090 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
15091 mips32_op = OPC_ROUND_L_S;
15092 goto do_unaryfp;
15093 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
15094 mips32_op = OPC_ROUND_L_D;
15095 goto do_unaryfp;
15096 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
15097 mips32_op = OPC_ROUND_W_S;
15098 goto do_unaryfp;
15099 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
15100 mips32_op = OPC_ROUND_W_D;
15101 goto do_unaryfp;
15103 /* Integer to floating-point conversion */
15104 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
15105 mips32_op = OPC_CVT_L_S;
15106 goto do_unaryfp;
15107 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
15108 mips32_op = OPC_CVT_L_D;
15109 goto do_unaryfp;
15110 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
15111 mips32_op = OPC_CVT_W_S;
15112 goto do_unaryfp;
15113 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
15114 mips32_op = OPC_CVT_W_D;
15115 goto do_unaryfp;
15117 /* Paired-foo conversions */
15118 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
15119 mips32_op = OPC_CVT_S_PL;
15120 goto do_unaryfp;
15121 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
15122 mips32_op = OPC_CVT_S_PU;
15123 goto do_unaryfp;
15124 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
15125 mips32_op = OPC_CVT_PW_PS;
15126 goto do_unaryfp;
15127 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
15128 mips32_op = OPC_CVT_PS_PW;
15129 goto do_unaryfp;
15131 /* Floating-point moves */
15132 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
15133 mips32_op = OPC_MOV_S;
15134 goto do_unaryfp;
15135 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
15136 mips32_op = OPC_MOV_D;
15137 goto do_unaryfp;
15138 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
15139 mips32_op = OPC_MOV_PS;
15140 goto do_unaryfp;
15142 /* Absolute value */
15143 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
15144 mips32_op = OPC_ABS_S;
15145 goto do_unaryfp;
15146 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
15147 mips32_op = OPC_ABS_D;
15148 goto do_unaryfp;
15149 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
15150 mips32_op = OPC_ABS_PS;
15151 goto do_unaryfp;
15153 /* Negation */
15154 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
15155 mips32_op = OPC_NEG_S;
15156 goto do_unaryfp;
15157 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
15158 mips32_op = OPC_NEG_D;
15159 goto do_unaryfp;
15160 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
15161 mips32_op = OPC_NEG_PS;
15162 goto do_unaryfp;
15164 /* Reciprocal square root step */
15165 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
15166 mips32_op = OPC_RSQRT1_S;
15167 goto do_unaryfp;
15168 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
15169 mips32_op = OPC_RSQRT1_D;
15170 goto do_unaryfp;
15171 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
15172 mips32_op = OPC_RSQRT1_PS;
15173 goto do_unaryfp;
15175 /* Reciprocal step */
15176 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
15177 mips32_op = OPC_RECIP1_S;
15178 goto do_unaryfp;
15179 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
15180 mips32_op = OPC_RECIP1_S;
15181 goto do_unaryfp;
15182 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
15183 mips32_op = OPC_RECIP1_PS;
15184 goto do_unaryfp;
15186 /* Conversions from double */
15187 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
15188 mips32_op = OPC_CVT_D_S;
15189 goto do_unaryfp;
15190 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
15191 mips32_op = OPC_CVT_D_W;
15192 goto do_unaryfp;
15193 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
15194 mips32_op = OPC_CVT_D_L;
15195 goto do_unaryfp;
15197 /* Conversions from single */
15198 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
15199 mips32_op = OPC_CVT_S_D;
15200 goto do_unaryfp;
15201 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
15202 mips32_op = OPC_CVT_S_W;
15203 goto do_unaryfp;
15204 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
15205 mips32_op = OPC_CVT_S_L;
15206 do_unaryfp:
15207 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
15208 break;
15210 /* Conditional moves on floating-point codes */
15211 case COND_FLOAT_MOV(MOVT, 0):
15212 case COND_FLOAT_MOV(MOVT, 1):
15213 case COND_FLOAT_MOV(MOVT, 2):
15214 case COND_FLOAT_MOV(MOVT, 3):
15215 case COND_FLOAT_MOV(MOVT, 4):
15216 case COND_FLOAT_MOV(MOVT, 5):
15217 case COND_FLOAT_MOV(MOVT, 6):
15218 case COND_FLOAT_MOV(MOVT, 7):
15219 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15220 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
15221 break;
15222 case COND_FLOAT_MOV(MOVF, 0):
15223 case COND_FLOAT_MOV(MOVF, 1):
15224 case COND_FLOAT_MOV(MOVF, 2):
15225 case COND_FLOAT_MOV(MOVF, 3):
15226 case COND_FLOAT_MOV(MOVF, 4):
15227 case COND_FLOAT_MOV(MOVF, 5):
15228 case COND_FLOAT_MOV(MOVF, 6):
15229 case COND_FLOAT_MOV(MOVF, 7):
15230 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15231 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
15232 break;
15233 default:
15234 MIPS_INVAL("pool32fxf");
15235 gen_reserved_instruction(ctx);
15236 break;
15240 static void decode_micromips32_opc(CPUMIPSState *env, DisasContext *ctx)
15242 int32_t offset;
15243 uint16_t insn;
15244 int rt, rs, rd, rr;
15245 int16_t imm;
15246 uint32_t op, minor, minor2, mips32_op;
15247 uint32_t cond, fmt, cc;
15249 insn = translator_lduw(env, ctx->base.pc_next + 2);
15250 ctx->opcode = (ctx->opcode << 16) | insn;
15252 rt = (ctx->opcode >> 21) & 0x1f;
15253 rs = (ctx->opcode >> 16) & 0x1f;
15254 rd = (ctx->opcode >> 11) & 0x1f;
15255 rr = (ctx->opcode >> 6) & 0x1f;
15256 imm = (int16_t) ctx->opcode;
15258 op = (ctx->opcode >> 26) & 0x3f;
15259 switch (op) {
15260 case POOL32A:
15261 minor = ctx->opcode & 0x3f;
15262 switch (minor) {
15263 case 0x00:
15264 minor = (ctx->opcode >> 6) & 0xf;
15265 switch (minor) {
15266 case SLL32:
15267 mips32_op = OPC_SLL;
15268 goto do_shifti;
15269 case SRA:
15270 mips32_op = OPC_SRA;
15271 goto do_shifti;
15272 case SRL32:
15273 mips32_op = OPC_SRL;
15274 goto do_shifti;
15275 case ROTR:
15276 mips32_op = OPC_ROTR;
15277 do_shifti:
15278 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
15279 break;
15280 case SELEQZ:
15281 check_insn(ctx, ISA_MIPS_R6);
15282 gen_cond_move(ctx, OPC_SELEQZ, rd, rs, rt);
15283 break;
15284 case SELNEZ:
15285 check_insn(ctx, ISA_MIPS_R6);
15286 gen_cond_move(ctx, OPC_SELNEZ, rd, rs, rt);
15287 break;
15288 case R6_RDHWR:
15289 check_insn(ctx, ISA_MIPS_R6);
15290 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
15291 break;
15292 default:
15293 goto pool32a_invalid;
15295 break;
15296 case 0x10:
15297 minor = (ctx->opcode >> 6) & 0xf;
15298 switch (minor) {
15299 /* Arithmetic */
15300 case ADD:
15301 mips32_op = OPC_ADD;
15302 goto do_arith;
15303 case ADDU32:
15304 mips32_op = OPC_ADDU;
15305 goto do_arith;
15306 case SUB:
15307 mips32_op = OPC_SUB;
15308 goto do_arith;
15309 case SUBU32:
15310 mips32_op = OPC_SUBU;
15311 goto do_arith;
15312 case MUL:
15313 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15314 mips32_op = OPC_MUL;
15315 do_arith:
15316 gen_arith(ctx, mips32_op, rd, rs, rt);
15317 break;
15318 /* Shifts */
15319 case SLLV:
15320 mips32_op = OPC_SLLV;
15321 goto do_shift;
15322 case SRLV:
15323 mips32_op = OPC_SRLV;
15324 goto do_shift;
15325 case SRAV:
15326 mips32_op = OPC_SRAV;
15327 goto do_shift;
15328 case ROTRV:
15329 mips32_op = OPC_ROTRV;
15330 do_shift:
15331 gen_shift(ctx, mips32_op, rd, rs, rt);
15332 break;
15333 /* Logical operations */
15334 case AND:
15335 mips32_op = OPC_AND;
15336 goto do_logic;
15337 case OR32:
15338 mips32_op = OPC_OR;
15339 goto do_logic;
15340 case NOR:
15341 mips32_op = OPC_NOR;
15342 goto do_logic;
15343 case XOR32:
15344 mips32_op = OPC_XOR;
15345 do_logic:
15346 gen_logic(ctx, mips32_op, rd, rs, rt);
15347 break;
15348 /* Set less than */
15349 case SLT:
15350 mips32_op = OPC_SLT;
15351 goto do_slt;
15352 case SLTU:
15353 mips32_op = OPC_SLTU;
15354 do_slt:
15355 gen_slt(ctx, mips32_op, rd, rs, rt);
15356 break;
15357 default:
15358 goto pool32a_invalid;
15360 break;
15361 case 0x18:
15362 minor = (ctx->opcode >> 6) & 0xf;
15363 switch (minor) {
15364 /* Conditional moves */
15365 case MOVN: /* MUL */
15366 if (ctx->insn_flags & ISA_MIPS_R6) {
15367 /* MUL */
15368 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
15369 } else {
15370 /* MOVN */
15371 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
15373 break;
15374 case MOVZ: /* MUH */
15375 if (ctx->insn_flags & ISA_MIPS_R6) {
15376 /* MUH */
15377 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
15378 } else {
15379 /* MOVZ */
15380 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
15382 break;
15383 case MULU:
15384 check_insn(ctx, ISA_MIPS_R6);
15385 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
15386 break;
15387 case MUHU:
15388 check_insn(ctx, ISA_MIPS_R6);
15389 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
15390 break;
15391 case LWXS: /* DIV */
15392 if (ctx->insn_flags & ISA_MIPS_R6) {
15393 /* DIV */
15394 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
15395 } else {
15396 /* LWXS */
15397 gen_ldxs(ctx, rs, rt, rd);
15399 break;
15400 case MOD:
15401 check_insn(ctx, ISA_MIPS_R6);
15402 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
15403 break;
15404 case R6_DIVU:
15405 check_insn(ctx, ISA_MIPS_R6);
15406 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
15407 break;
15408 case MODU:
15409 check_insn(ctx, ISA_MIPS_R6);
15410 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
15411 break;
15412 default:
15413 goto pool32a_invalid;
15415 break;
15416 case INS:
15417 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
15418 return;
15419 case LSA:
15420 check_insn(ctx, ISA_MIPS_R6);
15421 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2));
15422 break;
15423 case ALIGN:
15424 check_insn(ctx, ISA_MIPS_R6);
15425 gen_align(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 9, 2));
15426 break;
15427 case EXT:
15428 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
15429 return;
15430 case POOL32AXF:
15431 gen_pool32axf(env, ctx, rt, rs);
15432 break;
15433 case BREAK32:
15434 generate_exception_end(ctx, EXCP_BREAK);
15435 break;
15436 case SIGRIE:
15437 check_insn(ctx, ISA_MIPS_R6);
15438 gen_reserved_instruction(ctx);
15439 break;
15440 default:
15441 pool32a_invalid:
15442 MIPS_INVAL("pool32a");
15443 gen_reserved_instruction(ctx);
15444 break;
15446 break;
15447 case POOL32B:
15448 minor = (ctx->opcode >> 12) & 0xf;
15449 switch (minor) {
15450 case CACHE:
15451 check_cp0_enabled(ctx);
15452 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
15453 gen_cache_operation(ctx, rt, rs, imm);
15455 break;
15456 case LWC2:
15457 case SWC2:
15458 /* COP2: Not implemented. */
15459 generate_exception_err(ctx, EXCP_CpU, 2);
15460 break;
15461 #ifdef TARGET_MIPS64
15462 case LDP:
15463 case SDP:
15464 check_insn(ctx, ISA_MIPS3);
15465 check_mips_64(ctx);
15466 #endif
15467 /* fall through */
15468 case LWP:
15469 case SWP:
15470 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15471 break;
15472 #ifdef TARGET_MIPS64
15473 case LDM:
15474 case SDM:
15475 check_insn(ctx, ISA_MIPS3);
15476 check_mips_64(ctx);
15477 #endif
15478 /* fall through */
15479 case LWM32:
15480 case SWM32:
15481 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
15482 break;
15483 default:
15484 MIPS_INVAL("pool32b");
15485 gen_reserved_instruction(ctx);
15486 break;
15488 break;
15489 case POOL32F:
15490 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15491 minor = ctx->opcode & 0x3f;
15492 check_cp1_enabled(ctx);
15493 switch (minor) {
15494 case ALNV_PS:
15495 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15496 mips32_op = OPC_ALNV_PS;
15497 goto do_madd;
15498 case MADD_S:
15499 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15500 mips32_op = OPC_MADD_S;
15501 goto do_madd;
15502 case MADD_D:
15503 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15504 mips32_op = OPC_MADD_D;
15505 goto do_madd;
15506 case MADD_PS:
15507 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15508 mips32_op = OPC_MADD_PS;
15509 goto do_madd;
15510 case MSUB_S:
15511 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15512 mips32_op = OPC_MSUB_S;
15513 goto do_madd;
15514 case MSUB_D:
15515 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15516 mips32_op = OPC_MSUB_D;
15517 goto do_madd;
15518 case MSUB_PS:
15519 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15520 mips32_op = OPC_MSUB_PS;
15521 goto do_madd;
15522 case NMADD_S:
15523 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15524 mips32_op = OPC_NMADD_S;
15525 goto do_madd;
15526 case NMADD_D:
15527 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15528 mips32_op = OPC_NMADD_D;
15529 goto do_madd;
15530 case NMADD_PS:
15531 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15532 mips32_op = OPC_NMADD_PS;
15533 goto do_madd;
15534 case NMSUB_S:
15535 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15536 mips32_op = OPC_NMSUB_S;
15537 goto do_madd;
15538 case NMSUB_D:
15539 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15540 mips32_op = OPC_NMSUB_D;
15541 goto do_madd;
15542 case NMSUB_PS:
15543 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15544 mips32_op = OPC_NMSUB_PS;
15545 do_madd:
15546 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
15547 break;
15548 case CABS_COND_FMT:
15549 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15550 cond = (ctx->opcode >> 6) & 0xf;
15551 cc = (ctx->opcode >> 13) & 0x7;
15552 fmt = (ctx->opcode >> 10) & 0x3;
15553 switch (fmt) {
15554 case 0x0:
15555 gen_cmpabs_s(ctx, cond, rt, rs, cc);
15556 break;
15557 case 0x1:
15558 gen_cmpabs_d(ctx, cond, rt, rs, cc);
15559 break;
15560 case 0x2:
15561 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
15562 break;
15563 default:
15564 goto pool32f_invalid;
15566 break;
15567 case C_COND_FMT:
15568 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15569 cond = (ctx->opcode >> 6) & 0xf;
15570 cc = (ctx->opcode >> 13) & 0x7;
15571 fmt = (ctx->opcode >> 10) & 0x3;
15572 switch (fmt) {
15573 case 0x0:
15574 gen_cmp_s(ctx, cond, rt, rs, cc);
15575 break;
15576 case 0x1:
15577 gen_cmp_d(ctx, cond, rt, rs, cc);
15578 break;
15579 case 0x2:
15580 gen_cmp_ps(ctx, cond, rt, rs, cc);
15581 break;
15582 default:
15583 goto pool32f_invalid;
15585 break;
15586 case CMP_CONDN_S:
15587 check_insn(ctx, ISA_MIPS_R6);
15588 gen_r6_cmp_s(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15589 break;
15590 case CMP_CONDN_D:
15591 check_insn(ctx, ISA_MIPS_R6);
15592 gen_r6_cmp_d(ctx, (ctx->opcode >> 6) & 0x1f, rt, rs, rd);
15593 break;
15594 case POOL32FXF:
15595 gen_pool32fxf(ctx, rt, rs);
15596 break;
15597 case 0x00:
15598 /* PLL foo */
15599 switch ((ctx->opcode >> 6) & 0x7) {
15600 case PLL_PS:
15601 mips32_op = OPC_PLL_PS;
15602 goto do_ps;
15603 case PLU_PS:
15604 mips32_op = OPC_PLU_PS;
15605 goto do_ps;
15606 case PUL_PS:
15607 mips32_op = OPC_PUL_PS;
15608 goto do_ps;
15609 case PUU_PS:
15610 mips32_op = OPC_PUU_PS;
15611 goto do_ps;
15612 case CVT_PS_S:
15613 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15614 mips32_op = OPC_CVT_PS_S;
15615 do_ps:
15616 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15617 break;
15618 default:
15619 goto pool32f_invalid;
15621 break;
15622 case MIN_FMT:
15623 check_insn(ctx, ISA_MIPS_R6);
15624 switch ((ctx->opcode >> 9) & 0x3) {
15625 case FMT_SDPS_S:
15626 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
15627 break;
15628 case FMT_SDPS_D:
15629 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
15630 break;
15631 default:
15632 goto pool32f_invalid;
15634 break;
15635 case 0x08:
15636 /* [LS][WDU]XC1 */
15637 switch ((ctx->opcode >> 6) & 0x7) {
15638 case LWXC1:
15639 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15640 mips32_op = OPC_LWXC1;
15641 goto do_ldst_cp1;
15642 case SWXC1:
15643 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15644 mips32_op = OPC_SWXC1;
15645 goto do_ldst_cp1;
15646 case LDXC1:
15647 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15648 mips32_op = OPC_LDXC1;
15649 goto do_ldst_cp1;
15650 case SDXC1:
15651 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15652 mips32_op = OPC_SDXC1;
15653 goto do_ldst_cp1;
15654 case LUXC1:
15655 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15656 mips32_op = OPC_LUXC1;
15657 goto do_ldst_cp1;
15658 case SUXC1:
15659 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15660 mips32_op = OPC_SUXC1;
15661 do_ldst_cp1:
15662 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
15663 break;
15664 default:
15665 goto pool32f_invalid;
15667 break;
15668 case MAX_FMT:
15669 check_insn(ctx, ISA_MIPS_R6);
15670 switch ((ctx->opcode >> 9) & 0x3) {
15671 case FMT_SDPS_S:
15672 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
15673 break;
15674 case FMT_SDPS_D:
15675 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
15676 break;
15677 default:
15678 goto pool32f_invalid;
15680 break;
15681 case 0x18:
15682 /* 3D insns */
15683 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15684 fmt = (ctx->opcode >> 9) & 0x3;
15685 switch ((ctx->opcode >> 6) & 0x7) {
15686 case RSQRT2_FMT:
15687 switch (fmt) {
15688 case FMT_SDPS_S:
15689 mips32_op = OPC_RSQRT2_S;
15690 goto do_3d;
15691 case FMT_SDPS_D:
15692 mips32_op = OPC_RSQRT2_D;
15693 goto do_3d;
15694 case FMT_SDPS_PS:
15695 mips32_op = OPC_RSQRT2_PS;
15696 goto do_3d;
15697 default:
15698 goto pool32f_invalid;
15700 break;
15701 case RECIP2_FMT:
15702 switch (fmt) {
15703 case FMT_SDPS_S:
15704 mips32_op = OPC_RECIP2_S;
15705 goto do_3d;
15706 case FMT_SDPS_D:
15707 mips32_op = OPC_RECIP2_D;
15708 goto do_3d;
15709 case FMT_SDPS_PS:
15710 mips32_op = OPC_RECIP2_PS;
15711 goto do_3d;
15712 default:
15713 goto pool32f_invalid;
15715 break;
15716 case ADDR_PS:
15717 mips32_op = OPC_ADDR_PS;
15718 goto do_3d;
15719 case MULR_PS:
15720 mips32_op = OPC_MULR_PS;
15721 do_3d:
15722 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15723 break;
15724 default:
15725 goto pool32f_invalid;
15727 break;
15728 case 0x20:
15729 /* MOV[FT].fmt, PREFX, RINT.fmt, CLASS.fmt*/
15730 cc = (ctx->opcode >> 13) & 0x7;
15731 fmt = (ctx->opcode >> 9) & 0x3;
15732 switch ((ctx->opcode >> 6) & 0x7) {
15733 case MOVF_FMT: /* RINT_FMT */
15734 if (ctx->insn_flags & ISA_MIPS_R6) {
15735 /* RINT_FMT */
15736 switch (fmt) {
15737 case FMT_SDPS_S:
15738 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
15739 break;
15740 case FMT_SDPS_D:
15741 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
15742 break;
15743 default:
15744 goto pool32f_invalid;
15746 } else {
15747 /* MOVF_FMT */
15748 switch (fmt) {
15749 case FMT_SDPS_S:
15750 gen_movcf_s(ctx, rs, rt, cc, 0);
15751 break;
15752 case FMT_SDPS_D:
15753 gen_movcf_d(ctx, rs, rt, cc, 0);
15754 break;
15755 case FMT_SDPS_PS:
15756 check_ps(ctx);
15757 gen_movcf_ps(ctx, rs, rt, cc, 0);
15758 break;
15759 default:
15760 goto pool32f_invalid;
15763 break;
15764 case MOVT_FMT: /* CLASS_FMT */
15765 if (ctx->insn_flags & ISA_MIPS_R6) {
15766 /* CLASS_FMT */
15767 switch (fmt) {
15768 case FMT_SDPS_S:
15769 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
15770 break;
15771 case FMT_SDPS_D:
15772 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
15773 break;
15774 default:
15775 goto pool32f_invalid;
15777 } else {
15778 /* MOVT_FMT */
15779 switch (fmt) {
15780 case FMT_SDPS_S:
15781 gen_movcf_s(ctx, rs, rt, cc, 1);
15782 break;
15783 case FMT_SDPS_D:
15784 gen_movcf_d(ctx, rs, rt, cc, 1);
15785 break;
15786 case FMT_SDPS_PS:
15787 check_ps(ctx);
15788 gen_movcf_ps(ctx, rs, rt, cc, 1);
15789 break;
15790 default:
15791 goto pool32f_invalid;
15794 break;
15795 case PREFX:
15796 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15797 break;
15798 default:
15799 goto pool32f_invalid;
15801 break;
15802 #define FINSN_3ARG_SDPS(prfx) \
15803 switch ((ctx->opcode >> 8) & 0x3) { \
15804 case FMT_SDPS_S: \
15805 mips32_op = OPC_##prfx##_S; \
15806 goto do_fpop; \
15807 case FMT_SDPS_D: \
15808 mips32_op = OPC_##prfx##_D; \
15809 goto do_fpop; \
15810 case FMT_SDPS_PS: \
15811 check_ps(ctx); \
15812 mips32_op = OPC_##prfx##_PS; \
15813 goto do_fpop; \
15814 default: \
15815 goto pool32f_invalid; \
15817 case MINA_FMT:
15818 check_insn(ctx, ISA_MIPS_R6);
15819 switch ((ctx->opcode >> 9) & 0x3) {
15820 case FMT_SDPS_S:
15821 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
15822 break;
15823 case FMT_SDPS_D:
15824 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
15825 break;
15826 default:
15827 goto pool32f_invalid;
15829 break;
15830 case MAXA_FMT:
15831 check_insn(ctx, ISA_MIPS_R6);
15832 switch ((ctx->opcode >> 9) & 0x3) {
15833 case FMT_SDPS_S:
15834 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
15835 break;
15836 case FMT_SDPS_D:
15837 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
15838 break;
15839 default:
15840 goto pool32f_invalid;
15842 break;
15843 case 0x30:
15844 /* regular FP ops */
15845 switch ((ctx->opcode >> 6) & 0x3) {
15846 case ADD_FMT:
15847 FINSN_3ARG_SDPS(ADD);
15848 break;
15849 case SUB_FMT:
15850 FINSN_3ARG_SDPS(SUB);
15851 break;
15852 case MUL_FMT:
15853 FINSN_3ARG_SDPS(MUL);
15854 break;
15855 case DIV_FMT:
15856 fmt = (ctx->opcode >> 8) & 0x3;
15857 if (fmt == 1) {
15858 mips32_op = OPC_DIV_D;
15859 } else if (fmt == 0) {
15860 mips32_op = OPC_DIV_S;
15861 } else {
15862 goto pool32f_invalid;
15864 goto do_fpop;
15865 default:
15866 goto pool32f_invalid;
15868 break;
15869 case 0x38:
15870 /* cmovs */
15871 switch ((ctx->opcode >> 6) & 0x7) {
15872 case MOVN_FMT: /* SELEQZ_FMT */
15873 if (ctx->insn_flags & ISA_MIPS_R6) {
15874 /* SELEQZ_FMT */
15875 switch ((ctx->opcode >> 9) & 0x3) {
15876 case FMT_SDPS_S:
15877 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
15878 break;
15879 case FMT_SDPS_D:
15880 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
15881 break;
15882 default:
15883 goto pool32f_invalid;
15885 } else {
15886 /* MOVN_FMT */
15887 FINSN_3ARG_SDPS(MOVN);
15889 break;
15890 case MOVN_FMT_04:
15891 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15892 FINSN_3ARG_SDPS(MOVN);
15893 break;
15894 case MOVZ_FMT: /* SELNEZ_FMT */
15895 if (ctx->insn_flags & ISA_MIPS_R6) {
15896 /* SELNEZ_FMT */
15897 switch ((ctx->opcode >> 9) & 0x3) {
15898 case FMT_SDPS_S:
15899 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
15900 break;
15901 case FMT_SDPS_D:
15902 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
15903 break;
15904 default:
15905 goto pool32f_invalid;
15907 } else {
15908 /* MOVZ_FMT */
15909 FINSN_3ARG_SDPS(MOVZ);
15911 break;
15912 case MOVZ_FMT_05:
15913 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15914 FINSN_3ARG_SDPS(MOVZ);
15915 break;
15916 case SEL_FMT:
15917 check_insn(ctx, ISA_MIPS_R6);
15918 switch ((ctx->opcode >> 9) & 0x3) {
15919 case FMT_SDPS_S:
15920 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
15921 break;
15922 case FMT_SDPS_D:
15923 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
15924 break;
15925 default:
15926 goto pool32f_invalid;
15928 break;
15929 case MADDF_FMT:
15930 check_insn(ctx, ISA_MIPS_R6);
15931 switch ((ctx->opcode >> 9) & 0x3) {
15932 case FMT_SDPS_S:
15933 mips32_op = OPC_MADDF_S;
15934 goto do_fpop;
15935 case FMT_SDPS_D:
15936 mips32_op = OPC_MADDF_D;
15937 goto do_fpop;
15938 default:
15939 goto pool32f_invalid;
15941 break;
15942 case MSUBF_FMT:
15943 check_insn(ctx, ISA_MIPS_R6);
15944 switch ((ctx->opcode >> 9) & 0x3) {
15945 case FMT_SDPS_S:
15946 mips32_op = OPC_MSUBF_S;
15947 goto do_fpop;
15948 case FMT_SDPS_D:
15949 mips32_op = OPC_MSUBF_D;
15950 goto do_fpop;
15951 default:
15952 goto pool32f_invalid;
15954 break;
15955 default:
15956 goto pool32f_invalid;
15958 break;
15959 do_fpop:
15960 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
15961 break;
15962 default:
15963 pool32f_invalid:
15964 MIPS_INVAL("pool32f");
15965 gen_reserved_instruction(ctx);
15966 break;
15968 } else {
15969 generate_exception_err(ctx, EXCP_CpU, 1);
15971 break;
15972 case POOL32I:
15973 minor = (ctx->opcode >> 21) & 0x1f;
15974 switch (minor) {
15975 case BLTZ:
15976 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15977 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
15978 break;
15979 case BLTZAL:
15980 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15981 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
15982 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15983 break;
15984 case BLTZALS:
15985 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15986 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
15987 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15988 break;
15989 case BGEZ:
15990 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15991 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
15992 break;
15993 case BGEZAL:
15994 check_insn_opc_removed(ctx, ISA_MIPS_R6);
15995 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
15996 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
15997 break;
15998 case BGEZALS:
15999 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16000 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
16001 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16002 break;
16003 case BLEZ:
16004 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16005 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
16006 break;
16007 case BGTZ:
16008 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16009 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
16010 break;
16012 /* Traps */
16013 case TLTI: /* BC1EQZC */
16014 if (ctx->insn_flags & ISA_MIPS_R6) {
16015 /* BC1EQZC */
16016 check_cp1_enabled(ctx);
16017 gen_compute_branch1_r6(ctx, OPC_BC1EQZ, rs, imm << 1, 0);
16018 } else {
16019 /* TLTI */
16020 mips32_op = OPC_TLTI;
16021 goto do_trapi;
16023 break;
16024 case TGEI: /* BC1NEZC */
16025 if (ctx->insn_flags & ISA_MIPS_R6) {
16026 /* BC1NEZC */
16027 check_cp1_enabled(ctx);
16028 gen_compute_branch1_r6(ctx, OPC_BC1NEZ, rs, imm << 1, 0);
16029 } else {
16030 /* TGEI */
16031 mips32_op = OPC_TGEI;
16032 goto do_trapi;
16034 break;
16035 case TLTIU:
16036 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16037 mips32_op = OPC_TLTIU;
16038 goto do_trapi;
16039 case TGEIU:
16040 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16041 mips32_op = OPC_TGEIU;
16042 goto do_trapi;
16043 case TNEI: /* SYNCI */
16044 if (ctx->insn_flags & ISA_MIPS_R6) {
16045 /* SYNCI */
16047 * Break the TB to be able to sync copied instructions
16048 * immediately.
16050 ctx->base.is_jmp = DISAS_STOP;
16051 } else {
16052 /* TNEI */
16053 mips32_op = OPC_TNEI;
16054 goto do_trapi;
16056 break;
16057 case TEQI:
16058 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16059 mips32_op = OPC_TEQI;
16060 do_trapi:
16061 gen_trap(ctx, mips32_op, rs, -1, imm);
16062 break;
16064 case BNEZC:
16065 case BEQZC:
16066 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16067 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
16068 4, rs, 0, imm << 1, 0);
16070 * Compact branches don't have a delay slot, so just let
16071 * the normal delay slot handling take us to the branch
16072 * target.
16074 break;
16075 case LUI:
16076 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16077 gen_logic_imm(ctx, OPC_LUI, rs, 0, imm);
16078 break;
16079 case SYNCI:
16080 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16082 * Break the TB to be able to sync copied instructions
16083 * immediately.
16085 ctx->base.is_jmp = DISAS_STOP;
16086 break;
16087 case BC2F:
16088 case BC2T:
16089 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16090 /* COP2: Not implemented. */
16091 generate_exception_err(ctx, EXCP_CpU, 2);
16092 break;
16093 case BC1F:
16094 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16095 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
16096 goto do_cp1branch;
16097 case BC1T:
16098 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16099 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
16100 goto do_cp1branch;
16101 case BC1ANY4F:
16102 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16103 mips32_op = OPC_BC1FANY4;
16104 goto do_cp1mips3d;
16105 case BC1ANY4T:
16106 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16107 mips32_op = OPC_BC1TANY4;
16108 do_cp1mips3d:
16109 check_cop1x(ctx);
16110 check_insn(ctx, ASE_MIPS3D);
16111 /* Fall through */
16112 do_cp1branch:
16113 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16114 check_cp1_enabled(ctx);
16115 gen_compute_branch1(ctx, mips32_op,
16116 (ctx->opcode >> 18) & 0x7, imm << 1);
16117 } else {
16118 generate_exception_err(ctx, EXCP_CpU, 1);
16120 break;
16121 default:
16122 MIPS_INVAL("pool32i");
16123 gen_reserved_instruction(ctx);
16124 break;
16126 break;
16127 case POOL32C:
16128 minor = (ctx->opcode >> 12) & 0xf;
16129 offset = sextract32(ctx->opcode, 0,
16130 (ctx->insn_flags & ISA_MIPS_R6) ? 9 : 12);
16131 switch (minor) {
16132 case LWL:
16133 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16134 mips32_op = OPC_LWL;
16135 goto do_ld_lr;
16136 case SWL:
16137 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16138 mips32_op = OPC_SWL;
16139 goto do_st_lr;
16140 case LWR:
16141 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16142 mips32_op = OPC_LWR;
16143 goto do_ld_lr;
16144 case SWR:
16145 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16146 mips32_op = OPC_SWR;
16147 goto do_st_lr;
16148 #if defined(TARGET_MIPS64)
16149 case LDL:
16150 check_insn(ctx, ISA_MIPS3);
16151 check_mips_64(ctx);
16152 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16153 mips32_op = OPC_LDL;
16154 goto do_ld_lr;
16155 case SDL:
16156 check_insn(ctx, ISA_MIPS3);
16157 check_mips_64(ctx);
16158 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16159 mips32_op = OPC_SDL;
16160 goto do_st_lr;
16161 case LDR:
16162 check_insn(ctx, ISA_MIPS3);
16163 check_mips_64(ctx);
16164 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16165 mips32_op = OPC_LDR;
16166 goto do_ld_lr;
16167 case SDR:
16168 check_insn(ctx, ISA_MIPS3);
16169 check_mips_64(ctx);
16170 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16171 mips32_op = OPC_SDR;
16172 goto do_st_lr;
16173 case LWU:
16174 check_insn(ctx, ISA_MIPS3);
16175 check_mips_64(ctx);
16176 mips32_op = OPC_LWU;
16177 goto do_ld_lr;
16178 case LLD:
16179 check_insn(ctx, ISA_MIPS3);
16180 check_mips_64(ctx);
16181 mips32_op = OPC_LLD;
16182 goto do_ld_lr;
16183 #endif
16184 case LL:
16185 mips32_op = OPC_LL;
16186 goto do_ld_lr;
16187 do_ld_lr:
16188 gen_ld(ctx, mips32_op, rt, rs, offset);
16189 break;
16190 do_st_lr:
16191 gen_st(ctx, mips32_op, rt, rs, offset);
16192 break;
16193 case SC:
16194 gen_st_cond(ctx, rt, rs, offset, MO_TESL, false);
16195 break;
16196 #if defined(TARGET_MIPS64)
16197 case SCD:
16198 check_insn(ctx, ISA_MIPS3);
16199 check_mips_64(ctx);
16200 gen_st_cond(ctx, rt, rs, offset, MO_TEQ, false);
16201 break;
16202 #endif
16203 case LD_EVA:
16204 if (!ctx->eva) {
16205 MIPS_INVAL("pool32c ld-eva");
16206 gen_reserved_instruction(ctx);
16207 break;
16209 check_cp0_enabled(ctx);
16211 minor2 = (ctx->opcode >> 9) & 0x7;
16212 offset = sextract32(ctx->opcode, 0, 9);
16213 switch (minor2) {
16214 case LBUE:
16215 mips32_op = OPC_LBUE;
16216 goto do_ld_lr;
16217 case LHUE:
16218 mips32_op = OPC_LHUE;
16219 goto do_ld_lr;
16220 case LWLE:
16221 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16222 mips32_op = OPC_LWLE;
16223 goto do_ld_lr;
16224 case LWRE:
16225 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16226 mips32_op = OPC_LWRE;
16227 goto do_ld_lr;
16228 case LBE:
16229 mips32_op = OPC_LBE;
16230 goto do_ld_lr;
16231 case LHE:
16232 mips32_op = OPC_LHE;
16233 goto do_ld_lr;
16234 case LLE:
16235 mips32_op = OPC_LLE;
16236 goto do_ld_lr;
16237 case LWE:
16238 mips32_op = OPC_LWE;
16239 goto do_ld_lr;
16241 break;
16242 case ST_EVA:
16243 if (!ctx->eva) {
16244 MIPS_INVAL("pool32c st-eva");
16245 gen_reserved_instruction(ctx);
16246 break;
16248 check_cp0_enabled(ctx);
16250 minor2 = (ctx->opcode >> 9) & 0x7;
16251 offset = sextract32(ctx->opcode, 0, 9);
16252 switch (minor2) {
16253 case SWLE:
16254 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16255 mips32_op = OPC_SWLE;
16256 goto do_st_lr;
16257 case SWRE:
16258 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16259 mips32_op = OPC_SWRE;
16260 goto do_st_lr;
16261 case PREFE:
16262 /* Treat as no-op */
16263 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16264 /* hint codes 24-31 are reserved and signal RI */
16265 generate_exception(ctx, EXCP_RI);
16267 break;
16268 case CACHEE:
16269 /* Treat as no-op */
16270 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
16271 gen_cache_operation(ctx, rt, rs, offset);
16273 break;
16274 case SBE:
16275 mips32_op = OPC_SBE;
16276 goto do_st_lr;
16277 case SHE:
16278 mips32_op = OPC_SHE;
16279 goto do_st_lr;
16280 case SCE:
16281 gen_st_cond(ctx, rt, rs, offset, MO_TESL, true);
16282 break;
16283 case SWE:
16284 mips32_op = OPC_SWE;
16285 goto do_st_lr;
16287 break;
16288 case PREF:
16289 /* Treat as no-op */
16290 if ((ctx->insn_flags & ISA_MIPS_R6) && (rt >= 24)) {
16291 /* hint codes 24-31 are reserved and signal RI */
16292 generate_exception(ctx, EXCP_RI);
16294 break;
16295 default:
16296 MIPS_INVAL("pool32c");
16297 gen_reserved_instruction(ctx);
16298 break;
16300 break;
16301 case ADDI32: /* AUI, LUI */
16302 if (ctx->insn_flags & ISA_MIPS_R6) {
16303 /* AUI, LUI */
16304 gen_logic_imm(ctx, OPC_LUI, rt, rs, imm);
16305 } else {
16306 /* ADDI32 */
16307 mips32_op = OPC_ADDI;
16308 goto do_addi;
16310 break;
16311 case ADDIU32:
16312 mips32_op = OPC_ADDIU;
16313 do_addi:
16314 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
16315 break;
16317 /* Logical operations */
16318 case ORI32:
16319 mips32_op = OPC_ORI;
16320 goto do_logici;
16321 case XORI32:
16322 mips32_op = OPC_XORI;
16323 goto do_logici;
16324 case ANDI32:
16325 mips32_op = OPC_ANDI;
16326 do_logici:
16327 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
16328 break;
16330 /* Set less than immediate */
16331 case SLTI32:
16332 mips32_op = OPC_SLTI;
16333 goto do_slti;
16334 case SLTIU32:
16335 mips32_op = OPC_SLTIU;
16336 do_slti:
16337 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
16338 break;
16339 case JALX32:
16340 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16341 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16342 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
16343 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16344 break;
16345 case JALS32: /* BOVC, BEQC, BEQZALC */
16346 if (ctx->insn_flags & ISA_MIPS_R6) {
16347 if (rs >= rt) {
16348 /* BOVC */
16349 mips32_op = OPC_BOVC;
16350 } else if (rs < rt && rs == 0) {
16351 /* BEQZALC */
16352 mips32_op = OPC_BEQZALC;
16353 } else {
16354 /* BEQC */
16355 mips32_op = OPC_BEQC;
16357 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16358 } else {
16359 /* JALS32 */
16360 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
16361 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
16362 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16364 break;
16365 case BEQ32: /* BC */
16366 if (ctx->insn_flags & ISA_MIPS_R6) {
16367 /* BC */
16368 gen_compute_compact_branch(ctx, OPC_BC, 0, 0,
16369 sextract32(ctx->opcode << 1, 0, 27));
16370 } else {
16371 /* BEQ32 */
16372 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
16374 break;
16375 case BNE32: /* BALC */
16376 if (ctx->insn_flags & ISA_MIPS_R6) {
16377 /* BALC */
16378 gen_compute_compact_branch(ctx, OPC_BALC, 0, 0,
16379 sextract32(ctx->opcode << 1, 0, 27));
16380 } else {
16381 /* BNE32 */
16382 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
16384 break;
16385 case J32: /* BGTZC, BLTZC, BLTC */
16386 if (ctx->insn_flags & ISA_MIPS_R6) {
16387 if (rs == 0 && rt != 0) {
16388 /* BGTZC */
16389 mips32_op = OPC_BGTZC;
16390 } else if (rs != 0 && rt != 0 && rs == rt) {
16391 /* BLTZC */
16392 mips32_op = OPC_BLTZC;
16393 } else {
16394 /* BLTC */
16395 mips32_op = OPC_BLTC;
16397 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16398 } else {
16399 /* J32 */
16400 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
16401 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16403 break;
16404 case JAL32: /* BLEZC, BGEZC, BGEC */
16405 if (ctx->insn_flags & ISA_MIPS_R6) {
16406 if (rs == 0 && rt != 0) {
16407 /* BLEZC */
16408 mips32_op = OPC_BLEZC;
16409 } else if (rs != 0 && rt != 0 && rs == rt) {
16410 /* BGEZC */
16411 mips32_op = OPC_BGEZC;
16412 } else {
16413 /* BGEC */
16414 mips32_op = OPC_BGEC;
16416 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16417 } else {
16418 /* JAL32 */
16419 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
16420 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
16421 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
16423 break;
16424 /* Floating point (COP1) */
16425 case LWC132:
16426 mips32_op = OPC_LWC1;
16427 goto do_cop1;
16428 case LDC132:
16429 mips32_op = OPC_LDC1;
16430 goto do_cop1;
16431 case SWC132:
16432 mips32_op = OPC_SWC1;
16433 goto do_cop1;
16434 case SDC132:
16435 mips32_op = OPC_SDC1;
16436 do_cop1:
16437 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
16438 break;
16439 case ADDIUPC: /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16440 if (ctx->insn_flags & ISA_MIPS_R6) {
16441 /* PCREL: ADDIUPC, AUIPC, ALUIPC, LWPC */
16442 switch ((ctx->opcode >> 16) & 0x1f) {
16443 case ADDIUPC_00:
16444 case ADDIUPC_01:
16445 case ADDIUPC_02:
16446 case ADDIUPC_03:
16447 case ADDIUPC_04:
16448 case ADDIUPC_05:
16449 case ADDIUPC_06:
16450 case ADDIUPC_07:
16451 gen_pcrel(ctx, OPC_ADDIUPC, ctx->base.pc_next & ~0x3, rt);
16452 break;
16453 case AUIPC:
16454 gen_pcrel(ctx, OPC_AUIPC, ctx->base.pc_next, rt);
16455 break;
16456 case ALUIPC:
16457 gen_pcrel(ctx, OPC_ALUIPC, ctx->base.pc_next, rt);
16458 break;
16459 case LWPC_08:
16460 case LWPC_09:
16461 case LWPC_0A:
16462 case LWPC_0B:
16463 case LWPC_0C:
16464 case LWPC_0D:
16465 case LWPC_0E:
16466 case LWPC_0F:
16467 gen_pcrel(ctx, R6_OPC_LWPC, ctx->base.pc_next & ~0x3, rt);
16468 break;
16469 default:
16470 generate_exception(ctx, EXCP_RI);
16471 break;
16473 } else {
16474 /* ADDIUPC */
16475 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
16476 offset = SIMM(ctx->opcode, 0, 23) << 2;
16478 gen_addiupc(ctx, reg, offset, 0, 0);
16480 break;
16481 case BNVC: /* BNEC, BNEZALC */
16482 check_insn(ctx, ISA_MIPS_R6);
16483 if (rs >= rt) {
16484 /* BNVC */
16485 mips32_op = OPC_BNVC;
16486 } else if (rs < rt && rs == 0) {
16487 /* BNEZALC */
16488 mips32_op = OPC_BNEZALC;
16489 } else {
16490 /* BNEC */
16491 mips32_op = OPC_BNEC;
16493 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16494 break;
16495 case R6_BNEZC: /* JIALC */
16496 check_insn(ctx, ISA_MIPS_R6);
16497 if (rt != 0) {
16498 /* BNEZC */
16499 gen_compute_compact_branch(ctx, OPC_BNEZC, rt, 0,
16500 sextract32(ctx->opcode << 1, 0, 22));
16501 } else {
16502 /* JIALC */
16503 gen_compute_compact_branch(ctx, OPC_JIALC, 0, rs, imm);
16505 break;
16506 case R6_BEQZC: /* JIC */
16507 check_insn(ctx, ISA_MIPS_R6);
16508 if (rt != 0) {
16509 /* BEQZC */
16510 gen_compute_compact_branch(ctx, OPC_BEQZC, rt, 0,
16511 sextract32(ctx->opcode << 1, 0, 22));
16512 } else {
16513 /* JIC */
16514 gen_compute_compact_branch(ctx, OPC_JIC, 0, rs, imm);
16516 break;
16517 case BLEZALC: /* BGEZALC, BGEUC */
16518 check_insn(ctx, ISA_MIPS_R6);
16519 if (rs == 0 && rt != 0) {
16520 /* BLEZALC */
16521 mips32_op = OPC_BLEZALC;
16522 } else if (rs != 0 && rt != 0 && rs == rt) {
16523 /* BGEZALC */
16524 mips32_op = OPC_BGEZALC;
16525 } else {
16526 /* BGEUC */
16527 mips32_op = OPC_BGEUC;
16529 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16530 break;
16531 case BGTZALC: /* BLTZALC, BLTUC */
16532 check_insn(ctx, ISA_MIPS_R6);
16533 if (rs == 0 && rt != 0) {
16534 /* BGTZALC */
16535 mips32_op = OPC_BGTZALC;
16536 } else if (rs != 0 && rt != 0 && rs == rt) {
16537 /* BLTZALC */
16538 mips32_op = OPC_BLTZALC;
16539 } else {
16540 /* BLTUC */
16541 mips32_op = OPC_BLTUC;
16543 gen_compute_compact_branch(ctx, mips32_op, rs, rt, imm << 1);
16544 break;
16545 /* Loads and stores */
16546 case LB32:
16547 mips32_op = OPC_LB;
16548 goto do_ld;
16549 case LBU32:
16550 mips32_op = OPC_LBU;
16551 goto do_ld;
16552 case LH32:
16553 mips32_op = OPC_LH;
16554 goto do_ld;
16555 case LHU32:
16556 mips32_op = OPC_LHU;
16557 goto do_ld;
16558 case LW32:
16559 mips32_op = OPC_LW;
16560 goto do_ld;
16561 #ifdef TARGET_MIPS64
16562 case LD32:
16563 check_insn(ctx, ISA_MIPS3);
16564 check_mips_64(ctx);
16565 mips32_op = OPC_LD;
16566 goto do_ld;
16567 case SD32:
16568 check_insn(ctx, ISA_MIPS3);
16569 check_mips_64(ctx);
16570 mips32_op = OPC_SD;
16571 goto do_st;
16572 #endif
16573 case SB32:
16574 mips32_op = OPC_SB;
16575 goto do_st;
16576 case SH32:
16577 mips32_op = OPC_SH;
16578 goto do_st;
16579 case SW32:
16580 mips32_op = OPC_SW;
16581 goto do_st;
16582 do_ld:
16583 gen_ld(ctx, mips32_op, rt, rs, imm);
16584 break;
16585 do_st:
16586 gen_st(ctx, mips32_op, rt, rs, imm);
16587 break;
16588 default:
16589 gen_reserved_instruction(ctx);
16590 break;
16594 static int decode_micromips_opc(CPUMIPSState *env, DisasContext *ctx)
16596 uint32_t op;
16598 /* make sure instructions are on a halfword boundary */
16599 if (ctx->base.pc_next & 0x1) {
16600 env->CP0_BadVAddr = ctx->base.pc_next;
16601 generate_exception_end(ctx, EXCP_AdEL);
16602 return 2;
16605 op = (ctx->opcode >> 10) & 0x3f;
16606 /* Enforce properly-sized instructions in a delay slot */
16607 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
16608 switch (op & 0x7) { /* MSB-3..MSB-5 */
16609 case 0:
16610 /* POOL32A, POOL32B, POOL32I, POOL32C */
16611 case 4:
16612 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
16613 case 5:
16614 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
16615 case 6:
16616 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
16617 case 7:
16618 /* LB32, LH32, LWC132, LDC132, LW32 */
16619 if (ctx->hflags & MIPS_HFLAG_BDS16) {
16620 gen_reserved_instruction(ctx);
16621 return 2;
16623 break;
16624 case 1:
16625 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
16626 case 2:
16627 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
16628 case 3:
16629 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
16630 if (ctx->hflags & MIPS_HFLAG_BDS32) {
16631 gen_reserved_instruction(ctx);
16632 return 2;
16634 break;
16638 switch (op) {
16639 case POOL16A:
16641 int rd = mmreg(uMIPS_RD(ctx->opcode));
16642 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
16643 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
16644 uint32_t opc = 0;
16646 switch (ctx->opcode & 0x1) {
16647 case ADDU16:
16648 opc = OPC_ADDU;
16649 break;
16650 case SUBU16:
16651 opc = OPC_SUBU;
16652 break;
16654 if (ctx->insn_flags & ISA_MIPS_R6) {
16656 * In the Release 6, the register number location in
16657 * the instruction encoding has changed.
16659 gen_arith(ctx, opc, rs1, rd, rs2);
16660 } else {
16661 gen_arith(ctx, opc, rd, rs1, rs2);
16664 break;
16665 case POOL16B:
16667 int rd = mmreg(uMIPS_RD(ctx->opcode));
16668 int rs = mmreg(uMIPS_RS(ctx->opcode));
16669 int amount = (ctx->opcode >> 1) & 0x7;
16670 uint32_t opc = 0;
16671 amount = amount == 0 ? 8 : amount;
16673 switch (ctx->opcode & 0x1) {
16674 case SLL16:
16675 opc = OPC_SLL;
16676 break;
16677 case SRL16:
16678 opc = OPC_SRL;
16679 break;
16682 gen_shift_imm(ctx, opc, rd, rs, amount);
16684 break;
16685 case POOL16C:
16686 if (ctx->insn_flags & ISA_MIPS_R6) {
16687 gen_pool16c_r6_insn(ctx);
16688 } else {
16689 gen_pool16c_insn(ctx);
16691 break;
16692 case LWGP16:
16694 int rd = mmreg(uMIPS_RD(ctx->opcode));
16695 int rb = 28; /* GP */
16696 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
16698 gen_ld(ctx, OPC_LW, rd, rb, offset);
16700 break;
16701 case POOL16F:
16702 check_insn_opc_removed(ctx, ISA_MIPS_R6);
16703 if (ctx->opcode & 1) {
16704 gen_reserved_instruction(ctx);
16705 } else {
16706 /* MOVEP */
16707 int enc_dest = uMIPS_RD(ctx->opcode);
16708 int enc_rt = uMIPS_RS2(ctx->opcode);
16709 int enc_rs = uMIPS_RS1(ctx->opcode);
16710 gen_movep(ctx, enc_dest, enc_rt, enc_rs);
16712 break;
16713 case LBU16:
16715 int rd = mmreg(uMIPS_RD(ctx->opcode));
16716 int rb = mmreg(uMIPS_RS(ctx->opcode));
16717 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16718 offset = (offset == 0xf ? -1 : offset);
16720 gen_ld(ctx, OPC_LBU, rd, rb, offset);
16722 break;
16723 case LHU16:
16725 int rd = mmreg(uMIPS_RD(ctx->opcode));
16726 int rb = mmreg(uMIPS_RS(ctx->opcode));
16727 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16729 gen_ld(ctx, OPC_LHU, rd, rb, offset);
16731 break;
16732 case LWSP16:
16734 int rd = (ctx->opcode >> 5) & 0x1f;
16735 int rb = 29; /* SP */
16736 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16738 gen_ld(ctx, OPC_LW, rd, rb, offset);
16740 break;
16741 case LW16:
16743 int rd = mmreg(uMIPS_RD(ctx->opcode));
16744 int rb = mmreg(uMIPS_RS(ctx->opcode));
16745 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16747 gen_ld(ctx, OPC_LW, rd, rb, offset);
16749 break;
16750 case SB16:
16752 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16753 int rb = mmreg(uMIPS_RS(ctx->opcode));
16754 int16_t offset = ZIMM(ctx->opcode, 0, 4);
16756 gen_st(ctx, OPC_SB, rd, rb, offset);
16758 break;
16759 case SH16:
16761 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16762 int rb = mmreg(uMIPS_RS(ctx->opcode));
16763 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
16765 gen_st(ctx, OPC_SH, rd, rb, offset);
16767 break;
16768 case SWSP16:
16770 int rd = (ctx->opcode >> 5) & 0x1f;
16771 int rb = 29; /* SP */
16772 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
16774 gen_st(ctx, OPC_SW, rd, rb, offset);
16776 break;
16777 case SW16:
16779 int rd = mmreg2(uMIPS_RD(ctx->opcode));
16780 int rb = mmreg(uMIPS_RS(ctx->opcode));
16781 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
16783 gen_st(ctx, OPC_SW, rd, rb, offset);
16785 break;
16786 case MOVE16:
16788 int rd = uMIPS_RD5(ctx->opcode);
16789 int rs = uMIPS_RS5(ctx->opcode);
16791 gen_arith(ctx, OPC_ADDU, rd, rs, 0);
16793 break;
16794 case ANDI16:
16795 gen_andi16(ctx);
16796 break;
16797 case POOL16D:
16798 switch (ctx->opcode & 0x1) {
16799 case ADDIUS5:
16800 gen_addius5(ctx);
16801 break;
16802 case ADDIUSP:
16803 gen_addiusp(ctx);
16804 break;
16806 break;
16807 case POOL16E:
16808 switch (ctx->opcode & 0x1) {
16809 case ADDIUR2:
16810 gen_addiur2(ctx);
16811 break;
16812 case ADDIUR1SP:
16813 gen_addiur1sp(ctx);
16814 break;
16816 break;
16817 case B16: /* BC16 */
16818 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
16819 sextract32(ctx->opcode, 0, 10) << 1,
16820 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16821 break;
16822 case BNEZ16: /* BNEZC16 */
16823 case BEQZ16: /* BEQZC16 */
16824 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
16825 mmreg(uMIPS_RD(ctx->opcode)),
16826 0, sextract32(ctx->opcode, 0, 7) << 1,
16827 (ctx->insn_flags & ISA_MIPS_R6) ? 0 : 4);
16829 break;
16830 case LI16:
16832 int reg = mmreg(uMIPS_RD(ctx->opcode));
16833 int imm = ZIMM(ctx->opcode, 0, 7);
16835 imm = (imm == 0x7f ? -1 : imm);
16836 tcg_gen_movi_tl(cpu_gpr[reg], imm);
16838 break;
16839 case RES_29:
16840 case RES_31:
16841 case RES_39:
16842 gen_reserved_instruction(ctx);
16843 break;
16844 default:
16845 decode_micromips32_opc(env, ctx);
16846 return 4;
16849 return 2;
16854 * nanoMIPS opcodes
16858 /* MAJOR, P16, and P32 pools opcodes */
16859 enum {
16860 NM_P_ADDIU = 0x00,
16861 NM_ADDIUPC = 0x01,
16862 NM_MOVE_BALC = 0x02,
16863 NM_P16_MV = 0x04,
16864 NM_LW16 = 0x05,
16865 NM_BC16 = 0x06,
16866 NM_P16_SR = 0x07,
16868 NM_POOL32A = 0x08,
16869 NM_P_BAL = 0x0a,
16870 NM_P16_SHIFT = 0x0c,
16871 NM_LWSP16 = 0x0d,
16872 NM_BALC16 = 0x0e,
16873 NM_P16_4X4 = 0x0f,
16875 NM_P_GP_W = 0x10,
16876 NM_P_GP_BH = 0x11,
16877 NM_P_J = 0x12,
16878 NM_P16C = 0x14,
16879 NM_LWGP16 = 0x15,
16880 NM_P16_LB = 0x17,
16882 NM_P48I = 0x18,
16883 NM_P16_A1 = 0x1c,
16884 NM_LW4X4 = 0x1d,
16885 NM_P16_LH = 0x1f,
16887 NM_P_U12 = 0x20,
16888 NM_P_LS_U12 = 0x21,
16889 NM_P_BR1 = 0x22,
16890 NM_P16_A2 = 0x24,
16891 NM_SW16 = 0x25,
16892 NM_BEQZC16 = 0x26,
16894 NM_POOL32F = 0x28,
16895 NM_P_LS_S9 = 0x29,
16896 NM_P_BR2 = 0x2a,
16898 NM_P16_ADDU = 0x2c,
16899 NM_SWSP16 = 0x2d,
16900 NM_BNEZC16 = 0x2e,
16901 NM_MOVEP = 0x2f,
16903 NM_POOL32S = 0x30,
16904 NM_P_BRI = 0x32,
16905 NM_LI16 = 0x34,
16906 NM_SWGP16 = 0x35,
16907 NM_P16_BR = 0x36,
16909 NM_P_LUI = 0x38,
16910 NM_ANDI16 = 0x3c,
16911 NM_SW4X4 = 0x3d,
16912 NM_MOVEPREV = 0x3f,
16915 /* POOL32A instruction pool */
16916 enum {
16917 NM_POOL32A0 = 0x00,
16918 NM_SPECIAL2 = 0x01,
16919 NM_COP2_1 = 0x02,
16920 NM_UDI = 0x03,
16921 NM_POOL32A5 = 0x05,
16922 NM_POOL32A7 = 0x07,
16925 /* P.GP.W instruction pool */
16926 enum {
16927 NM_ADDIUGP_W = 0x00,
16928 NM_LWGP = 0x02,
16929 NM_SWGP = 0x03,
16932 /* P48I instruction pool */
16933 enum {
16934 NM_LI48 = 0x00,
16935 NM_ADDIU48 = 0x01,
16936 NM_ADDIUGP48 = 0x02,
16937 NM_ADDIUPC48 = 0x03,
16938 NM_LWPC48 = 0x0b,
16939 NM_SWPC48 = 0x0f,
16942 /* P.U12 instruction pool */
16943 enum {
16944 NM_ORI = 0x00,
16945 NM_XORI = 0x01,
16946 NM_ANDI = 0x02,
16947 NM_P_SR = 0x03,
16948 NM_SLTI = 0x04,
16949 NM_SLTIU = 0x05,
16950 NM_SEQI = 0x06,
16951 NM_ADDIUNEG = 0x08,
16952 NM_P_SHIFT = 0x0c,
16953 NM_P_ROTX = 0x0d,
16954 NM_P_INS = 0x0e,
16955 NM_P_EXT = 0x0f,
16958 /* POOL32F instruction pool */
16959 enum {
16960 NM_POOL32F_0 = 0x00,
16961 NM_POOL32F_3 = 0x03,
16962 NM_POOL32F_5 = 0x05,
16965 /* POOL32S instruction pool */
16966 enum {
16967 NM_POOL32S_0 = 0x00,
16968 NM_POOL32S_4 = 0x04,
16971 /* P.LUI instruction pool */
16972 enum {
16973 NM_LUI = 0x00,
16974 NM_ALUIPC = 0x01,
16977 /* P.GP.BH instruction pool */
16978 enum {
16979 NM_LBGP = 0x00,
16980 NM_SBGP = 0x01,
16981 NM_LBUGP = 0x02,
16982 NM_ADDIUGP_B = 0x03,
16983 NM_P_GP_LH = 0x04,
16984 NM_P_GP_SH = 0x05,
16985 NM_P_GP_CP1 = 0x06,
16988 /* P.LS.U12 instruction pool */
16989 enum {
16990 NM_LB = 0x00,
16991 NM_SB = 0x01,
16992 NM_LBU = 0x02,
16993 NM_P_PREFU12 = 0x03,
16994 NM_LH = 0x04,
16995 NM_SH = 0x05,
16996 NM_LHU = 0x06,
16997 NM_LWU = 0x07,
16998 NM_LW = 0x08,
16999 NM_SW = 0x09,
17000 NM_LWC1 = 0x0a,
17001 NM_SWC1 = 0x0b,
17002 NM_LDC1 = 0x0e,
17003 NM_SDC1 = 0x0f,
17006 /* P.LS.S9 instruction pool */
17007 enum {
17008 NM_P_LS_S0 = 0x00,
17009 NM_P_LS_S1 = 0x01,
17010 NM_P_LS_E0 = 0x02,
17011 NM_P_LS_WM = 0x04,
17012 NM_P_LS_UAWM = 0x05,
17015 /* P.BAL instruction pool */
17016 enum {
17017 NM_BC = 0x00,
17018 NM_BALC = 0x01,
17021 /* P.J instruction pool */
17022 enum {
17023 NM_JALRC = 0x00,
17024 NM_JALRC_HB = 0x01,
17025 NM_P_BALRSC = 0x08,
17028 /* P.BR1 instruction pool */
17029 enum {
17030 NM_BEQC = 0x00,
17031 NM_P_BR3A = 0x01,
17032 NM_BGEC = 0x02,
17033 NM_BGEUC = 0x03,
17036 /* P.BR2 instruction pool */
17037 enum {
17038 NM_BNEC = 0x00,
17039 NM_BLTC = 0x02,
17040 NM_BLTUC = 0x03,
17043 /* P.BRI instruction pool */
17044 enum {
17045 NM_BEQIC = 0x00,
17046 NM_BBEQZC = 0x01,
17047 NM_BGEIC = 0x02,
17048 NM_BGEIUC = 0x03,
17049 NM_BNEIC = 0x04,
17050 NM_BBNEZC = 0x05,
17051 NM_BLTIC = 0x06,
17052 NM_BLTIUC = 0x07,
17055 /* P16.SHIFT instruction pool */
17056 enum {
17057 NM_SLL16 = 0x00,
17058 NM_SRL16 = 0x01,
17061 /* POOL16C instruction pool */
17062 enum {
17063 NM_POOL16C_0 = 0x00,
17064 NM_LWXS16 = 0x01,
17067 /* P16.A1 instruction pool */
17068 enum {
17069 NM_ADDIUR1SP = 0x01,
17072 /* P16.A2 instruction pool */
17073 enum {
17074 NM_ADDIUR2 = 0x00,
17075 NM_P_ADDIURS5 = 0x01,
17078 /* P16.ADDU instruction pool */
17079 enum {
17080 NM_ADDU16 = 0x00,
17081 NM_SUBU16 = 0x01,
17084 /* P16.SR instruction pool */
17085 enum {
17086 NM_SAVE16 = 0x00,
17087 NM_RESTORE_JRC16 = 0x01,
17090 /* P16.4X4 instruction pool */
17091 enum {
17092 NM_ADDU4X4 = 0x00,
17093 NM_MUL4X4 = 0x01,
17096 /* P16.LB instruction pool */
17097 enum {
17098 NM_LB16 = 0x00,
17099 NM_SB16 = 0x01,
17100 NM_LBU16 = 0x02,
17103 /* P16.LH instruction pool */
17104 enum {
17105 NM_LH16 = 0x00,
17106 NM_SH16 = 0x01,
17107 NM_LHU16 = 0x02,
17110 /* P.RI instruction pool */
17111 enum {
17112 NM_SIGRIE = 0x00,
17113 NM_P_SYSCALL = 0x01,
17114 NM_BREAK = 0x02,
17115 NM_SDBBP = 0x03,
17118 /* POOL32A0 instruction pool */
17119 enum {
17120 NM_P_TRAP = 0x00,
17121 NM_SEB = 0x01,
17122 NM_SLLV = 0x02,
17123 NM_MUL = 0x03,
17124 NM_MFC0 = 0x06,
17125 NM_MFHC0 = 0x07,
17126 NM_SEH = 0x09,
17127 NM_SRLV = 0x0a,
17128 NM_MUH = 0x0b,
17129 NM_MTC0 = 0x0e,
17130 NM_MTHC0 = 0x0f,
17131 NM_SRAV = 0x12,
17132 NM_MULU = 0x13,
17133 NM_ROTRV = 0x1a,
17134 NM_MUHU = 0x1b,
17135 NM_ADD = 0x22,
17136 NM_DIV = 0x23,
17137 NM_ADDU = 0x2a,
17138 NM_MOD = 0x2b,
17139 NM_SUB = 0x32,
17140 NM_DIVU = 0x33,
17141 NM_RDHWR = 0x38,
17142 NM_SUBU = 0x3a,
17143 NM_MODU = 0x3b,
17144 NM_P_CMOVE = 0x42,
17145 NM_FORK = 0x45,
17146 NM_MFTR = 0x46,
17147 NM_MFHTR = 0x47,
17148 NM_AND = 0x4a,
17149 NM_YIELD = 0x4d,
17150 NM_MTTR = 0x4e,
17151 NM_MTHTR = 0x4f,
17152 NM_OR = 0x52,
17153 NM_D_E_MT_VPE = 0x56,
17154 NM_NOR = 0x5a,
17155 NM_XOR = 0x62,
17156 NM_SLT = 0x6a,
17157 NM_P_SLTU = 0x72,
17158 NM_SOV = 0x7a,
17161 /* CRC32 instruction pool */
17162 enum {
17163 NM_CRC32B = 0x00,
17164 NM_CRC32H = 0x01,
17165 NM_CRC32W = 0x02,
17166 NM_CRC32CB = 0x04,
17167 NM_CRC32CH = 0x05,
17168 NM_CRC32CW = 0x06,
17171 /* POOL32A5 instruction pool */
17172 enum {
17173 NM_CMP_EQ_PH = 0x00,
17174 NM_CMP_LT_PH = 0x08,
17175 NM_CMP_LE_PH = 0x10,
17176 NM_CMPGU_EQ_QB = 0x18,
17177 NM_CMPGU_LT_QB = 0x20,
17178 NM_CMPGU_LE_QB = 0x28,
17179 NM_CMPGDU_EQ_QB = 0x30,
17180 NM_CMPGDU_LT_QB = 0x38,
17181 NM_CMPGDU_LE_QB = 0x40,
17182 NM_CMPU_EQ_QB = 0x48,
17183 NM_CMPU_LT_QB = 0x50,
17184 NM_CMPU_LE_QB = 0x58,
17185 NM_ADDQ_S_W = 0x60,
17186 NM_SUBQ_S_W = 0x68,
17187 NM_ADDSC = 0x70,
17188 NM_ADDWC = 0x78,
17190 NM_ADDQ_S_PH = 0x01,
17191 NM_ADDQH_R_PH = 0x09,
17192 NM_ADDQH_R_W = 0x11,
17193 NM_ADDU_S_QB = 0x19,
17194 NM_ADDU_S_PH = 0x21,
17195 NM_ADDUH_R_QB = 0x29,
17196 NM_SHRAV_R_PH = 0x31,
17197 NM_SHRAV_R_QB = 0x39,
17198 NM_SUBQ_S_PH = 0x41,
17199 NM_SUBQH_R_PH = 0x49,
17200 NM_SUBQH_R_W = 0x51,
17201 NM_SUBU_S_QB = 0x59,
17202 NM_SUBU_S_PH = 0x61,
17203 NM_SUBUH_R_QB = 0x69,
17204 NM_SHLLV_S_PH = 0x71,
17205 NM_PRECR_SRA_R_PH_W = 0x79,
17207 NM_MULEU_S_PH_QBL = 0x12,
17208 NM_MULEU_S_PH_QBR = 0x1a,
17209 NM_MULQ_RS_PH = 0x22,
17210 NM_MULQ_S_PH = 0x2a,
17211 NM_MULQ_RS_W = 0x32,
17212 NM_MULQ_S_W = 0x3a,
17213 NM_APPEND = 0x42,
17214 NM_MODSUB = 0x52,
17215 NM_SHRAV_R_W = 0x5a,
17216 NM_SHRLV_PH = 0x62,
17217 NM_SHRLV_QB = 0x6a,
17218 NM_SHLLV_QB = 0x72,
17219 NM_SHLLV_S_W = 0x7a,
17221 NM_SHILO = 0x03,
17223 NM_MULEQ_S_W_PHL = 0x04,
17224 NM_MULEQ_S_W_PHR = 0x0c,
17226 NM_MUL_S_PH = 0x05,
17227 NM_PRECR_QB_PH = 0x0d,
17228 NM_PRECRQ_QB_PH = 0x15,
17229 NM_PRECRQ_PH_W = 0x1d,
17230 NM_PRECRQ_RS_PH_W = 0x25,
17231 NM_PRECRQU_S_QB_PH = 0x2d,
17232 NM_PACKRL_PH = 0x35,
17233 NM_PICK_QB = 0x3d,
17234 NM_PICK_PH = 0x45,
17236 NM_SHRA_R_W = 0x5e,
17237 NM_SHRA_R_PH = 0x66,
17238 NM_SHLL_S_PH = 0x76,
17239 NM_SHLL_S_W = 0x7e,
17241 NM_REPL_PH = 0x07
17244 /* POOL32A7 instruction pool */
17245 enum {
17246 NM_P_LSX = 0x00,
17247 NM_LSA = 0x01,
17248 NM_EXTW = 0x03,
17249 NM_POOL32AXF = 0x07,
17252 /* P.SR instruction pool */
17253 enum {
17254 NM_PP_SR = 0x00,
17255 NM_P_SR_F = 0x01,
17258 /* P.SHIFT instruction pool */
17259 enum {
17260 NM_P_SLL = 0x00,
17261 NM_SRL = 0x02,
17262 NM_SRA = 0x04,
17263 NM_ROTR = 0x06,
17266 /* P.ROTX instruction pool */
17267 enum {
17268 NM_ROTX = 0x00,
17271 /* P.INS instruction pool */
17272 enum {
17273 NM_INS = 0x00,
17276 /* P.EXT instruction pool */
17277 enum {
17278 NM_EXT = 0x00,
17281 /* POOL32F_0 (fmt) instruction pool */
17282 enum {
17283 NM_RINT_S = 0x04,
17284 NM_RINT_D = 0x44,
17285 NM_ADD_S = 0x06,
17286 NM_SELEQZ_S = 0x07,
17287 NM_SELEQZ_D = 0x47,
17288 NM_CLASS_S = 0x0c,
17289 NM_CLASS_D = 0x4c,
17290 NM_SUB_S = 0x0e,
17291 NM_SELNEZ_S = 0x0f,
17292 NM_SELNEZ_D = 0x4f,
17293 NM_MUL_S = 0x16,
17294 NM_SEL_S = 0x17,
17295 NM_SEL_D = 0x57,
17296 NM_DIV_S = 0x1e,
17297 NM_ADD_D = 0x26,
17298 NM_SUB_D = 0x2e,
17299 NM_MUL_D = 0x36,
17300 NM_MADDF_S = 0x37,
17301 NM_MADDF_D = 0x77,
17302 NM_DIV_D = 0x3e,
17303 NM_MSUBF_S = 0x3f,
17304 NM_MSUBF_D = 0x7f,
17307 /* POOL32F_3 instruction pool */
17308 enum {
17309 NM_MIN_FMT = 0x00,
17310 NM_MAX_FMT = 0x01,
17311 NM_MINA_FMT = 0x04,
17312 NM_MAXA_FMT = 0x05,
17313 NM_POOL32FXF = 0x07,
17316 /* POOL32F_5 instruction pool */
17317 enum {
17318 NM_CMP_CONDN_S = 0x00,
17319 NM_CMP_CONDN_D = 0x02,
17322 /* P.GP.LH instruction pool */
17323 enum {
17324 NM_LHGP = 0x00,
17325 NM_LHUGP = 0x01,
17328 /* P.GP.SH instruction pool */
17329 enum {
17330 NM_SHGP = 0x00,
17333 /* P.GP.CP1 instruction pool */
17334 enum {
17335 NM_LWC1GP = 0x00,
17336 NM_SWC1GP = 0x01,
17337 NM_LDC1GP = 0x02,
17338 NM_SDC1GP = 0x03,
17341 /* P.LS.S0 instruction pool */
17342 enum {
17343 NM_LBS9 = 0x00,
17344 NM_LHS9 = 0x04,
17345 NM_LWS9 = 0x08,
17346 NM_LDS9 = 0x0c,
17348 NM_SBS9 = 0x01,
17349 NM_SHS9 = 0x05,
17350 NM_SWS9 = 0x09,
17351 NM_SDS9 = 0x0d,
17353 NM_LBUS9 = 0x02,
17354 NM_LHUS9 = 0x06,
17355 NM_LWC1S9 = 0x0a,
17356 NM_LDC1S9 = 0x0e,
17358 NM_P_PREFS9 = 0x03,
17359 NM_LWUS9 = 0x07,
17360 NM_SWC1S9 = 0x0b,
17361 NM_SDC1S9 = 0x0f,
17364 /* P.LS.S1 instruction pool */
17365 enum {
17366 NM_ASET_ACLR = 0x02,
17367 NM_UALH = 0x04,
17368 NM_UASH = 0x05,
17369 NM_CACHE = 0x07,
17370 NM_P_LL = 0x0a,
17371 NM_P_SC = 0x0b,
17374 /* P.LS.E0 instruction pool */
17375 enum {
17376 NM_LBE = 0x00,
17377 NM_SBE = 0x01,
17378 NM_LBUE = 0x02,
17379 NM_P_PREFE = 0x03,
17380 NM_LHE = 0x04,
17381 NM_SHE = 0x05,
17382 NM_LHUE = 0x06,
17383 NM_CACHEE = 0x07,
17384 NM_LWE = 0x08,
17385 NM_SWE = 0x09,
17386 NM_P_LLE = 0x0a,
17387 NM_P_SCE = 0x0b,
17390 /* P.PREFE instruction pool */
17391 enum {
17392 NM_SYNCIE = 0x00,
17393 NM_PREFE = 0x01,
17396 /* P.LLE instruction pool */
17397 enum {
17398 NM_LLE = 0x00,
17399 NM_LLWPE = 0x01,
17402 /* P.SCE instruction pool */
17403 enum {
17404 NM_SCE = 0x00,
17405 NM_SCWPE = 0x01,
17408 /* P.LS.WM instruction pool */
17409 enum {
17410 NM_LWM = 0x00,
17411 NM_SWM = 0x01,
17414 /* P.LS.UAWM instruction pool */
17415 enum {
17416 NM_UALWM = 0x00,
17417 NM_UASWM = 0x01,
17420 /* P.BR3A instruction pool */
17421 enum {
17422 NM_BC1EQZC = 0x00,
17423 NM_BC1NEZC = 0x01,
17424 NM_BC2EQZC = 0x02,
17425 NM_BC2NEZC = 0x03,
17426 NM_BPOSGE32C = 0x04,
17429 /* P16.RI instruction pool */
17430 enum {
17431 NM_P16_SYSCALL = 0x01,
17432 NM_BREAK16 = 0x02,
17433 NM_SDBBP16 = 0x03,
17436 /* POOL16C_0 instruction pool */
17437 enum {
17438 NM_POOL16C_00 = 0x00,
17441 /* P16.JRC instruction pool */
17442 enum {
17443 NM_JRC = 0x00,
17444 NM_JALRC16 = 0x01,
17447 /* P.SYSCALL instruction pool */
17448 enum {
17449 NM_SYSCALL = 0x00,
17450 NM_HYPCALL = 0x01,
17453 /* P.TRAP instruction pool */
17454 enum {
17455 NM_TEQ = 0x00,
17456 NM_TNE = 0x01,
17459 /* P.CMOVE instruction pool */
17460 enum {
17461 NM_MOVZ = 0x00,
17462 NM_MOVN = 0x01,
17465 /* POOL32Axf instruction pool */
17466 enum {
17467 NM_POOL32AXF_1 = 0x01,
17468 NM_POOL32AXF_2 = 0x02,
17469 NM_POOL32AXF_4 = 0x04,
17470 NM_POOL32AXF_5 = 0x05,
17471 NM_POOL32AXF_7 = 0x07,
17474 /* POOL32Axf_1 instruction pool */
17475 enum {
17476 NM_POOL32AXF_1_0 = 0x00,
17477 NM_POOL32AXF_1_1 = 0x01,
17478 NM_POOL32AXF_1_3 = 0x03,
17479 NM_POOL32AXF_1_4 = 0x04,
17480 NM_POOL32AXF_1_5 = 0x05,
17481 NM_POOL32AXF_1_7 = 0x07,
17484 /* POOL32Axf_2 instruction pool */
17485 enum {
17486 NM_POOL32AXF_2_0_7 = 0x00,
17487 NM_POOL32AXF_2_8_15 = 0x01,
17488 NM_POOL32AXF_2_16_23 = 0x02,
17489 NM_POOL32AXF_2_24_31 = 0x03,
17492 /* POOL32Axf_7 instruction pool */
17493 enum {
17494 NM_SHRA_R_QB = 0x0,
17495 NM_SHRL_PH = 0x1,
17496 NM_REPL_QB = 0x2,
17499 /* POOL32Axf_1_0 instruction pool */
17500 enum {
17501 NM_MFHI = 0x0,
17502 NM_MFLO = 0x1,
17503 NM_MTHI = 0x2,
17504 NM_MTLO = 0x3,
17507 /* POOL32Axf_1_1 instruction pool */
17508 enum {
17509 NM_MTHLIP = 0x0,
17510 NM_SHILOV = 0x1,
17513 /* POOL32Axf_1_3 instruction pool */
17514 enum {
17515 NM_RDDSP = 0x0,
17516 NM_WRDSP = 0x1,
17517 NM_EXTP = 0x2,
17518 NM_EXTPDP = 0x3,
17521 /* POOL32Axf_1_4 instruction pool */
17522 enum {
17523 NM_SHLL_QB = 0x0,
17524 NM_SHRL_QB = 0x1,
17527 /* POOL32Axf_1_5 instruction pool */
17528 enum {
17529 NM_MAQ_S_W_PHR = 0x0,
17530 NM_MAQ_S_W_PHL = 0x1,
17531 NM_MAQ_SA_W_PHR = 0x2,
17532 NM_MAQ_SA_W_PHL = 0x3,
17535 /* POOL32Axf_1_7 instruction pool */
17536 enum {
17537 NM_EXTR_W = 0x0,
17538 NM_EXTR_R_W = 0x1,
17539 NM_EXTR_RS_W = 0x2,
17540 NM_EXTR_S_H = 0x3,
17543 /* POOL32Axf_2_0_7 instruction pool */
17544 enum {
17545 NM_DPA_W_PH = 0x0,
17546 NM_DPAQ_S_W_PH = 0x1,
17547 NM_DPS_W_PH = 0x2,
17548 NM_DPSQ_S_W_PH = 0x3,
17549 NM_BALIGN = 0x4,
17550 NM_MADD = 0x5,
17551 NM_MULT = 0x6,
17552 NM_EXTRV_W = 0x7,
17555 /* POOL32Axf_2_8_15 instruction pool */
17556 enum {
17557 NM_DPAX_W_PH = 0x0,
17558 NM_DPAQ_SA_L_W = 0x1,
17559 NM_DPSX_W_PH = 0x2,
17560 NM_DPSQ_SA_L_W = 0x3,
17561 NM_MADDU = 0x5,
17562 NM_MULTU = 0x6,
17563 NM_EXTRV_R_W = 0x7,
17566 /* POOL32Axf_2_16_23 instruction pool */
17567 enum {
17568 NM_DPAU_H_QBL = 0x0,
17569 NM_DPAQX_S_W_PH = 0x1,
17570 NM_DPSU_H_QBL = 0x2,
17571 NM_DPSQX_S_W_PH = 0x3,
17572 NM_EXTPV = 0x4,
17573 NM_MSUB = 0x5,
17574 NM_MULSA_W_PH = 0x6,
17575 NM_EXTRV_RS_W = 0x7,
17578 /* POOL32Axf_2_24_31 instruction pool */
17579 enum {
17580 NM_DPAU_H_QBR = 0x0,
17581 NM_DPAQX_SA_W_PH = 0x1,
17582 NM_DPSU_H_QBR = 0x2,
17583 NM_DPSQX_SA_W_PH = 0x3,
17584 NM_EXTPDPV = 0x4,
17585 NM_MSUBU = 0x5,
17586 NM_MULSAQ_S_W_PH = 0x6,
17587 NM_EXTRV_S_H = 0x7,
17590 /* POOL32Axf_{4, 5} instruction pool */
17591 enum {
17592 NM_CLO = 0x25,
17593 NM_CLZ = 0x2d,
17595 NM_TLBP = 0x01,
17596 NM_TLBR = 0x09,
17597 NM_TLBWI = 0x11,
17598 NM_TLBWR = 0x19,
17599 NM_TLBINV = 0x03,
17600 NM_TLBINVF = 0x0b,
17601 NM_DI = 0x23,
17602 NM_EI = 0x2b,
17603 NM_RDPGPR = 0x70,
17604 NM_WRPGPR = 0x78,
17605 NM_WAIT = 0x61,
17606 NM_DERET = 0x71,
17607 NM_ERETX = 0x79,
17609 /* nanoMIPS DSP instructions */
17610 NM_ABSQ_S_QB = 0x00,
17611 NM_ABSQ_S_PH = 0x08,
17612 NM_ABSQ_S_W = 0x10,
17613 NM_PRECEQ_W_PHL = 0x28,
17614 NM_PRECEQ_W_PHR = 0x30,
17615 NM_PRECEQU_PH_QBL = 0x38,
17616 NM_PRECEQU_PH_QBR = 0x48,
17617 NM_PRECEU_PH_QBL = 0x58,
17618 NM_PRECEU_PH_QBR = 0x68,
17619 NM_PRECEQU_PH_QBLA = 0x39,
17620 NM_PRECEQU_PH_QBRA = 0x49,
17621 NM_PRECEU_PH_QBLA = 0x59,
17622 NM_PRECEU_PH_QBRA = 0x69,
17623 NM_REPLV_PH = 0x01,
17624 NM_REPLV_QB = 0x09,
17625 NM_BITREV = 0x18,
17626 NM_INSV = 0x20,
17627 NM_RADDU_W_QB = 0x78,
17629 NM_BITSWAP = 0x05,
17630 NM_WSBH = 0x3d,
17633 /* PP.SR instruction pool */
17634 enum {
17635 NM_SAVE = 0x00,
17636 NM_RESTORE = 0x02,
17637 NM_RESTORE_JRC = 0x03,
17640 /* P.SR.F instruction pool */
17641 enum {
17642 NM_SAVEF = 0x00,
17643 NM_RESTOREF = 0x01,
17646 /* P16.SYSCALL instruction pool */
17647 enum {
17648 NM_SYSCALL16 = 0x00,
17649 NM_HYPCALL16 = 0x01,
17652 /* POOL16C_00 instruction pool */
17653 enum {
17654 NM_NOT16 = 0x00,
17655 NM_XOR16 = 0x01,
17656 NM_AND16 = 0x02,
17657 NM_OR16 = 0x03,
17660 /* PP.LSX and PP.LSXS instruction pool */
17661 enum {
17662 NM_LBX = 0x00,
17663 NM_LHX = 0x04,
17664 NM_LWX = 0x08,
17665 NM_LDX = 0x0c,
17667 NM_SBX = 0x01,
17668 NM_SHX = 0x05,
17669 NM_SWX = 0x09,
17670 NM_SDX = 0x0d,
17672 NM_LBUX = 0x02,
17673 NM_LHUX = 0x06,
17674 NM_LWC1X = 0x0a,
17675 NM_LDC1X = 0x0e,
17677 NM_LWUX = 0x07,
17678 NM_SWC1X = 0x0b,
17679 NM_SDC1X = 0x0f,
17681 NM_LHXS = 0x04,
17682 NM_LWXS = 0x08,
17683 NM_LDXS = 0x0c,
17685 NM_SHXS = 0x05,
17686 NM_SWXS = 0x09,
17687 NM_SDXS = 0x0d,
17689 NM_LHUXS = 0x06,
17690 NM_LWC1XS = 0x0a,
17691 NM_LDC1XS = 0x0e,
17693 NM_LWUXS = 0x07,
17694 NM_SWC1XS = 0x0b,
17695 NM_SDC1XS = 0x0f,
17698 /* ERETx instruction pool */
17699 enum {
17700 NM_ERET = 0x00,
17701 NM_ERETNC = 0x01,
17704 /* POOL32FxF_{0, 1} insturction pool */
17705 enum {
17706 NM_CFC1 = 0x40,
17707 NM_CTC1 = 0x60,
17708 NM_MFC1 = 0x80,
17709 NM_MTC1 = 0xa0,
17710 NM_MFHC1 = 0xc0,
17711 NM_MTHC1 = 0xe0,
17713 NM_CVT_S_PL = 0x84,
17714 NM_CVT_S_PU = 0xa4,
17716 NM_CVT_L_S = 0x004,
17717 NM_CVT_L_D = 0x104,
17718 NM_CVT_W_S = 0x024,
17719 NM_CVT_W_D = 0x124,
17721 NM_RSQRT_S = 0x008,
17722 NM_RSQRT_D = 0x108,
17724 NM_SQRT_S = 0x028,
17725 NM_SQRT_D = 0x128,
17727 NM_RECIP_S = 0x048,
17728 NM_RECIP_D = 0x148,
17730 NM_FLOOR_L_S = 0x00c,
17731 NM_FLOOR_L_D = 0x10c,
17733 NM_FLOOR_W_S = 0x02c,
17734 NM_FLOOR_W_D = 0x12c,
17736 NM_CEIL_L_S = 0x04c,
17737 NM_CEIL_L_D = 0x14c,
17738 NM_CEIL_W_S = 0x06c,
17739 NM_CEIL_W_D = 0x16c,
17740 NM_TRUNC_L_S = 0x08c,
17741 NM_TRUNC_L_D = 0x18c,
17742 NM_TRUNC_W_S = 0x0ac,
17743 NM_TRUNC_W_D = 0x1ac,
17744 NM_ROUND_L_S = 0x0cc,
17745 NM_ROUND_L_D = 0x1cc,
17746 NM_ROUND_W_S = 0x0ec,
17747 NM_ROUND_W_D = 0x1ec,
17749 NM_MOV_S = 0x01,
17750 NM_MOV_D = 0x81,
17751 NM_ABS_S = 0x0d,
17752 NM_ABS_D = 0x8d,
17753 NM_NEG_S = 0x2d,
17754 NM_NEG_D = 0xad,
17755 NM_CVT_D_S = 0x04d,
17756 NM_CVT_D_W = 0x0cd,
17757 NM_CVT_D_L = 0x14d,
17758 NM_CVT_S_D = 0x06d,
17759 NM_CVT_S_W = 0x0ed,
17760 NM_CVT_S_L = 0x16d,
17763 /* P.LL instruction pool */
17764 enum {
17765 NM_LL = 0x00,
17766 NM_LLWP = 0x01,
17769 /* P.SC instruction pool */
17770 enum {
17771 NM_SC = 0x00,
17772 NM_SCWP = 0x01,
17775 /* P.DVP instruction pool */
17776 enum {
17777 NM_DVP = 0x00,
17778 NM_EVP = 0x01,
17784 * nanoMIPS decoding engine
17789 /* extraction utilities */
17791 #define NANOMIPS_EXTRACT_RT3(op) ((op >> 7) & 0x7)
17792 #define NANOMIPS_EXTRACT_RS3(op) ((op >> 4) & 0x7)
17793 #define NANOMIPS_EXTRACT_RD3(op) ((op >> 1) & 0x7)
17794 #define NANOMIPS_EXTRACT_RD5(op) ((op >> 5) & 0x1f)
17795 #define NANOMIPS_EXTRACT_RS5(op) (op & 0x1f)
17797 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3'). */
17798 static inline int decode_gpr_gpr3(int r)
17800 static const int map[] = { 16, 17, 18, 19, 4, 5, 6, 7 };
17802 return map[r & 0x7];
17805 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr3.src.store'). */
17806 static inline int decode_gpr_gpr3_src_store(int r)
17808 static const int map[] = { 0, 17, 18, 19, 4, 5, 6, 7 };
17810 return map[r & 0x7];
17813 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4'). */
17814 static inline int decode_gpr_gpr4(int r)
17816 static const int map[] = { 8, 9, 10, 11, 4, 5, 6, 7,
17817 16, 17, 18, 19, 20, 21, 22, 23 };
17819 return map[r & 0xf];
17822 /* Implement nanoMIPS pseudocode decode_gpr(encoded_gpr, 'gpr4.zero'). */
17823 static inline int decode_gpr_gpr4_zero(int r)
17825 static const int map[] = { 8, 9, 10, 0, 4, 5, 6, 7,
17826 16, 17, 18, 19, 20, 21, 22, 23 };
17828 return map[r & 0xf];
17832 static void gen_adjust_sp(DisasContext *ctx, int u)
17834 gen_op_addr_addi(ctx, cpu_gpr[29], cpu_gpr[29], u);
17837 static void gen_save(DisasContext *ctx, uint8_t rt, uint8_t count,
17838 uint8_t gp, uint16_t u)
17840 int counter = 0;
17841 TCGv va = tcg_temp_new();
17842 TCGv t0 = tcg_temp_new();
17844 while (counter != count) {
17845 bool use_gp = gp && (counter == count - 1);
17846 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17847 int this_offset = -((counter + 1) << 2);
17848 gen_base_offset_addr(ctx, va, 29, this_offset);
17849 gen_load_gpr(t0, this_rt);
17850 tcg_gen_qemu_st_tl(t0, va, ctx->mem_idx,
17851 (MO_TEUL | ctx->default_tcg_memop_mask));
17852 counter++;
17855 /* adjust stack pointer */
17856 gen_adjust_sp(ctx, -u);
17858 tcg_temp_free(t0);
17859 tcg_temp_free(va);
17862 static void gen_restore(DisasContext *ctx, uint8_t rt, uint8_t count,
17863 uint8_t gp, uint16_t u)
17865 int counter = 0;
17866 TCGv va = tcg_temp_new();
17867 TCGv t0 = tcg_temp_new();
17869 while (counter != count) {
17870 bool use_gp = gp && (counter == count - 1);
17871 int this_rt = use_gp ? 28 : (rt & 0x10) | ((rt + counter) & 0x1f);
17872 int this_offset = u - ((counter + 1) << 2);
17873 gen_base_offset_addr(ctx, va, 29, this_offset);
17874 tcg_gen_qemu_ld_tl(t0, va, ctx->mem_idx, MO_TESL |
17875 ctx->default_tcg_memop_mask);
17876 tcg_gen_ext32s_tl(t0, t0);
17877 gen_store_gpr(t0, this_rt);
17878 counter++;
17881 /* adjust stack pointer */
17882 gen_adjust_sp(ctx, u);
17884 tcg_temp_free(t0);
17885 tcg_temp_free(va);
17888 static void gen_pool16c_nanomips_insn(DisasContext *ctx)
17890 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
17891 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
17893 switch (extract32(ctx->opcode, 2, 2)) {
17894 case NM_NOT16:
17895 gen_logic(ctx, OPC_NOR, rt, rs, 0);
17896 break;
17897 case NM_AND16:
17898 gen_logic(ctx, OPC_AND, rt, rt, rs);
17899 break;
17900 case NM_XOR16:
17901 gen_logic(ctx, OPC_XOR, rt, rt, rs);
17902 break;
17903 case NM_OR16:
17904 gen_logic(ctx, OPC_OR, rt, rt, rs);
17905 break;
17909 static void gen_pool32a0_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
17911 int rt = extract32(ctx->opcode, 21, 5);
17912 int rs = extract32(ctx->opcode, 16, 5);
17913 int rd = extract32(ctx->opcode, 11, 5);
17915 switch (extract32(ctx->opcode, 3, 7)) {
17916 case NM_P_TRAP:
17917 switch (extract32(ctx->opcode, 10, 1)) {
17918 case NM_TEQ:
17919 check_nms(ctx);
17920 gen_trap(ctx, OPC_TEQ, rs, rt, -1);
17921 break;
17922 case NM_TNE:
17923 check_nms(ctx);
17924 gen_trap(ctx, OPC_TNE, rs, rt, -1);
17925 break;
17927 break;
17928 case NM_RDHWR:
17929 check_nms(ctx);
17930 gen_rdhwr(ctx, rt, rs, extract32(ctx->opcode, 11, 3));
17931 break;
17932 case NM_SEB:
17933 check_nms(ctx);
17934 gen_bshfl(ctx, OPC_SEB, rs, rt);
17935 break;
17936 case NM_SEH:
17937 gen_bshfl(ctx, OPC_SEH, rs, rt);
17938 break;
17939 case NM_SLLV:
17940 gen_shift(ctx, OPC_SLLV, rd, rt, rs);
17941 break;
17942 case NM_SRLV:
17943 gen_shift(ctx, OPC_SRLV, rd, rt, rs);
17944 break;
17945 case NM_SRAV:
17946 gen_shift(ctx, OPC_SRAV, rd, rt, rs);
17947 break;
17948 case NM_ROTRV:
17949 gen_shift(ctx, OPC_ROTRV, rd, rt, rs);
17950 break;
17951 case NM_ADD:
17952 gen_arith(ctx, OPC_ADD, rd, rs, rt);
17953 break;
17954 case NM_ADDU:
17955 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
17956 break;
17957 case NM_SUB:
17958 check_nms(ctx);
17959 gen_arith(ctx, OPC_SUB, rd, rs, rt);
17960 break;
17961 case NM_SUBU:
17962 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
17963 break;
17964 case NM_P_CMOVE:
17965 switch (extract32(ctx->opcode, 10, 1)) {
17966 case NM_MOVZ:
17967 gen_cond_move(ctx, OPC_MOVZ, rd, rs, rt);
17968 break;
17969 case NM_MOVN:
17970 gen_cond_move(ctx, OPC_MOVN, rd, rs, rt);
17971 break;
17973 break;
17974 case NM_AND:
17975 gen_logic(ctx, OPC_AND, rd, rs, rt);
17976 break;
17977 case NM_OR:
17978 gen_logic(ctx, OPC_OR, rd, rs, rt);
17979 break;
17980 case NM_NOR:
17981 gen_logic(ctx, OPC_NOR, rd, rs, rt);
17982 break;
17983 case NM_XOR:
17984 gen_logic(ctx, OPC_XOR, rd, rs, rt);
17985 break;
17986 case NM_SLT:
17987 gen_slt(ctx, OPC_SLT, rd, rs, rt);
17988 break;
17989 case NM_P_SLTU:
17990 if (rd == 0) {
17991 /* P_DVP */
17992 #ifndef CONFIG_USER_ONLY
17993 TCGv t0 = tcg_temp_new();
17994 switch (extract32(ctx->opcode, 10, 1)) {
17995 case NM_DVP:
17996 if (ctx->vp) {
17997 check_cp0_enabled(ctx);
17998 gen_helper_dvp(t0, cpu_env);
17999 gen_store_gpr(t0, rt);
18001 break;
18002 case NM_EVP:
18003 if (ctx->vp) {
18004 check_cp0_enabled(ctx);
18005 gen_helper_evp(t0, cpu_env);
18006 gen_store_gpr(t0, rt);
18008 break;
18010 tcg_temp_free(t0);
18011 #endif
18012 } else {
18013 gen_slt(ctx, OPC_SLTU, rd, rs, rt);
18015 break;
18016 case NM_SOV:
18018 TCGv t0 = tcg_temp_new();
18019 TCGv t1 = tcg_temp_new();
18020 TCGv t2 = tcg_temp_new();
18022 gen_load_gpr(t1, rs);
18023 gen_load_gpr(t2, rt);
18024 tcg_gen_add_tl(t0, t1, t2);
18025 tcg_gen_ext32s_tl(t0, t0);
18026 tcg_gen_xor_tl(t1, t1, t2);
18027 tcg_gen_xor_tl(t2, t0, t2);
18028 tcg_gen_andc_tl(t1, t2, t1);
18030 /* operands of same sign, result different sign */
18031 tcg_gen_setcondi_tl(TCG_COND_LT, t0, t1, 0);
18032 gen_store_gpr(t0, rd);
18034 tcg_temp_free(t0);
18035 tcg_temp_free(t1);
18036 tcg_temp_free(t2);
18038 break;
18039 case NM_MUL:
18040 gen_r6_muldiv(ctx, R6_OPC_MUL, rd, rs, rt);
18041 break;
18042 case NM_MUH:
18043 gen_r6_muldiv(ctx, R6_OPC_MUH, rd, rs, rt);
18044 break;
18045 case NM_MULU:
18046 gen_r6_muldiv(ctx, R6_OPC_MULU, rd, rs, rt);
18047 break;
18048 case NM_MUHU:
18049 gen_r6_muldiv(ctx, R6_OPC_MUHU, rd, rs, rt);
18050 break;
18051 case NM_DIV:
18052 gen_r6_muldiv(ctx, R6_OPC_DIV, rd, rs, rt);
18053 break;
18054 case NM_MOD:
18055 gen_r6_muldiv(ctx, R6_OPC_MOD, rd, rs, rt);
18056 break;
18057 case NM_DIVU:
18058 gen_r6_muldiv(ctx, R6_OPC_DIVU, rd, rs, rt);
18059 break;
18060 case NM_MODU:
18061 gen_r6_muldiv(ctx, R6_OPC_MODU, rd, rs, rt);
18062 break;
18063 #ifndef CONFIG_USER_ONLY
18064 case NM_MFC0:
18065 check_cp0_enabled(ctx);
18066 if (rt == 0) {
18067 /* Treat as NOP. */
18068 break;
18070 gen_mfc0(ctx, cpu_gpr[rt], rs, extract32(ctx->opcode, 11, 3));
18071 break;
18072 case NM_MTC0:
18073 check_cp0_enabled(ctx);
18075 TCGv t0 = tcg_temp_new();
18077 gen_load_gpr(t0, rt);
18078 gen_mtc0(ctx, t0, rs, extract32(ctx->opcode, 11, 3));
18079 tcg_temp_free(t0);
18081 break;
18082 case NM_D_E_MT_VPE:
18084 uint8_t sc = extract32(ctx->opcode, 10, 1);
18085 TCGv t0 = tcg_temp_new();
18087 switch (sc) {
18088 case 0:
18089 if (rs == 1) {
18090 /* DMT */
18091 check_cp0_mt(ctx);
18092 gen_helper_dmt(t0);
18093 gen_store_gpr(t0, rt);
18094 } else if (rs == 0) {
18095 /* DVPE */
18096 check_cp0_mt(ctx);
18097 gen_helper_dvpe(t0, cpu_env);
18098 gen_store_gpr(t0, rt);
18099 } else {
18100 gen_reserved_instruction(ctx);
18102 break;
18103 case 1:
18104 if (rs == 1) {
18105 /* EMT */
18106 check_cp0_mt(ctx);
18107 gen_helper_emt(t0);
18108 gen_store_gpr(t0, rt);
18109 } else if (rs == 0) {
18110 /* EVPE */
18111 check_cp0_mt(ctx);
18112 gen_helper_evpe(t0, cpu_env);
18113 gen_store_gpr(t0, rt);
18114 } else {
18115 gen_reserved_instruction(ctx);
18117 break;
18120 tcg_temp_free(t0);
18122 break;
18123 case NM_FORK:
18124 check_mt(ctx);
18126 TCGv t0 = tcg_temp_new();
18127 TCGv t1 = tcg_temp_new();
18129 gen_load_gpr(t0, rt);
18130 gen_load_gpr(t1, rs);
18131 gen_helper_fork(t0, t1);
18132 tcg_temp_free(t0);
18133 tcg_temp_free(t1);
18135 break;
18136 case NM_MFTR:
18137 case NM_MFHTR:
18138 check_cp0_enabled(ctx);
18139 if (rd == 0) {
18140 /* Treat as NOP. */
18141 return;
18143 gen_mftr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18144 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18145 break;
18146 case NM_MTTR:
18147 case NM_MTHTR:
18148 check_cp0_enabled(ctx);
18149 gen_mttr(env, ctx, rs, rt, extract32(ctx->opcode, 10, 1),
18150 extract32(ctx->opcode, 11, 5), extract32(ctx->opcode, 3, 1));
18151 break;
18152 case NM_YIELD:
18153 check_mt(ctx);
18155 TCGv t0 = tcg_temp_new();
18157 gen_load_gpr(t0, rs);
18158 gen_helper_yield(t0, cpu_env, t0);
18159 gen_store_gpr(t0, rt);
18160 tcg_temp_free(t0);
18162 break;
18163 #endif
18164 default:
18165 gen_reserved_instruction(ctx);
18166 break;
18170 /* dsp */
18171 static void gen_pool32axf_1_5_nanomips_insn(DisasContext *ctx, uint32_t opc,
18172 int ret, int v1, int v2)
18174 TCGv_i32 t0;
18175 TCGv v0_t;
18176 TCGv v1_t;
18178 t0 = tcg_temp_new_i32();
18180 v0_t = tcg_temp_new();
18181 v1_t = tcg_temp_new();
18183 tcg_gen_movi_i32(t0, v2 >> 3);
18185 gen_load_gpr(v0_t, ret);
18186 gen_load_gpr(v1_t, v1);
18188 switch (opc) {
18189 case NM_MAQ_S_W_PHR:
18190 check_dsp(ctx);
18191 gen_helper_maq_s_w_phr(t0, v1_t, v0_t, cpu_env);
18192 break;
18193 case NM_MAQ_S_W_PHL:
18194 check_dsp(ctx);
18195 gen_helper_maq_s_w_phl(t0, v1_t, v0_t, cpu_env);
18196 break;
18197 case NM_MAQ_SA_W_PHR:
18198 check_dsp(ctx);
18199 gen_helper_maq_sa_w_phr(t0, v1_t, v0_t, cpu_env);
18200 break;
18201 case NM_MAQ_SA_W_PHL:
18202 check_dsp(ctx);
18203 gen_helper_maq_sa_w_phl(t0, v1_t, v0_t, cpu_env);
18204 break;
18205 default:
18206 gen_reserved_instruction(ctx);
18207 break;
18210 tcg_temp_free_i32(t0);
18212 tcg_temp_free(v0_t);
18213 tcg_temp_free(v1_t);
18217 static void gen_pool32axf_1_nanomips_insn(DisasContext *ctx, uint32_t opc,
18218 int ret, int v1, int v2)
18220 int16_t imm;
18221 TCGv t0 = tcg_temp_new();
18222 TCGv t1 = tcg_temp_new();
18223 TCGv v0_t = tcg_temp_new();
18225 gen_load_gpr(v0_t, v1);
18227 switch (opc) {
18228 case NM_POOL32AXF_1_0:
18229 check_dsp(ctx);
18230 switch (extract32(ctx->opcode, 12, 2)) {
18231 case NM_MFHI:
18232 gen_HILO(ctx, OPC_MFHI, v2 >> 3, ret);
18233 break;
18234 case NM_MFLO:
18235 gen_HILO(ctx, OPC_MFLO, v2 >> 3, ret);
18236 break;
18237 case NM_MTHI:
18238 gen_HILO(ctx, OPC_MTHI, v2 >> 3, v1);
18239 break;
18240 case NM_MTLO:
18241 gen_HILO(ctx, OPC_MTLO, v2 >> 3, v1);
18242 break;
18244 break;
18245 case NM_POOL32AXF_1_1:
18246 check_dsp(ctx);
18247 switch (extract32(ctx->opcode, 12, 2)) {
18248 case NM_MTHLIP:
18249 tcg_gen_movi_tl(t0, v2);
18250 gen_helper_mthlip(t0, v0_t, cpu_env);
18251 break;
18252 case NM_SHILOV:
18253 tcg_gen_movi_tl(t0, v2 >> 3);
18254 gen_helper_shilo(t0, v0_t, cpu_env);
18255 break;
18256 default:
18257 gen_reserved_instruction(ctx);
18258 break;
18260 break;
18261 case NM_POOL32AXF_1_3:
18262 check_dsp(ctx);
18263 imm = extract32(ctx->opcode, 14, 7);
18264 switch (extract32(ctx->opcode, 12, 2)) {
18265 case NM_RDDSP:
18266 tcg_gen_movi_tl(t0, imm);
18267 gen_helper_rddsp(t0, t0, cpu_env);
18268 gen_store_gpr(t0, ret);
18269 break;
18270 case NM_WRDSP:
18271 gen_load_gpr(t0, ret);
18272 tcg_gen_movi_tl(t1, imm);
18273 gen_helper_wrdsp(t0, t1, cpu_env);
18274 break;
18275 case NM_EXTP:
18276 tcg_gen_movi_tl(t0, v2 >> 3);
18277 tcg_gen_movi_tl(t1, v1);
18278 gen_helper_extp(t0, t0, t1, cpu_env);
18279 gen_store_gpr(t0, ret);
18280 break;
18281 case NM_EXTPDP:
18282 tcg_gen_movi_tl(t0, v2 >> 3);
18283 tcg_gen_movi_tl(t1, v1);
18284 gen_helper_extpdp(t0, t0, t1, cpu_env);
18285 gen_store_gpr(t0, ret);
18286 break;
18288 break;
18289 case NM_POOL32AXF_1_4:
18290 check_dsp(ctx);
18291 tcg_gen_movi_tl(t0, v2 >> 2);
18292 switch (extract32(ctx->opcode, 12, 1)) {
18293 case NM_SHLL_QB:
18294 gen_helper_shll_qb(t0, t0, v0_t, cpu_env);
18295 gen_store_gpr(t0, ret);
18296 break;
18297 case NM_SHRL_QB:
18298 gen_helper_shrl_qb(t0, t0, v0_t);
18299 gen_store_gpr(t0, ret);
18300 break;
18302 break;
18303 case NM_POOL32AXF_1_5:
18304 opc = extract32(ctx->opcode, 12, 2);
18305 gen_pool32axf_1_5_nanomips_insn(ctx, opc, ret, v1, v2);
18306 break;
18307 case NM_POOL32AXF_1_7:
18308 check_dsp(ctx);
18309 tcg_gen_movi_tl(t0, v2 >> 3);
18310 tcg_gen_movi_tl(t1, v1);
18311 switch (extract32(ctx->opcode, 12, 2)) {
18312 case NM_EXTR_W:
18313 gen_helper_extr_w(t0, t0, t1, cpu_env);
18314 gen_store_gpr(t0, ret);
18315 break;
18316 case NM_EXTR_R_W:
18317 gen_helper_extr_r_w(t0, t0, t1, cpu_env);
18318 gen_store_gpr(t0, ret);
18319 break;
18320 case NM_EXTR_RS_W:
18321 gen_helper_extr_rs_w(t0, t0, t1, cpu_env);
18322 gen_store_gpr(t0, ret);
18323 break;
18324 case NM_EXTR_S_H:
18325 gen_helper_extr_s_h(t0, t0, t1, cpu_env);
18326 gen_store_gpr(t0, ret);
18327 break;
18329 break;
18330 default:
18331 gen_reserved_instruction(ctx);
18332 break;
18335 tcg_temp_free(t0);
18336 tcg_temp_free(t1);
18337 tcg_temp_free(v0_t);
18340 static void gen_pool32axf_2_multiply(DisasContext *ctx, uint32_t opc,
18341 TCGv v0, TCGv v1, int rd)
18343 TCGv_i32 t0;
18345 t0 = tcg_temp_new_i32();
18347 tcg_gen_movi_i32(t0, rd >> 3);
18349 switch (opc) {
18350 case NM_POOL32AXF_2_0_7:
18351 switch (extract32(ctx->opcode, 9, 3)) {
18352 case NM_DPA_W_PH:
18353 check_dsp_r2(ctx);
18354 gen_helper_dpa_w_ph(t0, v1, v0, cpu_env);
18355 break;
18356 case NM_DPAQ_S_W_PH:
18357 check_dsp(ctx);
18358 gen_helper_dpaq_s_w_ph(t0, v1, v0, cpu_env);
18359 break;
18360 case NM_DPS_W_PH:
18361 check_dsp_r2(ctx);
18362 gen_helper_dps_w_ph(t0, v1, v0, cpu_env);
18363 break;
18364 case NM_DPSQ_S_W_PH:
18365 check_dsp(ctx);
18366 gen_helper_dpsq_s_w_ph(t0, v1, v0, cpu_env);
18367 break;
18368 default:
18369 gen_reserved_instruction(ctx);
18370 break;
18372 break;
18373 case NM_POOL32AXF_2_8_15:
18374 switch (extract32(ctx->opcode, 9, 3)) {
18375 case NM_DPAX_W_PH:
18376 check_dsp_r2(ctx);
18377 gen_helper_dpax_w_ph(t0, v0, v1, cpu_env);
18378 break;
18379 case NM_DPAQ_SA_L_W:
18380 check_dsp(ctx);
18381 gen_helper_dpaq_sa_l_w(t0, v0, v1, cpu_env);
18382 break;
18383 case NM_DPSX_W_PH:
18384 check_dsp_r2(ctx);
18385 gen_helper_dpsx_w_ph(t0, v0, v1, cpu_env);
18386 break;
18387 case NM_DPSQ_SA_L_W:
18388 check_dsp(ctx);
18389 gen_helper_dpsq_sa_l_w(t0, v0, v1, cpu_env);
18390 break;
18391 default:
18392 gen_reserved_instruction(ctx);
18393 break;
18395 break;
18396 case NM_POOL32AXF_2_16_23:
18397 switch (extract32(ctx->opcode, 9, 3)) {
18398 case NM_DPAU_H_QBL:
18399 check_dsp(ctx);
18400 gen_helper_dpau_h_qbl(t0, v0, v1, cpu_env);
18401 break;
18402 case NM_DPAQX_S_W_PH:
18403 check_dsp_r2(ctx);
18404 gen_helper_dpaqx_s_w_ph(t0, v0, v1, cpu_env);
18405 break;
18406 case NM_DPSU_H_QBL:
18407 check_dsp(ctx);
18408 gen_helper_dpsu_h_qbl(t0, v0, v1, cpu_env);
18409 break;
18410 case NM_DPSQX_S_W_PH:
18411 check_dsp_r2(ctx);
18412 gen_helper_dpsqx_s_w_ph(t0, v0, v1, cpu_env);
18413 break;
18414 case NM_MULSA_W_PH:
18415 check_dsp_r2(ctx);
18416 gen_helper_mulsa_w_ph(t0, v0, v1, cpu_env);
18417 break;
18418 default:
18419 gen_reserved_instruction(ctx);
18420 break;
18422 break;
18423 case NM_POOL32AXF_2_24_31:
18424 switch (extract32(ctx->opcode, 9, 3)) {
18425 case NM_DPAU_H_QBR:
18426 check_dsp(ctx);
18427 gen_helper_dpau_h_qbr(t0, v1, v0, cpu_env);
18428 break;
18429 case NM_DPAQX_SA_W_PH:
18430 check_dsp_r2(ctx);
18431 gen_helper_dpaqx_sa_w_ph(t0, v1, v0, cpu_env);
18432 break;
18433 case NM_DPSU_H_QBR:
18434 check_dsp(ctx);
18435 gen_helper_dpsu_h_qbr(t0, v1, v0, cpu_env);
18436 break;
18437 case NM_DPSQX_SA_W_PH:
18438 check_dsp_r2(ctx);
18439 gen_helper_dpsqx_sa_w_ph(t0, v1, v0, cpu_env);
18440 break;
18441 case NM_MULSAQ_S_W_PH:
18442 check_dsp(ctx);
18443 gen_helper_mulsaq_s_w_ph(t0, v1, v0, cpu_env);
18444 break;
18445 default:
18446 gen_reserved_instruction(ctx);
18447 break;
18449 break;
18450 default:
18451 gen_reserved_instruction(ctx);
18452 break;
18455 tcg_temp_free_i32(t0);
18458 static void gen_pool32axf_2_nanomips_insn(DisasContext *ctx, uint32_t opc,
18459 int rt, int rs, int rd)
18461 int ret = rt;
18462 TCGv t0 = tcg_temp_new();
18463 TCGv t1 = tcg_temp_new();
18464 TCGv v0_t = tcg_temp_new();
18465 TCGv v1_t = tcg_temp_new();
18467 gen_load_gpr(v0_t, rt);
18468 gen_load_gpr(v1_t, rs);
18470 switch (opc) {
18471 case NM_POOL32AXF_2_0_7:
18472 switch (extract32(ctx->opcode, 9, 3)) {
18473 case NM_DPA_W_PH:
18474 case NM_DPAQ_S_W_PH:
18475 case NM_DPS_W_PH:
18476 case NM_DPSQ_S_W_PH:
18477 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18478 break;
18479 case NM_BALIGN:
18480 check_dsp_r2(ctx);
18481 if (rt != 0) {
18482 gen_load_gpr(t0, rs);
18483 rd &= 3;
18484 if (rd != 0 && rd != 2) {
18485 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 8 * rd);
18486 tcg_gen_ext32u_tl(t0, t0);
18487 tcg_gen_shri_tl(t0, t0, 8 * (4 - rd));
18488 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
18490 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
18492 break;
18493 case NM_MADD:
18494 check_dsp(ctx);
18496 int acc = extract32(ctx->opcode, 14, 2);
18497 TCGv_i64 t2 = tcg_temp_new_i64();
18498 TCGv_i64 t3 = tcg_temp_new_i64();
18500 gen_load_gpr(t0, rt);
18501 gen_load_gpr(t1, rs);
18502 tcg_gen_ext_tl_i64(t2, t0);
18503 tcg_gen_ext_tl_i64(t3, t1);
18504 tcg_gen_mul_i64(t2, t2, t3);
18505 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18506 tcg_gen_add_i64(t2, t2, t3);
18507 tcg_temp_free_i64(t3);
18508 gen_move_low32(cpu_LO[acc], t2);
18509 gen_move_high32(cpu_HI[acc], t2);
18510 tcg_temp_free_i64(t2);
18512 break;
18513 case NM_MULT:
18514 check_dsp(ctx);
18516 int acc = extract32(ctx->opcode, 14, 2);
18517 TCGv_i32 t2 = tcg_temp_new_i32();
18518 TCGv_i32 t3 = tcg_temp_new_i32();
18520 gen_load_gpr(t0, rs);
18521 gen_load_gpr(t1, rt);
18522 tcg_gen_trunc_tl_i32(t2, t0);
18523 tcg_gen_trunc_tl_i32(t3, t1);
18524 tcg_gen_muls2_i32(t2, t3, t2, t3);
18525 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18526 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18527 tcg_temp_free_i32(t2);
18528 tcg_temp_free_i32(t3);
18530 break;
18531 case NM_EXTRV_W:
18532 check_dsp(ctx);
18533 gen_load_gpr(v1_t, rs);
18534 tcg_gen_movi_tl(t0, rd >> 3);
18535 gen_helper_extr_w(t0, t0, v1_t, cpu_env);
18536 gen_store_gpr(t0, ret);
18537 break;
18539 break;
18540 case NM_POOL32AXF_2_8_15:
18541 switch (extract32(ctx->opcode, 9, 3)) {
18542 case NM_DPAX_W_PH:
18543 case NM_DPAQ_SA_L_W:
18544 case NM_DPSX_W_PH:
18545 case NM_DPSQ_SA_L_W:
18546 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18547 break;
18548 case NM_MADDU:
18549 check_dsp(ctx);
18551 int acc = extract32(ctx->opcode, 14, 2);
18552 TCGv_i64 t2 = tcg_temp_new_i64();
18553 TCGv_i64 t3 = tcg_temp_new_i64();
18555 gen_load_gpr(t0, rs);
18556 gen_load_gpr(t1, rt);
18557 tcg_gen_ext32u_tl(t0, t0);
18558 tcg_gen_ext32u_tl(t1, t1);
18559 tcg_gen_extu_tl_i64(t2, t0);
18560 tcg_gen_extu_tl_i64(t3, t1);
18561 tcg_gen_mul_i64(t2, t2, t3);
18562 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18563 tcg_gen_add_i64(t2, t2, t3);
18564 tcg_temp_free_i64(t3);
18565 gen_move_low32(cpu_LO[acc], t2);
18566 gen_move_high32(cpu_HI[acc], t2);
18567 tcg_temp_free_i64(t2);
18569 break;
18570 case NM_MULTU:
18571 check_dsp(ctx);
18573 int acc = extract32(ctx->opcode, 14, 2);
18574 TCGv_i32 t2 = tcg_temp_new_i32();
18575 TCGv_i32 t3 = tcg_temp_new_i32();
18577 gen_load_gpr(t0, rs);
18578 gen_load_gpr(t1, rt);
18579 tcg_gen_trunc_tl_i32(t2, t0);
18580 tcg_gen_trunc_tl_i32(t3, t1);
18581 tcg_gen_mulu2_i32(t2, t3, t2, t3);
18582 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
18583 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
18584 tcg_temp_free_i32(t2);
18585 tcg_temp_free_i32(t3);
18587 break;
18588 case NM_EXTRV_R_W:
18589 check_dsp(ctx);
18590 tcg_gen_movi_tl(t0, rd >> 3);
18591 gen_helper_extr_r_w(t0, t0, v1_t, cpu_env);
18592 gen_store_gpr(t0, ret);
18593 break;
18594 default:
18595 gen_reserved_instruction(ctx);
18596 break;
18598 break;
18599 case NM_POOL32AXF_2_16_23:
18600 switch (extract32(ctx->opcode, 9, 3)) {
18601 case NM_DPAU_H_QBL:
18602 case NM_DPAQX_S_W_PH:
18603 case NM_DPSU_H_QBL:
18604 case NM_DPSQX_S_W_PH:
18605 case NM_MULSA_W_PH:
18606 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18607 break;
18608 case NM_EXTPV:
18609 check_dsp(ctx);
18610 tcg_gen_movi_tl(t0, rd >> 3);
18611 gen_helper_extp(t0, t0, v1_t, cpu_env);
18612 gen_store_gpr(t0, ret);
18613 break;
18614 case NM_MSUB:
18615 check_dsp(ctx);
18617 int acc = extract32(ctx->opcode, 14, 2);
18618 TCGv_i64 t2 = tcg_temp_new_i64();
18619 TCGv_i64 t3 = tcg_temp_new_i64();
18621 gen_load_gpr(t0, rs);
18622 gen_load_gpr(t1, rt);
18623 tcg_gen_ext_tl_i64(t2, t0);
18624 tcg_gen_ext_tl_i64(t3, t1);
18625 tcg_gen_mul_i64(t2, t2, t3);
18626 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18627 tcg_gen_sub_i64(t2, t3, t2);
18628 tcg_temp_free_i64(t3);
18629 gen_move_low32(cpu_LO[acc], t2);
18630 gen_move_high32(cpu_HI[acc], t2);
18631 tcg_temp_free_i64(t2);
18633 break;
18634 case NM_EXTRV_RS_W:
18635 check_dsp(ctx);
18636 tcg_gen_movi_tl(t0, rd >> 3);
18637 gen_helper_extr_rs_w(t0, t0, v1_t, cpu_env);
18638 gen_store_gpr(t0, ret);
18639 break;
18641 break;
18642 case NM_POOL32AXF_2_24_31:
18643 switch (extract32(ctx->opcode, 9, 3)) {
18644 case NM_DPAU_H_QBR:
18645 case NM_DPAQX_SA_W_PH:
18646 case NM_DPSU_H_QBR:
18647 case NM_DPSQX_SA_W_PH:
18648 case NM_MULSAQ_S_W_PH:
18649 gen_pool32axf_2_multiply(ctx, opc, v0_t, v1_t, rd);
18650 break;
18651 case NM_EXTPDPV:
18652 check_dsp(ctx);
18653 tcg_gen_movi_tl(t0, rd >> 3);
18654 gen_helper_extpdp(t0, t0, v1_t, cpu_env);
18655 gen_store_gpr(t0, ret);
18656 break;
18657 case NM_MSUBU:
18658 check_dsp(ctx);
18660 int acc = extract32(ctx->opcode, 14, 2);
18661 TCGv_i64 t2 = tcg_temp_new_i64();
18662 TCGv_i64 t3 = tcg_temp_new_i64();
18664 gen_load_gpr(t0, rs);
18665 gen_load_gpr(t1, rt);
18666 tcg_gen_ext32u_tl(t0, t0);
18667 tcg_gen_ext32u_tl(t1, t1);
18668 tcg_gen_extu_tl_i64(t2, t0);
18669 tcg_gen_extu_tl_i64(t3, t1);
18670 tcg_gen_mul_i64(t2, t2, t3);
18671 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
18672 tcg_gen_sub_i64(t2, t3, t2);
18673 tcg_temp_free_i64(t3);
18674 gen_move_low32(cpu_LO[acc], t2);
18675 gen_move_high32(cpu_HI[acc], t2);
18676 tcg_temp_free_i64(t2);
18678 break;
18679 case NM_EXTRV_S_H:
18680 check_dsp(ctx);
18681 tcg_gen_movi_tl(t0, rd >> 3);
18682 gen_helper_extr_s_h(t0, t0, v0_t, cpu_env);
18683 gen_store_gpr(t0, ret);
18684 break;
18686 break;
18687 default:
18688 gen_reserved_instruction(ctx);
18689 break;
18692 tcg_temp_free(t0);
18693 tcg_temp_free(t1);
18695 tcg_temp_free(v0_t);
18696 tcg_temp_free(v1_t);
18699 static void gen_pool32axf_4_nanomips_insn(DisasContext *ctx, uint32_t opc,
18700 int rt, int rs)
18702 int ret = rt;
18703 TCGv t0 = tcg_temp_new();
18704 TCGv v0_t = tcg_temp_new();
18706 gen_load_gpr(v0_t, rs);
18708 switch (opc) {
18709 case NM_ABSQ_S_QB:
18710 check_dsp_r2(ctx);
18711 gen_helper_absq_s_qb(v0_t, v0_t, cpu_env);
18712 gen_store_gpr(v0_t, ret);
18713 break;
18714 case NM_ABSQ_S_PH:
18715 check_dsp(ctx);
18716 gen_helper_absq_s_ph(v0_t, v0_t, cpu_env);
18717 gen_store_gpr(v0_t, ret);
18718 break;
18719 case NM_ABSQ_S_W:
18720 check_dsp(ctx);
18721 gen_helper_absq_s_w(v0_t, v0_t, cpu_env);
18722 gen_store_gpr(v0_t, ret);
18723 break;
18724 case NM_PRECEQ_W_PHL:
18725 check_dsp(ctx);
18726 tcg_gen_andi_tl(v0_t, v0_t, 0xFFFF0000);
18727 tcg_gen_ext32s_tl(v0_t, v0_t);
18728 gen_store_gpr(v0_t, ret);
18729 break;
18730 case NM_PRECEQ_W_PHR:
18731 check_dsp(ctx);
18732 tcg_gen_andi_tl(v0_t, v0_t, 0x0000FFFF);
18733 tcg_gen_shli_tl(v0_t, v0_t, 16);
18734 tcg_gen_ext32s_tl(v0_t, v0_t);
18735 gen_store_gpr(v0_t, ret);
18736 break;
18737 case NM_PRECEQU_PH_QBL:
18738 check_dsp(ctx);
18739 gen_helper_precequ_ph_qbl(v0_t, v0_t);
18740 gen_store_gpr(v0_t, ret);
18741 break;
18742 case NM_PRECEQU_PH_QBR:
18743 check_dsp(ctx);
18744 gen_helper_precequ_ph_qbr(v0_t, v0_t);
18745 gen_store_gpr(v0_t, ret);
18746 break;
18747 case NM_PRECEQU_PH_QBLA:
18748 check_dsp(ctx);
18749 gen_helper_precequ_ph_qbla(v0_t, v0_t);
18750 gen_store_gpr(v0_t, ret);
18751 break;
18752 case NM_PRECEQU_PH_QBRA:
18753 check_dsp(ctx);
18754 gen_helper_precequ_ph_qbra(v0_t, v0_t);
18755 gen_store_gpr(v0_t, ret);
18756 break;
18757 case NM_PRECEU_PH_QBL:
18758 check_dsp(ctx);
18759 gen_helper_preceu_ph_qbl(v0_t, v0_t);
18760 gen_store_gpr(v0_t, ret);
18761 break;
18762 case NM_PRECEU_PH_QBR:
18763 check_dsp(ctx);
18764 gen_helper_preceu_ph_qbr(v0_t, v0_t);
18765 gen_store_gpr(v0_t, ret);
18766 break;
18767 case NM_PRECEU_PH_QBLA:
18768 check_dsp(ctx);
18769 gen_helper_preceu_ph_qbla(v0_t, v0_t);
18770 gen_store_gpr(v0_t, ret);
18771 break;
18772 case NM_PRECEU_PH_QBRA:
18773 check_dsp(ctx);
18774 gen_helper_preceu_ph_qbra(v0_t, v0_t);
18775 gen_store_gpr(v0_t, ret);
18776 break;
18777 case NM_REPLV_PH:
18778 check_dsp(ctx);
18779 tcg_gen_ext16u_tl(v0_t, v0_t);
18780 tcg_gen_shli_tl(t0, v0_t, 16);
18781 tcg_gen_or_tl(v0_t, v0_t, t0);
18782 tcg_gen_ext32s_tl(v0_t, v0_t);
18783 gen_store_gpr(v0_t, ret);
18784 break;
18785 case NM_REPLV_QB:
18786 check_dsp(ctx);
18787 tcg_gen_ext8u_tl(v0_t, v0_t);
18788 tcg_gen_shli_tl(t0, v0_t, 8);
18789 tcg_gen_or_tl(v0_t, v0_t, t0);
18790 tcg_gen_shli_tl(t0, v0_t, 16);
18791 tcg_gen_or_tl(v0_t, v0_t, t0);
18792 tcg_gen_ext32s_tl(v0_t, v0_t);
18793 gen_store_gpr(v0_t, ret);
18794 break;
18795 case NM_BITREV:
18796 check_dsp(ctx);
18797 gen_helper_bitrev(v0_t, v0_t);
18798 gen_store_gpr(v0_t, ret);
18799 break;
18800 case NM_INSV:
18801 check_dsp(ctx);
18803 TCGv tv0 = tcg_temp_new();
18805 gen_load_gpr(tv0, rt);
18806 gen_helper_insv(v0_t, cpu_env, v0_t, tv0);
18807 gen_store_gpr(v0_t, ret);
18808 tcg_temp_free(tv0);
18810 break;
18811 case NM_RADDU_W_QB:
18812 check_dsp(ctx);
18813 gen_helper_raddu_w_qb(v0_t, v0_t);
18814 gen_store_gpr(v0_t, ret);
18815 break;
18816 case NM_BITSWAP:
18817 gen_bitswap(ctx, OPC_BITSWAP, ret, rs);
18818 break;
18819 case NM_CLO:
18820 check_nms(ctx);
18821 gen_cl(ctx, OPC_CLO, ret, rs);
18822 break;
18823 case NM_CLZ:
18824 check_nms(ctx);
18825 gen_cl(ctx, OPC_CLZ, ret, rs);
18826 break;
18827 case NM_WSBH:
18828 gen_bshfl(ctx, OPC_WSBH, ret, rs);
18829 break;
18830 default:
18831 gen_reserved_instruction(ctx);
18832 break;
18835 tcg_temp_free(v0_t);
18836 tcg_temp_free(t0);
18839 static void gen_pool32axf_7_nanomips_insn(DisasContext *ctx, uint32_t opc,
18840 int rt, int rs, int rd)
18842 TCGv t0 = tcg_temp_new();
18843 TCGv rs_t = tcg_temp_new();
18845 gen_load_gpr(rs_t, rs);
18847 switch (opc) {
18848 case NM_SHRA_R_QB:
18849 check_dsp_r2(ctx);
18850 tcg_gen_movi_tl(t0, rd >> 2);
18851 switch (extract32(ctx->opcode, 12, 1)) {
18852 case 0:
18853 /* NM_SHRA_QB */
18854 gen_helper_shra_qb(t0, t0, rs_t);
18855 gen_store_gpr(t0, rt);
18856 break;
18857 case 1:
18858 /* NM_SHRA_R_QB */
18859 gen_helper_shra_r_qb(t0, t0, rs_t);
18860 gen_store_gpr(t0, rt);
18861 break;
18863 break;
18864 case NM_SHRL_PH:
18865 check_dsp_r2(ctx);
18866 tcg_gen_movi_tl(t0, rd >> 1);
18867 gen_helper_shrl_ph(t0, t0, rs_t);
18868 gen_store_gpr(t0, rt);
18869 break;
18870 case NM_REPL_QB:
18871 check_dsp(ctx);
18873 int16_t imm;
18874 target_long result;
18875 imm = extract32(ctx->opcode, 13, 8);
18876 result = (uint32_t)imm << 24 |
18877 (uint32_t)imm << 16 |
18878 (uint32_t)imm << 8 |
18879 (uint32_t)imm;
18880 result = (int32_t)result;
18881 tcg_gen_movi_tl(t0, result);
18882 gen_store_gpr(t0, rt);
18884 break;
18885 default:
18886 gen_reserved_instruction(ctx);
18887 break;
18889 tcg_temp_free(t0);
18890 tcg_temp_free(rs_t);
18894 static void gen_pool32axf_nanomips_insn(CPUMIPSState *env, DisasContext *ctx)
18896 int rt = extract32(ctx->opcode, 21, 5);
18897 int rs = extract32(ctx->opcode, 16, 5);
18898 int rd = extract32(ctx->opcode, 11, 5);
18900 switch (extract32(ctx->opcode, 6, 3)) {
18901 case NM_POOL32AXF_1:
18903 int32_t op1 = extract32(ctx->opcode, 9, 3);
18904 gen_pool32axf_1_nanomips_insn(ctx, op1, rt, rs, rd);
18906 break;
18907 case NM_POOL32AXF_2:
18909 int32_t op1 = extract32(ctx->opcode, 12, 2);
18910 gen_pool32axf_2_nanomips_insn(ctx, op1, rt, rs, rd);
18912 break;
18913 case NM_POOL32AXF_4:
18915 int32_t op1 = extract32(ctx->opcode, 9, 7);
18916 gen_pool32axf_4_nanomips_insn(ctx, op1, rt, rs);
18918 break;
18919 case NM_POOL32AXF_5:
18920 switch (extract32(ctx->opcode, 9, 7)) {
18921 #ifndef CONFIG_USER_ONLY
18922 case NM_TLBP:
18923 gen_cp0(env, ctx, OPC_TLBP, 0, 0);
18924 break;
18925 case NM_TLBR:
18926 gen_cp0(env, ctx, OPC_TLBR, 0, 0);
18927 break;
18928 case NM_TLBWI:
18929 gen_cp0(env, ctx, OPC_TLBWI, 0, 0);
18930 break;
18931 case NM_TLBWR:
18932 gen_cp0(env, ctx, OPC_TLBWR, 0, 0);
18933 break;
18934 case NM_TLBINV:
18935 gen_cp0(env, ctx, OPC_TLBINV, 0, 0);
18936 break;
18937 case NM_TLBINVF:
18938 gen_cp0(env, ctx, OPC_TLBINVF, 0, 0);
18939 break;
18940 case NM_DI:
18941 check_cp0_enabled(ctx);
18943 TCGv t0 = tcg_temp_new();
18945 save_cpu_state(ctx, 1);
18946 gen_helper_di(t0, cpu_env);
18947 gen_store_gpr(t0, rt);
18948 /* Stop translation as we may have switched the execution mode */
18949 ctx->base.is_jmp = DISAS_STOP;
18950 tcg_temp_free(t0);
18952 break;
18953 case NM_EI:
18954 check_cp0_enabled(ctx);
18956 TCGv t0 = tcg_temp_new();
18958 save_cpu_state(ctx, 1);
18959 gen_helper_ei(t0, cpu_env);
18960 gen_store_gpr(t0, rt);
18961 /* Stop translation as we may have switched the execution mode */
18962 ctx->base.is_jmp = DISAS_STOP;
18963 tcg_temp_free(t0);
18965 break;
18966 case NM_RDPGPR:
18967 check_cp0_enabled(ctx);
18968 gen_load_srsgpr(rs, rt);
18969 break;
18970 case NM_WRPGPR:
18971 check_cp0_enabled(ctx);
18972 gen_store_srsgpr(rs, rt);
18973 break;
18974 case NM_WAIT:
18975 gen_cp0(env, ctx, OPC_WAIT, 0, 0);
18976 break;
18977 case NM_DERET:
18978 gen_cp0(env, ctx, OPC_DERET, 0, 0);
18979 break;
18980 case NM_ERETX:
18981 gen_cp0(env, ctx, OPC_ERET, 0, 0);
18982 break;
18983 #endif
18984 default:
18985 gen_reserved_instruction(ctx);
18986 break;
18988 break;
18989 case NM_POOL32AXF_7:
18991 int32_t op1 = extract32(ctx->opcode, 9, 3);
18992 gen_pool32axf_7_nanomips_insn(ctx, op1, rt, rs, rd);
18994 break;
18995 default:
18996 gen_reserved_instruction(ctx);
18997 break;
19001 /* Immediate Value Compact Branches */
19002 static void gen_compute_imm_branch(DisasContext *ctx, uint32_t opc,
19003 int rt, int32_t imm, int32_t offset)
19005 TCGCond cond = TCG_COND_ALWAYS;
19006 TCGv t0 = tcg_temp_new();
19007 TCGv t1 = tcg_temp_new();
19009 gen_load_gpr(t0, rt);
19010 tcg_gen_movi_tl(t1, imm);
19011 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19013 /* Load needed operands and calculate btarget */
19014 switch (opc) {
19015 case NM_BEQIC:
19016 if (rt == 0 && imm == 0) {
19017 /* Unconditional branch */
19018 } else if (rt == 0 && imm != 0) {
19019 /* Treat as NOP */
19020 goto out;
19021 } else {
19022 cond = TCG_COND_EQ;
19024 break;
19025 case NM_BBEQZC:
19026 case NM_BBNEZC:
19027 check_nms(ctx);
19028 if (imm >= 32 && !(ctx->hflags & MIPS_HFLAG_64)) {
19029 gen_reserved_instruction(ctx);
19030 goto out;
19031 } else if (rt == 0 && opc == NM_BBEQZC) {
19032 /* Unconditional branch */
19033 } else if (rt == 0 && opc == NM_BBNEZC) {
19034 /* Treat as NOP */
19035 goto out;
19036 } else {
19037 tcg_gen_shri_tl(t0, t0, imm);
19038 tcg_gen_andi_tl(t0, t0, 1);
19039 tcg_gen_movi_tl(t1, 0);
19040 if (opc == NM_BBEQZC) {
19041 cond = TCG_COND_EQ;
19042 } else {
19043 cond = TCG_COND_NE;
19046 break;
19047 case NM_BNEIC:
19048 if (rt == 0 && imm == 0) {
19049 /* Treat as NOP */
19050 goto out;
19051 } else if (rt == 0 && imm != 0) {
19052 /* Unconditional branch */
19053 } else {
19054 cond = TCG_COND_NE;
19056 break;
19057 case NM_BGEIC:
19058 if (rt == 0 && imm == 0) {
19059 /* Unconditional branch */
19060 } else {
19061 cond = TCG_COND_GE;
19063 break;
19064 case NM_BLTIC:
19065 cond = TCG_COND_LT;
19066 break;
19067 case NM_BGEIUC:
19068 if (rt == 0 && imm == 0) {
19069 /* Unconditional branch */
19070 } else {
19071 cond = TCG_COND_GEU;
19073 break;
19074 case NM_BLTIUC:
19075 cond = TCG_COND_LTU;
19076 break;
19077 default:
19078 MIPS_INVAL("Immediate Value Compact branch");
19079 gen_reserved_instruction(ctx);
19080 goto out;
19083 /* branch completion */
19084 clear_branch_hflags(ctx);
19085 ctx->base.is_jmp = DISAS_NORETURN;
19087 if (cond == TCG_COND_ALWAYS) {
19088 /* Unconditional compact branch */
19089 gen_goto_tb(ctx, 0, ctx->btarget);
19090 } else {
19091 /* Conditional compact branch */
19092 TCGLabel *fs = gen_new_label();
19094 tcg_gen_brcond_tl(tcg_invert_cond(cond), t0, t1, fs);
19096 gen_goto_tb(ctx, 1, ctx->btarget);
19097 gen_set_label(fs);
19099 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19102 out:
19103 tcg_temp_free(t0);
19104 tcg_temp_free(t1);
19107 /* P.BALRSC type nanoMIPS R6 branches: BALRSC and BRSC */
19108 static void gen_compute_nanomips_pbalrsc_branch(DisasContext *ctx, int rs,
19109 int rt)
19111 TCGv t0 = tcg_temp_new();
19112 TCGv t1 = tcg_temp_new();
19114 /* load rs */
19115 gen_load_gpr(t0, rs);
19117 /* link */
19118 if (rt != 0) {
19119 tcg_gen_movi_tl(cpu_gpr[rt], ctx->base.pc_next + 4);
19122 /* calculate btarget */
19123 tcg_gen_shli_tl(t0, t0, 1);
19124 tcg_gen_movi_tl(t1, ctx->base.pc_next + 4);
19125 gen_op_addr_add(ctx, btarget, t1, t0);
19127 /* branch completion */
19128 clear_branch_hflags(ctx);
19129 ctx->base.is_jmp = DISAS_NORETURN;
19131 /* unconditional branch to register */
19132 tcg_gen_mov_tl(cpu_PC, btarget);
19133 tcg_gen_lookup_and_goto_ptr();
19135 tcg_temp_free(t0);
19136 tcg_temp_free(t1);
19139 /* nanoMIPS Branches */
19140 static void gen_compute_compact_branch_nm(DisasContext *ctx, uint32_t opc,
19141 int rs, int rt, int32_t offset)
19143 int bcond_compute = 0;
19144 TCGv t0 = tcg_temp_new();
19145 TCGv t1 = tcg_temp_new();
19147 /* Load needed operands and calculate btarget */
19148 switch (opc) {
19149 /* compact branch */
19150 case OPC_BGEC:
19151 case OPC_BLTC:
19152 gen_load_gpr(t0, rs);
19153 gen_load_gpr(t1, rt);
19154 bcond_compute = 1;
19155 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19156 break;
19157 case OPC_BGEUC:
19158 case OPC_BLTUC:
19159 if (rs == 0 || rs == rt) {
19160 /* OPC_BLEZALC, OPC_BGEZALC */
19161 /* OPC_BGTZALC, OPC_BLTZALC */
19162 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4);
19164 gen_load_gpr(t0, rs);
19165 gen_load_gpr(t1, rt);
19166 bcond_compute = 1;
19167 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19168 break;
19169 case OPC_BC:
19170 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19171 break;
19172 case OPC_BEQZC:
19173 if (rs != 0) {
19174 /* OPC_BEQZC, OPC_BNEZC */
19175 gen_load_gpr(t0, rs);
19176 bcond_compute = 1;
19177 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19178 } else {
19179 /* OPC_JIC, OPC_JIALC */
19180 TCGv tbase = tcg_temp_new();
19181 TCGv toffset = tcg_temp_new();
19183 gen_load_gpr(tbase, rt);
19184 tcg_gen_movi_tl(toffset, offset);
19185 gen_op_addr_add(ctx, btarget, tbase, toffset);
19186 tcg_temp_free(tbase);
19187 tcg_temp_free(toffset);
19189 break;
19190 default:
19191 MIPS_INVAL("Compact branch/jump");
19192 gen_reserved_instruction(ctx);
19193 goto out;
19196 if (bcond_compute == 0) {
19197 /* Unconditional compact branch */
19198 switch (opc) {
19199 case OPC_BC:
19200 gen_goto_tb(ctx, 0, ctx->btarget);
19201 break;
19202 default:
19203 MIPS_INVAL("Compact branch/jump");
19204 gen_reserved_instruction(ctx);
19205 goto out;
19207 } else {
19208 /* Conditional compact branch */
19209 TCGLabel *fs = gen_new_label();
19211 switch (opc) {
19212 case OPC_BGEUC:
19213 if (rs == 0 && rt != 0) {
19214 /* OPC_BLEZALC */
19215 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19216 } else if (rs != 0 && rt != 0 && rs == rt) {
19217 /* OPC_BGEZALC */
19218 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19219 } else {
19220 /* OPC_BGEUC */
19221 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
19223 break;
19224 case OPC_BLTUC:
19225 if (rs == 0 && rt != 0) {
19226 /* OPC_BGTZALC */
19227 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19228 } else if (rs != 0 && rt != 0 && rs == rt) {
19229 /* OPC_BLTZALC */
19230 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19231 } else {
19232 /* OPC_BLTUC */
19233 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
19235 break;
19236 case OPC_BGEC:
19237 if (rs == 0 && rt != 0) {
19238 /* OPC_BLEZC */
19239 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
19240 } else if (rs != 0 && rt != 0 && rs == rt) {
19241 /* OPC_BGEZC */
19242 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
19243 } else {
19244 /* OPC_BGEC */
19245 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
19247 break;
19248 case OPC_BLTC:
19249 if (rs == 0 && rt != 0) {
19250 /* OPC_BGTZC */
19251 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
19252 } else if (rs != 0 && rt != 0 && rs == rt) {
19253 /* OPC_BLTZC */
19254 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
19255 } else {
19256 /* OPC_BLTC */
19257 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
19259 break;
19260 case OPC_BEQZC:
19261 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
19262 break;
19263 default:
19264 MIPS_INVAL("Compact conditional branch/jump");
19265 gen_reserved_instruction(ctx);
19266 goto out;
19269 /* branch completion */
19270 clear_branch_hflags(ctx);
19271 ctx->base.is_jmp = DISAS_NORETURN;
19273 /* Generating branch here as compact branches don't have delay slot */
19274 gen_goto_tb(ctx, 1, ctx->btarget);
19275 gen_set_label(fs);
19277 gen_goto_tb(ctx, 0, ctx->base.pc_next + 4);
19280 out:
19281 tcg_temp_free(t0);
19282 tcg_temp_free(t1);
19286 /* nanoMIPS CP1 Branches */
19287 static void gen_compute_branch_cp1_nm(DisasContext *ctx, uint32_t op,
19288 int32_t ft, int32_t offset)
19290 target_ulong btarget;
19291 TCGv_i64 t0 = tcg_temp_new_i64();
19293 gen_load_fpr64(ctx, t0, ft);
19294 tcg_gen_andi_i64(t0, t0, 1);
19296 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
19298 switch (op) {
19299 case NM_BC1EQZC:
19300 tcg_gen_xori_i64(t0, t0, 1);
19301 ctx->hflags |= MIPS_HFLAG_BC;
19302 break;
19303 case NM_BC1NEZC:
19304 /* t0 already set */
19305 ctx->hflags |= MIPS_HFLAG_BC;
19306 break;
19307 default:
19308 MIPS_INVAL("cp1 cond branch");
19309 gen_reserved_instruction(ctx);
19310 goto out;
19313 tcg_gen_trunc_i64_tl(bcond, t0);
19315 ctx->btarget = btarget;
19317 out:
19318 tcg_temp_free_i64(t0);
19322 static void gen_p_lsx(DisasContext *ctx, int rd, int rs, int rt)
19324 TCGv t0, t1;
19325 t0 = tcg_temp_new();
19326 t1 = tcg_temp_new();
19328 gen_load_gpr(t0, rs);
19329 gen_load_gpr(t1, rt);
19331 if ((extract32(ctx->opcode, 6, 1)) == 1) {
19332 /* PP.LSXS instructions require shifting */
19333 switch (extract32(ctx->opcode, 7, 4)) {
19334 case NM_SHXS:
19335 check_nms(ctx);
19336 /* fall through */
19337 case NM_LHXS:
19338 case NM_LHUXS:
19339 tcg_gen_shli_tl(t0, t0, 1);
19340 break;
19341 case NM_SWXS:
19342 check_nms(ctx);
19343 /* fall through */
19344 case NM_LWXS:
19345 case NM_LWC1XS:
19346 case NM_SWC1XS:
19347 tcg_gen_shli_tl(t0, t0, 2);
19348 break;
19349 case NM_LDC1XS:
19350 case NM_SDC1XS:
19351 tcg_gen_shli_tl(t0, t0, 3);
19352 break;
19355 gen_op_addr_add(ctx, t0, t0, t1);
19357 switch (extract32(ctx->opcode, 7, 4)) {
19358 case NM_LBX:
19359 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19360 MO_SB);
19361 gen_store_gpr(t0, rd);
19362 break;
19363 case NM_LHX:
19364 /*case NM_LHXS:*/
19365 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19366 MO_TESW);
19367 gen_store_gpr(t0, rd);
19368 break;
19369 case NM_LWX:
19370 /*case NM_LWXS:*/
19371 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19372 MO_TESL);
19373 gen_store_gpr(t0, rd);
19374 break;
19375 case NM_LBUX:
19376 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19377 MO_UB);
19378 gen_store_gpr(t0, rd);
19379 break;
19380 case NM_LHUX:
19381 /*case NM_LHUXS:*/
19382 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx,
19383 MO_TEUW);
19384 gen_store_gpr(t0, rd);
19385 break;
19386 case NM_SBX:
19387 check_nms(ctx);
19388 gen_load_gpr(t1, rd);
19389 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19390 MO_8);
19391 break;
19392 case NM_SHX:
19393 /*case NM_SHXS:*/
19394 check_nms(ctx);
19395 gen_load_gpr(t1, rd);
19396 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19397 MO_TEUW);
19398 break;
19399 case NM_SWX:
19400 /*case NM_SWXS:*/
19401 check_nms(ctx);
19402 gen_load_gpr(t1, rd);
19403 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx,
19404 MO_TEUL);
19405 break;
19406 case NM_LWC1X:
19407 /*case NM_LWC1XS:*/
19408 case NM_LDC1X:
19409 /*case NM_LDC1XS:*/
19410 case NM_SWC1X:
19411 /*case NM_SWC1XS:*/
19412 case NM_SDC1X:
19413 /*case NM_SDC1XS:*/
19414 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
19415 check_cp1_enabled(ctx);
19416 switch (extract32(ctx->opcode, 7, 4)) {
19417 case NM_LWC1X:
19418 /*case NM_LWC1XS:*/
19419 gen_flt_ldst(ctx, OPC_LWC1, rd, t0);
19420 break;
19421 case NM_LDC1X:
19422 /*case NM_LDC1XS:*/
19423 gen_flt_ldst(ctx, OPC_LDC1, rd, t0);
19424 break;
19425 case NM_SWC1X:
19426 /*case NM_SWC1XS:*/
19427 gen_flt_ldst(ctx, OPC_SWC1, rd, t0);
19428 break;
19429 case NM_SDC1X:
19430 /*case NM_SDC1XS:*/
19431 gen_flt_ldst(ctx, OPC_SDC1, rd, t0);
19432 break;
19434 } else {
19435 generate_exception_err(ctx, EXCP_CpU, 1);
19437 break;
19438 default:
19439 gen_reserved_instruction(ctx);
19440 break;
19443 tcg_temp_free(t0);
19444 tcg_temp_free(t1);
19447 static void gen_pool32f_nanomips_insn(DisasContext *ctx)
19449 int rt, rs, rd;
19451 rt = extract32(ctx->opcode, 21, 5);
19452 rs = extract32(ctx->opcode, 16, 5);
19453 rd = extract32(ctx->opcode, 11, 5);
19455 if (!(ctx->CP0_Config1 & (1 << CP0C1_FP))) {
19456 gen_reserved_instruction(ctx);
19457 return;
19459 check_cp1_enabled(ctx);
19460 switch (extract32(ctx->opcode, 0, 3)) {
19461 case NM_POOL32F_0:
19462 switch (extract32(ctx->opcode, 3, 7)) {
19463 case NM_RINT_S:
19464 gen_farith(ctx, OPC_RINT_S, 0, rt, rs, 0);
19465 break;
19466 case NM_RINT_D:
19467 gen_farith(ctx, OPC_RINT_D, 0, rt, rs, 0);
19468 break;
19469 case NM_CLASS_S:
19470 gen_farith(ctx, OPC_CLASS_S, 0, rt, rs, 0);
19471 break;
19472 case NM_CLASS_D:
19473 gen_farith(ctx, OPC_CLASS_D, 0, rt, rs, 0);
19474 break;
19475 case NM_ADD_S:
19476 gen_farith(ctx, OPC_ADD_S, rt, rs, rd, 0);
19477 break;
19478 case NM_ADD_D:
19479 gen_farith(ctx, OPC_ADD_D, rt, rs, rd, 0);
19480 break;
19481 case NM_SUB_S:
19482 gen_farith(ctx, OPC_SUB_S, rt, rs, rd, 0);
19483 break;
19484 case NM_SUB_D:
19485 gen_farith(ctx, OPC_SUB_D, rt, rs, rd, 0);
19486 break;
19487 case NM_MUL_S:
19488 gen_farith(ctx, OPC_MUL_S, rt, rs, rd, 0);
19489 break;
19490 case NM_MUL_D:
19491 gen_farith(ctx, OPC_MUL_D, rt, rs, rd, 0);
19492 break;
19493 case NM_DIV_S:
19494 gen_farith(ctx, OPC_DIV_S, rt, rs, rd, 0);
19495 break;
19496 case NM_DIV_D:
19497 gen_farith(ctx, OPC_DIV_D, rt, rs, rd, 0);
19498 break;
19499 case NM_SELEQZ_S:
19500 gen_sel_s(ctx, OPC_SELEQZ_S, rd, rt, rs);
19501 break;
19502 case NM_SELEQZ_D:
19503 gen_sel_d(ctx, OPC_SELEQZ_D, rd, rt, rs);
19504 break;
19505 case NM_SELNEZ_S:
19506 gen_sel_s(ctx, OPC_SELNEZ_S, rd, rt, rs);
19507 break;
19508 case NM_SELNEZ_D:
19509 gen_sel_d(ctx, OPC_SELNEZ_D, rd, rt, rs);
19510 break;
19511 case NM_SEL_S:
19512 gen_sel_s(ctx, OPC_SEL_S, rd, rt, rs);
19513 break;
19514 case NM_SEL_D:
19515 gen_sel_d(ctx, OPC_SEL_D, rd, rt, rs);
19516 break;
19517 case NM_MADDF_S:
19518 gen_farith(ctx, OPC_MADDF_S, rt, rs, rd, 0);
19519 break;
19520 case NM_MADDF_D:
19521 gen_farith(ctx, OPC_MADDF_D, rt, rs, rd, 0);
19522 break;
19523 case NM_MSUBF_S:
19524 gen_farith(ctx, OPC_MSUBF_S, rt, rs, rd, 0);
19525 break;
19526 case NM_MSUBF_D:
19527 gen_farith(ctx, OPC_MSUBF_D, rt, rs, rd, 0);
19528 break;
19529 default:
19530 gen_reserved_instruction(ctx);
19531 break;
19533 break;
19534 case NM_POOL32F_3:
19535 switch (extract32(ctx->opcode, 3, 3)) {
19536 case NM_MIN_FMT:
19537 switch (extract32(ctx->opcode, 9, 1)) {
19538 case FMT_SDPS_S:
19539 gen_farith(ctx, OPC_MIN_S, rt, rs, rd, 0);
19540 break;
19541 case FMT_SDPS_D:
19542 gen_farith(ctx, OPC_MIN_D, rt, rs, rd, 0);
19543 break;
19545 break;
19546 case NM_MAX_FMT:
19547 switch (extract32(ctx->opcode, 9, 1)) {
19548 case FMT_SDPS_S:
19549 gen_farith(ctx, OPC_MAX_S, rt, rs, rd, 0);
19550 break;
19551 case FMT_SDPS_D:
19552 gen_farith(ctx, OPC_MAX_D, rt, rs, rd, 0);
19553 break;
19555 break;
19556 case NM_MINA_FMT:
19557 switch (extract32(ctx->opcode, 9, 1)) {
19558 case FMT_SDPS_S:
19559 gen_farith(ctx, OPC_MINA_S, rt, rs, rd, 0);
19560 break;
19561 case FMT_SDPS_D:
19562 gen_farith(ctx, OPC_MINA_D, rt, rs, rd, 0);
19563 break;
19565 break;
19566 case NM_MAXA_FMT:
19567 switch (extract32(ctx->opcode, 9, 1)) {
19568 case FMT_SDPS_S:
19569 gen_farith(ctx, OPC_MAXA_S, rt, rs, rd, 0);
19570 break;
19571 case FMT_SDPS_D:
19572 gen_farith(ctx, OPC_MAXA_D, rt, rs, rd, 0);
19573 break;
19575 break;
19576 case NM_POOL32FXF:
19577 switch (extract32(ctx->opcode, 6, 8)) {
19578 case NM_CFC1:
19579 gen_cp1(ctx, OPC_CFC1, rt, rs);
19580 break;
19581 case NM_CTC1:
19582 gen_cp1(ctx, OPC_CTC1, rt, rs);
19583 break;
19584 case NM_MFC1:
19585 gen_cp1(ctx, OPC_MFC1, rt, rs);
19586 break;
19587 case NM_MTC1:
19588 gen_cp1(ctx, OPC_MTC1, rt, rs);
19589 break;
19590 case NM_MFHC1:
19591 gen_cp1(ctx, OPC_MFHC1, rt, rs);
19592 break;
19593 case NM_MTHC1:
19594 gen_cp1(ctx, OPC_MTHC1, rt, rs);
19595 break;
19596 case NM_CVT_S_PL:
19597 gen_farith(ctx, OPC_CVT_S_PL, -1, rs, rt, 0);
19598 break;
19599 case NM_CVT_S_PU:
19600 gen_farith(ctx, OPC_CVT_S_PU, -1, rs, rt, 0);
19601 break;
19602 default:
19603 switch (extract32(ctx->opcode, 6, 9)) {
19604 case NM_CVT_L_S:
19605 gen_farith(ctx, OPC_CVT_L_S, -1, rs, rt, 0);
19606 break;
19607 case NM_CVT_L_D:
19608 gen_farith(ctx, OPC_CVT_L_D, -1, rs, rt, 0);
19609 break;
19610 case NM_CVT_W_S:
19611 gen_farith(ctx, OPC_CVT_W_S, -1, rs, rt, 0);
19612 break;
19613 case NM_CVT_W_D:
19614 gen_farith(ctx, OPC_CVT_W_D, -1, rs, rt, 0);
19615 break;
19616 case NM_RSQRT_S:
19617 gen_farith(ctx, OPC_RSQRT_S, -1, rs, rt, 0);
19618 break;
19619 case NM_RSQRT_D:
19620 gen_farith(ctx, OPC_RSQRT_D, -1, rs, rt, 0);
19621 break;
19622 case NM_SQRT_S:
19623 gen_farith(ctx, OPC_SQRT_S, -1, rs, rt, 0);
19624 break;
19625 case NM_SQRT_D:
19626 gen_farith(ctx, OPC_SQRT_D, -1, rs, rt, 0);
19627 break;
19628 case NM_RECIP_S:
19629 gen_farith(ctx, OPC_RECIP_S, -1, rs, rt, 0);
19630 break;
19631 case NM_RECIP_D:
19632 gen_farith(ctx, OPC_RECIP_D, -1, rs, rt, 0);
19633 break;
19634 case NM_FLOOR_L_S:
19635 gen_farith(ctx, OPC_FLOOR_L_S, -1, rs, rt, 0);
19636 break;
19637 case NM_FLOOR_L_D:
19638 gen_farith(ctx, OPC_FLOOR_L_D, -1, rs, rt, 0);
19639 break;
19640 case NM_FLOOR_W_S:
19641 gen_farith(ctx, OPC_FLOOR_W_S, -1, rs, rt, 0);
19642 break;
19643 case NM_FLOOR_W_D:
19644 gen_farith(ctx, OPC_FLOOR_W_D, -1, rs, rt, 0);
19645 break;
19646 case NM_CEIL_L_S:
19647 gen_farith(ctx, OPC_CEIL_L_S, -1, rs, rt, 0);
19648 break;
19649 case NM_CEIL_L_D:
19650 gen_farith(ctx, OPC_CEIL_L_D, -1, rs, rt, 0);
19651 break;
19652 case NM_CEIL_W_S:
19653 gen_farith(ctx, OPC_CEIL_W_S, -1, rs, rt, 0);
19654 break;
19655 case NM_CEIL_W_D:
19656 gen_farith(ctx, OPC_CEIL_W_D, -1, rs, rt, 0);
19657 break;
19658 case NM_TRUNC_L_S:
19659 gen_farith(ctx, OPC_TRUNC_L_S, -1, rs, rt, 0);
19660 break;
19661 case NM_TRUNC_L_D:
19662 gen_farith(ctx, OPC_TRUNC_L_D, -1, rs, rt, 0);
19663 break;
19664 case NM_TRUNC_W_S:
19665 gen_farith(ctx, OPC_TRUNC_W_S, -1, rs, rt, 0);
19666 break;
19667 case NM_TRUNC_W_D:
19668 gen_farith(ctx, OPC_TRUNC_W_D, -1, rs, rt, 0);
19669 break;
19670 case NM_ROUND_L_S:
19671 gen_farith(ctx, OPC_ROUND_L_S, -1, rs, rt, 0);
19672 break;
19673 case NM_ROUND_L_D:
19674 gen_farith(ctx, OPC_ROUND_L_D, -1, rs, rt, 0);
19675 break;
19676 case NM_ROUND_W_S:
19677 gen_farith(ctx, OPC_ROUND_W_S, -1, rs, rt, 0);
19678 break;
19679 case NM_ROUND_W_D:
19680 gen_farith(ctx, OPC_ROUND_W_D, -1, rs, rt, 0);
19681 break;
19682 case NM_MOV_S:
19683 gen_farith(ctx, OPC_MOV_S, -1, rs, rt, 0);
19684 break;
19685 case NM_MOV_D:
19686 gen_farith(ctx, OPC_MOV_D, -1, rs, rt, 0);
19687 break;
19688 case NM_ABS_S:
19689 gen_farith(ctx, OPC_ABS_S, -1, rs, rt, 0);
19690 break;
19691 case NM_ABS_D:
19692 gen_farith(ctx, OPC_ABS_D, -1, rs, rt, 0);
19693 break;
19694 case NM_NEG_S:
19695 gen_farith(ctx, OPC_NEG_S, -1, rs, rt, 0);
19696 break;
19697 case NM_NEG_D:
19698 gen_farith(ctx, OPC_NEG_D, -1, rs, rt, 0);
19699 break;
19700 case NM_CVT_D_S:
19701 gen_farith(ctx, OPC_CVT_D_S, -1, rs, rt, 0);
19702 break;
19703 case NM_CVT_D_W:
19704 gen_farith(ctx, OPC_CVT_D_W, -1, rs, rt, 0);
19705 break;
19706 case NM_CVT_D_L:
19707 gen_farith(ctx, OPC_CVT_D_L, -1, rs, rt, 0);
19708 break;
19709 case NM_CVT_S_D:
19710 gen_farith(ctx, OPC_CVT_S_D, -1, rs, rt, 0);
19711 break;
19712 case NM_CVT_S_W:
19713 gen_farith(ctx, OPC_CVT_S_W, -1, rs, rt, 0);
19714 break;
19715 case NM_CVT_S_L:
19716 gen_farith(ctx, OPC_CVT_S_L, -1, rs, rt, 0);
19717 break;
19718 default:
19719 gen_reserved_instruction(ctx);
19720 break;
19722 break;
19724 break;
19726 break;
19727 case NM_POOL32F_5:
19728 switch (extract32(ctx->opcode, 3, 3)) {
19729 case NM_CMP_CONDN_S:
19730 gen_r6_cmp_s(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19731 break;
19732 case NM_CMP_CONDN_D:
19733 gen_r6_cmp_d(ctx, extract32(ctx->opcode, 6, 5), rt, rs, rd);
19734 break;
19735 default:
19736 gen_reserved_instruction(ctx);
19737 break;
19739 break;
19740 default:
19741 gen_reserved_instruction(ctx);
19742 break;
19746 static void gen_pool32a5_nanomips_insn(DisasContext *ctx, int opc,
19747 int rd, int rs, int rt)
19749 int ret = rd;
19750 TCGv t0 = tcg_temp_new();
19751 TCGv v1_t = tcg_temp_new();
19752 TCGv v2_t = tcg_temp_new();
19754 gen_load_gpr(v1_t, rs);
19755 gen_load_gpr(v2_t, rt);
19757 switch (opc) {
19758 case NM_CMP_EQ_PH:
19759 check_dsp(ctx);
19760 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
19761 break;
19762 case NM_CMP_LT_PH:
19763 check_dsp(ctx);
19764 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
19765 break;
19766 case NM_CMP_LE_PH:
19767 check_dsp(ctx);
19768 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
19769 break;
19770 case NM_CMPU_EQ_QB:
19771 check_dsp(ctx);
19772 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
19773 break;
19774 case NM_CMPU_LT_QB:
19775 check_dsp(ctx);
19776 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
19777 break;
19778 case NM_CMPU_LE_QB:
19779 check_dsp(ctx);
19780 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
19781 break;
19782 case NM_CMPGU_EQ_QB:
19783 check_dsp(ctx);
19784 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19785 gen_store_gpr(v1_t, ret);
19786 break;
19787 case NM_CMPGU_LT_QB:
19788 check_dsp(ctx);
19789 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19790 gen_store_gpr(v1_t, ret);
19791 break;
19792 case NM_CMPGU_LE_QB:
19793 check_dsp(ctx);
19794 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19795 gen_store_gpr(v1_t, ret);
19796 break;
19797 case NM_CMPGDU_EQ_QB:
19798 check_dsp_r2(ctx);
19799 gen_helper_cmpgu_eq_qb(v1_t, v1_t, v2_t);
19800 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19801 gen_store_gpr(v1_t, ret);
19802 break;
19803 case NM_CMPGDU_LT_QB:
19804 check_dsp_r2(ctx);
19805 gen_helper_cmpgu_lt_qb(v1_t, v1_t, v2_t);
19806 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19807 gen_store_gpr(v1_t, ret);
19808 break;
19809 case NM_CMPGDU_LE_QB:
19810 check_dsp_r2(ctx);
19811 gen_helper_cmpgu_le_qb(v1_t, v1_t, v2_t);
19812 tcg_gen_deposit_tl(cpu_dspctrl, cpu_dspctrl, v1_t, 24, 4);
19813 gen_store_gpr(v1_t, ret);
19814 break;
19815 case NM_PACKRL_PH:
19816 check_dsp(ctx);
19817 gen_helper_packrl_ph(v1_t, v1_t, v2_t);
19818 gen_store_gpr(v1_t, ret);
19819 break;
19820 case NM_PICK_QB:
19821 check_dsp(ctx);
19822 gen_helper_pick_qb(v1_t, v1_t, v2_t, cpu_env);
19823 gen_store_gpr(v1_t, ret);
19824 break;
19825 case NM_PICK_PH:
19826 check_dsp(ctx);
19827 gen_helper_pick_ph(v1_t, v1_t, v2_t, cpu_env);
19828 gen_store_gpr(v1_t, ret);
19829 break;
19830 case NM_ADDQ_S_W:
19831 check_dsp(ctx);
19832 gen_helper_addq_s_w(v1_t, v1_t, v2_t, cpu_env);
19833 gen_store_gpr(v1_t, ret);
19834 break;
19835 case NM_SUBQ_S_W:
19836 check_dsp(ctx);
19837 gen_helper_subq_s_w(v1_t, v1_t, v2_t, cpu_env);
19838 gen_store_gpr(v1_t, ret);
19839 break;
19840 case NM_ADDSC:
19841 check_dsp(ctx);
19842 gen_helper_addsc(v1_t, v1_t, v2_t, cpu_env);
19843 gen_store_gpr(v1_t, ret);
19844 break;
19845 case NM_ADDWC:
19846 check_dsp(ctx);
19847 gen_helper_addwc(v1_t, v1_t, v2_t, cpu_env);
19848 gen_store_gpr(v1_t, ret);
19849 break;
19850 case NM_ADDQ_S_PH:
19851 check_dsp(ctx);
19852 switch (extract32(ctx->opcode, 10, 1)) {
19853 case 0:
19854 /* ADDQ_PH */
19855 gen_helper_addq_ph(v1_t, v1_t, v2_t, cpu_env);
19856 gen_store_gpr(v1_t, ret);
19857 break;
19858 case 1:
19859 /* ADDQ_S_PH */
19860 gen_helper_addq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19861 gen_store_gpr(v1_t, ret);
19862 break;
19864 break;
19865 case NM_ADDQH_R_PH:
19866 check_dsp_r2(ctx);
19867 switch (extract32(ctx->opcode, 10, 1)) {
19868 case 0:
19869 /* ADDQH_PH */
19870 gen_helper_addqh_ph(v1_t, v1_t, v2_t);
19871 gen_store_gpr(v1_t, ret);
19872 break;
19873 case 1:
19874 /* ADDQH_R_PH */
19875 gen_helper_addqh_r_ph(v1_t, v1_t, v2_t);
19876 gen_store_gpr(v1_t, ret);
19877 break;
19879 break;
19880 case NM_ADDQH_R_W:
19881 check_dsp_r2(ctx);
19882 switch (extract32(ctx->opcode, 10, 1)) {
19883 case 0:
19884 /* ADDQH_W */
19885 gen_helper_addqh_w(v1_t, v1_t, v2_t);
19886 gen_store_gpr(v1_t, ret);
19887 break;
19888 case 1:
19889 /* ADDQH_R_W */
19890 gen_helper_addqh_r_w(v1_t, v1_t, v2_t);
19891 gen_store_gpr(v1_t, ret);
19892 break;
19894 break;
19895 case NM_ADDU_S_QB:
19896 check_dsp(ctx);
19897 switch (extract32(ctx->opcode, 10, 1)) {
19898 case 0:
19899 /* ADDU_QB */
19900 gen_helper_addu_qb(v1_t, v1_t, v2_t, cpu_env);
19901 gen_store_gpr(v1_t, ret);
19902 break;
19903 case 1:
19904 /* ADDU_S_QB */
19905 gen_helper_addu_s_qb(v1_t, v1_t, v2_t, cpu_env);
19906 gen_store_gpr(v1_t, ret);
19907 break;
19909 break;
19910 case NM_ADDU_S_PH:
19911 check_dsp_r2(ctx);
19912 switch (extract32(ctx->opcode, 10, 1)) {
19913 case 0:
19914 /* ADDU_PH */
19915 gen_helper_addu_ph(v1_t, v1_t, v2_t, cpu_env);
19916 gen_store_gpr(v1_t, ret);
19917 break;
19918 case 1:
19919 /* ADDU_S_PH */
19920 gen_helper_addu_s_ph(v1_t, v1_t, v2_t, cpu_env);
19921 gen_store_gpr(v1_t, ret);
19922 break;
19924 break;
19925 case NM_ADDUH_R_QB:
19926 check_dsp_r2(ctx);
19927 switch (extract32(ctx->opcode, 10, 1)) {
19928 case 0:
19929 /* ADDUH_QB */
19930 gen_helper_adduh_qb(v1_t, v1_t, v2_t);
19931 gen_store_gpr(v1_t, ret);
19932 break;
19933 case 1:
19934 /* ADDUH_R_QB */
19935 gen_helper_adduh_r_qb(v1_t, v1_t, v2_t);
19936 gen_store_gpr(v1_t, ret);
19937 break;
19939 break;
19940 case NM_SHRAV_R_PH:
19941 check_dsp(ctx);
19942 switch (extract32(ctx->opcode, 10, 1)) {
19943 case 0:
19944 /* SHRAV_PH */
19945 gen_helper_shra_ph(v1_t, v1_t, v2_t);
19946 gen_store_gpr(v1_t, ret);
19947 break;
19948 case 1:
19949 /* SHRAV_R_PH */
19950 gen_helper_shra_r_ph(v1_t, v1_t, v2_t);
19951 gen_store_gpr(v1_t, ret);
19952 break;
19954 break;
19955 case NM_SHRAV_R_QB:
19956 check_dsp_r2(ctx);
19957 switch (extract32(ctx->opcode, 10, 1)) {
19958 case 0:
19959 /* SHRAV_QB */
19960 gen_helper_shra_qb(v1_t, v1_t, v2_t);
19961 gen_store_gpr(v1_t, ret);
19962 break;
19963 case 1:
19964 /* SHRAV_R_QB */
19965 gen_helper_shra_r_qb(v1_t, v1_t, v2_t);
19966 gen_store_gpr(v1_t, ret);
19967 break;
19969 break;
19970 case NM_SUBQ_S_PH:
19971 check_dsp(ctx);
19972 switch (extract32(ctx->opcode, 10, 1)) {
19973 case 0:
19974 /* SUBQ_PH */
19975 gen_helper_subq_ph(v1_t, v1_t, v2_t, cpu_env);
19976 gen_store_gpr(v1_t, ret);
19977 break;
19978 case 1:
19979 /* SUBQ_S_PH */
19980 gen_helper_subq_s_ph(v1_t, v1_t, v2_t, cpu_env);
19981 gen_store_gpr(v1_t, ret);
19982 break;
19984 break;
19985 case NM_SUBQH_R_PH:
19986 check_dsp_r2(ctx);
19987 switch (extract32(ctx->opcode, 10, 1)) {
19988 case 0:
19989 /* SUBQH_PH */
19990 gen_helper_subqh_ph(v1_t, v1_t, v2_t);
19991 gen_store_gpr(v1_t, ret);
19992 break;
19993 case 1:
19994 /* SUBQH_R_PH */
19995 gen_helper_subqh_r_ph(v1_t, v1_t, v2_t);
19996 gen_store_gpr(v1_t, ret);
19997 break;
19999 break;
20000 case NM_SUBQH_R_W:
20001 check_dsp_r2(ctx);
20002 switch (extract32(ctx->opcode, 10, 1)) {
20003 case 0:
20004 /* SUBQH_W */
20005 gen_helper_subqh_w(v1_t, v1_t, v2_t);
20006 gen_store_gpr(v1_t, ret);
20007 break;
20008 case 1:
20009 /* SUBQH_R_W */
20010 gen_helper_subqh_r_w(v1_t, v1_t, v2_t);
20011 gen_store_gpr(v1_t, ret);
20012 break;
20014 break;
20015 case NM_SUBU_S_QB:
20016 check_dsp(ctx);
20017 switch (extract32(ctx->opcode, 10, 1)) {
20018 case 0:
20019 /* SUBU_QB */
20020 gen_helper_subu_qb(v1_t, v1_t, v2_t, cpu_env);
20021 gen_store_gpr(v1_t, ret);
20022 break;
20023 case 1:
20024 /* SUBU_S_QB */
20025 gen_helper_subu_s_qb(v1_t, v1_t, v2_t, cpu_env);
20026 gen_store_gpr(v1_t, ret);
20027 break;
20029 break;
20030 case NM_SUBU_S_PH:
20031 check_dsp_r2(ctx);
20032 switch (extract32(ctx->opcode, 10, 1)) {
20033 case 0:
20034 /* SUBU_PH */
20035 gen_helper_subu_ph(v1_t, v1_t, v2_t, cpu_env);
20036 gen_store_gpr(v1_t, ret);
20037 break;
20038 case 1:
20039 /* SUBU_S_PH */
20040 gen_helper_subu_s_ph(v1_t, v1_t, v2_t, cpu_env);
20041 gen_store_gpr(v1_t, ret);
20042 break;
20044 break;
20045 case NM_SUBUH_R_QB:
20046 check_dsp_r2(ctx);
20047 switch (extract32(ctx->opcode, 10, 1)) {
20048 case 0:
20049 /* SUBUH_QB */
20050 gen_helper_subuh_qb(v1_t, v1_t, v2_t);
20051 gen_store_gpr(v1_t, ret);
20052 break;
20053 case 1:
20054 /* SUBUH_R_QB */
20055 gen_helper_subuh_r_qb(v1_t, v1_t, v2_t);
20056 gen_store_gpr(v1_t, ret);
20057 break;
20059 break;
20060 case NM_SHLLV_S_PH:
20061 check_dsp(ctx);
20062 switch (extract32(ctx->opcode, 10, 1)) {
20063 case 0:
20064 /* SHLLV_PH */
20065 gen_helper_shll_ph(v1_t, v1_t, v2_t, cpu_env);
20066 gen_store_gpr(v1_t, ret);
20067 break;
20068 case 1:
20069 /* SHLLV_S_PH */
20070 gen_helper_shll_s_ph(v1_t, v1_t, v2_t, cpu_env);
20071 gen_store_gpr(v1_t, ret);
20072 break;
20074 break;
20075 case NM_PRECR_SRA_R_PH_W:
20076 check_dsp_r2(ctx);
20077 switch (extract32(ctx->opcode, 10, 1)) {
20078 case 0:
20079 /* PRECR_SRA_PH_W */
20081 TCGv_i32 sa_t = tcg_const_i32(rd);
20082 gen_helper_precr_sra_ph_w(v1_t, sa_t, v1_t,
20083 cpu_gpr[rt]);
20084 gen_store_gpr(v1_t, rt);
20085 tcg_temp_free_i32(sa_t);
20087 break;
20088 case 1:
20089 /* PRECR_SRA_R_PH_W */
20091 TCGv_i32 sa_t = tcg_const_i32(rd);
20092 gen_helper_precr_sra_r_ph_w(v1_t, sa_t, v1_t,
20093 cpu_gpr[rt]);
20094 gen_store_gpr(v1_t, rt);
20095 tcg_temp_free_i32(sa_t);
20097 break;
20099 break;
20100 case NM_MULEU_S_PH_QBL:
20101 check_dsp(ctx);
20102 gen_helper_muleu_s_ph_qbl(v1_t, v1_t, v2_t, cpu_env);
20103 gen_store_gpr(v1_t, ret);
20104 break;
20105 case NM_MULEU_S_PH_QBR:
20106 check_dsp(ctx);
20107 gen_helper_muleu_s_ph_qbr(v1_t, v1_t, v2_t, cpu_env);
20108 gen_store_gpr(v1_t, ret);
20109 break;
20110 case NM_MULQ_RS_PH:
20111 check_dsp(ctx);
20112 gen_helper_mulq_rs_ph(v1_t, v1_t, v2_t, cpu_env);
20113 gen_store_gpr(v1_t, ret);
20114 break;
20115 case NM_MULQ_S_PH:
20116 check_dsp_r2(ctx);
20117 gen_helper_mulq_s_ph(v1_t, v1_t, v2_t, cpu_env);
20118 gen_store_gpr(v1_t, ret);
20119 break;
20120 case NM_MULQ_RS_W:
20121 check_dsp_r2(ctx);
20122 gen_helper_mulq_rs_w(v1_t, v1_t, v2_t, cpu_env);
20123 gen_store_gpr(v1_t, ret);
20124 break;
20125 case NM_MULQ_S_W:
20126 check_dsp_r2(ctx);
20127 gen_helper_mulq_s_w(v1_t, v1_t, v2_t, cpu_env);
20128 gen_store_gpr(v1_t, ret);
20129 break;
20130 case NM_APPEND:
20131 check_dsp_r2(ctx);
20132 gen_load_gpr(t0, rs);
20133 if (rd != 0) {
20134 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], rd, 32 - rd);
20136 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20137 break;
20138 case NM_MODSUB:
20139 check_dsp(ctx);
20140 gen_helper_modsub(v1_t, v1_t, v2_t);
20141 gen_store_gpr(v1_t, ret);
20142 break;
20143 case NM_SHRAV_R_W:
20144 check_dsp(ctx);
20145 gen_helper_shra_r_w(v1_t, v1_t, v2_t);
20146 gen_store_gpr(v1_t, ret);
20147 break;
20148 case NM_SHRLV_PH:
20149 check_dsp_r2(ctx);
20150 gen_helper_shrl_ph(v1_t, v1_t, v2_t);
20151 gen_store_gpr(v1_t, ret);
20152 break;
20153 case NM_SHRLV_QB:
20154 check_dsp(ctx);
20155 gen_helper_shrl_qb(v1_t, v1_t, v2_t);
20156 gen_store_gpr(v1_t, ret);
20157 break;
20158 case NM_SHLLV_QB:
20159 check_dsp(ctx);
20160 gen_helper_shll_qb(v1_t, v1_t, v2_t, cpu_env);
20161 gen_store_gpr(v1_t, ret);
20162 break;
20163 case NM_SHLLV_S_W:
20164 check_dsp(ctx);
20165 gen_helper_shll_s_w(v1_t, v1_t, v2_t, cpu_env);
20166 gen_store_gpr(v1_t, ret);
20167 break;
20168 case NM_SHILO:
20169 check_dsp(ctx);
20171 TCGv tv0 = tcg_temp_new();
20172 TCGv tv1 = tcg_temp_new();
20173 int16_t imm = extract32(ctx->opcode, 16, 7);
20175 tcg_gen_movi_tl(tv0, rd >> 3);
20176 tcg_gen_movi_tl(tv1, imm);
20177 gen_helper_shilo(tv0, tv1, cpu_env);
20178 tcg_temp_free(tv1);
20179 tcg_temp_free(tv0);
20181 break;
20182 case NM_MULEQ_S_W_PHL:
20183 check_dsp(ctx);
20184 gen_helper_muleq_s_w_phl(v1_t, v1_t, v2_t, cpu_env);
20185 gen_store_gpr(v1_t, ret);
20186 break;
20187 case NM_MULEQ_S_W_PHR:
20188 check_dsp(ctx);
20189 gen_helper_muleq_s_w_phr(v1_t, v1_t, v2_t, cpu_env);
20190 gen_store_gpr(v1_t, ret);
20191 break;
20192 case NM_MUL_S_PH:
20193 check_dsp_r2(ctx);
20194 switch (extract32(ctx->opcode, 10, 1)) {
20195 case 0:
20196 /* MUL_PH */
20197 gen_helper_mul_ph(v1_t, v1_t, v2_t, cpu_env);
20198 gen_store_gpr(v1_t, ret);
20199 break;
20200 case 1:
20201 /* MUL_S_PH */
20202 gen_helper_mul_s_ph(v1_t, v1_t, v2_t, cpu_env);
20203 gen_store_gpr(v1_t, ret);
20204 break;
20206 break;
20207 case NM_PRECR_QB_PH:
20208 check_dsp_r2(ctx);
20209 gen_helper_precr_qb_ph(v1_t, v1_t, v2_t);
20210 gen_store_gpr(v1_t, ret);
20211 break;
20212 case NM_PRECRQ_QB_PH:
20213 check_dsp(ctx);
20214 gen_helper_precrq_qb_ph(v1_t, v1_t, v2_t);
20215 gen_store_gpr(v1_t, ret);
20216 break;
20217 case NM_PRECRQ_PH_W:
20218 check_dsp(ctx);
20219 gen_helper_precrq_ph_w(v1_t, v1_t, v2_t);
20220 gen_store_gpr(v1_t, ret);
20221 break;
20222 case NM_PRECRQ_RS_PH_W:
20223 check_dsp(ctx);
20224 gen_helper_precrq_rs_ph_w(v1_t, v1_t, v2_t, cpu_env);
20225 gen_store_gpr(v1_t, ret);
20226 break;
20227 case NM_PRECRQU_S_QB_PH:
20228 check_dsp(ctx);
20229 gen_helper_precrqu_s_qb_ph(v1_t, v1_t, v2_t, cpu_env);
20230 gen_store_gpr(v1_t, ret);
20231 break;
20232 case NM_SHRA_R_W:
20233 check_dsp(ctx);
20234 tcg_gen_movi_tl(t0, rd);
20235 gen_helper_shra_r_w(v1_t, t0, v1_t);
20236 gen_store_gpr(v1_t, rt);
20237 break;
20238 case NM_SHRA_R_PH:
20239 check_dsp(ctx);
20240 tcg_gen_movi_tl(t0, rd >> 1);
20241 switch (extract32(ctx->opcode, 10, 1)) {
20242 case 0:
20243 /* SHRA_PH */
20244 gen_helper_shra_ph(v1_t, t0, v1_t);
20245 gen_store_gpr(v1_t, rt);
20246 break;
20247 case 1:
20248 /* SHRA_R_PH */
20249 gen_helper_shra_r_ph(v1_t, t0, v1_t);
20250 gen_store_gpr(v1_t, rt);
20251 break;
20253 break;
20254 case NM_SHLL_S_PH:
20255 check_dsp(ctx);
20256 tcg_gen_movi_tl(t0, rd >> 1);
20257 switch (extract32(ctx->opcode, 10, 2)) {
20258 case 0:
20259 /* SHLL_PH */
20260 gen_helper_shll_ph(v1_t, t0, v1_t, cpu_env);
20261 gen_store_gpr(v1_t, rt);
20262 break;
20263 case 2:
20264 /* SHLL_S_PH */
20265 gen_helper_shll_s_ph(v1_t, t0, v1_t, cpu_env);
20266 gen_store_gpr(v1_t, rt);
20267 break;
20268 default:
20269 gen_reserved_instruction(ctx);
20270 break;
20272 break;
20273 case NM_SHLL_S_W:
20274 check_dsp(ctx);
20275 tcg_gen_movi_tl(t0, rd);
20276 gen_helper_shll_s_w(v1_t, t0, v1_t, cpu_env);
20277 gen_store_gpr(v1_t, rt);
20278 break;
20279 case NM_REPL_PH:
20280 check_dsp(ctx);
20282 int16_t imm;
20283 imm = sextract32(ctx->opcode, 11, 11);
20284 imm = (int16_t)(imm << 6) >> 6;
20285 if (rt != 0) {
20286 tcg_gen_movi_tl(cpu_gpr[rt], dup_const(MO_16, imm));
20289 break;
20290 default:
20291 gen_reserved_instruction(ctx);
20292 break;
20295 tcg_temp_free(v2_t);
20296 tcg_temp_free(v1_t);
20297 tcg_temp_free(t0);
20300 static int decode_nanomips_32_48_opc(CPUMIPSState *env, DisasContext *ctx)
20302 uint16_t insn;
20303 uint32_t op;
20304 int rt, rs, rd;
20305 int offset;
20306 int imm;
20308 insn = translator_lduw(env, ctx->base.pc_next + 2);
20309 ctx->opcode = (ctx->opcode << 16) | insn;
20311 rt = extract32(ctx->opcode, 21, 5);
20312 rs = extract32(ctx->opcode, 16, 5);
20313 rd = extract32(ctx->opcode, 11, 5);
20315 op = extract32(ctx->opcode, 26, 6);
20316 switch (op) {
20317 case NM_P_ADDIU:
20318 if (rt == 0) {
20319 /* P.RI */
20320 switch (extract32(ctx->opcode, 19, 2)) {
20321 case NM_SIGRIE:
20322 default:
20323 gen_reserved_instruction(ctx);
20324 break;
20325 case NM_P_SYSCALL:
20326 if ((extract32(ctx->opcode, 18, 1)) == NM_SYSCALL) {
20327 generate_exception_end(ctx, EXCP_SYSCALL);
20328 } else {
20329 gen_reserved_instruction(ctx);
20331 break;
20332 case NM_BREAK:
20333 generate_exception_end(ctx, EXCP_BREAK);
20334 break;
20335 case NM_SDBBP:
20336 if (is_uhi(extract32(ctx->opcode, 0, 19))) {
20337 gen_helper_do_semihosting(cpu_env);
20338 } else {
20339 if (ctx->hflags & MIPS_HFLAG_SBRI) {
20340 gen_reserved_instruction(ctx);
20341 } else {
20342 generate_exception_end(ctx, EXCP_DBp);
20345 break;
20347 } else {
20348 /* NM_ADDIU */
20349 imm = extract32(ctx->opcode, 0, 16);
20350 if (rs != 0) {
20351 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm);
20352 } else {
20353 tcg_gen_movi_tl(cpu_gpr[rt], imm);
20355 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20357 break;
20358 case NM_ADDIUPC:
20359 if (rt != 0) {
20360 offset = sextract32(ctx->opcode, 0, 1) << 21 |
20361 extract32(ctx->opcode, 1, 20) << 1;
20362 target_long addr = addr_add(ctx, ctx->base.pc_next + 4, offset);
20363 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20365 break;
20366 case NM_POOL32A:
20367 switch (ctx->opcode & 0x07) {
20368 case NM_POOL32A0:
20369 gen_pool32a0_nanomips_insn(env, ctx);
20370 break;
20371 case NM_POOL32A5:
20373 int32_t op1 = extract32(ctx->opcode, 3, 7);
20374 gen_pool32a5_nanomips_insn(ctx, op1, rd, rs, rt);
20376 break;
20377 case NM_POOL32A7:
20378 switch (extract32(ctx->opcode, 3, 3)) {
20379 case NM_P_LSX:
20380 gen_p_lsx(ctx, rd, rs, rt);
20381 break;
20382 case NM_LSA:
20384 * In nanoMIPS, the shift field directly encodes the shift
20385 * amount, meaning that the supported shift values are in
20386 * the range 0 to 3 (instead of 1 to 4 in MIPSR6).
20388 gen_lsa(ctx, rd, rt, rs, extract32(ctx->opcode, 9, 2) - 1);
20389 break;
20390 case NM_EXTW:
20391 gen_ext(ctx, 32, rd, rs, rt, extract32(ctx->opcode, 6, 5));
20392 break;
20393 case NM_POOL32AXF:
20394 gen_pool32axf_nanomips_insn(env, ctx);
20395 break;
20396 default:
20397 gen_reserved_instruction(ctx);
20398 break;
20400 break;
20401 default:
20402 gen_reserved_instruction(ctx);
20403 break;
20405 break;
20406 case NM_P_GP_W:
20407 switch (ctx->opcode & 0x03) {
20408 case NM_ADDIUGP_W:
20409 if (rt != 0) {
20410 offset = extract32(ctx->opcode, 0, 21);
20411 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], offset);
20413 break;
20414 case NM_LWGP:
20415 gen_ld(ctx, OPC_LW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20416 break;
20417 case NM_SWGP:
20418 gen_st(ctx, OPC_SW, rt, 28, extract32(ctx->opcode, 2, 19) << 2);
20419 break;
20420 default:
20421 gen_reserved_instruction(ctx);
20422 break;
20424 break;
20425 case NM_P48I:
20427 insn = translator_lduw(env, ctx->base.pc_next + 4);
20428 target_long addr_off = extract32(ctx->opcode, 0, 16) | insn << 16;
20429 switch (extract32(ctx->opcode, 16, 5)) {
20430 case NM_LI48:
20431 check_nms(ctx);
20432 if (rt != 0) {
20433 tcg_gen_movi_tl(cpu_gpr[rt], addr_off);
20435 break;
20436 case NM_ADDIU48:
20437 check_nms(ctx);
20438 if (rt != 0) {
20439 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rt], addr_off);
20440 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
20442 break;
20443 case NM_ADDIUGP48:
20444 check_nms(ctx);
20445 if (rt != 0) {
20446 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], addr_off);
20448 break;
20449 case NM_ADDIUPC48:
20450 check_nms(ctx);
20451 if (rt != 0) {
20452 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20453 addr_off);
20455 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20457 break;
20458 case NM_LWPC48:
20459 check_nms(ctx);
20460 if (rt != 0) {
20461 TCGv t0;
20462 t0 = tcg_temp_new();
20464 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20465 addr_off);
20467 tcg_gen_movi_tl(t0, addr);
20468 tcg_gen_qemu_ld_tl(cpu_gpr[rt], t0, ctx->mem_idx, MO_TESL);
20469 tcg_temp_free(t0);
20471 break;
20472 case NM_SWPC48:
20473 check_nms(ctx);
20475 TCGv t0, t1;
20476 t0 = tcg_temp_new();
20477 t1 = tcg_temp_new();
20479 target_long addr = addr_add(ctx, ctx->base.pc_next + 6,
20480 addr_off);
20482 tcg_gen_movi_tl(t0, addr);
20483 gen_load_gpr(t1, rt);
20485 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
20487 tcg_temp_free(t0);
20488 tcg_temp_free(t1);
20490 break;
20491 default:
20492 gen_reserved_instruction(ctx);
20493 break;
20495 return 6;
20497 case NM_P_U12:
20498 switch (extract32(ctx->opcode, 12, 4)) {
20499 case NM_ORI:
20500 gen_logic_imm(ctx, OPC_ORI, rt, rs, extract32(ctx->opcode, 0, 12));
20501 break;
20502 case NM_XORI:
20503 gen_logic_imm(ctx, OPC_XORI, rt, rs, extract32(ctx->opcode, 0, 12));
20504 break;
20505 case NM_ANDI:
20506 gen_logic_imm(ctx, OPC_ANDI, rt, rs, extract32(ctx->opcode, 0, 12));
20507 break;
20508 case NM_P_SR:
20509 switch (extract32(ctx->opcode, 20, 1)) {
20510 case NM_PP_SR:
20511 switch (ctx->opcode & 3) {
20512 case NM_SAVE:
20513 gen_save(ctx, rt, extract32(ctx->opcode, 16, 4),
20514 extract32(ctx->opcode, 2, 1),
20515 extract32(ctx->opcode, 3, 9) << 3);
20516 break;
20517 case NM_RESTORE:
20518 case NM_RESTORE_JRC:
20519 gen_restore(ctx, rt, extract32(ctx->opcode, 16, 4),
20520 extract32(ctx->opcode, 2, 1),
20521 extract32(ctx->opcode, 3, 9) << 3);
20522 if ((ctx->opcode & 3) == NM_RESTORE_JRC) {
20523 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
20525 break;
20526 default:
20527 gen_reserved_instruction(ctx);
20528 break;
20530 break;
20531 case NM_P_SR_F:
20532 gen_reserved_instruction(ctx);
20533 break;
20535 break;
20536 case NM_SLTI:
20537 gen_slt_imm(ctx, OPC_SLTI, rt, rs, extract32(ctx->opcode, 0, 12));
20538 break;
20539 case NM_SLTIU:
20540 gen_slt_imm(ctx, OPC_SLTIU, rt, rs, extract32(ctx->opcode, 0, 12));
20541 break;
20542 case NM_SEQI:
20544 TCGv t0 = tcg_temp_new();
20546 imm = extract32(ctx->opcode, 0, 12);
20547 gen_load_gpr(t0, rs);
20548 tcg_gen_setcondi_tl(TCG_COND_EQ, t0, t0, imm);
20549 gen_store_gpr(t0, rt);
20551 tcg_temp_free(t0);
20553 break;
20554 case NM_ADDIUNEG:
20555 imm = (int16_t) extract32(ctx->opcode, 0, 12);
20556 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, -imm);
20557 break;
20558 case NM_P_SHIFT:
20560 int shift = extract32(ctx->opcode, 0, 5);
20561 switch (extract32(ctx->opcode, 5, 4)) {
20562 case NM_P_SLL:
20563 if (rt == 0 && shift == 0) {
20564 /* NOP */
20565 } else if (rt == 0 && shift == 3) {
20566 /* EHB - treat as NOP */
20567 } else if (rt == 0 && shift == 5) {
20568 /* PAUSE - treat as NOP */
20569 } else if (rt == 0 && shift == 6) {
20570 /* SYNC */
20571 gen_sync(extract32(ctx->opcode, 16, 5));
20572 } else {
20573 /* SLL */
20574 gen_shift_imm(ctx, OPC_SLL, rt, rs,
20575 extract32(ctx->opcode, 0, 5));
20577 break;
20578 case NM_SRL:
20579 gen_shift_imm(ctx, OPC_SRL, rt, rs,
20580 extract32(ctx->opcode, 0, 5));
20581 break;
20582 case NM_SRA:
20583 gen_shift_imm(ctx, OPC_SRA, rt, rs,
20584 extract32(ctx->opcode, 0, 5));
20585 break;
20586 case NM_ROTR:
20587 gen_shift_imm(ctx, OPC_ROTR, rt, rs,
20588 extract32(ctx->opcode, 0, 5));
20589 break;
20592 break;
20593 case NM_P_ROTX:
20594 check_nms(ctx);
20595 if (rt != 0) {
20596 TCGv t0 = tcg_temp_new();
20597 TCGv_i32 shift = tcg_const_i32(extract32(ctx->opcode, 0, 5));
20598 TCGv_i32 shiftx = tcg_const_i32(extract32(ctx->opcode, 7, 4)
20599 << 1);
20600 TCGv_i32 stripe = tcg_const_i32(extract32(ctx->opcode, 6, 1));
20602 gen_load_gpr(t0, rs);
20603 gen_helper_rotx(cpu_gpr[rt], t0, shift, shiftx, stripe);
20604 tcg_temp_free(t0);
20606 tcg_temp_free_i32(shift);
20607 tcg_temp_free_i32(shiftx);
20608 tcg_temp_free_i32(stripe);
20610 break;
20611 case NM_P_INS:
20612 switch (((ctx->opcode >> 10) & 2) |
20613 (extract32(ctx->opcode, 5, 1))) {
20614 case NM_INS:
20615 check_nms(ctx);
20616 gen_bitops(ctx, OPC_INS, rt, rs, extract32(ctx->opcode, 0, 5),
20617 extract32(ctx->opcode, 6, 5));
20618 break;
20619 default:
20620 gen_reserved_instruction(ctx);
20621 break;
20623 break;
20624 case NM_P_EXT:
20625 switch (((ctx->opcode >> 10) & 2) |
20626 (extract32(ctx->opcode, 5, 1))) {
20627 case NM_EXT:
20628 check_nms(ctx);
20629 gen_bitops(ctx, OPC_EXT, rt, rs, extract32(ctx->opcode, 0, 5),
20630 extract32(ctx->opcode, 6, 5));
20631 break;
20632 default:
20633 gen_reserved_instruction(ctx);
20634 break;
20636 break;
20637 default:
20638 gen_reserved_instruction(ctx);
20639 break;
20641 break;
20642 case NM_POOL32F:
20643 gen_pool32f_nanomips_insn(ctx);
20644 break;
20645 case NM_POOL32S:
20646 break;
20647 case NM_P_LUI:
20648 switch (extract32(ctx->opcode, 1, 1)) {
20649 case NM_LUI:
20650 if (rt != 0) {
20651 tcg_gen_movi_tl(cpu_gpr[rt],
20652 sextract32(ctx->opcode, 0, 1) << 31 |
20653 extract32(ctx->opcode, 2, 10) << 21 |
20654 extract32(ctx->opcode, 12, 9) << 12);
20656 break;
20657 case NM_ALUIPC:
20658 if (rt != 0) {
20659 offset = sextract32(ctx->opcode, 0, 1) << 31 |
20660 extract32(ctx->opcode, 2, 10) << 21 |
20661 extract32(ctx->opcode, 12, 9) << 12;
20662 target_long addr;
20663 addr = ~0xFFF & addr_add(ctx, ctx->base.pc_next + 4, offset);
20664 tcg_gen_movi_tl(cpu_gpr[rt], addr);
20666 break;
20668 break;
20669 case NM_P_GP_BH:
20671 uint32_t u = extract32(ctx->opcode, 0, 18);
20673 switch (extract32(ctx->opcode, 18, 3)) {
20674 case NM_LBGP:
20675 gen_ld(ctx, OPC_LB, rt, 28, u);
20676 break;
20677 case NM_SBGP:
20678 gen_st(ctx, OPC_SB, rt, 28, u);
20679 break;
20680 case NM_LBUGP:
20681 gen_ld(ctx, OPC_LBU, rt, 28, u);
20682 break;
20683 case NM_ADDIUGP_B:
20684 if (rt != 0) {
20685 gen_op_addr_addi(ctx, cpu_gpr[rt], cpu_gpr[28], u);
20687 break;
20688 case NM_P_GP_LH:
20689 u &= ~1;
20690 switch (ctx->opcode & 1) {
20691 case NM_LHGP:
20692 gen_ld(ctx, OPC_LH, rt, 28, u);
20693 break;
20694 case NM_LHUGP:
20695 gen_ld(ctx, OPC_LHU, rt, 28, u);
20696 break;
20698 break;
20699 case NM_P_GP_SH:
20700 u &= ~1;
20701 switch (ctx->opcode & 1) {
20702 case NM_SHGP:
20703 gen_st(ctx, OPC_SH, rt, 28, u);
20704 break;
20705 default:
20706 gen_reserved_instruction(ctx);
20707 break;
20709 break;
20710 case NM_P_GP_CP1:
20711 u &= ~0x3;
20712 switch (ctx->opcode & 0x3) {
20713 case NM_LWC1GP:
20714 gen_cop1_ldst(ctx, OPC_LWC1, rt, 28, u);
20715 break;
20716 case NM_LDC1GP:
20717 gen_cop1_ldst(ctx, OPC_LDC1, rt, 28, u);
20718 break;
20719 case NM_SWC1GP:
20720 gen_cop1_ldst(ctx, OPC_SWC1, rt, 28, u);
20721 break;
20722 case NM_SDC1GP:
20723 gen_cop1_ldst(ctx, OPC_SDC1, rt, 28, u);
20724 break;
20726 break;
20727 default:
20728 gen_reserved_instruction(ctx);
20729 break;
20732 break;
20733 case NM_P_LS_U12:
20735 uint32_t u = extract32(ctx->opcode, 0, 12);
20737 switch (extract32(ctx->opcode, 12, 4)) {
20738 case NM_P_PREFU12:
20739 if (rt == 31) {
20740 /* SYNCI */
20742 * Break the TB to be able to sync copied instructions
20743 * immediately.
20745 ctx->base.is_jmp = DISAS_STOP;
20746 } else {
20747 /* PREF */
20748 /* Treat as NOP. */
20750 break;
20751 case NM_LB:
20752 gen_ld(ctx, OPC_LB, rt, rs, u);
20753 break;
20754 case NM_LH:
20755 gen_ld(ctx, OPC_LH, rt, rs, u);
20756 break;
20757 case NM_LW:
20758 gen_ld(ctx, OPC_LW, rt, rs, u);
20759 break;
20760 case NM_LBU:
20761 gen_ld(ctx, OPC_LBU, rt, rs, u);
20762 break;
20763 case NM_LHU:
20764 gen_ld(ctx, OPC_LHU, rt, rs, u);
20765 break;
20766 case NM_SB:
20767 gen_st(ctx, OPC_SB, rt, rs, u);
20768 break;
20769 case NM_SH:
20770 gen_st(ctx, OPC_SH, rt, rs, u);
20771 break;
20772 case NM_SW:
20773 gen_st(ctx, OPC_SW, rt, rs, u);
20774 break;
20775 case NM_LWC1:
20776 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, u);
20777 break;
20778 case NM_LDC1:
20779 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, u);
20780 break;
20781 case NM_SWC1:
20782 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, u);
20783 break;
20784 case NM_SDC1:
20785 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, u);
20786 break;
20787 default:
20788 gen_reserved_instruction(ctx);
20789 break;
20792 break;
20793 case NM_P_LS_S9:
20795 int32_t s = (sextract32(ctx->opcode, 15, 1) << 8) |
20796 extract32(ctx->opcode, 0, 8);
20798 switch (extract32(ctx->opcode, 8, 3)) {
20799 case NM_P_LS_S0:
20800 switch (extract32(ctx->opcode, 11, 4)) {
20801 case NM_LBS9:
20802 gen_ld(ctx, OPC_LB, rt, rs, s);
20803 break;
20804 case NM_LHS9:
20805 gen_ld(ctx, OPC_LH, rt, rs, s);
20806 break;
20807 case NM_LWS9:
20808 gen_ld(ctx, OPC_LW, rt, rs, s);
20809 break;
20810 case NM_LBUS9:
20811 gen_ld(ctx, OPC_LBU, rt, rs, s);
20812 break;
20813 case NM_LHUS9:
20814 gen_ld(ctx, OPC_LHU, rt, rs, s);
20815 break;
20816 case NM_SBS9:
20817 gen_st(ctx, OPC_SB, rt, rs, s);
20818 break;
20819 case NM_SHS9:
20820 gen_st(ctx, OPC_SH, rt, rs, s);
20821 break;
20822 case NM_SWS9:
20823 gen_st(ctx, OPC_SW, rt, rs, s);
20824 break;
20825 case NM_LWC1S9:
20826 gen_cop1_ldst(ctx, OPC_LWC1, rt, rs, s);
20827 break;
20828 case NM_LDC1S9:
20829 gen_cop1_ldst(ctx, OPC_LDC1, rt, rs, s);
20830 break;
20831 case NM_SWC1S9:
20832 gen_cop1_ldst(ctx, OPC_SWC1, rt, rs, s);
20833 break;
20834 case NM_SDC1S9:
20835 gen_cop1_ldst(ctx, OPC_SDC1, rt, rs, s);
20836 break;
20837 case NM_P_PREFS9:
20838 if (rt == 31) {
20839 /* SYNCI */
20841 * Break the TB to be able to sync copied instructions
20842 * immediately.
20844 ctx->base.is_jmp = DISAS_STOP;
20845 } else {
20846 /* PREF */
20847 /* Treat as NOP. */
20849 break;
20850 default:
20851 gen_reserved_instruction(ctx);
20852 break;
20854 break;
20855 case NM_P_LS_S1:
20856 switch (extract32(ctx->opcode, 11, 4)) {
20857 case NM_UALH:
20858 case NM_UASH:
20859 check_nms(ctx);
20861 TCGv t0 = tcg_temp_new();
20862 TCGv t1 = tcg_temp_new();
20864 gen_base_offset_addr(ctx, t0, rs, s);
20866 switch (extract32(ctx->opcode, 11, 4)) {
20867 case NM_UALH:
20868 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW |
20869 MO_UNALN);
20870 gen_store_gpr(t0, rt);
20871 break;
20872 case NM_UASH:
20873 gen_load_gpr(t1, rt);
20874 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW |
20875 MO_UNALN);
20876 break;
20878 tcg_temp_free(t0);
20879 tcg_temp_free(t1);
20881 break;
20882 case NM_P_LL:
20883 switch (ctx->opcode & 0x03) {
20884 case NM_LL:
20885 gen_ld(ctx, OPC_LL, rt, rs, s);
20886 break;
20887 case NM_LLWP:
20888 check_xnp(ctx);
20889 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20890 break;
20892 break;
20893 case NM_P_SC:
20894 switch (ctx->opcode & 0x03) {
20895 case NM_SC:
20896 gen_st_cond(ctx, rt, rs, s, MO_TESL, false);
20897 break;
20898 case NM_SCWP:
20899 check_xnp(ctx);
20900 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
20901 false);
20902 break;
20904 break;
20905 case NM_CACHE:
20906 check_cp0_enabled(ctx);
20907 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
20908 gen_cache_operation(ctx, rt, rs, s);
20910 break;
20912 break;
20913 case NM_P_LS_E0:
20914 switch (extract32(ctx->opcode, 11, 4)) {
20915 case NM_LBE:
20916 check_eva(ctx);
20917 check_cp0_enabled(ctx);
20918 gen_ld(ctx, OPC_LBE, rt, rs, s);
20919 break;
20920 case NM_SBE:
20921 check_eva(ctx);
20922 check_cp0_enabled(ctx);
20923 gen_st(ctx, OPC_SBE, rt, rs, s);
20924 break;
20925 case NM_LBUE:
20926 check_eva(ctx);
20927 check_cp0_enabled(ctx);
20928 gen_ld(ctx, OPC_LBUE, rt, rs, s);
20929 break;
20930 case NM_P_PREFE:
20931 if (rt == 31) {
20932 /* case NM_SYNCIE */
20933 check_eva(ctx);
20934 check_cp0_enabled(ctx);
20936 * Break the TB to be able to sync copied instructions
20937 * immediately.
20939 ctx->base.is_jmp = DISAS_STOP;
20940 } else {
20941 /* case NM_PREFE */
20942 check_eva(ctx);
20943 check_cp0_enabled(ctx);
20944 /* Treat as NOP. */
20946 break;
20947 case NM_LHE:
20948 check_eva(ctx);
20949 check_cp0_enabled(ctx);
20950 gen_ld(ctx, OPC_LHE, rt, rs, s);
20951 break;
20952 case NM_SHE:
20953 check_eva(ctx);
20954 check_cp0_enabled(ctx);
20955 gen_st(ctx, OPC_SHE, rt, rs, s);
20956 break;
20957 case NM_LHUE:
20958 check_eva(ctx);
20959 check_cp0_enabled(ctx);
20960 gen_ld(ctx, OPC_LHUE, rt, rs, s);
20961 break;
20962 case NM_CACHEE:
20963 check_eva(ctx);
20964 check_cp0_enabled(ctx);
20965 check_nms_dl_il_sl_tl_l2c(ctx);
20966 gen_cache_operation(ctx, rt, rs, s);
20967 break;
20968 case NM_LWE:
20969 check_eva(ctx);
20970 check_cp0_enabled(ctx);
20971 gen_ld(ctx, OPC_LWE, rt, rs, s);
20972 break;
20973 case NM_SWE:
20974 check_eva(ctx);
20975 check_cp0_enabled(ctx);
20976 gen_st(ctx, OPC_SWE, rt, rs, s);
20977 break;
20978 case NM_P_LLE:
20979 switch (extract32(ctx->opcode, 2, 2)) {
20980 case NM_LLE:
20981 check_xnp(ctx);
20982 check_eva(ctx);
20983 check_cp0_enabled(ctx);
20984 gen_ld(ctx, OPC_LLE, rt, rs, s);
20985 break;
20986 case NM_LLWPE:
20987 check_xnp(ctx);
20988 check_eva(ctx);
20989 check_cp0_enabled(ctx);
20990 gen_llwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5));
20991 break;
20992 default:
20993 gen_reserved_instruction(ctx);
20994 break;
20996 break;
20997 case NM_P_SCE:
20998 switch (extract32(ctx->opcode, 2, 2)) {
20999 case NM_SCE:
21000 check_xnp(ctx);
21001 check_eva(ctx);
21002 check_cp0_enabled(ctx);
21003 gen_st_cond(ctx, rt, rs, s, MO_TESL, true);
21004 break;
21005 case NM_SCWPE:
21006 check_xnp(ctx);
21007 check_eva(ctx);
21008 check_cp0_enabled(ctx);
21009 gen_scwp(ctx, rs, 0, rt, extract32(ctx->opcode, 3, 5),
21010 true);
21011 break;
21012 default:
21013 gen_reserved_instruction(ctx);
21014 break;
21016 break;
21018 break;
21019 case NM_P_LS_WM:
21020 case NM_P_LS_UAWM:
21021 check_nms(ctx);
21023 int count = extract32(ctx->opcode, 12, 3);
21024 int counter = 0;
21026 offset = sextract32(ctx->opcode, 15, 1) << 8 |
21027 extract32(ctx->opcode, 0, 8);
21028 TCGv va = tcg_temp_new();
21029 TCGv t1 = tcg_temp_new();
21030 MemOp memop = (extract32(ctx->opcode, 8, 3)) ==
21031 NM_P_LS_UAWM ? MO_UNALN : 0;
21033 count = (count == 0) ? 8 : count;
21034 while (counter != count) {
21035 int this_rt = ((rt + counter) & 0x1f) | (rt & 0x10);
21036 int this_offset = offset + (counter << 2);
21038 gen_base_offset_addr(ctx, va, rs, this_offset);
21040 switch (extract32(ctx->opcode, 11, 1)) {
21041 case NM_LWM:
21042 tcg_gen_qemu_ld_tl(t1, va, ctx->mem_idx,
21043 memop | MO_TESL);
21044 gen_store_gpr(t1, this_rt);
21045 if ((this_rt == rs) &&
21046 (counter != (count - 1))) {
21047 /* UNPREDICTABLE */
21049 break;
21050 case NM_SWM:
21051 this_rt = (rt == 0) ? 0 : this_rt;
21052 gen_load_gpr(t1, this_rt);
21053 tcg_gen_qemu_st_tl(t1, va, ctx->mem_idx,
21054 memop | MO_TEUL);
21055 break;
21057 counter++;
21059 tcg_temp_free(va);
21060 tcg_temp_free(t1);
21062 break;
21063 default:
21064 gen_reserved_instruction(ctx);
21065 break;
21068 break;
21069 case NM_MOVE_BALC:
21070 check_nms(ctx);
21072 TCGv t0 = tcg_temp_new();
21073 int32_t s = sextract32(ctx->opcode, 0, 1) << 21 |
21074 extract32(ctx->opcode, 1, 20) << 1;
21075 rd = (extract32(ctx->opcode, 24, 1)) == 0 ? 4 : 5;
21076 rt = decode_gpr_gpr4_zero(extract32(ctx->opcode, 25, 1) << 3 |
21077 extract32(ctx->opcode, 21, 3));
21078 gen_load_gpr(t0, rt);
21079 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21080 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21081 tcg_temp_free(t0);
21083 break;
21084 case NM_P_BAL:
21086 int32_t s = sextract32(ctx->opcode, 0, 1) << 25 |
21087 extract32(ctx->opcode, 1, 24) << 1;
21089 if ((extract32(ctx->opcode, 25, 1)) == 0) {
21090 /* BC */
21091 gen_compute_branch_nm(ctx, OPC_BEQ, 4, 0, 0, s);
21092 } else {
21093 /* BALC */
21094 gen_compute_branch_nm(ctx, OPC_BGEZAL, 4, 0, 0, s);
21097 break;
21098 case NM_P_J:
21099 switch (extract32(ctx->opcode, 12, 4)) {
21100 case NM_JALRC:
21101 case NM_JALRC_HB:
21102 gen_compute_branch_nm(ctx, OPC_JALR, 4, rs, rt, 0);
21103 break;
21104 case NM_P_BALRSC:
21105 gen_compute_nanomips_pbalrsc_branch(ctx, rs, rt);
21106 break;
21107 default:
21108 gen_reserved_instruction(ctx);
21109 break;
21111 break;
21112 case NM_P_BR1:
21114 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21115 extract32(ctx->opcode, 1, 13) << 1;
21116 switch (extract32(ctx->opcode, 14, 2)) {
21117 case NM_BEQC:
21118 check_nms(ctx);
21119 gen_compute_branch_nm(ctx, OPC_BEQ, 4, rs, rt, s);
21120 break;
21121 case NM_P_BR3A:
21122 s = sextract32(ctx->opcode, 0, 1) << 14 |
21123 extract32(ctx->opcode, 1, 13) << 1;
21124 check_cp1_enabled(ctx);
21125 switch (extract32(ctx->opcode, 16, 5)) {
21126 case NM_BC1EQZC:
21127 gen_compute_branch_cp1_nm(ctx, OPC_BC1EQZ, rt, s);
21128 break;
21129 case NM_BC1NEZC:
21130 gen_compute_branch_cp1_nm(ctx, OPC_BC1NEZ, rt, s);
21131 break;
21132 case NM_BPOSGE32C:
21133 check_dsp_r3(ctx);
21135 int32_t imm = extract32(ctx->opcode, 1, 13) |
21136 extract32(ctx->opcode, 0, 1) << 13;
21138 gen_compute_branch_nm(ctx, OPC_BPOSGE32, 4, -1, -2,
21139 imm << 1);
21141 break;
21142 default:
21143 gen_reserved_instruction(ctx);
21144 break;
21146 break;
21147 case NM_BGEC:
21148 if (rs == rt) {
21149 gen_compute_compact_branch_nm(ctx, OPC_BC, rs, rt, s);
21150 } else {
21151 gen_compute_compact_branch_nm(ctx, OPC_BGEC, rs, rt, s);
21153 break;
21154 case NM_BGEUC:
21155 if (rs == rt || rt == 0) {
21156 gen_compute_compact_branch_nm(ctx, OPC_BC, 0, 0, s);
21157 } else if (rs == 0) {
21158 gen_compute_compact_branch_nm(ctx, OPC_BEQZC, rt, 0, s);
21159 } else {
21160 gen_compute_compact_branch_nm(ctx, OPC_BGEUC, rs, rt, s);
21162 break;
21165 break;
21166 case NM_P_BR2:
21168 int32_t s = sextract32(ctx->opcode, 0, 1) << 14 |
21169 extract32(ctx->opcode, 1, 13) << 1;
21170 switch (extract32(ctx->opcode, 14, 2)) {
21171 case NM_BNEC:
21172 check_nms(ctx);
21173 gen_compute_branch_nm(ctx, OPC_BNE, 4, rs, rt, s);
21174 break;
21175 case NM_BLTC:
21176 if (rs != 0 && rt != 0 && rs == rt) {
21177 /* NOP */
21178 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21179 } else {
21180 gen_compute_compact_branch_nm(ctx, OPC_BLTC, rs, rt, s);
21182 break;
21183 case NM_BLTUC:
21184 if (rs == 0 || rs == rt) {
21185 /* NOP */
21186 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
21187 } else {
21188 gen_compute_compact_branch_nm(ctx, OPC_BLTUC, rs, rt, s);
21190 break;
21191 default:
21192 gen_reserved_instruction(ctx);
21193 break;
21196 break;
21197 case NM_P_BRI:
21199 int32_t s = sextract32(ctx->opcode, 0, 1) << 11 |
21200 extract32(ctx->opcode, 1, 10) << 1;
21201 uint32_t u = extract32(ctx->opcode, 11, 7);
21203 gen_compute_imm_branch(ctx, extract32(ctx->opcode, 18, 3),
21204 rt, u, s);
21206 break;
21207 default:
21208 gen_reserved_instruction(ctx);
21209 break;
21211 return 4;
21214 static int decode_nanomips_opc(CPUMIPSState *env, DisasContext *ctx)
21216 uint32_t op;
21217 int rt = decode_gpr_gpr3(NANOMIPS_EXTRACT_RT3(ctx->opcode));
21218 int rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21219 int rd = decode_gpr_gpr3(NANOMIPS_EXTRACT_RD3(ctx->opcode));
21220 int offset;
21221 int imm;
21223 /* make sure instructions are on a halfword boundary */
21224 if (ctx->base.pc_next & 0x1) {
21225 TCGv tmp = tcg_const_tl(ctx->base.pc_next);
21226 tcg_gen_st_tl(tmp, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
21227 tcg_temp_free(tmp);
21228 generate_exception_end(ctx, EXCP_AdEL);
21229 return 2;
21232 op = extract32(ctx->opcode, 10, 6);
21233 switch (op) {
21234 case NM_P16_MV:
21235 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21236 if (rt != 0) {
21237 /* MOVE */
21238 rs = NANOMIPS_EXTRACT_RS5(ctx->opcode);
21239 gen_arith(ctx, OPC_ADDU, rt, rs, 0);
21240 } else {
21241 /* P16.RI */
21242 switch (extract32(ctx->opcode, 3, 2)) {
21243 case NM_P16_SYSCALL:
21244 if (extract32(ctx->opcode, 2, 1) == 0) {
21245 generate_exception_end(ctx, EXCP_SYSCALL);
21246 } else {
21247 gen_reserved_instruction(ctx);
21249 break;
21250 case NM_BREAK16:
21251 generate_exception_end(ctx, EXCP_BREAK);
21252 break;
21253 case NM_SDBBP16:
21254 if (is_uhi(extract32(ctx->opcode, 0, 3))) {
21255 gen_helper_do_semihosting(cpu_env);
21256 } else {
21257 if (ctx->hflags & MIPS_HFLAG_SBRI) {
21258 gen_reserved_instruction(ctx);
21259 } else {
21260 generate_exception_end(ctx, EXCP_DBp);
21263 break;
21264 default:
21265 gen_reserved_instruction(ctx);
21266 break;
21269 break;
21270 case NM_P16_SHIFT:
21272 int shift = extract32(ctx->opcode, 0, 3);
21273 uint32_t opc = 0;
21274 shift = (shift == 0) ? 8 : shift;
21276 switch (extract32(ctx->opcode, 3, 1)) {
21277 case NM_SLL16:
21278 opc = OPC_SLL;
21279 break;
21280 case NM_SRL16:
21281 opc = OPC_SRL;
21282 break;
21284 gen_shift_imm(ctx, opc, rt, rs, shift);
21286 break;
21287 case NM_P16C:
21288 switch (ctx->opcode & 1) {
21289 case NM_POOL16C_0:
21290 gen_pool16c_nanomips_insn(ctx);
21291 break;
21292 case NM_LWXS16:
21293 gen_ldxs(ctx, rt, rs, rd);
21294 break;
21296 break;
21297 case NM_P16_A1:
21298 switch (extract32(ctx->opcode, 6, 1)) {
21299 case NM_ADDIUR1SP:
21300 imm = extract32(ctx->opcode, 0, 6) << 2;
21301 gen_arith_imm(ctx, OPC_ADDIU, rt, 29, imm);
21302 break;
21303 default:
21304 gen_reserved_instruction(ctx);
21305 break;
21307 break;
21308 case NM_P16_A2:
21309 switch (extract32(ctx->opcode, 3, 1)) {
21310 case NM_ADDIUR2:
21311 imm = extract32(ctx->opcode, 0, 3) << 2;
21312 gen_arith_imm(ctx, OPC_ADDIU, rt, rs, imm);
21313 break;
21314 case NM_P_ADDIURS5:
21315 rt = extract32(ctx->opcode, 5, 5);
21316 if (rt != 0) {
21317 /* imm = sign_extend(s[3] . s[2:0] , from_nbits = 4) */
21318 imm = (sextract32(ctx->opcode, 4, 1) << 3) |
21319 (extract32(ctx->opcode, 0, 3));
21320 gen_arith_imm(ctx, OPC_ADDIU, rt, rt, imm);
21322 break;
21324 break;
21325 case NM_P16_ADDU:
21326 switch (ctx->opcode & 0x1) {
21327 case NM_ADDU16:
21328 gen_arith(ctx, OPC_ADDU, rd, rs, rt);
21329 break;
21330 case NM_SUBU16:
21331 gen_arith(ctx, OPC_SUBU, rd, rs, rt);
21332 break;
21334 break;
21335 case NM_P16_4X4:
21336 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21337 extract32(ctx->opcode, 5, 3);
21338 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21339 extract32(ctx->opcode, 0, 3);
21340 rt = decode_gpr_gpr4(rt);
21341 rs = decode_gpr_gpr4(rs);
21342 switch ((extract32(ctx->opcode, 7, 2) & 0x2) |
21343 (extract32(ctx->opcode, 3, 1))) {
21344 case NM_ADDU4X4:
21345 check_nms(ctx);
21346 gen_arith(ctx, OPC_ADDU, rt, rs, rt);
21347 break;
21348 case NM_MUL4X4:
21349 check_nms(ctx);
21350 gen_r6_muldiv(ctx, R6_OPC_MUL, rt, rs, rt);
21351 break;
21352 default:
21353 gen_reserved_instruction(ctx);
21354 break;
21356 break;
21357 case NM_LI16:
21359 int imm = extract32(ctx->opcode, 0, 7);
21360 imm = (imm == 0x7f ? -1 : imm);
21361 if (rt != 0) {
21362 tcg_gen_movi_tl(cpu_gpr[rt], imm);
21365 break;
21366 case NM_ANDI16:
21368 uint32_t u = extract32(ctx->opcode, 0, 4);
21369 u = (u == 12) ? 0xff :
21370 (u == 13) ? 0xffff : u;
21371 gen_logic_imm(ctx, OPC_ANDI, rt, rs, u);
21373 break;
21374 case NM_P16_LB:
21375 offset = extract32(ctx->opcode, 0, 2);
21376 switch (extract32(ctx->opcode, 2, 2)) {
21377 case NM_LB16:
21378 gen_ld(ctx, OPC_LB, rt, rs, offset);
21379 break;
21380 case NM_SB16:
21381 rt = decode_gpr_gpr3_src_store(
21382 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21383 gen_st(ctx, OPC_SB, rt, rs, offset);
21384 break;
21385 case NM_LBU16:
21386 gen_ld(ctx, OPC_LBU, rt, rs, offset);
21387 break;
21388 default:
21389 gen_reserved_instruction(ctx);
21390 break;
21392 break;
21393 case NM_P16_LH:
21394 offset = extract32(ctx->opcode, 1, 2) << 1;
21395 switch ((extract32(ctx->opcode, 3, 1) << 1) | (ctx->opcode & 1)) {
21396 case NM_LH16:
21397 gen_ld(ctx, OPC_LH, rt, rs, offset);
21398 break;
21399 case NM_SH16:
21400 rt = decode_gpr_gpr3_src_store(
21401 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21402 gen_st(ctx, OPC_SH, rt, rs, offset);
21403 break;
21404 case NM_LHU16:
21405 gen_ld(ctx, OPC_LHU, rt, rs, offset);
21406 break;
21407 default:
21408 gen_reserved_instruction(ctx);
21409 break;
21411 break;
21412 case NM_LW16:
21413 offset = extract32(ctx->opcode, 0, 4) << 2;
21414 gen_ld(ctx, OPC_LW, rt, rs, offset);
21415 break;
21416 case NM_LWSP16:
21417 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21418 offset = extract32(ctx->opcode, 0, 5) << 2;
21419 gen_ld(ctx, OPC_LW, rt, 29, offset);
21420 break;
21421 case NM_LW4X4:
21422 check_nms(ctx);
21423 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21424 extract32(ctx->opcode, 5, 3);
21425 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21426 extract32(ctx->opcode, 0, 3);
21427 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21428 (extract32(ctx->opcode, 8, 1) << 2);
21429 rt = decode_gpr_gpr4(rt);
21430 rs = decode_gpr_gpr4(rs);
21431 gen_ld(ctx, OPC_LW, rt, rs, offset);
21432 break;
21433 case NM_SW4X4:
21434 check_nms(ctx);
21435 rt = (extract32(ctx->opcode, 9, 1) << 3) |
21436 extract32(ctx->opcode, 5, 3);
21437 rs = (extract32(ctx->opcode, 4, 1) << 3) |
21438 extract32(ctx->opcode, 0, 3);
21439 offset = (extract32(ctx->opcode, 3, 1) << 3) |
21440 (extract32(ctx->opcode, 8, 1) << 2);
21441 rt = decode_gpr_gpr4_zero(rt);
21442 rs = decode_gpr_gpr4(rs);
21443 gen_st(ctx, OPC_SW, rt, rs, offset);
21444 break;
21445 case NM_LWGP16:
21446 offset = extract32(ctx->opcode, 0, 7) << 2;
21447 gen_ld(ctx, OPC_LW, rt, 28, offset);
21448 break;
21449 case NM_SWSP16:
21450 rt = NANOMIPS_EXTRACT_RD5(ctx->opcode);
21451 offset = extract32(ctx->opcode, 0, 5) << 2;
21452 gen_st(ctx, OPC_SW, rt, 29, offset);
21453 break;
21454 case NM_SW16:
21455 rt = decode_gpr_gpr3_src_store(
21456 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21457 rs = decode_gpr_gpr3(NANOMIPS_EXTRACT_RS3(ctx->opcode));
21458 offset = extract32(ctx->opcode, 0, 4) << 2;
21459 gen_st(ctx, OPC_SW, rt, rs, offset);
21460 break;
21461 case NM_SWGP16:
21462 rt = decode_gpr_gpr3_src_store(
21463 NANOMIPS_EXTRACT_RT3(ctx->opcode));
21464 offset = extract32(ctx->opcode, 0, 7) << 2;
21465 gen_st(ctx, OPC_SW, rt, 28, offset);
21466 break;
21467 case NM_BC16:
21468 gen_compute_branch_nm(ctx, OPC_BEQ, 2, 0, 0,
21469 (sextract32(ctx->opcode, 0, 1) << 10) |
21470 (extract32(ctx->opcode, 1, 9) << 1));
21471 break;
21472 case NM_BALC16:
21473 gen_compute_branch_nm(ctx, OPC_BGEZAL, 2, 0, 0,
21474 (sextract32(ctx->opcode, 0, 1) << 10) |
21475 (extract32(ctx->opcode, 1, 9) << 1));
21476 break;
21477 case NM_BEQZC16:
21478 gen_compute_branch_nm(ctx, OPC_BEQ, 2, rt, 0,
21479 (sextract32(ctx->opcode, 0, 1) << 7) |
21480 (extract32(ctx->opcode, 1, 6) << 1));
21481 break;
21482 case NM_BNEZC16:
21483 gen_compute_branch_nm(ctx, OPC_BNE, 2, rt, 0,
21484 (sextract32(ctx->opcode, 0, 1) << 7) |
21485 (extract32(ctx->opcode, 1, 6) << 1));
21486 break;
21487 case NM_P16_BR:
21488 switch (ctx->opcode & 0xf) {
21489 case 0:
21490 /* P16.JRC */
21491 switch (extract32(ctx->opcode, 4, 1)) {
21492 case NM_JRC:
21493 gen_compute_branch_nm(ctx, OPC_JR, 2,
21494 extract32(ctx->opcode, 5, 5), 0, 0);
21495 break;
21496 case NM_JALRC16:
21497 gen_compute_branch_nm(ctx, OPC_JALR, 2,
21498 extract32(ctx->opcode, 5, 5), 31, 0);
21499 break;
21501 break;
21502 default:
21504 /* P16.BRI */
21505 uint32_t opc = extract32(ctx->opcode, 4, 3) <
21506 extract32(ctx->opcode, 7, 3) ? OPC_BEQ : OPC_BNE;
21507 gen_compute_branch_nm(ctx, opc, 2, rs, rt,
21508 extract32(ctx->opcode, 0, 4) << 1);
21510 break;
21512 break;
21513 case NM_P16_SR:
21515 int count = extract32(ctx->opcode, 0, 4);
21516 int u = extract32(ctx->opcode, 4, 4) << 4;
21518 rt = 30 + extract32(ctx->opcode, 9, 1);
21519 switch (extract32(ctx->opcode, 8, 1)) {
21520 case NM_SAVE16:
21521 gen_save(ctx, rt, count, 0, u);
21522 break;
21523 case NM_RESTORE_JRC16:
21524 gen_restore(ctx, rt, count, 0, u);
21525 gen_compute_branch_nm(ctx, OPC_JR, 2, 31, 0, 0);
21526 break;
21529 break;
21530 case NM_MOVEP:
21531 case NM_MOVEPREV:
21532 check_nms(ctx);
21534 static const int gpr2reg1[] = {4, 5, 6, 7};
21535 static const int gpr2reg2[] = {5, 6, 7, 8};
21536 int re;
21537 int rd2 = extract32(ctx->opcode, 3, 1) << 1 |
21538 extract32(ctx->opcode, 8, 1);
21539 int r1 = gpr2reg1[rd2];
21540 int r2 = gpr2reg2[rd2];
21541 int r3 = extract32(ctx->opcode, 4, 1) << 3 |
21542 extract32(ctx->opcode, 0, 3);
21543 int r4 = extract32(ctx->opcode, 9, 1) << 3 |
21544 extract32(ctx->opcode, 5, 3);
21545 TCGv t0 = tcg_temp_new();
21546 TCGv t1 = tcg_temp_new();
21547 if (op == NM_MOVEP) {
21548 rd = r1;
21549 re = r2;
21550 rs = decode_gpr_gpr4_zero(r3);
21551 rt = decode_gpr_gpr4_zero(r4);
21552 } else {
21553 rd = decode_gpr_gpr4(r3);
21554 re = decode_gpr_gpr4(r4);
21555 rs = r1;
21556 rt = r2;
21558 gen_load_gpr(t0, rs);
21559 gen_load_gpr(t1, rt);
21560 tcg_gen_mov_tl(cpu_gpr[rd], t0);
21561 tcg_gen_mov_tl(cpu_gpr[re], t1);
21562 tcg_temp_free(t0);
21563 tcg_temp_free(t1);
21565 break;
21566 default:
21567 return decode_nanomips_32_48_opc(env, ctx);
21570 return 2;
21574 /* MIPSDSP functions. */
21575 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
21576 int rd, int base, int offset)
21578 TCGv t0;
21580 check_dsp(ctx);
21581 t0 = tcg_temp_new();
21583 if (base == 0) {
21584 gen_load_gpr(t0, offset);
21585 } else if (offset == 0) {
21586 gen_load_gpr(t0, base);
21587 } else {
21588 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
21591 switch (opc) {
21592 case OPC_LBUX:
21593 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
21594 gen_store_gpr(t0, rd);
21595 break;
21596 case OPC_LHX:
21597 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
21598 gen_store_gpr(t0, rd);
21599 break;
21600 case OPC_LWX:
21601 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
21602 gen_store_gpr(t0, rd);
21603 break;
21604 #if defined(TARGET_MIPS64)
21605 case OPC_LDX:
21606 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
21607 gen_store_gpr(t0, rd);
21608 break;
21609 #endif
21611 tcg_temp_free(t0);
21614 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
21615 int ret, int v1, int v2)
21617 TCGv v1_t;
21618 TCGv v2_t;
21620 if (ret == 0) {
21621 /* Treat as NOP. */
21622 return;
21625 v1_t = tcg_temp_new();
21626 v2_t = tcg_temp_new();
21628 gen_load_gpr(v1_t, v1);
21629 gen_load_gpr(v2_t, v2);
21631 switch (op1) {
21632 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
21633 case OPC_MULT_G_2E:
21634 check_dsp_r2(ctx);
21635 switch (op2) {
21636 case OPC_ADDUH_QB:
21637 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
21638 break;
21639 case OPC_ADDUH_R_QB:
21640 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21641 break;
21642 case OPC_ADDQH_PH:
21643 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
21644 break;
21645 case OPC_ADDQH_R_PH:
21646 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21647 break;
21648 case OPC_ADDQH_W:
21649 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
21650 break;
21651 case OPC_ADDQH_R_W:
21652 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21653 break;
21654 case OPC_SUBUH_QB:
21655 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
21656 break;
21657 case OPC_SUBUH_R_QB:
21658 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
21659 break;
21660 case OPC_SUBQH_PH:
21661 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
21662 break;
21663 case OPC_SUBQH_R_PH:
21664 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
21665 break;
21666 case OPC_SUBQH_W:
21667 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
21668 break;
21669 case OPC_SUBQH_R_W:
21670 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
21671 break;
21673 break;
21674 case OPC_ABSQ_S_PH_DSP:
21675 switch (op2) {
21676 case OPC_ABSQ_S_QB:
21677 check_dsp_r2(ctx);
21678 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
21679 break;
21680 case OPC_ABSQ_S_PH:
21681 check_dsp(ctx);
21682 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
21683 break;
21684 case OPC_ABSQ_S_W:
21685 check_dsp(ctx);
21686 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
21687 break;
21688 case OPC_PRECEQ_W_PHL:
21689 check_dsp(ctx);
21690 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
21691 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21692 break;
21693 case OPC_PRECEQ_W_PHR:
21694 check_dsp(ctx);
21695 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
21696 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
21697 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
21698 break;
21699 case OPC_PRECEQU_PH_QBL:
21700 check_dsp(ctx);
21701 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
21702 break;
21703 case OPC_PRECEQU_PH_QBR:
21704 check_dsp(ctx);
21705 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
21706 break;
21707 case OPC_PRECEQU_PH_QBLA:
21708 check_dsp(ctx);
21709 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
21710 break;
21711 case OPC_PRECEQU_PH_QBRA:
21712 check_dsp(ctx);
21713 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
21714 break;
21715 case OPC_PRECEU_PH_QBL:
21716 check_dsp(ctx);
21717 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
21718 break;
21719 case OPC_PRECEU_PH_QBR:
21720 check_dsp(ctx);
21721 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
21722 break;
21723 case OPC_PRECEU_PH_QBLA:
21724 check_dsp(ctx);
21725 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
21726 break;
21727 case OPC_PRECEU_PH_QBRA:
21728 check_dsp(ctx);
21729 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
21730 break;
21732 break;
21733 case OPC_ADDU_QB_DSP:
21734 switch (op2) {
21735 case OPC_ADDQ_PH:
21736 check_dsp(ctx);
21737 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21738 break;
21739 case OPC_ADDQ_S_PH:
21740 check_dsp(ctx);
21741 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21742 break;
21743 case OPC_ADDQ_S_W:
21744 check_dsp(ctx);
21745 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21746 break;
21747 case OPC_ADDU_QB:
21748 check_dsp(ctx);
21749 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21750 break;
21751 case OPC_ADDU_S_QB:
21752 check_dsp(ctx);
21753 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21754 break;
21755 case OPC_ADDU_PH:
21756 check_dsp_r2(ctx);
21757 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21758 break;
21759 case OPC_ADDU_S_PH:
21760 check_dsp_r2(ctx);
21761 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21762 break;
21763 case OPC_SUBQ_PH:
21764 check_dsp(ctx);
21765 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21766 break;
21767 case OPC_SUBQ_S_PH:
21768 check_dsp(ctx);
21769 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21770 break;
21771 case OPC_SUBQ_S_W:
21772 check_dsp(ctx);
21773 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21774 break;
21775 case OPC_SUBU_QB:
21776 check_dsp(ctx);
21777 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21778 break;
21779 case OPC_SUBU_S_QB:
21780 check_dsp(ctx);
21781 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21782 break;
21783 case OPC_SUBU_PH:
21784 check_dsp_r2(ctx);
21785 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21786 break;
21787 case OPC_SUBU_S_PH:
21788 check_dsp_r2(ctx);
21789 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21790 break;
21791 case OPC_ADDSC:
21792 check_dsp(ctx);
21793 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21794 break;
21795 case OPC_ADDWC:
21796 check_dsp(ctx);
21797 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21798 break;
21799 case OPC_MODSUB:
21800 check_dsp(ctx);
21801 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
21802 break;
21803 case OPC_RADDU_W_QB:
21804 check_dsp(ctx);
21805 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
21806 break;
21808 break;
21809 case OPC_CMPU_EQ_QB_DSP:
21810 switch (op2) {
21811 case OPC_PRECR_QB_PH:
21812 check_dsp_r2(ctx);
21813 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21814 break;
21815 case OPC_PRECRQ_QB_PH:
21816 check_dsp(ctx);
21817 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
21818 break;
21819 case OPC_PRECR_SRA_PH_W:
21820 check_dsp_r2(ctx);
21822 TCGv_i32 sa_t = tcg_const_i32(v2);
21823 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
21824 cpu_gpr[ret]);
21825 tcg_temp_free_i32(sa_t);
21826 break;
21828 case OPC_PRECR_SRA_R_PH_W:
21829 check_dsp_r2(ctx);
21831 TCGv_i32 sa_t = tcg_const_i32(v2);
21832 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
21833 cpu_gpr[ret]);
21834 tcg_temp_free_i32(sa_t);
21835 break;
21837 case OPC_PRECRQ_PH_W:
21838 check_dsp(ctx);
21839 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
21840 break;
21841 case OPC_PRECRQ_RS_PH_W:
21842 check_dsp(ctx);
21843 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21844 break;
21845 case OPC_PRECRQU_S_QB_PH:
21846 check_dsp(ctx);
21847 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21848 break;
21850 break;
21851 #ifdef TARGET_MIPS64
21852 case OPC_ABSQ_S_QH_DSP:
21853 switch (op2) {
21854 case OPC_PRECEQ_L_PWL:
21855 check_dsp(ctx);
21856 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
21857 break;
21858 case OPC_PRECEQ_L_PWR:
21859 check_dsp(ctx);
21860 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
21861 break;
21862 case OPC_PRECEQ_PW_QHL:
21863 check_dsp(ctx);
21864 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
21865 break;
21866 case OPC_PRECEQ_PW_QHR:
21867 check_dsp(ctx);
21868 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
21869 break;
21870 case OPC_PRECEQ_PW_QHLA:
21871 check_dsp(ctx);
21872 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
21873 break;
21874 case OPC_PRECEQ_PW_QHRA:
21875 check_dsp(ctx);
21876 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
21877 break;
21878 case OPC_PRECEQU_QH_OBL:
21879 check_dsp(ctx);
21880 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
21881 break;
21882 case OPC_PRECEQU_QH_OBR:
21883 check_dsp(ctx);
21884 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
21885 break;
21886 case OPC_PRECEQU_QH_OBLA:
21887 check_dsp(ctx);
21888 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
21889 break;
21890 case OPC_PRECEQU_QH_OBRA:
21891 check_dsp(ctx);
21892 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
21893 break;
21894 case OPC_PRECEU_QH_OBL:
21895 check_dsp(ctx);
21896 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
21897 break;
21898 case OPC_PRECEU_QH_OBR:
21899 check_dsp(ctx);
21900 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
21901 break;
21902 case OPC_PRECEU_QH_OBLA:
21903 check_dsp(ctx);
21904 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
21905 break;
21906 case OPC_PRECEU_QH_OBRA:
21907 check_dsp(ctx);
21908 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
21909 break;
21910 case OPC_ABSQ_S_OB:
21911 check_dsp_r2(ctx);
21912 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
21913 break;
21914 case OPC_ABSQ_S_PW:
21915 check_dsp(ctx);
21916 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
21917 break;
21918 case OPC_ABSQ_S_QH:
21919 check_dsp(ctx);
21920 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
21921 break;
21923 break;
21924 case OPC_ADDU_OB_DSP:
21925 switch (op2) {
21926 case OPC_RADDU_L_OB:
21927 check_dsp(ctx);
21928 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
21929 break;
21930 case OPC_SUBQ_PW:
21931 check_dsp(ctx);
21932 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21933 break;
21934 case OPC_SUBQ_S_PW:
21935 check_dsp(ctx);
21936 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21937 break;
21938 case OPC_SUBQ_QH:
21939 check_dsp(ctx);
21940 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21941 break;
21942 case OPC_SUBQ_S_QH:
21943 check_dsp(ctx);
21944 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21945 break;
21946 case OPC_SUBU_OB:
21947 check_dsp(ctx);
21948 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21949 break;
21950 case OPC_SUBU_S_OB:
21951 check_dsp(ctx);
21952 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21953 break;
21954 case OPC_SUBU_QH:
21955 check_dsp_r2(ctx);
21956 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21957 break;
21958 case OPC_SUBU_S_QH:
21959 check_dsp_r2(ctx);
21960 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21961 break;
21962 case OPC_SUBUH_OB:
21963 check_dsp_r2(ctx);
21964 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
21965 break;
21966 case OPC_SUBUH_R_OB:
21967 check_dsp_r2(ctx);
21968 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
21969 break;
21970 case OPC_ADDQ_PW:
21971 check_dsp(ctx);
21972 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21973 break;
21974 case OPC_ADDQ_S_PW:
21975 check_dsp(ctx);
21976 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21977 break;
21978 case OPC_ADDQ_QH:
21979 check_dsp(ctx);
21980 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21981 break;
21982 case OPC_ADDQ_S_QH:
21983 check_dsp(ctx);
21984 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21985 break;
21986 case OPC_ADDU_OB:
21987 check_dsp(ctx);
21988 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21989 break;
21990 case OPC_ADDU_S_OB:
21991 check_dsp(ctx);
21992 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21993 break;
21994 case OPC_ADDU_QH:
21995 check_dsp_r2(ctx);
21996 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
21997 break;
21998 case OPC_ADDU_S_QH:
21999 check_dsp_r2(ctx);
22000 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22001 break;
22002 case OPC_ADDUH_OB:
22003 check_dsp_r2(ctx);
22004 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
22005 break;
22006 case OPC_ADDUH_R_OB:
22007 check_dsp_r2(ctx);
22008 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
22009 break;
22011 break;
22012 case OPC_CMPU_EQ_OB_DSP:
22013 switch (op2) {
22014 case OPC_PRECR_OB_QH:
22015 check_dsp_r2(ctx);
22016 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22017 break;
22018 case OPC_PRECR_SRA_QH_PW:
22019 check_dsp_r2(ctx);
22021 TCGv_i32 ret_t = tcg_const_i32(ret);
22022 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
22023 tcg_temp_free_i32(ret_t);
22024 break;
22026 case OPC_PRECR_SRA_R_QH_PW:
22027 check_dsp_r2(ctx);
22029 TCGv_i32 sa_v = tcg_const_i32(ret);
22030 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
22031 tcg_temp_free_i32(sa_v);
22032 break;
22034 case OPC_PRECRQ_OB_QH:
22035 check_dsp(ctx);
22036 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
22037 break;
22038 case OPC_PRECRQ_PW_L:
22039 check_dsp(ctx);
22040 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
22041 break;
22042 case OPC_PRECRQ_QH_PW:
22043 check_dsp(ctx);
22044 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
22045 break;
22046 case OPC_PRECRQ_RS_QH_PW:
22047 check_dsp(ctx);
22048 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22049 break;
22050 case OPC_PRECRQU_S_OB_QH:
22051 check_dsp(ctx);
22052 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22053 break;
22055 break;
22056 #endif
22059 tcg_temp_free(v1_t);
22060 tcg_temp_free(v2_t);
22063 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
22064 int ret, int v1, int v2)
22066 uint32_t op2;
22067 TCGv t0;
22068 TCGv v1_t;
22069 TCGv v2_t;
22071 if (ret == 0) {
22072 /* Treat as NOP. */
22073 return;
22076 t0 = tcg_temp_new();
22077 v1_t = tcg_temp_new();
22078 v2_t = tcg_temp_new();
22080 tcg_gen_movi_tl(t0, v1);
22081 gen_load_gpr(v1_t, v1);
22082 gen_load_gpr(v2_t, v2);
22084 switch (opc) {
22085 case OPC_SHLL_QB_DSP:
22087 op2 = MASK_SHLL_QB(ctx->opcode);
22088 switch (op2) {
22089 case OPC_SHLL_QB:
22090 check_dsp(ctx);
22091 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
22092 break;
22093 case OPC_SHLLV_QB:
22094 check_dsp(ctx);
22095 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22096 break;
22097 case OPC_SHLL_PH:
22098 check_dsp(ctx);
22099 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22100 break;
22101 case OPC_SHLLV_PH:
22102 check_dsp(ctx);
22103 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22104 break;
22105 case OPC_SHLL_S_PH:
22106 check_dsp(ctx);
22107 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
22108 break;
22109 case OPC_SHLLV_S_PH:
22110 check_dsp(ctx);
22111 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22112 break;
22113 case OPC_SHLL_S_W:
22114 check_dsp(ctx);
22115 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
22116 break;
22117 case OPC_SHLLV_S_W:
22118 check_dsp(ctx);
22119 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22120 break;
22121 case OPC_SHRL_QB:
22122 check_dsp(ctx);
22123 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
22124 break;
22125 case OPC_SHRLV_QB:
22126 check_dsp(ctx);
22127 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
22128 break;
22129 case OPC_SHRL_PH:
22130 check_dsp_r2(ctx);
22131 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
22132 break;
22133 case OPC_SHRLV_PH:
22134 check_dsp_r2(ctx);
22135 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
22136 break;
22137 case OPC_SHRA_QB:
22138 check_dsp_r2(ctx);
22139 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
22140 break;
22141 case OPC_SHRA_R_QB:
22142 check_dsp_r2(ctx);
22143 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
22144 break;
22145 case OPC_SHRAV_QB:
22146 check_dsp_r2(ctx);
22147 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
22148 break;
22149 case OPC_SHRAV_R_QB:
22150 check_dsp_r2(ctx);
22151 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
22152 break;
22153 case OPC_SHRA_PH:
22154 check_dsp(ctx);
22155 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
22156 break;
22157 case OPC_SHRA_R_PH:
22158 check_dsp(ctx);
22159 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
22160 break;
22161 case OPC_SHRAV_PH:
22162 check_dsp(ctx);
22163 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
22164 break;
22165 case OPC_SHRAV_R_PH:
22166 check_dsp(ctx);
22167 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
22168 break;
22169 case OPC_SHRA_R_W:
22170 check_dsp(ctx);
22171 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
22172 break;
22173 case OPC_SHRAV_R_W:
22174 check_dsp(ctx);
22175 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
22176 break;
22177 default: /* Invalid */
22178 MIPS_INVAL("MASK SHLL.QB");
22179 gen_reserved_instruction(ctx);
22180 break;
22182 break;
22184 #ifdef TARGET_MIPS64
22185 case OPC_SHLL_OB_DSP:
22186 op2 = MASK_SHLL_OB(ctx->opcode);
22187 switch (op2) {
22188 case OPC_SHLL_PW:
22189 check_dsp(ctx);
22190 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22191 break;
22192 case OPC_SHLLV_PW:
22193 check_dsp(ctx);
22194 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22195 break;
22196 case OPC_SHLL_S_PW:
22197 check_dsp(ctx);
22198 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
22199 break;
22200 case OPC_SHLLV_S_PW:
22201 check_dsp(ctx);
22202 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22203 break;
22204 case OPC_SHLL_OB:
22205 check_dsp(ctx);
22206 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
22207 break;
22208 case OPC_SHLLV_OB:
22209 check_dsp(ctx);
22210 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22211 break;
22212 case OPC_SHLL_QH:
22213 check_dsp(ctx);
22214 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22215 break;
22216 case OPC_SHLLV_QH:
22217 check_dsp(ctx);
22218 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22219 break;
22220 case OPC_SHLL_S_QH:
22221 check_dsp(ctx);
22222 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
22223 break;
22224 case OPC_SHLLV_S_QH:
22225 check_dsp(ctx);
22226 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
22227 break;
22228 case OPC_SHRA_OB:
22229 check_dsp_r2(ctx);
22230 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
22231 break;
22232 case OPC_SHRAV_OB:
22233 check_dsp_r2(ctx);
22234 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
22235 break;
22236 case OPC_SHRA_R_OB:
22237 check_dsp_r2(ctx);
22238 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
22239 break;
22240 case OPC_SHRAV_R_OB:
22241 check_dsp_r2(ctx);
22242 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
22243 break;
22244 case OPC_SHRA_PW:
22245 check_dsp(ctx);
22246 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
22247 break;
22248 case OPC_SHRAV_PW:
22249 check_dsp(ctx);
22250 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
22251 break;
22252 case OPC_SHRA_R_PW:
22253 check_dsp(ctx);
22254 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
22255 break;
22256 case OPC_SHRAV_R_PW:
22257 check_dsp(ctx);
22258 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
22259 break;
22260 case OPC_SHRA_QH:
22261 check_dsp(ctx);
22262 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
22263 break;
22264 case OPC_SHRAV_QH:
22265 check_dsp(ctx);
22266 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
22267 break;
22268 case OPC_SHRA_R_QH:
22269 check_dsp(ctx);
22270 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
22271 break;
22272 case OPC_SHRAV_R_QH:
22273 check_dsp(ctx);
22274 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
22275 break;
22276 case OPC_SHRL_OB:
22277 check_dsp(ctx);
22278 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
22279 break;
22280 case OPC_SHRLV_OB:
22281 check_dsp(ctx);
22282 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
22283 break;
22284 case OPC_SHRL_QH:
22285 check_dsp_r2(ctx);
22286 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
22287 break;
22288 case OPC_SHRLV_QH:
22289 check_dsp_r2(ctx);
22290 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
22291 break;
22292 default: /* Invalid */
22293 MIPS_INVAL("MASK SHLL.OB");
22294 gen_reserved_instruction(ctx);
22295 break;
22297 break;
22298 #endif
22301 tcg_temp_free(t0);
22302 tcg_temp_free(v1_t);
22303 tcg_temp_free(v2_t);
22306 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
22307 int ret, int v1, int v2, int check_ret)
22309 TCGv_i32 t0;
22310 TCGv v1_t;
22311 TCGv v2_t;
22313 if ((ret == 0) && (check_ret == 1)) {
22314 /* Treat as NOP. */
22315 return;
22318 t0 = tcg_temp_new_i32();
22319 v1_t = tcg_temp_new();
22320 v2_t = tcg_temp_new();
22322 tcg_gen_movi_i32(t0, ret);
22323 gen_load_gpr(v1_t, v1);
22324 gen_load_gpr(v2_t, v2);
22326 switch (op1) {
22328 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
22329 * the same mask and op1.
22331 case OPC_MULT_G_2E:
22332 check_dsp_r2(ctx);
22333 switch (op2) {
22334 case OPC_MUL_PH:
22335 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22336 break;
22337 case OPC_MUL_S_PH:
22338 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22339 break;
22340 case OPC_MULQ_S_W:
22341 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22342 break;
22343 case OPC_MULQ_RS_W:
22344 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22345 break;
22347 break;
22348 case OPC_DPA_W_PH_DSP:
22349 switch (op2) {
22350 case OPC_DPAU_H_QBL:
22351 check_dsp(ctx);
22352 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
22353 break;
22354 case OPC_DPAU_H_QBR:
22355 check_dsp(ctx);
22356 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
22357 break;
22358 case OPC_DPSU_H_QBL:
22359 check_dsp(ctx);
22360 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
22361 break;
22362 case OPC_DPSU_H_QBR:
22363 check_dsp(ctx);
22364 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
22365 break;
22366 case OPC_DPA_W_PH:
22367 check_dsp_r2(ctx);
22368 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
22369 break;
22370 case OPC_DPAX_W_PH:
22371 check_dsp_r2(ctx);
22372 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
22373 break;
22374 case OPC_DPAQ_S_W_PH:
22375 check_dsp(ctx);
22376 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22377 break;
22378 case OPC_DPAQX_S_W_PH:
22379 check_dsp_r2(ctx);
22380 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22381 break;
22382 case OPC_DPAQX_SA_W_PH:
22383 check_dsp_r2(ctx);
22384 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22385 break;
22386 case OPC_DPS_W_PH:
22387 check_dsp_r2(ctx);
22388 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
22389 break;
22390 case OPC_DPSX_W_PH:
22391 check_dsp_r2(ctx);
22392 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
22393 break;
22394 case OPC_DPSQ_S_W_PH:
22395 check_dsp(ctx);
22396 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22397 break;
22398 case OPC_DPSQX_S_W_PH:
22399 check_dsp_r2(ctx);
22400 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
22401 break;
22402 case OPC_DPSQX_SA_W_PH:
22403 check_dsp_r2(ctx);
22404 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
22405 break;
22406 case OPC_MULSAQ_S_W_PH:
22407 check_dsp(ctx);
22408 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
22409 break;
22410 case OPC_DPAQ_SA_L_W:
22411 check_dsp(ctx);
22412 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22413 break;
22414 case OPC_DPSQ_SA_L_W:
22415 check_dsp(ctx);
22416 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
22417 break;
22418 case OPC_MAQ_S_W_PHL:
22419 check_dsp(ctx);
22420 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
22421 break;
22422 case OPC_MAQ_S_W_PHR:
22423 check_dsp(ctx);
22424 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
22425 break;
22426 case OPC_MAQ_SA_W_PHL:
22427 check_dsp(ctx);
22428 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
22429 break;
22430 case OPC_MAQ_SA_W_PHR:
22431 check_dsp(ctx);
22432 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
22433 break;
22434 case OPC_MULSA_W_PH:
22435 check_dsp_r2(ctx);
22436 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
22437 break;
22439 break;
22440 #ifdef TARGET_MIPS64
22441 case OPC_DPAQ_W_QH_DSP:
22443 int ac = ret & 0x03;
22444 tcg_gen_movi_i32(t0, ac);
22446 switch (op2) {
22447 case OPC_DMADD:
22448 check_dsp(ctx);
22449 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
22450 break;
22451 case OPC_DMADDU:
22452 check_dsp(ctx);
22453 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
22454 break;
22455 case OPC_DMSUB:
22456 check_dsp(ctx);
22457 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
22458 break;
22459 case OPC_DMSUBU:
22460 check_dsp(ctx);
22461 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
22462 break;
22463 case OPC_DPA_W_QH:
22464 check_dsp_r2(ctx);
22465 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
22466 break;
22467 case OPC_DPAQ_S_W_QH:
22468 check_dsp(ctx);
22469 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22470 break;
22471 case OPC_DPAQ_SA_L_PW:
22472 check_dsp(ctx);
22473 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22474 break;
22475 case OPC_DPAU_H_OBL:
22476 check_dsp(ctx);
22477 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
22478 break;
22479 case OPC_DPAU_H_OBR:
22480 check_dsp(ctx);
22481 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
22482 break;
22483 case OPC_DPS_W_QH:
22484 check_dsp_r2(ctx);
22485 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
22486 break;
22487 case OPC_DPSQ_S_W_QH:
22488 check_dsp(ctx);
22489 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22490 break;
22491 case OPC_DPSQ_SA_L_PW:
22492 check_dsp(ctx);
22493 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
22494 break;
22495 case OPC_DPSU_H_OBL:
22496 check_dsp(ctx);
22497 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
22498 break;
22499 case OPC_DPSU_H_OBR:
22500 check_dsp(ctx);
22501 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
22502 break;
22503 case OPC_MAQ_S_L_PWL:
22504 check_dsp(ctx);
22505 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
22506 break;
22507 case OPC_MAQ_S_L_PWR:
22508 check_dsp(ctx);
22509 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
22510 break;
22511 case OPC_MAQ_S_W_QHLL:
22512 check_dsp(ctx);
22513 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
22514 break;
22515 case OPC_MAQ_SA_W_QHLL:
22516 check_dsp(ctx);
22517 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
22518 break;
22519 case OPC_MAQ_S_W_QHLR:
22520 check_dsp(ctx);
22521 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
22522 break;
22523 case OPC_MAQ_SA_W_QHLR:
22524 check_dsp(ctx);
22525 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
22526 break;
22527 case OPC_MAQ_S_W_QHRL:
22528 check_dsp(ctx);
22529 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
22530 break;
22531 case OPC_MAQ_SA_W_QHRL:
22532 check_dsp(ctx);
22533 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
22534 break;
22535 case OPC_MAQ_S_W_QHRR:
22536 check_dsp(ctx);
22537 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
22538 break;
22539 case OPC_MAQ_SA_W_QHRR:
22540 check_dsp(ctx);
22541 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
22542 break;
22543 case OPC_MULSAQ_S_L_PW:
22544 check_dsp(ctx);
22545 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
22546 break;
22547 case OPC_MULSAQ_S_W_QH:
22548 check_dsp(ctx);
22549 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
22550 break;
22553 break;
22554 #endif
22555 case OPC_ADDU_QB_DSP:
22556 switch (op2) {
22557 case OPC_MULEU_S_PH_QBL:
22558 check_dsp(ctx);
22559 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22560 break;
22561 case OPC_MULEU_S_PH_QBR:
22562 check_dsp(ctx);
22563 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22564 break;
22565 case OPC_MULQ_RS_PH:
22566 check_dsp(ctx);
22567 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22568 break;
22569 case OPC_MULEQ_S_W_PHL:
22570 check_dsp(ctx);
22571 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22572 break;
22573 case OPC_MULEQ_S_W_PHR:
22574 check_dsp(ctx);
22575 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22576 break;
22577 case OPC_MULQ_S_PH:
22578 check_dsp_r2(ctx);
22579 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22580 break;
22582 break;
22583 #ifdef TARGET_MIPS64
22584 case OPC_ADDU_OB_DSP:
22585 switch (op2) {
22586 case OPC_MULEQ_S_PW_QHL:
22587 check_dsp(ctx);
22588 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22589 break;
22590 case OPC_MULEQ_S_PW_QHR:
22591 check_dsp(ctx);
22592 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22593 break;
22594 case OPC_MULEU_S_QH_OBL:
22595 check_dsp(ctx);
22596 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22597 break;
22598 case OPC_MULEU_S_QH_OBR:
22599 check_dsp(ctx);
22600 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22601 break;
22602 case OPC_MULQ_RS_QH:
22603 check_dsp(ctx);
22604 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22605 break;
22607 break;
22608 #endif
22611 tcg_temp_free_i32(t0);
22612 tcg_temp_free(v1_t);
22613 tcg_temp_free(v2_t);
22616 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
22617 int ret, int val)
22619 int16_t imm;
22620 TCGv t0;
22621 TCGv val_t;
22623 if (ret == 0) {
22624 /* Treat as NOP. */
22625 return;
22628 t0 = tcg_temp_new();
22629 val_t = tcg_temp_new();
22630 gen_load_gpr(val_t, val);
22632 switch (op1) {
22633 case OPC_ABSQ_S_PH_DSP:
22634 switch (op2) {
22635 case OPC_BITREV:
22636 check_dsp(ctx);
22637 gen_helper_bitrev(cpu_gpr[ret], val_t);
22638 break;
22639 case OPC_REPL_QB:
22640 check_dsp(ctx);
22642 target_long result;
22643 imm = (ctx->opcode >> 16) & 0xFF;
22644 result = (uint32_t)imm << 24 |
22645 (uint32_t)imm << 16 |
22646 (uint32_t)imm << 8 |
22647 (uint32_t)imm;
22648 result = (int32_t)result;
22649 tcg_gen_movi_tl(cpu_gpr[ret], result);
22651 break;
22652 case OPC_REPLV_QB:
22653 check_dsp(ctx);
22654 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22655 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22656 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22657 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22658 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22659 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22660 break;
22661 case OPC_REPL_PH:
22662 check_dsp(ctx);
22664 imm = (ctx->opcode >> 16) & 0x03FF;
22665 imm = (int16_t)(imm << 6) >> 6;
22666 tcg_gen_movi_tl(cpu_gpr[ret], \
22667 (target_long)((int32_t)imm << 16 | \
22668 (uint16_t)imm));
22670 break;
22671 case OPC_REPLV_PH:
22672 check_dsp(ctx);
22673 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22674 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22675 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22676 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
22677 break;
22679 break;
22680 #ifdef TARGET_MIPS64
22681 case OPC_ABSQ_S_QH_DSP:
22682 switch (op2) {
22683 case OPC_REPL_OB:
22684 check_dsp(ctx);
22686 target_long temp;
22688 imm = (ctx->opcode >> 16) & 0xFF;
22689 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
22690 temp = (temp << 16) | temp;
22691 temp = (temp << 32) | temp;
22692 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22693 break;
22695 case OPC_REPL_PW:
22696 check_dsp(ctx);
22698 target_long temp;
22700 imm = (ctx->opcode >> 16) & 0x03FF;
22701 imm = (int16_t)(imm << 6) >> 6;
22702 temp = ((target_long)imm << 32) \
22703 | ((target_long)imm & 0xFFFFFFFF);
22704 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22705 break;
22707 case OPC_REPL_QH:
22708 check_dsp(ctx);
22710 target_long temp;
22712 imm = (ctx->opcode >> 16) & 0x03FF;
22713 imm = (int16_t)(imm << 6) >> 6;
22715 temp = ((uint64_t)(uint16_t)imm << 48) |
22716 ((uint64_t)(uint16_t)imm << 32) |
22717 ((uint64_t)(uint16_t)imm << 16) |
22718 (uint64_t)(uint16_t)imm;
22719 tcg_gen_movi_tl(cpu_gpr[ret], temp);
22720 break;
22722 case OPC_REPLV_OB:
22723 check_dsp(ctx);
22724 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
22725 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
22726 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22727 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22728 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22729 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22730 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22731 break;
22732 case OPC_REPLV_PW:
22733 check_dsp(ctx);
22734 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
22735 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22736 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22737 break;
22738 case OPC_REPLV_QH:
22739 check_dsp(ctx);
22740 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
22741 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
22742 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22743 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
22744 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
22745 break;
22747 break;
22748 #endif
22750 tcg_temp_free(t0);
22751 tcg_temp_free(val_t);
22754 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
22755 uint32_t op1, uint32_t op2,
22756 int ret, int v1, int v2, int check_ret)
22758 TCGv t1;
22759 TCGv v1_t;
22760 TCGv v2_t;
22762 if ((ret == 0) && (check_ret == 1)) {
22763 /* Treat as NOP. */
22764 return;
22767 t1 = tcg_temp_new();
22768 v1_t = tcg_temp_new();
22769 v2_t = tcg_temp_new();
22771 gen_load_gpr(v1_t, v1);
22772 gen_load_gpr(v2_t, v2);
22774 switch (op1) {
22775 case OPC_CMPU_EQ_QB_DSP:
22776 switch (op2) {
22777 case OPC_CMPU_EQ_QB:
22778 check_dsp(ctx);
22779 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
22780 break;
22781 case OPC_CMPU_LT_QB:
22782 check_dsp(ctx);
22783 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
22784 break;
22785 case OPC_CMPU_LE_QB:
22786 check_dsp(ctx);
22787 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
22788 break;
22789 case OPC_CMPGU_EQ_QB:
22790 check_dsp(ctx);
22791 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
22792 break;
22793 case OPC_CMPGU_LT_QB:
22794 check_dsp(ctx);
22795 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
22796 break;
22797 case OPC_CMPGU_LE_QB:
22798 check_dsp(ctx);
22799 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
22800 break;
22801 case OPC_CMPGDU_EQ_QB:
22802 check_dsp_r2(ctx);
22803 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
22804 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22805 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22806 tcg_gen_shli_tl(t1, t1, 24);
22807 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22808 break;
22809 case OPC_CMPGDU_LT_QB:
22810 check_dsp_r2(ctx);
22811 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
22812 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22813 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22814 tcg_gen_shli_tl(t1, t1, 24);
22815 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22816 break;
22817 case OPC_CMPGDU_LE_QB:
22818 check_dsp_r2(ctx);
22819 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
22820 tcg_gen_mov_tl(cpu_gpr[ret], t1);
22821 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
22822 tcg_gen_shli_tl(t1, t1, 24);
22823 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
22824 break;
22825 case OPC_CMP_EQ_PH:
22826 check_dsp(ctx);
22827 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
22828 break;
22829 case OPC_CMP_LT_PH:
22830 check_dsp(ctx);
22831 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
22832 break;
22833 case OPC_CMP_LE_PH:
22834 check_dsp(ctx);
22835 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
22836 break;
22837 case OPC_PICK_QB:
22838 check_dsp(ctx);
22839 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22840 break;
22841 case OPC_PICK_PH:
22842 check_dsp(ctx);
22843 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22844 break;
22845 case OPC_PACKRL_PH:
22846 check_dsp(ctx);
22847 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
22848 break;
22850 break;
22851 #ifdef TARGET_MIPS64
22852 case OPC_CMPU_EQ_OB_DSP:
22853 switch (op2) {
22854 case OPC_CMP_EQ_PW:
22855 check_dsp(ctx);
22856 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
22857 break;
22858 case OPC_CMP_LT_PW:
22859 check_dsp(ctx);
22860 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
22861 break;
22862 case OPC_CMP_LE_PW:
22863 check_dsp(ctx);
22864 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
22865 break;
22866 case OPC_CMP_EQ_QH:
22867 check_dsp(ctx);
22868 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
22869 break;
22870 case OPC_CMP_LT_QH:
22871 check_dsp(ctx);
22872 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
22873 break;
22874 case OPC_CMP_LE_QH:
22875 check_dsp(ctx);
22876 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
22877 break;
22878 case OPC_CMPGDU_EQ_OB:
22879 check_dsp_r2(ctx);
22880 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22881 break;
22882 case OPC_CMPGDU_LT_OB:
22883 check_dsp_r2(ctx);
22884 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22885 break;
22886 case OPC_CMPGDU_LE_OB:
22887 check_dsp_r2(ctx);
22888 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22889 break;
22890 case OPC_CMPGU_EQ_OB:
22891 check_dsp(ctx);
22892 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
22893 break;
22894 case OPC_CMPGU_LT_OB:
22895 check_dsp(ctx);
22896 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
22897 break;
22898 case OPC_CMPGU_LE_OB:
22899 check_dsp(ctx);
22900 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
22901 break;
22902 case OPC_CMPU_EQ_OB:
22903 check_dsp(ctx);
22904 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
22905 break;
22906 case OPC_CMPU_LT_OB:
22907 check_dsp(ctx);
22908 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
22909 break;
22910 case OPC_CMPU_LE_OB:
22911 check_dsp(ctx);
22912 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
22913 break;
22914 case OPC_PACKRL_PW:
22915 check_dsp(ctx);
22916 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
22917 break;
22918 case OPC_PICK_OB:
22919 check_dsp(ctx);
22920 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22921 break;
22922 case OPC_PICK_PW:
22923 check_dsp(ctx);
22924 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22925 break;
22926 case OPC_PICK_QH:
22927 check_dsp(ctx);
22928 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
22929 break;
22931 break;
22932 #endif
22935 tcg_temp_free(t1);
22936 tcg_temp_free(v1_t);
22937 tcg_temp_free(v2_t);
22940 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
22941 uint32_t op1, int rt, int rs, int sa)
22943 TCGv t0;
22945 check_dsp_r2(ctx);
22947 if (rt == 0) {
22948 /* Treat as NOP. */
22949 return;
22952 t0 = tcg_temp_new();
22953 gen_load_gpr(t0, rs);
22955 switch (op1) {
22956 case OPC_APPEND_DSP:
22957 switch (MASK_APPEND(ctx->opcode)) {
22958 case OPC_APPEND:
22959 if (sa != 0) {
22960 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
22962 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22963 break;
22964 case OPC_PREPEND:
22965 if (sa != 0) {
22966 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
22967 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
22968 tcg_gen_shli_tl(t0, t0, 32 - sa);
22969 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22971 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22972 break;
22973 case OPC_BALIGN:
22974 sa &= 3;
22975 if (sa != 0 && sa != 2) {
22976 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
22977 tcg_gen_ext32u_tl(t0, t0);
22978 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
22979 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
22981 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
22982 break;
22983 default: /* Invalid */
22984 MIPS_INVAL("MASK APPEND");
22985 gen_reserved_instruction(ctx);
22986 break;
22988 break;
22989 #ifdef TARGET_MIPS64
22990 case OPC_DAPPEND_DSP:
22991 switch (MASK_DAPPEND(ctx->opcode)) {
22992 case OPC_DAPPEND:
22993 if (sa != 0) {
22994 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
22996 break;
22997 case OPC_PREPENDD:
22998 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
22999 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
23000 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
23001 break;
23002 case OPC_PREPENDW:
23003 if (sa != 0) {
23004 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
23005 tcg_gen_shli_tl(t0, t0, 64 - sa);
23006 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23008 break;
23009 case OPC_DBALIGN:
23010 sa &= 7;
23011 if (sa != 0 && sa != 2 && sa != 4) {
23012 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
23013 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
23014 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
23016 break;
23017 default: /* Invalid */
23018 MIPS_INVAL("MASK DAPPEND");
23019 gen_reserved_instruction(ctx);
23020 break;
23022 break;
23023 #endif
23025 tcg_temp_free(t0);
23028 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
23029 int ret, int v1, int v2, int check_ret)
23032 TCGv t0;
23033 TCGv t1;
23034 TCGv v1_t;
23035 TCGv v2_t;
23036 int16_t imm;
23038 if ((ret == 0) && (check_ret == 1)) {
23039 /* Treat as NOP. */
23040 return;
23043 t0 = tcg_temp_new();
23044 t1 = tcg_temp_new();
23045 v1_t = tcg_temp_new();
23046 v2_t = tcg_temp_new();
23048 gen_load_gpr(v1_t, v1);
23049 gen_load_gpr(v2_t, v2);
23051 switch (op1) {
23052 case OPC_EXTR_W_DSP:
23053 check_dsp(ctx);
23054 switch (op2) {
23055 case OPC_EXTR_W:
23056 tcg_gen_movi_tl(t0, v2);
23057 tcg_gen_movi_tl(t1, v1);
23058 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
23059 break;
23060 case OPC_EXTR_R_W:
23061 tcg_gen_movi_tl(t0, v2);
23062 tcg_gen_movi_tl(t1, v1);
23063 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23064 break;
23065 case OPC_EXTR_RS_W:
23066 tcg_gen_movi_tl(t0, v2);
23067 tcg_gen_movi_tl(t1, v1);
23068 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23069 break;
23070 case OPC_EXTR_S_H:
23071 tcg_gen_movi_tl(t0, v2);
23072 tcg_gen_movi_tl(t1, v1);
23073 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23074 break;
23075 case OPC_EXTRV_S_H:
23076 tcg_gen_movi_tl(t0, v2);
23077 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
23078 break;
23079 case OPC_EXTRV_W:
23080 tcg_gen_movi_tl(t0, v2);
23081 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23082 break;
23083 case OPC_EXTRV_R_W:
23084 tcg_gen_movi_tl(t0, v2);
23085 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23086 break;
23087 case OPC_EXTRV_RS_W:
23088 tcg_gen_movi_tl(t0, v2);
23089 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23090 break;
23091 case OPC_EXTP:
23092 tcg_gen_movi_tl(t0, v2);
23093 tcg_gen_movi_tl(t1, v1);
23094 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
23095 break;
23096 case OPC_EXTPV:
23097 tcg_gen_movi_tl(t0, v2);
23098 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
23099 break;
23100 case OPC_EXTPDP:
23101 tcg_gen_movi_tl(t0, v2);
23102 tcg_gen_movi_tl(t1, v1);
23103 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
23104 break;
23105 case OPC_EXTPDPV:
23106 tcg_gen_movi_tl(t0, v2);
23107 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23108 break;
23109 case OPC_SHILO:
23110 imm = (ctx->opcode >> 20) & 0x3F;
23111 tcg_gen_movi_tl(t0, ret);
23112 tcg_gen_movi_tl(t1, imm);
23113 gen_helper_shilo(t0, t1, cpu_env);
23114 break;
23115 case OPC_SHILOV:
23116 tcg_gen_movi_tl(t0, ret);
23117 gen_helper_shilo(t0, v1_t, cpu_env);
23118 break;
23119 case OPC_MTHLIP:
23120 tcg_gen_movi_tl(t0, ret);
23121 gen_helper_mthlip(t0, v1_t, cpu_env);
23122 break;
23123 case OPC_WRDSP:
23124 imm = (ctx->opcode >> 11) & 0x3FF;
23125 tcg_gen_movi_tl(t0, imm);
23126 gen_helper_wrdsp(v1_t, t0, cpu_env);
23127 break;
23128 case OPC_RDDSP:
23129 imm = (ctx->opcode >> 16) & 0x03FF;
23130 tcg_gen_movi_tl(t0, imm);
23131 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
23132 break;
23134 break;
23135 #ifdef TARGET_MIPS64
23136 case OPC_DEXTR_W_DSP:
23137 check_dsp(ctx);
23138 switch (op2) {
23139 case OPC_DMTHLIP:
23140 tcg_gen_movi_tl(t0, ret);
23141 gen_helper_dmthlip(v1_t, t0, cpu_env);
23142 break;
23143 case OPC_DSHILO:
23145 int shift = (ctx->opcode >> 19) & 0x7F;
23146 int ac = (ctx->opcode >> 11) & 0x03;
23147 tcg_gen_movi_tl(t0, shift);
23148 tcg_gen_movi_tl(t1, ac);
23149 gen_helper_dshilo(t0, t1, cpu_env);
23150 break;
23152 case OPC_DSHILOV:
23154 int ac = (ctx->opcode >> 11) & 0x03;
23155 tcg_gen_movi_tl(t0, ac);
23156 gen_helper_dshilo(v1_t, t0, cpu_env);
23157 break;
23159 case OPC_DEXTP:
23160 tcg_gen_movi_tl(t0, v2);
23161 tcg_gen_movi_tl(t1, v1);
23163 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
23164 break;
23165 case OPC_DEXTPV:
23166 tcg_gen_movi_tl(t0, v2);
23167 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
23168 break;
23169 case OPC_DEXTPDP:
23170 tcg_gen_movi_tl(t0, v2);
23171 tcg_gen_movi_tl(t1, v1);
23172 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
23173 break;
23174 case OPC_DEXTPDPV:
23175 tcg_gen_movi_tl(t0, v2);
23176 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
23177 break;
23178 case OPC_DEXTR_L:
23179 tcg_gen_movi_tl(t0, v2);
23180 tcg_gen_movi_tl(t1, v1);
23181 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
23182 break;
23183 case OPC_DEXTR_R_L:
23184 tcg_gen_movi_tl(t0, v2);
23185 tcg_gen_movi_tl(t1, v1);
23186 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
23187 break;
23188 case OPC_DEXTR_RS_L:
23189 tcg_gen_movi_tl(t0, v2);
23190 tcg_gen_movi_tl(t1, v1);
23191 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
23192 break;
23193 case OPC_DEXTR_W:
23194 tcg_gen_movi_tl(t0, v2);
23195 tcg_gen_movi_tl(t1, v1);
23196 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
23197 break;
23198 case OPC_DEXTR_R_W:
23199 tcg_gen_movi_tl(t0, v2);
23200 tcg_gen_movi_tl(t1, v1);
23201 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
23202 break;
23203 case OPC_DEXTR_RS_W:
23204 tcg_gen_movi_tl(t0, v2);
23205 tcg_gen_movi_tl(t1, v1);
23206 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
23207 break;
23208 case OPC_DEXTR_S_H:
23209 tcg_gen_movi_tl(t0, v2);
23210 tcg_gen_movi_tl(t1, v1);
23211 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23212 break;
23213 case OPC_DEXTRV_S_H:
23214 tcg_gen_movi_tl(t0, v2);
23215 tcg_gen_movi_tl(t1, v1);
23216 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
23217 break;
23218 case OPC_DEXTRV_L:
23219 tcg_gen_movi_tl(t0, v2);
23220 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23221 break;
23222 case OPC_DEXTRV_R_L:
23223 tcg_gen_movi_tl(t0, v2);
23224 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23225 break;
23226 case OPC_DEXTRV_RS_L:
23227 tcg_gen_movi_tl(t0, v2);
23228 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
23229 break;
23230 case OPC_DEXTRV_W:
23231 tcg_gen_movi_tl(t0, v2);
23232 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23233 break;
23234 case OPC_DEXTRV_R_W:
23235 tcg_gen_movi_tl(t0, v2);
23236 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23237 break;
23238 case OPC_DEXTRV_RS_W:
23239 tcg_gen_movi_tl(t0, v2);
23240 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
23241 break;
23243 break;
23244 #endif
23247 tcg_temp_free(t0);
23248 tcg_temp_free(t1);
23249 tcg_temp_free(v1_t);
23250 tcg_temp_free(v2_t);
23253 /* End MIPSDSP functions. */
23255 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
23257 int rs, rt, rd, sa;
23258 uint32_t op1, op2;
23260 rs = (ctx->opcode >> 21) & 0x1f;
23261 rt = (ctx->opcode >> 16) & 0x1f;
23262 rd = (ctx->opcode >> 11) & 0x1f;
23263 sa = (ctx->opcode >> 6) & 0x1f;
23265 op1 = MASK_SPECIAL(ctx->opcode);
23266 switch (op1) {
23267 case OPC_MULT:
23268 case OPC_MULTU:
23269 case OPC_DIV:
23270 case OPC_DIVU:
23271 op2 = MASK_R6_MULDIV(ctx->opcode);
23272 switch (op2) {
23273 case R6_OPC_MUL:
23274 case R6_OPC_MUH:
23275 case R6_OPC_MULU:
23276 case R6_OPC_MUHU:
23277 case R6_OPC_DIV:
23278 case R6_OPC_MOD:
23279 case R6_OPC_DIVU:
23280 case R6_OPC_MODU:
23281 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23282 break;
23283 default:
23284 MIPS_INVAL("special_r6 muldiv");
23285 gen_reserved_instruction(ctx);
23286 break;
23288 break;
23289 case OPC_SELEQZ:
23290 case OPC_SELNEZ:
23291 gen_cond_move(ctx, op1, rd, rs, rt);
23292 break;
23293 case R6_OPC_CLO:
23294 case R6_OPC_CLZ:
23295 if (rt == 0 && sa == 1) {
23297 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23298 * We need additionally to check other fields.
23300 gen_cl(ctx, op1, rd, rs);
23301 } else {
23302 gen_reserved_instruction(ctx);
23304 break;
23305 case R6_OPC_SDBBP:
23306 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23307 gen_helper_do_semihosting(cpu_env);
23308 } else {
23309 if (ctx->hflags & MIPS_HFLAG_SBRI) {
23310 gen_reserved_instruction(ctx);
23311 } else {
23312 generate_exception_end(ctx, EXCP_DBp);
23315 break;
23316 #if defined(TARGET_MIPS64)
23317 case R6_OPC_DCLO:
23318 case R6_OPC_DCLZ:
23319 if (rt == 0 && sa == 1) {
23321 * Major opcode and function field is shared with preR6 MFHI/MTHI.
23322 * We need additionally to check other fields.
23324 check_mips_64(ctx);
23325 gen_cl(ctx, op1, rd, rs);
23326 } else {
23327 gen_reserved_instruction(ctx);
23329 break;
23330 case OPC_DMULT:
23331 case OPC_DMULTU:
23332 case OPC_DDIV:
23333 case OPC_DDIVU:
23335 op2 = MASK_R6_MULDIV(ctx->opcode);
23336 switch (op2) {
23337 case R6_OPC_DMUL:
23338 case R6_OPC_DMUH:
23339 case R6_OPC_DMULU:
23340 case R6_OPC_DMUHU:
23341 case R6_OPC_DDIV:
23342 case R6_OPC_DMOD:
23343 case R6_OPC_DDIVU:
23344 case R6_OPC_DMODU:
23345 check_mips_64(ctx);
23346 gen_r6_muldiv(ctx, op2, rd, rs, rt);
23347 break;
23348 default:
23349 MIPS_INVAL("special_r6 muldiv");
23350 gen_reserved_instruction(ctx);
23351 break;
23353 break;
23354 #endif
23355 default: /* Invalid */
23356 MIPS_INVAL("special_r6");
23357 gen_reserved_instruction(ctx);
23358 break;
23362 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
23364 int rs = extract32(ctx->opcode, 21, 5);
23365 int rt = extract32(ctx->opcode, 16, 5);
23366 int rd = extract32(ctx->opcode, 11, 5);
23367 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
23369 switch (op1) {
23370 case OPC_MOVN: /* Conditional move */
23371 case OPC_MOVZ:
23372 gen_cond_move(ctx, op1, rd, rs, rt);
23373 break;
23374 case OPC_MFHI: /* Move from HI/LO */
23375 case OPC_MFLO:
23376 gen_HILO(ctx, op1, 0, rd);
23377 break;
23378 case OPC_MTHI:
23379 case OPC_MTLO: /* Move to HI/LO */
23380 gen_HILO(ctx, op1, 0, rs);
23381 break;
23382 case OPC_MULT:
23383 case OPC_MULTU:
23384 gen_mul_txx9(ctx, op1, rd, rs, rt);
23385 break;
23386 case OPC_DIV:
23387 case OPC_DIVU:
23388 gen_muldiv(ctx, op1, 0, rs, rt);
23389 break;
23390 #if defined(TARGET_MIPS64)
23391 case OPC_DMULT:
23392 case OPC_DMULTU:
23393 case OPC_DDIV:
23394 case OPC_DDIVU:
23395 check_insn_opc_user_only(ctx, INSN_R5900);
23396 gen_muldiv(ctx, op1, 0, rs, rt);
23397 break;
23398 #endif
23399 case OPC_JR:
23400 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
23401 break;
23402 default: /* Invalid */
23403 MIPS_INVAL("special_tx79");
23404 gen_reserved_instruction(ctx);
23405 break;
23409 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
23411 int rs, rt, rd, sa;
23412 uint32_t op1;
23414 rs = (ctx->opcode >> 21) & 0x1f;
23415 rt = (ctx->opcode >> 16) & 0x1f;
23416 rd = (ctx->opcode >> 11) & 0x1f;
23417 sa = (ctx->opcode >> 6) & 0x1f;
23419 op1 = MASK_SPECIAL(ctx->opcode);
23420 switch (op1) {
23421 case OPC_MOVN: /* Conditional move */
23422 case OPC_MOVZ:
23423 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
23424 INSN_LOONGSON2E | INSN_LOONGSON2F);
23425 gen_cond_move(ctx, op1, rd, rs, rt);
23426 break;
23427 case OPC_MFHI: /* Move from HI/LO */
23428 case OPC_MFLO:
23429 gen_HILO(ctx, op1, rs & 3, rd);
23430 break;
23431 case OPC_MTHI:
23432 case OPC_MTLO: /* Move to HI/LO */
23433 gen_HILO(ctx, op1, rd & 3, rs);
23434 break;
23435 case OPC_MOVCI:
23436 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
23437 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
23438 check_cp1_enabled(ctx);
23439 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
23440 (ctx->opcode >> 16) & 1);
23441 } else {
23442 generate_exception_err(ctx, EXCP_CpU, 1);
23444 break;
23445 case OPC_MULT:
23446 case OPC_MULTU:
23447 if (sa) {
23448 check_insn(ctx, INSN_VR54XX);
23449 op1 = MASK_MUL_VR54XX(ctx->opcode);
23450 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
23451 } else {
23452 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23454 break;
23455 case OPC_DIV:
23456 case OPC_DIVU:
23457 gen_muldiv(ctx, op1, 0, rs, rt);
23458 break;
23459 #if defined(TARGET_MIPS64)
23460 case OPC_DMULT:
23461 case OPC_DMULTU:
23462 case OPC_DDIV:
23463 case OPC_DDIVU:
23464 check_insn(ctx, ISA_MIPS3);
23465 check_mips_64(ctx);
23466 gen_muldiv(ctx, op1, 0, rs, rt);
23467 break;
23468 #endif
23469 case OPC_JR:
23470 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23471 break;
23472 case OPC_SPIM:
23473 #ifdef MIPS_STRICT_STANDARD
23474 MIPS_INVAL("SPIM");
23475 gen_reserved_instruction(ctx);
23476 #else
23477 /* Implemented as RI exception for now. */
23478 MIPS_INVAL("spim (unofficial)");
23479 gen_reserved_instruction(ctx);
23480 #endif
23481 break;
23482 default: /* Invalid */
23483 MIPS_INVAL("special_legacy");
23484 gen_reserved_instruction(ctx);
23485 break;
23489 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
23491 int rs, rt, rd, sa;
23492 uint32_t op1;
23494 rs = (ctx->opcode >> 21) & 0x1f;
23495 rt = (ctx->opcode >> 16) & 0x1f;
23496 rd = (ctx->opcode >> 11) & 0x1f;
23497 sa = (ctx->opcode >> 6) & 0x1f;
23499 op1 = MASK_SPECIAL(ctx->opcode);
23500 switch (op1) {
23501 case OPC_SLL: /* Shift with immediate */
23502 if (sa == 5 && rd == 0 &&
23503 rs == 0 && rt == 0) { /* PAUSE */
23504 if ((ctx->insn_flags & ISA_MIPS_R6) &&
23505 (ctx->hflags & MIPS_HFLAG_BMASK)) {
23506 gen_reserved_instruction(ctx);
23507 break;
23510 /* Fallthrough */
23511 case OPC_SRA:
23512 gen_shift_imm(ctx, op1, rd, rt, sa);
23513 break;
23514 case OPC_SRL:
23515 switch ((ctx->opcode >> 21) & 0x1f) {
23516 case 1:
23517 /* rotr is decoded as srl on non-R2 CPUs */
23518 if (ctx->insn_flags & ISA_MIPS_R2) {
23519 op1 = OPC_ROTR;
23521 /* Fallthrough */
23522 case 0:
23523 gen_shift_imm(ctx, op1, rd, rt, sa);
23524 break;
23525 default:
23526 gen_reserved_instruction(ctx);
23527 break;
23529 break;
23530 case OPC_ADD:
23531 case OPC_ADDU:
23532 case OPC_SUB:
23533 case OPC_SUBU:
23534 gen_arith(ctx, op1, rd, rs, rt);
23535 break;
23536 case OPC_SLLV: /* Shifts */
23537 case OPC_SRAV:
23538 gen_shift(ctx, op1, rd, rs, rt);
23539 break;
23540 case OPC_SRLV:
23541 switch ((ctx->opcode >> 6) & 0x1f) {
23542 case 1:
23543 /* rotrv is decoded as srlv on non-R2 CPUs */
23544 if (ctx->insn_flags & ISA_MIPS_R2) {
23545 op1 = OPC_ROTRV;
23547 /* Fallthrough */
23548 case 0:
23549 gen_shift(ctx, op1, rd, rs, rt);
23550 break;
23551 default:
23552 gen_reserved_instruction(ctx);
23553 break;
23555 break;
23556 case OPC_SLT: /* Set on less than */
23557 case OPC_SLTU:
23558 gen_slt(ctx, op1, rd, rs, rt);
23559 break;
23560 case OPC_AND: /* Logic*/
23561 case OPC_OR:
23562 case OPC_NOR:
23563 case OPC_XOR:
23564 gen_logic(ctx, op1, rd, rs, rt);
23565 break;
23566 case OPC_JALR:
23567 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
23568 break;
23569 case OPC_TGE: /* Traps */
23570 case OPC_TGEU:
23571 case OPC_TLT:
23572 case OPC_TLTU:
23573 case OPC_TEQ:
23574 case OPC_TNE:
23575 check_insn(ctx, ISA_MIPS2);
23576 gen_trap(ctx, op1, rs, rt, -1);
23577 break;
23578 case OPC_PMON:
23579 /* Pmon entry point, also R4010 selsl */
23580 #ifdef MIPS_STRICT_STANDARD
23581 MIPS_INVAL("PMON / selsl");
23582 gen_reserved_instruction(ctx);
23583 #else
23584 gen_helper_0e0i(pmon, sa);
23585 #endif
23586 break;
23587 case OPC_SYSCALL:
23588 generate_exception_end(ctx, EXCP_SYSCALL);
23589 break;
23590 case OPC_BREAK:
23591 generate_exception_end(ctx, EXCP_BREAK);
23592 break;
23593 case OPC_SYNC:
23594 check_insn(ctx, ISA_MIPS2);
23595 gen_sync(extract32(ctx->opcode, 6, 5));
23596 break;
23598 #if defined(TARGET_MIPS64)
23599 /* MIPS64 specific opcodes */
23600 case OPC_DSLL:
23601 case OPC_DSRA:
23602 case OPC_DSLL32:
23603 case OPC_DSRA32:
23604 check_insn(ctx, ISA_MIPS3);
23605 check_mips_64(ctx);
23606 gen_shift_imm(ctx, op1, rd, rt, sa);
23607 break;
23608 case OPC_DSRL:
23609 switch ((ctx->opcode >> 21) & 0x1f) {
23610 case 1:
23611 /* drotr is decoded as dsrl on non-R2 CPUs */
23612 if (ctx->insn_flags & ISA_MIPS_R2) {
23613 op1 = OPC_DROTR;
23615 /* Fallthrough */
23616 case 0:
23617 check_insn(ctx, ISA_MIPS3);
23618 check_mips_64(ctx);
23619 gen_shift_imm(ctx, op1, rd, rt, sa);
23620 break;
23621 default:
23622 gen_reserved_instruction(ctx);
23623 break;
23625 break;
23626 case OPC_DSRL32:
23627 switch ((ctx->opcode >> 21) & 0x1f) {
23628 case 1:
23629 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
23630 if (ctx->insn_flags & ISA_MIPS_R2) {
23631 op1 = OPC_DROTR32;
23633 /* Fallthrough */
23634 case 0:
23635 check_insn(ctx, ISA_MIPS3);
23636 check_mips_64(ctx);
23637 gen_shift_imm(ctx, op1, rd, rt, sa);
23638 break;
23639 default:
23640 gen_reserved_instruction(ctx);
23641 break;
23643 break;
23644 case OPC_DADD:
23645 case OPC_DADDU:
23646 case OPC_DSUB:
23647 case OPC_DSUBU:
23648 check_insn(ctx, ISA_MIPS3);
23649 check_mips_64(ctx);
23650 gen_arith(ctx, op1, rd, rs, rt);
23651 break;
23652 case OPC_DSLLV:
23653 case OPC_DSRAV:
23654 check_insn(ctx, ISA_MIPS3);
23655 check_mips_64(ctx);
23656 gen_shift(ctx, op1, rd, rs, rt);
23657 break;
23658 case OPC_DSRLV:
23659 switch ((ctx->opcode >> 6) & 0x1f) {
23660 case 1:
23661 /* drotrv is decoded as dsrlv on non-R2 CPUs */
23662 if (ctx->insn_flags & ISA_MIPS_R2) {
23663 op1 = OPC_DROTRV;
23665 /* Fallthrough */
23666 case 0:
23667 check_insn(ctx, ISA_MIPS3);
23668 check_mips_64(ctx);
23669 gen_shift(ctx, op1, rd, rs, rt);
23670 break;
23671 default:
23672 gen_reserved_instruction(ctx);
23673 break;
23675 break;
23676 #endif
23677 default:
23678 if (ctx->insn_flags & ISA_MIPS_R6) {
23679 decode_opc_special_r6(env, ctx);
23680 } else if (ctx->insn_flags & INSN_R5900) {
23681 decode_opc_special_tx79(env, ctx);
23682 } else {
23683 decode_opc_special_legacy(env, ctx);
23689 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
23691 int rs, rt, rd;
23692 uint32_t op1;
23694 rs = (ctx->opcode >> 21) & 0x1f;
23695 rt = (ctx->opcode >> 16) & 0x1f;
23696 rd = (ctx->opcode >> 11) & 0x1f;
23698 op1 = MASK_SPECIAL2(ctx->opcode);
23699 switch (op1) {
23700 case OPC_MADD: /* Multiply and add/sub */
23701 case OPC_MADDU:
23702 case OPC_MSUB:
23703 case OPC_MSUBU:
23704 check_insn(ctx, ISA_MIPS_R1);
23705 gen_muldiv(ctx, op1, rd & 3, rs, rt);
23706 break;
23707 case OPC_MUL:
23708 gen_arith(ctx, op1, rd, rs, rt);
23709 break;
23710 case OPC_DIV_G_2F:
23711 case OPC_DIVU_G_2F:
23712 case OPC_MULT_G_2F:
23713 case OPC_MULTU_G_2F:
23714 case OPC_MOD_G_2F:
23715 case OPC_MODU_G_2F:
23716 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23717 gen_loongson_integer(ctx, op1, rd, rs, rt);
23718 break;
23719 case OPC_CLO:
23720 case OPC_CLZ:
23721 check_insn(ctx, ISA_MIPS_R1);
23722 gen_cl(ctx, op1, rd, rs);
23723 break;
23724 case OPC_SDBBP:
23725 if (is_uhi(extract32(ctx->opcode, 6, 20))) {
23726 gen_helper_do_semihosting(cpu_env);
23727 } else {
23729 * XXX: not clear which exception should be raised
23730 * when in debug mode...
23732 check_insn(ctx, ISA_MIPS_R1);
23733 generate_exception_end(ctx, EXCP_DBp);
23735 break;
23736 #if defined(TARGET_MIPS64)
23737 case OPC_DCLO:
23738 case OPC_DCLZ:
23739 check_insn(ctx, ISA_MIPS_R1);
23740 check_mips_64(ctx);
23741 gen_cl(ctx, op1, rd, rs);
23742 break;
23743 case OPC_DMULT_G_2F:
23744 case OPC_DMULTU_G_2F:
23745 case OPC_DDIV_G_2F:
23746 case OPC_DDIVU_G_2F:
23747 case OPC_DMOD_G_2F:
23748 case OPC_DMODU_G_2F:
23749 check_insn(ctx, INSN_LOONGSON2F | ASE_LEXT);
23750 gen_loongson_integer(ctx, op1, rd, rs, rt);
23751 break;
23752 #endif
23753 default: /* Invalid */
23754 MIPS_INVAL("special2_legacy");
23755 gen_reserved_instruction(ctx);
23756 break;
23760 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
23762 int rs, rt, rd, sa;
23763 uint32_t op1, op2;
23764 int16_t imm;
23766 rs = (ctx->opcode >> 21) & 0x1f;
23767 rt = (ctx->opcode >> 16) & 0x1f;
23768 rd = (ctx->opcode >> 11) & 0x1f;
23769 sa = (ctx->opcode >> 6) & 0x1f;
23770 imm = (int16_t)ctx->opcode >> 7;
23772 op1 = MASK_SPECIAL3(ctx->opcode);
23773 switch (op1) {
23774 case R6_OPC_PREF:
23775 if (rt >= 24) {
23776 /* hint codes 24-31 are reserved and signal RI */
23777 gen_reserved_instruction(ctx);
23779 /* Treat as NOP. */
23780 break;
23781 case R6_OPC_CACHE:
23782 check_cp0_enabled(ctx);
23783 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
23784 gen_cache_operation(ctx, rt, rs, imm);
23786 break;
23787 case R6_OPC_SC:
23788 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
23789 break;
23790 case R6_OPC_LL:
23791 gen_ld(ctx, op1, rt, rs, imm);
23792 break;
23793 case OPC_BSHFL:
23795 if (rd == 0) {
23796 /* Treat as NOP. */
23797 break;
23799 op2 = MASK_BSHFL(ctx->opcode);
23800 switch (op2) {
23801 case OPC_ALIGN:
23802 case OPC_ALIGN_1:
23803 case OPC_ALIGN_2:
23804 case OPC_ALIGN_3:
23805 gen_align(ctx, 32, rd, rs, rt, sa & 3);
23806 break;
23807 case OPC_BITSWAP:
23808 gen_bitswap(ctx, op2, rd, rt);
23809 break;
23812 break;
23813 #ifndef CONFIG_USER_ONLY
23814 case OPC_GINV:
23815 if (unlikely(ctx->gi <= 1)) {
23816 gen_reserved_instruction(ctx);
23818 check_cp0_enabled(ctx);
23819 switch ((ctx->opcode >> 6) & 3) {
23820 case 0: /* GINVI */
23821 /* Treat as NOP. */
23822 break;
23823 case 2: /* GINVT */
23824 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
23825 break;
23826 default:
23827 gen_reserved_instruction(ctx);
23828 break;
23830 break;
23831 #endif
23832 #if defined(TARGET_MIPS64)
23833 case R6_OPC_SCD:
23834 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
23835 break;
23836 case R6_OPC_LLD:
23837 gen_ld(ctx, op1, rt, rs, imm);
23838 break;
23839 case OPC_DBSHFL:
23840 check_mips_64(ctx);
23842 if (rd == 0) {
23843 /* Treat as NOP. */
23844 break;
23846 op2 = MASK_DBSHFL(ctx->opcode);
23847 switch (op2) {
23848 case OPC_DALIGN:
23849 case OPC_DALIGN_1:
23850 case OPC_DALIGN_2:
23851 case OPC_DALIGN_3:
23852 case OPC_DALIGN_4:
23853 case OPC_DALIGN_5:
23854 case OPC_DALIGN_6:
23855 case OPC_DALIGN_7:
23856 gen_align(ctx, 64, rd, rs, rt, sa & 7);
23857 break;
23858 case OPC_DBITSWAP:
23859 gen_bitswap(ctx, op2, rd, rt);
23860 break;
23864 break;
23865 #endif
23866 default: /* Invalid */
23867 MIPS_INVAL("special3_r6");
23868 gen_reserved_instruction(ctx);
23869 break;
23873 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
23875 int rs, rt, rd;
23876 uint32_t op1, op2;
23878 rs = (ctx->opcode >> 21) & 0x1f;
23879 rt = (ctx->opcode >> 16) & 0x1f;
23880 rd = (ctx->opcode >> 11) & 0x1f;
23882 op1 = MASK_SPECIAL3(ctx->opcode);
23883 switch (op1) {
23884 case OPC_DIV_G_2E:
23885 case OPC_DIVU_G_2E:
23886 case OPC_MOD_G_2E:
23887 case OPC_MODU_G_2E:
23888 case OPC_MULT_G_2E:
23889 case OPC_MULTU_G_2E:
23891 * OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
23892 * the same mask and op1.
23894 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MULT_G_2E)) {
23895 op2 = MASK_ADDUH_QB(ctx->opcode);
23896 switch (op2) {
23897 case OPC_ADDUH_QB:
23898 case OPC_ADDUH_R_QB:
23899 case OPC_ADDQH_PH:
23900 case OPC_ADDQH_R_PH:
23901 case OPC_ADDQH_W:
23902 case OPC_ADDQH_R_W:
23903 case OPC_SUBUH_QB:
23904 case OPC_SUBUH_R_QB:
23905 case OPC_SUBQH_PH:
23906 case OPC_SUBQH_R_PH:
23907 case OPC_SUBQH_W:
23908 case OPC_SUBQH_R_W:
23909 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23910 break;
23911 case OPC_MUL_PH:
23912 case OPC_MUL_S_PH:
23913 case OPC_MULQ_S_W:
23914 case OPC_MULQ_RS_W:
23915 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
23916 break;
23917 default:
23918 MIPS_INVAL("MASK ADDUH.QB");
23919 gen_reserved_instruction(ctx);
23920 break;
23922 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
23923 gen_loongson_integer(ctx, op1, rd, rs, rt);
23924 } else {
23925 gen_reserved_instruction(ctx);
23927 break;
23928 case OPC_LX_DSP:
23929 op2 = MASK_LX(ctx->opcode);
23930 switch (op2) {
23931 #if defined(TARGET_MIPS64)
23932 case OPC_LDX:
23933 #endif
23934 case OPC_LBUX:
23935 case OPC_LHX:
23936 case OPC_LWX:
23937 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
23938 break;
23939 default: /* Invalid */
23940 MIPS_INVAL("MASK LX");
23941 gen_reserved_instruction(ctx);
23942 break;
23944 break;
23945 case OPC_ABSQ_S_PH_DSP:
23946 op2 = MASK_ABSQ_S_PH(ctx->opcode);
23947 switch (op2) {
23948 case OPC_ABSQ_S_QB:
23949 case OPC_ABSQ_S_PH:
23950 case OPC_ABSQ_S_W:
23951 case OPC_PRECEQ_W_PHL:
23952 case OPC_PRECEQ_W_PHR:
23953 case OPC_PRECEQU_PH_QBL:
23954 case OPC_PRECEQU_PH_QBR:
23955 case OPC_PRECEQU_PH_QBLA:
23956 case OPC_PRECEQU_PH_QBRA:
23957 case OPC_PRECEU_PH_QBL:
23958 case OPC_PRECEU_PH_QBR:
23959 case OPC_PRECEU_PH_QBLA:
23960 case OPC_PRECEU_PH_QBRA:
23961 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23962 break;
23963 case OPC_BITREV:
23964 case OPC_REPL_QB:
23965 case OPC_REPLV_QB:
23966 case OPC_REPL_PH:
23967 case OPC_REPLV_PH:
23968 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
23969 break;
23970 default:
23971 MIPS_INVAL("MASK ABSQ_S.PH");
23972 gen_reserved_instruction(ctx);
23973 break;
23975 break;
23976 case OPC_ADDU_QB_DSP:
23977 op2 = MASK_ADDU_QB(ctx->opcode);
23978 switch (op2) {
23979 case OPC_ADDQ_PH:
23980 case OPC_ADDQ_S_PH:
23981 case OPC_ADDQ_S_W:
23982 case OPC_ADDU_QB:
23983 case OPC_ADDU_S_QB:
23984 case OPC_ADDU_PH:
23985 case OPC_ADDU_S_PH:
23986 case OPC_SUBQ_PH:
23987 case OPC_SUBQ_S_PH:
23988 case OPC_SUBQ_S_W:
23989 case OPC_SUBU_QB:
23990 case OPC_SUBU_S_QB:
23991 case OPC_SUBU_PH:
23992 case OPC_SUBU_S_PH:
23993 case OPC_ADDSC:
23994 case OPC_ADDWC:
23995 case OPC_MODSUB:
23996 case OPC_RADDU_W_QB:
23997 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
23998 break;
23999 case OPC_MULEU_S_PH_QBL:
24000 case OPC_MULEU_S_PH_QBR:
24001 case OPC_MULQ_RS_PH:
24002 case OPC_MULEQ_S_W_PHL:
24003 case OPC_MULEQ_S_W_PHR:
24004 case OPC_MULQ_S_PH:
24005 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24006 break;
24007 default: /* Invalid */
24008 MIPS_INVAL("MASK ADDU.QB");
24009 gen_reserved_instruction(ctx);
24010 break;
24013 break;
24014 case OPC_CMPU_EQ_QB_DSP:
24015 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
24016 switch (op2) {
24017 case OPC_PRECR_SRA_PH_W:
24018 case OPC_PRECR_SRA_R_PH_W:
24019 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24020 break;
24021 case OPC_PRECR_QB_PH:
24022 case OPC_PRECRQ_QB_PH:
24023 case OPC_PRECRQ_PH_W:
24024 case OPC_PRECRQ_RS_PH_W:
24025 case OPC_PRECRQU_S_QB_PH:
24026 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24027 break;
24028 case OPC_CMPU_EQ_QB:
24029 case OPC_CMPU_LT_QB:
24030 case OPC_CMPU_LE_QB:
24031 case OPC_CMP_EQ_PH:
24032 case OPC_CMP_LT_PH:
24033 case OPC_CMP_LE_PH:
24034 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24035 break;
24036 case OPC_CMPGU_EQ_QB:
24037 case OPC_CMPGU_LT_QB:
24038 case OPC_CMPGU_LE_QB:
24039 case OPC_CMPGDU_EQ_QB:
24040 case OPC_CMPGDU_LT_QB:
24041 case OPC_CMPGDU_LE_QB:
24042 case OPC_PICK_QB:
24043 case OPC_PICK_PH:
24044 case OPC_PACKRL_PH:
24045 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24046 break;
24047 default: /* Invalid */
24048 MIPS_INVAL("MASK CMPU.EQ.QB");
24049 gen_reserved_instruction(ctx);
24050 break;
24052 break;
24053 case OPC_SHLL_QB_DSP:
24054 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24055 break;
24056 case OPC_DPA_W_PH_DSP:
24057 op2 = MASK_DPA_W_PH(ctx->opcode);
24058 switch (op2) {
24059 case OPC_DPAU_H_QBL:
24060 case OPC_DPAU_H_QBR:
24061 case OPC_DPSU_H_QBL:
24062 case OPC_DPSU_H_QBR:
24063 case OPC_DPA_W_PH:
24064 case OPC_DPAX_W_PH:
24065 case OPC_DPAQ_S_W_PH:
24066 case OPC_DPAQX_S_W_PH:
24067 case OPC_DPAQX_SA_W_PH:
24068 case OPC_DPS_W_PH:
24069 case OPC_DPSX_W_PH:
24070 case OPC_DPSQ_S_W_PH:
24071 case OPC_DPSQX_S_W_PH:
24072 case OPC_DPSQX_SA_W_PH:
24073 case OPC_MULSAQ_S_W_PH:
24074 case OPC_DPAQ_SA_L_W:
24075 case OPC_DPSQ_SA_L_W:
24076 case OPC_MAQ_S_W_PHL:
24077 case OPC_MAQ_S_W_PHR:
24078 case OPC_MAQ_SA_W_PHL:
24079 case OPC_MAQ_SA_W_PHR:
24080 case OPC_MULSA_W_PH:
24081 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24082 break;
24083 default: /* Invalid */
24084 MIPS_INVAL("MASK DPAW.PH");
24085 gen_reserved_instruction(ctx);
24086 break;
24088 break;
24089 case OPC_INSV_DSP:
24090 op2 = MASK_INSV(ctx->opcode);
24091 switch (op2) {
24092 case OPC_INSV:
24093 check_dsp(ctx);
24095 TCGv t0, t1;
24097 if (rt == 0) {
24098 break;
24101 t0 = tcg_temp_new();
24102 t1 = tcg_temp_new();
24104 gen_load_gpr(t0, rt);
24105 gen_load_gpr(t1, rs);
24107 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
24109 tcg_temp_free(t0);
24110 tcg_temp_free(t1);
24111 break;
24113 default: /* Invalid */
24114 MIPS_INVAL("MASK INSV");
24115 gen_reserved_instruction(ctx);
24116 break;
24118 break;
24119 case OPC_APPEND_DSP:
24120 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24121 break;
24122 case OPC_EXTR_W_DSP:
24123 op2 = MASK_EXTR_W(ctx->opcode);
24124 switch (op2) {
24125 case OPC_EXTR_W:
24126 case OPC_EXTR_R_W:
24127 case OPC_EXTR_RS_W:
24128 case OPC_EXTR_S_H:
24129 case OPC_EXTRV_S_H:
24130 case OPC_EXTRV_W:
24131 case OPC_EXTRV_R_W:
24132 case OPC_EXTRV_RS_W:
24133 case OPC_EXTP:
24134 case OPC_EXTPV:
24135 case OPC_EXTPDP:
24136 case OPC_EXTPDPV:
24137 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24138 break;
24139 case OPC_RDDSP:
24140 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
24141 break;
24142 case OPC_SHILO:
24143 case OPC_SHILOV:
24144 case OPC_MTHLIP:
24145 case OPC_WRDSP:
24146 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24147 break;
24148 default: /* Invalid */
24149 MIPS_INVAL("MASK EXTR.W");
24150 gen_reserved_instruction(ctx);
24151 break;
24153 break;
24154 #if defined(TARGET_MIPS64)
24155 case OPC_DDIV_G_2E:
24156 case OPC_DDIVU_G_2E:
24157 case OPC_DMULT_G_2E:
24158 case OPC_DMULTU_G_2E:
24159 case OPC_DMOD_G_2E:
24160 case OPC_DMODU_G_2E:
24161 check_insn(ctx, INSN_LOONGSON2E);
24162 gen_loongson_integer(ctx, op1, rd, rs, rt);
24163 break;
24164 case OPC_ABSQ_S_QH_DSP:
24165 op2 = MASK_ABSQ_S_QH(ctx->opcode);
24166 switch (op2) {
24167 case OPC_PRECEQ_L_PWL:
24168 case OPC_PRECEQ_L_PWR:
24169 case OPC_PRECEQ_PW_QHL:
24170 case OPC_PRECEQ_PW_QHR:
24171 case OPC_PRECEQ_PW_QHLA:
24172 case OPC_PRECEQ_PW_QHRA:
24173 case OPC_PRECEQU_QH_OBL:
24174 case OPC_PRECEQU_QH_OBR:
24175 case OPC_PRECEQU_QH_OBLA:
24176 case OPC_PRECEQU_QH_OBRA:
24177 case OPC_PRECEU_QH_OBL:
24178 case OPC_PRECEU_QH_OBR:
24179 case OPC_PRECEU_QH_OBLA:
24180 case OPC_PRECEU_QH_OBRA:
24181 case OPC_ABSQ_S_OB:
24182 case OPC_ABSQ_S_PW:
24183 case OPC_ABSQ_S_QH:
24184 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24185 break;
24186 case OPC_REPL_OB:
24187 case OPC_REPL_PW:
24188 case OPC_REPL_QH:
24189 case OPC_REPLV_OB:
24190 case OPC_REPLV_PW:
24191 case OPC_REPLV_QH:
24192 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
24193 break;
24194 default: /* Invalid */
24195 MIPS_INVAL("MASK ABSQ_S.QH");
24196 gen_reserved_instruction(ctx);
24197 break;
24199 break;
24200 case OPC_ADDU_OB_DSP:
24201 op2 = MASK_ADDU_OB(ctx->opcode);
24202 switch (op2) {
24203 case OPC_RADDU_L_OB:
24204 case OPC_SUBQ_PW:
24205 case OPC_SUBQ_S_PW:
24206 case OPC_SUBQ_QH:
24207 case OPC_SUBQ_S_QH:
24208 case OPC_SUBU_OB:
24209 case OPC_SUBU_S_OB:
24210 case OPC_SUBU_QH:
24211 case OPC_SUBU_S_QH:
24212 case OPC_SUBUH_OB:
24213 case OPC_SUBUH_R_OB:
24214 case OPC_ADDQ_PW:
24215 case OPC_ADDQ_S_PW:
24216 case OPC_ADDQ_QH:
24217 case OPC_ADDQ_S_QH:
24218 case OPC_ADDU_OB:
24219 case OPC_ADDU_S_OB:
24220 case OPC_ADDU_QH:
24221 case OPC_ADDU_S_QH:
24222 case OPC_ADDUH_OB:
24223 case OPC_ADDUH_R_OB:
24224 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24225 break;
24226 case OPC_MULEQ_S_PW_QHL:
24227 case OPC_MULEQ_S_PW_QHR:
24228 case OPC_MULEU_S_QH_OBL:
24229 case OPC_MULEU_S_QH_OBR:
24230 case OPC_MULQ_RS_QH:
24231 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
24232 break;
24233 default: /* Invalid */
24234 MIPS_INVAL("MASK ADDU.OB");
24235 gen_reserved_instruction(ctx);
24236 break;
24238 break;
24239 case OPC_CMPU_EQ_OB_DSP:
24240 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
24241 switch (op2) {
24242 case OPC_PRECR_SRA_QH_PW:
24243 case OPC_PRECR_SRA_R_QH_PW:
24244 /* Return value is rt. */
24245 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
24246 break;
24247 case OPC_PRECR_OB_QH:
24248 case OPC_PRECRQ_OB_QH:
24249 case OPC_PRECRQ_PW_L:
24250 case OPC_PRECRQ_QH_PW:
24251 case OPC_PRECRQ_RS_QH_PW:
24252 case OPC_PRECRQU_S_OB_QH:
24253 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
24254 break;
24255 case OPC_CMPU_EQ_OB:
24256 case OPC_CMPU_LT_OB:
24257 case OPC_CMPU_LE_OB:
24258 case OPC_CMP_EQ_QH:
24259 case OPC_CMP_LT_QH:
24260 case OPC_CMP_LE_QH:
24261 case OPC_CMP_EQ_PW:
24262 case OPC_CMP_LT_PW:
24263 case OPC_CMP_LE_PW:
24264 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
24265 break;
24266 case OPC_CMPGDU_EQ_OB:
24267 case OPC_CMPGDU_LT_OB:
24268 case OPC_CMPGDU_LE_OB:
24269 case OPC_CMPGU_EQ_OB:
24270 case OPC_CMPGU_LT_OB:
24271 case OPC_CMPGU_LE_OB:
24272 case OPC_PACKRL_PW:
24273 case OPC_PICK_OB:
24274 case OPC_PICK_PW:
24275 case OPC_PICK_QH:
24276 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
24277 break;
24278 default: /* Invalid */
24279 MIPS_INVAL("MASK CMPU_EQ.OB");
24280 gen_reserved_instruction(ctx);
24281 break;
24283 break;
24284 case OPC_DAPPEND_DSP:
24285 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
24286 break;
24287 case OPC_DEXTR_W_DSP:
24288 op2 = MASK_DEXTR_W(ctx->opcode);
24289 switch (op2) {
24290 case OPC_DEXTP:
24291 case OPC_DEXTPDP:
24292 case OPC_DEXTPDPV:
24293 case OPC_DEXTPV:
24294 case OPC_DEXTR_L:
24295 case OPC_DEXTR_R_L:
24296 case OPC_DEXTR_RS_L:
24297 case OPC_DEXTR_W:
24298 case OPC_DEXTR_R_W:
24299 case OPC_DEXTR_RS_W:
24300 case OPC_DEXTR_S_H:
24301 case OPC_DEXTRV_L:
24302 case OPC_DEXTRV_R_L:
24303 case OPC_DEXTRV_RS_L:
24304 case OPC_DEXTRV_S_H:
24305 case OPC_DEXTRV_W:
24306 case OPC_DEXTRV_R_W:
24307 case OPC_DEXTRV_RS_W:
24308 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
24309 break;
24310 case OPC_DMTHLIP:
24311 case OPC_DSHILO:
24312 case OPC_DSHILOV:
24313 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
24314 break;
24315 default: /* Invalid */
24316 MIPS_INVAL("MASK EXTR.W");
24317 gen_reserved_instruction(ctx);
24318 break;
24320 break;
24321 case OPC_DPAQ_W_QH_DSP:
24322 op2 = MASK_DPAQ_W_QH(ctx->opcode);
24323 switch (op2) {
24324 case OPC_DPAU_H_OBL:
24325 case OPC_DPAU_H_OBR:
24326 case OPC_DPSU_H_OBL:
24327 case OPC_DPSU_H_OBR:
24328 case OPC_DPA_W_QH:
24329 case OPC_DPAQ_S_W_QH:
24330 case OPC_DPS_W_QH:
24331 case OPC_DPSQ_S_W_QH:
24332 case OPC_MULSAQ_S_W_QH:
24333 case OPC_DPAQ_SA_L_PW:
24334 case OPC_DPSQ_SA_L_PW:
24335 case OPC_MULSAQ_S_L_PW:
24336 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24337 break;
24338 case OPC_MAQ_S_W_QHLL:
24339 case OPC_MAQ_S_W_QHLR:
24340 case OPC_MAQ_S_W_QHRL:
24341 case OPC_MAQ_S_W_QHRR:
24342 case OPC_MAQ_SA_W_QHLL:
24343 case OPC_MAQ_SA_W_QHLR:
24344 case OPC_MAQ_SA_W_QHRL:
24345 case OPC_MAQ_SA_W_QHRR:
24346 case OPC_MAQ_S_L_PWL:
24347 case OPC_MAQ_S_L_PWR:
24348 case OPC_DMADD:
24349 case OPC_DMADDU:
24350 case OPC_DMSUB:
24351 case OPC_DMSUBU:
24352 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
24353 break;
24354 default: /* Invalid */
24355 MIPS_INVAL("MASK DPAQ.W.QH");
24356 gen_reserved_instruction(ctx);
24357 break;
24359 break;
24360 case OPC_DINSV_DSP:
24361 op2 = MASK_INSV(ctx->opcode);
24362 switch (op2) {
24363 case OPC_DINSV:
24365 TCGv t0, t1;
24367 check_dsp(ctx);
24369 if (rt == 0) {
24370 break;
24373 t0 = tcg_temp_new();
24374 t1 = tcg_temp_new();
24376 gen_load_gpr(t0, rt);
24377 gen_load_gpr(t1, rs);
24379 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
24381 tcg_temp_free(t0);
24382 tcg_temp_free(t1);
24383 break;
24385 default: /* Invalid */
24386 MIPS_INVAL("MASK DINSV");
24387 gen_reserved_instruction(ctx);
24388 break;
24390 break;
24391 case OPC_SHLL_OB_DSP:
24392 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
24393 break;
24394 #endif
24395 default: /* Invalid */
24396 MIPS_INVAL("special3_legacy");
24397 gen_reserved_instruction(ctx);
24398 break;
24403 #if defined(TARGET_MIPS64)
24405 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
24407 uint32_t opc = MASK_MMI(ctx->opcode);
24408 int rs = extract32(ctx->opcode, 21, 5);
24409 int rt = extract32(ctx->opcode, 16, 5);
24410 int rd = extract32(ctx->opcode, 11, 5);
24412 switch (opc) {
24413 case MMI_OPC_MULT1:
24414 case MMI_OPC_MULTU1:
24415 case MMI_OPC_MADD:
24416 case MMI_OPC_MADDU:
24417 case MMI_OPC_MADD1:
24418 case MMI_OPC_MADDU1:
24419 gen_mul_txx9(ctx, opc, rd, rs, rt);
24420 break;
24421 case MMI_OPC_DIV1:
24422 case MMI_OPC_DIVU1:
24423 gen_div1_tx79(ctx, opc, rs, rt);
24424 break;
24425 default:
24426 MIPS_INVAL("TX79 MMI class");
24427 gen_reserved_instruction(ctx);
24428 break;
24432 static void gen_mmi_lq(CPUMIPSState *env, DisasContext *ctx)
24434 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_LQ */
24437 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
24439 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
24443 * The TX79-specific instruction Store Quadword
24445 * +--------+-------+-------+------------------------+
24446 * | 011111 | base | rt | offset | SQ
24447 * +--------+-------+-------+------------------------+
24448 * 6 5 5 16
24450 * has the same opcode as the Read Hardware Register instruction
24452 * +--------+-------+-------+-------+-------+--------+
24453 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
24454 * +--------+-------+-------+-------+-------+--------+
24455 * 6 5 5 5 5 6
24457 * that is required, trapped and emulated by the Linux kernel. However, all
24458 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
24459 * offset is odd. Therefore all valid SQ instructions can execute normally.
24460 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
24461 * between SQ and RDHWR, as the Linux kernel does.
24463 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
24465 int base = extract32(ctx->opcode, 21, 5);
24466 int rt = extract32(ctx->opcode, 16, 5);
24467 int offset = extract32(ctx->opcode, 0, 16);
24469 #ifdef CONFIG_USER_ONLY
24470 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
24471 uint32_t op2 = extract32(ctx->opcode, 6, 5);
24473 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
24474 int rd = extract32(ctx->opcode, 11, 5);
24476 gen_rdhwr(ctx, rt, rd, 0);
24477 return;
24479 #endif
24481 gen_mmi_sq(ctx, base, rt, offset);
24484 #endif
24486 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
24488 int rs, rt, rd, sa;
24489 uint32_t op1, op2;
24490 int16_t imm;
24492 rs = (ctx->opcode >> 21) & 0x1f;
24493 rt = (ctx->opcode >> 16) & 0x1f;
24494 rd = (ctx->opcode >> 11) & 0x1f;
24495 sa = (ctx->opcode >> 6) & 0x1f;
24496 imm = sextract32(ctx->opcode, 7, 9);
24498 op1 = MASK_SPECIAL3(ctx->opcode);
24501 * EVA loads and stores overlap Loongson 2E instructions decoded by
24502 * decode_opc_special3_legacy(), so be careful to allow their decoding when
24503 * EVA is absent.
24505 if (ctx->eva) {
24506 switch (op1) {
24507 case OPC_LWLE:
24508 case OPC_LWRE:
24509 case OPC_LBUE:
24510 case OPC_LHUE:
24511 case OPC_LBE:
24512 case OPC_LHE:
24513 case OPC_LLE:
24514 case OPC_LWE:
24515 check_cp0_enabled(ctx);
24516 gen_ld(ctx, op1, rt, rs, imm);
24517 return;
24518 case OPC_SWLE:
24519 case OPC_SWRE:
24520 case OPC_SBE:
24521 case OPC_SHE:
24522 case OPC_SWE:
24523 check_cp0_enabled(ctx);
24524 gen_st(ctx, op1, rt, rs, imm);
24525 return;
24526 case OPC_SCE:
24527 check_cp0_enabled(ctx);
24528 gen_st_cond(ctx, rt, rs, imm, MO_TESL, true);
24529 return;
24530 case OPC_CACHEE:
24531 check_eva(ctx);
24532 check_cp0_enabled(ctx);
24533 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
24534 gen_cache_operation(ctx, rt, rs, imm);
24536 return;
24537 case OPC_PREFE:
24538 check_cp0_enabled(ctx);
24539 /* Treat as NOP. */
24540 return;
24544 switch (op1) {
24545 case OPC_EXT:
24546 case OPC_INS:
24547 check_insn(ctx, ISA_MIPS_R2);
24548 gen_bitops(ctx, op1, rt, rs, sa, rd);
24549 break;
24550 case OPC_BSHFL:
24551 op2 = MASK_BSHFL(ctx->opcode);
24552 switch (op2) {
24553 case OPC_ALIGN:
24554 case OPC_ALIGN_1:
24555 case OPC_ALIGN_2:
24556 case OPC_ALIGN_3:
24557 case OPC_BITSWAP:
24558 check_insn(ctx, ISA_MIPS_R6);
24559 decode_opc_special3_r6(env, ctx);
24560 break;
24561 default:
24562 check_insn(ctx, ISA_MIPS_R2);
24563 gen_bshfl(ctx, op2, rt, rd);
24564 break;
24566 break;
24567 #if defined(TARGET_MIPS64)
24568 case OPC_DEXTM:
24569 case OPC_DEXTU:
24570 case OPC_DEXT:
24571 case OPC_DINSM:
24572 case OPC_DINSU:
24573 case OPC_DINS:
24574 check_insn(ctx, ISA_MIPS_R2);
24575 check_mips_64(ctx);
24576 gen_bitops(ctx, op1, rt, rs, sa, rd);
24577 break;
24578 case OPC_DBSHFL:
24579 op2 = MASK_DBSHFL(ctx->opcode);
24580 switch (op2) {
24581 case OPC_DALIGN:
24582 case OPC_DALIGN_1:
24583 case OPC_DALIGN_2:
24584 case OPC_DALIGN_3:
24585 case OPC_DALIGN_4:
24586 case OPC_DALIGN_5:
24587 case OPC_DALIGN_6:
24588 case OPC_DALIGN_7:
24589 case OPC_DBITSWAP:
24590 check_insn(ctx, ISA_MIPS_R6);
24591 decode_opc_special3_r6(env, ctx);
24592 break;
24593 default:
24594 check_insn(ctx, ISA_MIPS_R2);
24595 check_mips_64(ctx);
24596 op2 = MASK_DBSHFL(ctx->opcode);
24597 gen_bshfl(ctx, op2, rt, rd);
24598 break;
24600 break;
24601 #endif
24602 case OPC_RDHWR:
24603 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
24604 break;
24605 case OPC_FORK:
24606 check_mt(ctx);
24608 TCGv t0 = tcg_temp_new();
24609 TCGv t1 = tcg_temp_new();
24611 gen_load_gpr(t0, rt);
24612 gen_load_gpr(t1, rs);
24613 gen_helper_fork(t0, t1);
24614 tcg_temp_free(t0);
24615 tcg_temp_free(t1);
24617 break;
24618 case OPC_YIELD:
24619 check_mt(ctx);
24621 TCGv t0 = tcg_temp_new();
24623 gen_load_gpr(t0, rs);
24624 gen_helper_yield(t0, cpu_env, t0);
24625 gen_store_gpr(t0, rd);
24626 tcg_temp_free(t0);
24628 break;
24629 default:
24630 if (ctx->insn_flags & ISA_MIPS_R6) {
24631 decode_opc_special3_r6(env, ctx);
24632 } else {
24633 decode_opc_special3_legacy(env, ctx);
24638 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
24640 int32_t offset;
24641 int rs, rt, rd, sa;
24642 uint32_t op, op1;
24643 int16_t imm;
24645 op = MASK_OP_MAJOR(ctx->opcode);
24646 rs = (ctx->opcode >> 21) & 0x1f;
24647 rt = (ctx->opcode >> 16) & 0x1f;
24648 rd = (ctx->opcode >> 11) & 0x1f;
24649 sa = (ctx->opcode >> 6) & 0x1f;
24650 imm = (int16_t)ctx->opcode;
24651 switch (op) {
24652 case OPC_SPECIAL:
24653 decode_opc_special(env, ctx);
24654 break;
24655 case OPC_SPECIAL2:
24656 #if defined(TARGET_MIPS64)
24657 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
24658 decode_mmi(env, ctx);
24659 break;
24661 #endif
24662 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
24663 if (MASK_SPECIAL2(ctx->opcode) == OPC_MUL) {
24664 gen_arith(ctx, OPC_MUL, rd, rs, rt);
24665 } else {
24666 decode_ase_mxu(ctx, ctx->opcode);
24668 break;
24670 decode_opc_special2_legacy(env, ctx);
24671 break;
24672 case OPC_SPECIAL3:
24673 #if defined(TARGET_MIPS64)
24674 if (ctx->insn_flags & INSN_R5900) {
24675 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
24676 } else {
24677 decode_opc_special3(env, ctx);
24679 #else
24680 decode_opc_special3(env, ctx);
24681 #endif
24682 break;
24683 case OPC_REGIMM:
24684 op1 = MASK_REGIMM(ctx->opcode);
24685 switch (op1) {
24686 case OPC_BLTZL: /* REGIMM branches */
24687 case OPC_BGEZL:
24688 case OPC_BLTZALL:
24689 case OPC_BGEZALL:
24690 check_insn(ctx, ISA_MIPS2);
24691 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24692 /* Fallthrough */
24693 case OPC_BLTZ:
24694 case OPC_BGEZ:
24695 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24696 break;
24697 case OPC_BLTZAL:
24698 case OPC_BGEZAL:
24699 if (ctx->insn_flags & ISA_MIPS_R6) {
24700 if (rs == 0) {
24701 /* OPC_NAL, OPC_BAL */
24702 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
24703 } else {
24704 gen_reserved_instruction(ctx);
24706 } else {
24707 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
24709 break;
24710 case OPC_TGEI: /* REGIMM traps */
24711 case OPC_TGEIU:
24712 case OPC_TLTI:
24713 case OPC_TLTIU:
24714 case OPC_TEQI:
24716 case OPC_TNEI:
24717 check_insn(ctx, ISA_MIPS2);
24718 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24719 gen_trap(ctx, op1, rs, -1, imm);
24720 break;
24721 case OPC_SIGRIE:
24722 check_insn(ctx, ISA_MIPS_R6);
24723 gen_reserved_instruction(ctx);
24724 break;
24725 case OPC_SYNCI:
24726 check_insn(ctx, ISA_MIPS_R2);
24728 * Break the TB to be able to sync copied instructions
24729 * immediately.
24731 ctx->base.is_jmp = DISAS_STOP;
24732 break;
24733 case OPC_BPOSGE32: /* MIPS DSP branch */
24734 #if defined(TARGET_MIPS64)
24735 case OPC_BPOSGE64:
24736 #endif
24737 check_dsp(ctx);
24738 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
24739 break;
24740 #if defined(TARGET_MIPS64)
24741 case OPC_DAHI:
24742 check_insn(ctx, ISA_MIPS_R6);
24743 check_mips_64(ctx);
24744 if (rs != 0) {
24745 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
24747 break;
24748 case OPC_DATI:
24749 check_insn(ctx, ISA_MIPS_R6);
24750 check_mips_64(ctx);
24751 if (rs != 0) {
24752 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
24754 break;
24755 #endif
24756 default: /* Invalid */
24757 MIPS_INVAL("regimm");
24758 gen_reserved_instruction(ctx);
24759 break;
24761 break;
24762 case OPC_CP0:
24763 check_cp0_enabled(ctx);
24764 op1 = MASK_CP0(ctx->opcode);
24765 switch (op1) {
24766 case OPC_MFC0:
24767 case OPC_MTC0:
24768 case OPC_MFTR:
24769 case OPC_MTTR:
24770 case OPC_MFHC0:
24771 case OPC_MTHC0:
24772 #if defined(TARGET_MIPS64)
24773 case OPC_DMFC0:
24774 case OPC_DMTC0:
24775 #endif
24776 #ifndef CONFIG_USER_ONLY
24777 gen_cp0(env, ctx, op1, rt, rd);
24778 #endif /* !CONFIG_USER_ONLY */
24779 break;
24780 case OPC_C0:
24781 case OPC_C0_1:
24782 case OPC_C0_2:
24783 case OPC_C0_3:
24784 case OPC_C0_4:
24785 case OPC_C0_5:
24786 case OPC_C0_6:
24787 case OPC_C0_7:
24788 case OPC_C0_8:
24789 case OPC_C0_9:
24790 case OPC_C0_A:
24791 case OPC_C0_B:
24792 case OPC_C0_C:
24793 case OPC_C0_D:
24794 case OPC_C0_E:
24795 case OPC_C0_F:
24796 #ifndef CONFIG_USER_ONLY
24797 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
24798 #endif /* !CONFIG_USER_ONLY */
24799 break;
24800 case OPC_MFMC0:
24801 #ifndef CONFIG_USER_ONLY
24803 uint32_t op2;
24804 TCGv t0 = tcg_temp_new();
24806 op2 = MASK_MFMC0(ctx->opcode);
24807 switch (op2) {
24808 case OPC_DMT:
24809 check_cp0_mt(ctx);
24810 gen_helper_dmt(t0);
24811 gen_store_gpr(t0, rt);
24812 break;
24813 case OPC_EMT:
24814 check_cp0_mt(ctx);
24815 gen_helper_emt(t0);
24816 gen_store_gpr(t0, rt);
24817 break;
24818 case OPC_DVPE:
24819 check_cp0_mt(ctx);
24820 gen_helper_dvpe(t0, cpu_env);
24821 gen_store_gpr(t0, rt);
24822 break;
24823 case OPC_EVPE:
24824 check_cp0_mt(ctx);
24825 gen_helper_evpe(t0, cpu_env);
24826 gen_store_gpr(t0, rt);
24827 break;
24828 case OPC_DVP:
24829 check_insn(ctx, ISA_MIPS_R6);
24830 if (ctx->vp) {
24831 gen_helper_dvp(t0, cpu_env);
24832 gen_store_gpr(t0, rt);
24834 break;
24835 case OPC_EVP:
24836 check_insn(ctx, ISA_MIPS_R6);
24837 if (ctx->vp) {
24838 gen_helper_evp(t0, cpu_env);
24839 gen_store_gpr(t0, rt);
24841 break;
24842 case OPC_DI:
24843 check_insn(ctx, ISA_MIPS_R2);
24844 save_cpu_state(ctx, 1);
24845 gen_helper_di(t0, cpu_env);
24846 gen_store_gpr(t0, rt);
24848 * Stop translation as we may have switched
24849 * the execution mode.
24851 ctx->base.is_jmp = DISAS_STOP;
24852 break;
24853 case OPC_EI:
24854 check_insn(ctx, ISA_MIPS_R2);
24855 save_cpu_state(ctx, 1);
24856 gen_helper_ei(t0, cpu_env);
24857 gen_store_gpr(t0, rt);
24859 * DISAS_STOP isn't sufficient, we need to ensure we break
24860 * out of translated code to check for pending interrupts.
24862 gen_save_pc(ctx->base.pc_next + 4);
24863 ctx->base.is_jmp = DISAS_EXIT;
24864 break;
24865 default: /* Invalid */
24866 MIPS_INVAL("mfmc0");
24867 gen_reserved_instruction(ctx);
24868 break;
24870 tcg_temp_free(t0);
24872 #endif /* !CONFIG_USER_ONLY */
24873 break;
24874 case OPC_RDPGPR:
24875 check_insn(ctx, ISA_MIPS_R2);
24876 gen_load_srsgpr(rt, rd);
24877 break;
24878 case OPC_WRPGPR:
24879 check_insn(ctx, ISA_MIPS_R2);
24880 gen_store_srsgpr(rt, rd);
24881 break;
24882 default:
24883 MIPS_INVAL("cp0");
24884 gen_reserved_instruction(ctx);
24885 break;
24887 break;
24888 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
24889 if (ctx->insn_flags & ISA_MIPS_R6) {
24890 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
24891 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24892 } else {
24893 /* OPC_ADDI */
24894 /* Arithmetic with immediate opcode */
24895 gen_arith_imm(ctx, op, rt, rs, imm);
24897 break;
24898 case OPC_ADDIU:
24899 gen_arith_imm(ctx, op, rt, rs, imm);
24900 break;
24901 case OPC_SLTI: /* Set on less than with immediate opcode */
24902 case OPC_SLTIU:
24903 gen_slt_imm(ctx, op, rt, rs, imm);
24904 break;
24905 case OPC_ANDI: /* Arithmetic with immediate opcode */
24906 case OPC_LUI: /* OPC_AUI */
24907 case OPC_ORI:
24908 case OPC_XORI:
24909 gen_logic_imm(ctx, op, rt, rs, imm);
24910 break;
24911 case OPC_J: /* Jump */
24912 case OPC_JAL:
24913 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
24914 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
24915 break;
24916 /* Branch */
24917 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
24918 if (ctx->insn_flags & ISA_MIPS_R6) {
24919 if (rt == 0) {
24920 gen_reserved_instruction(ctx);
24921 break;
24923 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
24924 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24925 } else {
24926 /* OPC_BLEZL */
24927 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24929 break;
24930 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
24931 if (ctx->insn_flags & ISA_MIPS_R6) {
24932 if (rt == 0) {
24933 gen_reserved_instruction(ctx);
24934 break;
24936 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
24937 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24938 } else {
24939 /* OPC_BGTZL */
24940 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24942 break;
24943 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
24944 if (rt == 0) {
24945 /* OPC_BLEZ */
24946 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24947 } else {
24948 check_insn(ctx, ISA_MIPS_R6);
24949 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
24950 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24952 break;
24953 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
24954 if (rt == 0) {
24955 /* OPC_BGTZ */
24956 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24957 } else {
24958 check_insn(ctx, ISA_MIPS_R6);
24959 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
24960 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
24962 break;
24963 case OPC_BEQL:
24964 case OPC_BNEL:
24965 check_insn(ctx, ISA_MIPS2);
24966 check_insn_opc_removed(ctx, ISA_MIPS_R6);
24967 /* Fallthrough */
24968 case OPC_BEQ:
24969 case OPC_BNE:
24970 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
24971 break;
24972 case OPC_LL: /* Load and stores */
24973 check_insn(ctx, ISA_MIPS2);
24974 if (ctx->insn_flags & INSN_R5900) {
24975 check_insn_opc_user_only(ctx, INSN_R5900);
24977 /* Fallthrough */
24978 case OPC_LWL:
24979 case OPC_LWR:
24980 case OPC_LB:
24981 case OPC_LH:
24982 case OPC_LW:
24983 case OPC_LWPC:
24984 case OPC_LBU:
24985 case OPC_LHU:
24986 gen_ld(ctx, op, rt, rs, imm);
24987 break;
24988 case OPC_SWL:
24989 case OPC_SWR:
24990 case OPC_SB:
24991 case OPC_SH:
24992 case OPC_SW:
24993 gen_st(ctx, op, rt, rs, imm);
24994 break;
24995 case OPC_SC:
24996 check_insn(ctx, ISA_MIPS2);
24997 if (ctx->insn_flags & INSN_R5900) {
24998 check_insn_opc_user_only(ctx, INSN_R5900);
25000 gen_st_cond(ctx, rt, rs, imm, MO_TESL, false);
25001 break;
25002 case OPC_CACHE:
25003 check_cp0_enabled(ctx);
25004 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
25005 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
25006 gen_cache_operation(ctx, rt, rs, imm);
25008 /* Treat as NOP. */
25009 break;
25010 case OPC_PREF:
25011 if (ctx->insn_flags & INSN_R5900) {
25012 /* Treat as NOP. */
25013 } else {
25014 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
25015 /* Treat as NOP. */
25017 break;
25019 /* Floating point (COP1). */
25020 case OPC_LWC1:
25021 case OPC_LDC1:
25022 case OPC_SWC1:
25023 case OPC_SDC1:
25024 gen_cop1_ldst(ctx, op, rt, rs, imm);
25025 break;
25027 case OPC_CP1:
25028 op1 = MASK_CP1(ctx->opcode);
25030 switch (op1) {
25031 case OPC_MFHC1:
25032 case OPC_MTHC1:
25033 check_cp1_enabled(ctx);
25034 check_insn(ctx, ISA_MIPS_R2);
25035 /* fall through */
25036 case OPC_MFC1:
25037 case OPC_CFC1:
25038 case OPC_MTC1:
25039 case OPC_CTC1:
25040 check_cp1_enabled(ctx);
25041 gen_cp1(ctx, op1, rt, rd);
25042 break;
25043 #if defined(TARGET_MIPS64)
25044 case OPC_DMFC1:
25045 case OPC_DMTC1:
25046 check_cp1_enabled(ctx);
25047 check_insn(ctx, ISA_MIPS3);
25048 check_mips_64(ctx);
25049 gen_cp1(ctx, op1, rt, rd);
25050 break;
25051 #endif
25052 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
25053 check_cp1_enabled(ctx);
25054 if (ctx->insn_flags & ISA_MIPS_R6) {
25055 /* OPC_BC1EQZ */
25056 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25057 rt, imm << 2, 4);
25058 } else {
25059 /* OPC_BC1ANY2 */
25060 check_cop1x(ctx);
25061 check_insn(ctx, ASE_MIPS3D);
25062 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25063 (rt >> 2) & 0x7, imm << 2);
25065 break;
25066 case OPC_BC1NEZ:
25067 check_cp1_enabled(ctx);
25068 check_insn(ctx, ISA_MIPS_R6);
25069 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
25070 rt, imm << 2, 4);
25071 break;
25072 case OPC_BC1ANY4:
25073 check_cp1_enabled(ctx);
25074 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25075 check_cop1x(ctx);
25076 check_insn(ctx, ASE_MIPS3D);
25077 /* fall through */
25078 case OPC_BC1:
25079 check_cp1_enabled(ctx);
25080 check_insn_opc_removed(ctx, ISA_MIPS_R6);
25081 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
25082 (rt >> 2) & 0x7, imm << 2);
25083 break;
25084 case OPC_PS_FMT:
25085 check_ps(ctx);
25086 /* fall through */
25087 case OPC_S_FMT:
25088 case OPC_D_FMT:
25089 check_cp1_enabled(ctx);
25090 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25091 (imm >> 8) & 0x7);
25092 break;
25093 case OPC_W_FMT:
25094 case OPC_L_FMT:
25096 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
25097 check_cp1_enabled(ctx);
25098 if (ctx->insn_flags & ISA_MIPS_R6) {
25099 switch (r6_op) {
25100 case R6_OPC_CMP_AF_S:
25101 case R6_OPC_CMP_UN_S:
25102 case R6_OPC_CMP_EQ_S:
25103 case R6_OPC_CMP_UEQ_S:
25104 case R6_OPC_CMP_LT_S:
25105 case R6_OPC_CMP_ULT_S:
25106 case R6_OPC_CMP_LE_S:
25107 case R6_OPC_CMP_ULE_S:
25108 case R6_OPC_CMP_SAF_S:
25109 case R6_OPC_CMP_SUN_S:
25110 case R6_OPC_CMP_SEQ_S:
25111 case R6_OPC_CMP_SEUQ_S:
25112 case R6_OPC_CMP_SLT_S:
25113 case R6_OPC_CMP_SULT_S:
25114 case R6_OPC_CMP_SLE_S:
25115 case R6_OPC_CMP_SULE_S:
25116 case R6_OPC_CMP_OR_S:
25117 case R6_OPC_CMP_UNE_S:
25118 case R6_OPC_CMP_NE_S:
25119 case R6_OPC_CMP_SOR_S:
25120 case R6_OPC_CMP_SUNE_S:
25121 case R6_OPC_CMP_SNE_S:
25122 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25123 break;
25124 case R6_OPC_CMP_AF_D:
25125 case R6_OPC_CMP_UN_D:
25126 case R6_OPC_CMP_EQ_D:
25127 case R6_OPC_CMP_UEQ_D:
25128 case R6_OPC_CMP_LT_D:
25129 case R6_OPC_CMP_ULT_D:
25130 case R6_OPC_CMP_LE_D:
25131 case R6_OPC_CMP_ULE_D:
25132 case R6_OPC_CMP_SAF_D:
25133 case R6_OPC_CMP_SUN_D:
25134 case R6_OPC_CMP_SEQ_D:
25135 case R6_OPC_CMP_SEUQ_D:
25136 case R6_OPC_CMP_SLT_D:
25137 case R6_OPC_CMP_SULT_D:
25138 case R6_OPC_CMP_SLE_D:
25139 case R6_OPC_CMP_SULE_D:
25140 case R6_OPC_CMP_OR_D:
25141 case R6_OPC_CMP_UNE_D:
25142 case R6_OPC_CMP_NE_D:
25143 case R6_OPC_CMP_SOR_D:
25144 case R6_OPC_CMP_SUNE_D:
25145 case R6_OPC_CMP_SNE_D:
25146 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
25147 break;
25148 default:
25149 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
25150 rt, rd, sa, (imm >> 8) & 0x7);
25152 break;
25154 } else {
25155 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
25156 (imm >> 8) & 0x7);
25158 break;
25160 default:
25161 MIPS_INVAL("cp1");
25162 gen_reserved_instruction(ctx);
25163 break;
25165 break;
25167 /* Compact branches [R6] and COP2 [non-R6] */
25168 case OPC_BC: /* OPC_LWC2 */
25169 case OPC_BALC: /* OPC_SWC2 */
25170 if (ctx->insn_flags & ISA_MIPS_R6) {
25171 /* OPC_BC, OPC_BALC */
25172 gen_compute_compact_branch(ctx, op, 0, 0,
25173 sextract32(ctx->opcode << 2, 0, 28));
25174 } else if (ctx->insn_flags & ASE_LEXT) {
25175 gen_loongson_lswc2(ctx, rt, rs, rd);
25176 } else {
25177 /* OPC_LWC2, OPC_SWC2 */
25178 /* COP2: Not implemented. */
25179 generate_exception_err(ctx, EXCP_CpU, 2);
25181 break;
25182 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
25183 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
25184 if (ctx->insn_flags & ISA_MIPS_R6) {
25185 if (rs != 0) {
25186 /* OPC_BEQZC, OPC_BNEZC */
25187 gen_compute_compact_branch(ctx, op, rs, 0,
25188 sextract32(ctx->opcode << 2, 0, 23));
25189 } else {
25190 /* OPC_JIC, OPC_JIALC */
25191 gen_compute_compact_branch(ctx, op, 0, rt, imm);
25193 } else if (ctx->insn_flags & ASE_LEXT) {
25194 gen_loongson_lsdc2(ctx, rt, rs, rd);
25195 } else {
25196 /* OPC_LWC2, OPC_SWC2 */
25197 /* COP2: Not implemented. */
25198 generate_exception_err(ctx, EXCP_CpU, 2);
25200 break;
25201 case OPC_CP2:
25202 check_insn(ctx, ASE_LMMI);
25203 /* Note that these instructions use different fields. */
25204 gen_loongson_multimedia(ctx, sa, rd, rt);
25205 break;
25207 case OPC_CP3:
25208 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
25209 check_cp1_enabled(ctx);
25210 op1 = MASK_CP3(ctx->opcode);
25211 switch (op1) {
25212 case OPC_LUXC1:
25213 case OPC_SUXC1:
25214 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25215 /* Fallthrough */
25216 case OPC_LWXC1:
25217 case OPC_LDXC1:
25218 case OPC_SWXC1:
25219 case OPC_SDXC1:
25220 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25221 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
25222 break;
25223 case OPC_PREFX:
25224 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25225 /* Treat as NOP. */
25226 break;
25227 case OPC_ALNV_PS:
25228 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
25229 /* Fallthrough */
25230 case OPC_MADD_S:
25231 case OPC_MADD_D:
25232 case OPC_MADD_PS:
25233 case OPC_MSUB_S:
25234 case OPC_MSUB_D:
25235 case OPC_MSUB_PS:
25236 case OPC_NMADD_S:
25237 case OPC_NMADD_D:
25238 case OPC_NMADD_PS:
25239 case OPC_NMSUB_S:
25240 case OPC_NMSUB_D:
25241 case OPC_NMSUB_PS:
25242 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
25243 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
25244 break;
25245 default:
25246 MIPS_INVAL("cp3");
25247 gen_reserved_instruction(ctx);
25248 break;
25250 } else {
25251 generate_exception_err(ctx, EXCP_CpU, 1);
25253 break;
25255 #if defined(TARGET_MIPS64)
25256 /* MIPS64 opcodes */
25257 case OPC_LLD:
25258 if (ctx->insn_flags & INSN_R5900) {
25259 check_insn_opc_user_only(ctx, INSN_R5900);
25261 /* fall through */
25262 case OPC_LDL:
25263 case OPC_LDR:
25264 case OPC_LWU:
25265 case OPC_LD:
25266 check_insn(ctx, ISA_MIPS3);
25267 check_mips_64(ctx);
25268 gen_ld(ctx, op, rt, rs, imm);
25269 break;
25270 case OPC_SDL:
25271 case OPC_SDR:
25272 case OPC_SD:
25273 check_insn(ctx, ISA_MIPS3);
25274 check_mips_64(ctx);
25275 gen_st(ctx, op, rt, rs, imm);
25276 break;
25277 case OPC_SCD:
25278 check_insn(ctx, ISA_MIPS3);
25279 if (ctx->insn_flags & INSN_R5900) {
25280 check_insn_opc_user_only(ctx, INSN_R5900);
25282 check_mips_64(ctx);
25283 gen_st_cond(ctx, rt, rs, imm, MO_TEQ, false);
25284 break;
25285 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
25286 if (ctx->insn_flags & ISA_MIPS_R6) {
25287 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
25288 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25289 } else {
25290 /* OPC_DADDI */
25291 check_insn(ctx, ISA_MIPS3);
25292 check_mips_64(ctx);
25293 gen_arith_imm(ctx, op, rt, rs, imm);
25295 break;
25296 case OPC_DADDIU:
25297 check_insn(ctx, ISA_MIPS3);
25298 check_mips_64(ctx);
25299 gen_arith_imm(ctx, op, rt, rs, imm);
25300 break;
25301 #else
25302 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
25303 if (ctx->insn_flags & ISA_MIPS_R6) {
25304 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
25305 } else {
25306 MIPS_INVAL("major opcode");
25307 gen_reserved_instruction(ctx);
25309 break;
25310 #endif
25311 case OPC_DAUI: /* OPC_JALX */
25312 if (ctx->insn_flags & ISA_MIPS_R6) {
25313 #if defined(TARGET_MIPS64)
25314 /* OPC_DAUI */
25315 check_mips_64(ctx);
25316 if (rs == 0) {
25317 generate_exception(ctx, EXCP_RI);
25318 } else if (rt != 0) {
25319 TCGv t0 = tcg_temp_new();
25320 gen_load_gpr(t0, rs);
25321 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
25322 tcg_temp_free(t0);
25324 #else
25325 gen_reserved_instruction(ctx);
25326 MIPS_INVAL("major opcode");
25327 #endif
25328 } else {
25329 /* OPC_JALX */
25330 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
25331 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
25332 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
25334 break;
25335 case OPC_MDMX: /* MMI_OPC_LQ */
25336 if (ctx->insn_flags & INSN_R5900) {
25337 #if defined(TARGET_MIPS64)
25338 gen_mmi_lq(env, ctx);
25339 #endif
25340 } else {
25341 /* MDMX: Not implemented. */
25343 break;
25344 case OPC_PCREL:
25345 check_insn(ctx, ISA_MIPS_R6);
25346 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
25347 break;
25348 default: /* Invalid */
25349 MIPS_INVAL("major opcode");
25350 return false;
25352 return true;
25355 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
25357 /* make sure instructions are on a word boundary */
25358 if (ctx->base.pc_next & 0x3) {
25359 env->CP0_BadVAddr = ctx->base.pc_next;
25360 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
25361 return;
25364 /* Handle blikely not taken case */
25365 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
25366 TCGLabel *l1 = gen_new_label();
25368 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
25369 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
25370 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
25371 gen_set_label(l1);
25374 /* Transition to the auto-generated decoder. */
25376 /* ISA extensions */
25377 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
25378 return;
25381 /* ISA (from latest to oldest) */
25382 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
25383 return;
25385 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
25386 return;
25389 if (decode_opc_legacy(env, ctx)) {
25390 return;
25393 gen_reserved_instruction(ctx);
25396 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
25398 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25399 CPUMIPSState *env = cs->env_ptr;
25401 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
25402 ctx->saved_pc = -1;
25403 ctx->insn_flags = env->insn_flags;
25404 ctx->CP0_Config1 = env->CP0_Config1;
25405 ctx->CP0_Config2 = env->CP0_Config2;
25406 ctx->CP0_Config3 = env->CP0_Config3;
25407 ctx->CP0_Config5 = env->CP0_Config5;
25408 ctx->btarget = 0;
25409 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
25410 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
25411 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
25412 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
25413 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
25414 ctx->PAMask = env->PAMask;
25415 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
25416 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
25417 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
25418 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
25419 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
25420 /* Restore delay slot state from the tb context. */
25421 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
25422 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
25423 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
25424 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
25425 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
25426 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
25427 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
25428 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
25429 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
25430 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
25431 restore_cpu_state(env, ctx);
25432 #ifdef CONFIG_USER_ONLY
25433 ctx->mem_idx = MIPS_HFLAG_UM;
25434 #else
25435 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
25436 #endif
25437 ctx->default_tcg_memop_mask = (ctx->insn_flags & (ISA_MIPS_R6 |
25438 INSN_LOONGSON3A)) ? MO_UNALN : MO_ALIGN;
25440 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
25441 ctx->hflags);
25444 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
25448 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
25450 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25452 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
25453 ctx->btarget);
25456 static bool mips_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cs,
25457 const CPUBreakpoint *bp)
25459 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25461 save_cpu_state(ctx, 1);
25462 ctx->base.is_jmp = DISAS_NORETURN;
25463 gen_helper_raise_exception_debug(cpu_env);
25465 * The address covered by the breakpoint must be included in
25466 * [tb->pc, tb->pc + tb->size) in order to for it to be
25467 * properly cleared -- thus we increment the PC here so that
25468 * the logic setting tb->size below does the right thing.
25470 ctx->base.pc_next += 4;
25471 return true;
25474 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
25476 CPUMIPSState *env = cs->env_ptr;
25477 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25478 int insn_bytes;
25479 int is_slot;
25481 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
25482 if (ctx->insn_flags & ISA_NANOMIPS32) {
25483 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25484 insn_bytes = decode_nanomips_opc(env, ctx);
25485 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
25486 ctx->opcode = translator_ldl(env, ctx->base.pc_next);
25487 insn_bytes = 4;
25488 decode_opc(env, ctx);
25489 } else if (ctx->insn_flags & ASE_MICROMIPS) {
25490 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25491 insn_bytes = decode_micromips_opc(env, ctx);
25492 } else if (ctx->insn_flags & ASE_MIPS16) {
25493 ctx->opcode = translator_lduw(env, ctx->base.pc_next);
25494 insn_bytes = decode_mips16_opc(env, ctx);
25495 } else {
25496 gen_reserved_instruction(ctx);
25497 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
25498 return;
25501 if (ctx->hflags & MIPS_HFLAG_BMASK) {
25502 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
25503 MIPS_HFLAG_FBNSLOT))) {
25505 * Force to generate branch as there is neither delay nor
25506 * forbidden slot.
25508 is_slot = 1;
25510 if ((ctx->hflags & MIPS_HFLAG_M16) &&
25511 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
25513 * Force to generate branch as microMIPS R6 doesn't restrict
25514 * branches in the forbidden slot.
25516 is_slot = 1;
25519 if (is_slot) {
25520 gen_branch(ctx, insn_bytes);
25522 ctx->base.pc_next += insn_bytes;
25524 if (ctx->base.is_jmp != DISAS_NEXT) {
25525 return;
25528 * Execute a branch and its delay slot as a single instruction.
25529 * This is what GDB expects and is consistent with what the
25530 * hardware does (e.g. if a delay slot instruction faults, the
25531 * reported PC is the PC of the branch).
25533 if (ctx->base.singlestep_enabled &&
25534 (ctx->hflags & MIPS_HFLAG_BMASK) == 0) {
25535 ctx->base.is_jmp = DISAS_TOO_MANY;
25537 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE) {
25538 ctx->base.is_jmp = DISAS_TOO_MANY;
25542 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
25544 DisasContext *ctx = container_of(dcbase, DisasContext, base);
25546 if (ctx->base.singlestep_enabled && ctx->base.is_jmp != DISAS_NORETURN) {
25547 save_cpu_state(ctx, ctx->base.is_jmp != DISAS_EXIT);
25548 gen_helper_raise_exception_debug(cpu_env);
25549 } else {
25550 switch (ctx->base.is_jmp) {
25551 case DISAS_STOP:
25552 gen_save_pc(ctx->base.pc_next);
25553 tcg_gen_lookup_and_goto_ptr();
25554 break;
25555 case DISAS_NEXT:
25556 case DISAS_TOO_MANY:
25557 save_cpu_state(ctx, 0);
25558 gen_goto_tb(ctx, 0, ctx->base.pc_next);
25559 break;
25560 case DISAS_EXIT:
25561 tcg_gen_exit_tb(NULL, 0);
25562 break;
25563 case DISAS_NORETURN:
25564 break;
25565 default:
25566 g_assert_not_reached();
25571 static void mips_tr_disas_log(const DisasContextBase *dcbase, CPUState *cs)
25573 qemu_log("IN: %s\n", lookup_symbol(dcbase->pc_first));
25574 log_target_disas(cs, dcbase->pc_first, dcbase->tb->size);
25577 static const TranslatorOps mips_tr_ops = {
25578 .init_disas_context = mips_tr_init_disas_context,
25579 .tb_start = mips_tr_tb_start,
25580 .insn_start = mips_tr_insn_start,
25581 .breakpoint_check = mips_tr_breakpoint_check,
25582 .translate_insn = mips_tr_translate_insn,
25583 .tb_stop = mips_tr_tb_stop,
25584 .disas_log = mips_tr_disas_log,
25587 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
25589 DisasContext ctx;
25591 translator_loop(&mips_tr_ops, &ctx.base, cs, tb, max_insns);
25594 void mips_tcg_init(void)
25596 int i;
25598 cpu_gpr[0] = NULL;
25599 for (i = 1; i < 32; i++)
25600 cpu_gpr[i] = tcg_global_mem_new(cpu_env,
25601 offsetof(CPUMIPSState,
25602 active_tc.gpr[i]),
25603 regnames[i]);
25604 #if defined(TARGET_MIPS64)
25605 cpu_gpr_hi[0] = NULL;
25607 for (unsigned i = 1; i < 32; i++) {
25608 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
25610 cpu_gpr_hi[i] = tcg_global_mem_new_i64(cpu_env,
25611 offsetof(CPUMIPSState,
25612 active_tc.gpr_hi[i]),
25613 rname);
25615 #endif /* !TARGET_MIPS64 */
25616 for (i = 0; i < 32; i++) {
25617 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
25619 fpu_f64[i] = tcg_global_mem_new_i64(cpu_env, off, fregnames[i]);
25621 msa_translate_init();
25622 cpu_PC = tcg_global_mem_new(cpu_env,
25623 offsetof(CPUMIPSState, active_tc.PC), "PC");
25624 for (i = 0; i < MIPS_DSP_ACC; i++) {
25625 cpu_HI[i] = tcg_global_mem_new(cpu_env,
25626 offsetof(CPUMIPSState, active_tc.HI[i]),
25627 regnames_HI[i]);
25628 cpu_LO[i] = tcg_global_mem_new(cpu_env,
25629 offsetof(CPUMIPSState, active_tc.LO[i]),
25630 regnames_LO[i]);
25632 cpu_dspctrl = tcg_global_mem_new(cpu_env,
25633 offsetof(CPUMIPSState,
25634 active_tc.DSPControl),
25635 "DSPControl");
25636 bcond = tcg_global_mem_new(cpu_env,
25637 offsetof(CPUMIPSState, bcond), "bcond");
25638 btarget = tcg_global_mem_new(cpu_env,
25639 offsetof(CPUMIPSState, btarget), "btarget");
25640 hflags = tcg_global_mem_new_i32(cpu_env,
25641 offsetof(CPUMIPSState, hflags), "hflags");
25643 fpu_fcr0 = tcg_global_mem_new_i32(cpu_env,
25644 offsetof(CPUMIPSState, active_fpu.fcr0),
25645 "fcr0");
25646 fpu_fcr31 = tcg_global_mem_new_i32(cpu_env,
25647 offsetof(CPUMIPSState, active_fpu.fcr31),
25648 "fcr31");
25649 cpu_lladdr = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, lladdr),
25650 "lladdr");
25651 cpu_llval = tcg_global_mem_new(cpu_env, offsetof(CPUMIPSState, llval),
25652 "llval");
25654 if (TARGET_LONG_BITS == 32) {
25655 mxu_translate_init();
25659 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb,
25660 target_ulong *data)
25662 env->active_tc.PC = data[0];
25663 env->hflags &= ~MIPS_HFLAG_BMASK;
25664 env->hflags |= data[1];
25665 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
25666 case MIPS_HFLAG_BR:
25667 break;
25668 case MIPS_HFLAG_BC:
25669 case MIPS_HFLAG_BL:
25670 case MIPS_HFLAG_B:
25671 env->btarget = data[2];
25672 break;