vhost-user: fix mmap offset calculation
[qemu/rayw.git] / target-mips / translate.c
blob446eb8a20f5920fb76f190c6fe6bd5e01d61e48c
1 /*
2 * MIPS32 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)
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
24 #include "cpu.h"
25 #include "disas/disas.h"
26 #include "tcg-op.h"
27 #include "exec/cpu_ldst.h"
29 #include "exec/helper-proto.h"
30 #include "exec/helper-gen.h"
31 #include "sysemu/kvm.h"
33 #include "trace-tcg.h"
36 #define MIPS_DEBUG_DISAS 0
37 //#define MIPS_DEBUG_SIGN_EXTENSIONS
39 /* MIPS major opcodes */
40 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
42 enum {
43 /* indirect opcode tables */
44 OPC_SPECIAL = (0x00 << 26),
45 OPC_REGIMM = (0x01 << 26),
46 OPC_CP0 = (0x10 << 26),
47 OPC_CP1 = (0x11 << 26),
48 OPC_CP2 = (0x12 << 26),
49 OPC_CP3 = (0x13 << 26),
50 OPC_SPECIAL2 = (0x1C << 26),
51 OPC_SPECIAL3 = (0x1F << 26),
52 /* arithmetic with immediate */
53 OPC_ADDI = (0x08 << 26),
54 OPC_ADDIU = (0x09 << 26),
55 OPC_SLTI = (0x0A << 26),
56 OPC_SLTIU = (0x0B << 26),
57 /* logic with immediate */
58 OPC_ANDI = (0x0C << 26),
59 OPC_ORI = (0x0D << 26),
60 OPC_XORI = (0x0E << 26),
61 OPC_LUI = (0x0F << 26),
62 /* arithmetic with immediate */
63 OPC_DADDI = (0x18 << 26),
64 OPC_DADDIU = (0x19 << 26),
65 /* Jump and branches */
66 OPC_J = (0x02 << 26),
67 OPC_JAL = (0x03 << 26),
68 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
69 OPC_BEQL = (0x14 << 26),
70 OPC_BNE = (0x05 << 26),
71 OPC_BNEL = (0x15 << 26),
72 OPC_BLEZ = (0x06 << 26),
73 OPC_BLEZL = (0x16 << 26),
74 OPC_BGTZ = (0x07 << 26),
75 OPC_BGTZL = (0x17 << 26),
76 OPC_JALX = (0x1D << 26),
77 OPC_DAUI = (0x1D << 26),
78 /* Load and stores */
79 OPC_LDL = (0x1A << 26),
80 OPC_LDR = (0x1B << 26),
81 OPC_LB = (0x20 << 26),
82 OPC_LH = (0x21 << 26),
83 OPC_LWL = (0x22 << 26),
84 OPC_LW = (0x23 << 26),
85 OPC_LWPC = OPC_LW | 0x5,
86 OPC_LBU = (0x24 << 26),
87 OPC_LHU = (0x25 << 26),
88 OPC_LWR = (0x26 << 26),
89 OPC_LWU = (0x27 << 26),
90 OPC_SB = (0x28 << 26),
91 OPC_SH = (0x29 << 26),
92 OPC_SWL = (0x2A << 26),
93 OPC_SW = (0x2B << 26),
94 OPC_SDL = (0x2C << 26),
95 OPC_SDR = (0x2D << 26),
96 OPC_SWR = (0x2E << 26),
97 OPC_LL = (0x30 << 26),
98 OPC_LLD = (0x34 << 26),
99 OPC_LD = (0x37 << 26),
100 OPC_LDPC = OPC_LD | 0x5,
101 OPC_SC = (0x38 << 26),
102 OPC_SCD = (0x3C << 26),
103 OPC_SD = (0x3F << 26),
104 /* Floating point load/store */
105 OPC_LWC1 = (0x31 << 26),
106 OPC_LWC2 = (0x32 << 26),
107 OPC_LDC1 = (0x35 << 26),
108 OPC_LDC2 = (0x36 << 26),
109 OPC_SWC1 = (0x39 << 26),
110 OPC_SWC2 = (0x3A << 26),
111 OPC_SDC1 = (0x3D << 26),
112 OPC_SDC2 = (0x3E << 26),
113 /* Compact Branches */
114 OPC_BLEZALC = (0x06 << 26),
115 OPC_BGEZALC = (0x06 << 26),
116 OPC_BGEUC = (0x06 << 26),
117 OPC_BGTZALC = (0x07 << 26),
118 OPC_BLTZALC = (0x07 << 26),
119 OPC_BLTUC = (0x07 << 26),
120 OPC_BOVC = (0x08 << 26),
121 OPC_BEQZALC = (0x08 << 26),
122 OPC_BEQC = (0x08 << 26),
123 OPC_BLEZC = (0x16 << 26),
124 OPC_BGEZC = (0x16 << 26),
125 OPC_BGEC = (0x16 << 26),
126 OPC_BGTZC = (0x17 << 26),
127 OPC_BLTZC = (0x17 << 26),
128 OPC_BLTC = (0x17 << 26),
129 OPC_BNVC = (0x18 << 26),
130 OPC_BNEZALC = (0x18 << 26),
131 OPC_BNEC = (0x18 << 26),
132 OPC_BC = (0x32 << 26),
133 OPC_BEQZC = (0x36 << 26),
134 OPC_JIC = (0x36 << 26),
135 OPC_BALC = (0x3A << 26),
136 OPC_BNEZC = (0x3E << 26),
137 OPC_JIALC = (0x3E << 26),
138 /* MDMX ASE specific */
139 OPC_MDMX = (0x1E << 26),
140 /* Cache and prefetch */
141 OPC_CACHE = (0x2F << 26),
142 OPC_PREF = (0x33 << 26),
143 /* PC-relative address computation / loads */
144 OPC_PCREL = (0x3B << 26),
147 /* PC-relative address computation / loads */
148 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
149 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
150 enum {
151 /* Instructions determined by bits 19 and 20 */
152 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
153 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
154 OPC_LWUPC = OPC_PCREL | (2 << 19),
156 /* Instructions determined by bits 16 ... 20 */
157 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
158 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
160 /* Other */
161 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
164 /* MIPS special opcodes */
165 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
167 enum {
168 /* Shifts */
169 OPC_SLL = 0x00 | OPC_SPECIAL,
170 /* NOP is SLL r0, r0, 0 */
171 /* SSNOP is SLL r0, r0, 1 */
172 /* EHB is SLL r0, r0, 3 */
173 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
174 OPC_ROTR = OPC_SRL | (1 << 21),
175 OPC_SRA = 0x03 | OPC_SPECIAL,
176 OPC_SLLV = 0x04 | OPC_SPECIAL,
177 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
178 OPC_ROTRV = OPC_SRLV | (1 << 6),
179 OPC_SRAV = 0x07 | OPC_SPECIAL,
180 OPC_DSLLV = 0x14 | OPC_SPECIAL,
181 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
182 OPC_DROTRV = OPC_DSRLV | (1 << 6),
183 OPC_DSRAV = 0x17 | OPC_SPECIAL,
184 OPC_DSLL = 0x38 | OPC_SPECIAL,
185 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
186 OPC_DROTR = OPC_DSRL | (1 << 21),
187 OPC_DSRA = 0x3B | OPC_SPECIAL,
188 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
189 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
190 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
191 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
192 /* Multiplication / division */
193 OPC_MULT = 0x18 | OPC_SPECIAL,
194 OPC_MULTU = 0x19 | OPC_SPECIAL,
195 OPC_DIV = 0x1A | OPC_SPECIAL,
196 OPC_DIVU = 0x1B | OPC_SPECIAL,
197 OPC_DMULT = 0x1C | OPC_SPECIAL,
198 OPC_DMULTU = 0x1D | OPC_SPECIAL,
199 OPC_DDIV = 0x1E | OPC_SPECIAL,
200 OPC_DDIVU = 0x1F | OPC_SPECIAL,
202 /* 2 registers arithmetic / logic */
203 OPC_ADD = 0x20 | OPC_SPECIAL,
204 OPC_ADDU = 0x21 | OPC_SPECIAL,
205 OPC_SUB = 0x22 | OPC_SPECIAL,
206 OPC_SUBU = 0x23 | OPC_SPECIAL,
207 OPC_AND = 0x24 | OPC_SPECIAL,
208 OPC_OR = 0x25 | OPC_SPECIAL,
209 OPC_XOR = 0x26 | OPC_SPECIAL,
210 OPC_NOR = 0x27 | OPC_SPECIAL,
211 OPC_SLT = 0x2A | OPC_SPECIAL,
212 OPC_SLTU = 0x2B | OPC_SPECIAL,
213 OPC_DADD = 0x2C | OPC_SPECIAL,
214 OPC_DADDU = 0x2D | OPC_SPECIAL,
215 OPC_DSUB = 0x2E | OPC_SPECIAL,
216 OPC_DSUBU = 0x2F | OPC_SPECIAL,
217 /* Jumps */
218 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
219 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
220 /* Traps */
221 OPC_TGE = 0x30 | OPC_SPECIAL,
222 OPC_TGEU = 0x31 | OPC_SPECIAL,
223 OPC_TLT = 0x32 | OPC_SPECIAL,
224 OPC_TLTU = 0x33 | OPC_SPECIAL,
225 OPC_TEQ = 0x34 | OPC_SPECIAL,
226 OPC_TNE = 0x36 | OPC_SPECIAL,
227 /* HI / LO registers load & stores */
228 OPC_MFHI = 0x10 | OPC_SPECIAL,
229 OPC_MTHI = 0x11 | OPC_SPECIAL,
230 OPC_MFLO = 0x12 | OPC_SPECIAL,
231 OPC_MTLO = 0x13 | OPC_SPECIAL,
232 /* Conditional moves */
233 OPC_MOVZ = 0x0A | OPC_SPECIAL,
234 OPC_MOVN = 0x0B | OPC_SPECIAL,
236 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
237 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
239 OPC_MOVCI = 0x01 | OPC_SPECIAL,
241 /* Special */
242 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
243 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
244 OPC_BREAK = 0x0D | OPC_SPECIAL,
245 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
246 OPC_SYNC = 0x0F | OPC_SPECIAL,
248 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
249 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
250 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
251 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
254 /* R6 Multiply and Divide instructions have the same Opcode
255 and function field as legacy OPC_MULT[U]/OPC_DIV[U] */
256 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
258 enum {
259 R6_OPC_MUL = OPC_MULT | (2 << 6),
260 R6_OPC_MUH = OPC_MULT | (3 << 6),
261 R6_OPC_MULU = OPC_MULTU | (2 << 6),
262 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
263 R6_OPC_DIV = OPC_DIV | (2 << 6),
264 R6_OPC_MOD = OPC_DIV | (3 << 6),
265 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
266 R6_OPC_MODU = OPC_DIVU | (3 << 6),
268 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
269 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
270 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
271 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
272 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
273 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
274 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
275 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
277 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
278 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
279 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
280 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
281 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
283 OPC_LSA = 0x05 | OPC_SPECIAL,
284 OPC_DLSA = 0x15 | OPC_SPECIAL,
287 /* Multiplication variants of the vr54xx. */
288 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
290 enum {
291 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
292 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
293 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
294 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
295 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
296 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
297 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
298 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
299 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
300 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
301 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
302 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
303 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
304 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
307 /* REGIMM (rt field) opcodes */
308 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
310 enum {
311 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
312 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
313 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
314 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
315 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
316 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
317 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
318 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
319 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
320 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
321 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
322 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
323 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
324 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
325 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
327 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
328 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
331 /* Special2 opcodes */
332 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
334 enum {
335 /* Multiply & xxx operations */
336 OPC_MADD = 0x00 | OPC_SPECIAL2,
337 OPC_MADDU = 0x01 | OPC_SPECIAL2,
338 OPC_MUL = 0x02 | OPC_SPECIAL2,
339 OPC_MSUB = 0x04 | OPC_SPECIAL2,
340 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
341 /* Loongson 2F */
342 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
343 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
344 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
345 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
346 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
347 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
348 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
349 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
350 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
351 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
352 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
353 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
354 /* Misc */
355 OPC_CLZ = 0x20 | OPC_SPECIAL2,
356 OPC_CLO = 0x21 | OPC_SPECIAL2,
357 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
358 OPC_DCLO = 0x25 | OPC_SPECIAL2,
359 /* Special */
360 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
363 /* Special3 opcodes */
364 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
366 enum {
367 OPC_EXT = 0x00 | OPC_SPECIAL3,
368 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
369 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
370 OPC_DEXT = 0x03 | OPC_SPECIAL3,
371 OPC_INS = 0x04 | OPC_SPECIAL3,
372 OPC_DINSM = 0x05 | OPC_SPECIAL3,
373 OPC_DINSU = 0x06 | OPC_SPECIAL3,
374 OPC_DINS = 0x07 | OPC_SPECIAL3,
375 OPC_FORK = 0x08 | OPC_SPECIAL3,
376 OPC_YIELD = 0x09 | OPC_SPECIAL3,
377 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
378 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
379 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
381 /* Loongson 2E */
382 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
383 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
384 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
385 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
386 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
387 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
388 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
389 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
390 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
391 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
392 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
393 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
395 /* MIPS DSP Load */
396 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
397 /* MIPS DSP Arithmetic */
398 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
399 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
400 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
401 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
402 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
403 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
404 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
405 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
406 /* MIPS DSP GPR-Based Shift Sub-class */
407 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
408 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
409 /* MIPS DSP Multiply Sub-class insns */
410 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
411 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
412 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
413 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
414 /* DSP Bit/Manipulation Sub-class */
415 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
416 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
417 /* MIPS DSP Append Sub-class */
418 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
419 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
420 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
421 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
422 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
424 /* R6 */
425 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
426 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
427 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
428 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
429 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
430 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
433 /* BSHFL opcodes */
434 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
436 enum {
437 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
438 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
439 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
440 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp */
441 OPC_ALIGN_END = (0x0B << 6) | OPC_BSHFL, /* 010.00 to 010.11 */
442 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
445 /* DBSHFL opcodes */
446 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
448 enum {
449 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
450 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
451 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp */
452 OPC_DALIGN_END = (0x0F << 6) | OPC_DBSHFL, /* 01.000 to 01.111 */
453 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
456 /* MIPS DSP REGIMM opcodes */
457 enum {
458 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
459 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
462 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
463 /* MIPS DSP Load */
464 enum {
465 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
466 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
467 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
468 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
471 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
472 enum {
473 /* MIPS DSP Arithmetic Sub-class */
474 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
475 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
476 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
477 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
478 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
479 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
480 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
481 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
482 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
483 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
484 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
485 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
486 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
487 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
488 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
489 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
490 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
491 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
492 /* MIPS DSP Multiply Sub-class insns */
493 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
494 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
495 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
496 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
497 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
498 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
501 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
502 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
503 enum {
504 /* MIPS DSP Arithmetic Sub-class */
505 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
506 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
507 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
508 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
509 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
510 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
511 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
512 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
513 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
514 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
515 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
516 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
517 /* MIPS DSP Multiply Sub-class insns */
518 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
519 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
520 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
521 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
524 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
525 enum {
526 /* MIPS DSP Arithmetic Sub-class */
527 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
528 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
529 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
530 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
531 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
532 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
533 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
534 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
535 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
536 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
537 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
538 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
539 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
540 /* DSP Bit/Manipulation Sub-class */
541 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
542 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
543 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
544 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
545 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
548 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
549 enum {
550 /* MIPS DSP Arithmetic Sub-class */
551 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
552 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
553 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
554 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
555 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
556 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
557 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
558 /* DSP Compare-Pick Sub-class */
559 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
560 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
561 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
562 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
563 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
564 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
565 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
566 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
567 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
568 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
569 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
570 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
571 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
572 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
573 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
576 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
577 enum {
578 /* MIPS DSP GPR-Based Shift Sub-class */
579 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
580 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
581 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
582 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
583 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
584 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
585 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
586 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
587 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
588 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
589 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
590 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
591 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
592 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
593 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
594 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
595 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
596 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
597 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
598 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
599 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
600 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
603 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
604 enum {
605 /* MIPS DSP Multiply Sub-class insns */
606 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
607 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
608 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
609 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
610 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
611 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
612 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
613 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
614 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
615 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
616 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
617 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
618 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
619 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
620 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
621 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
622 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
623 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
624 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
625 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
626 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
627 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
630 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
631 enum {
632 /* DSP Bit/Manipulation Sub-class */
633 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
636 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
637 enum {
638 /* MIPS DSP Append Sub-class */
639 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
640 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
641 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
644 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
645 enum {
646 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
647 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
648 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
649 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
650 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
651 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
652 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
653 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
654 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
655 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
656 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
657 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
658 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
659 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
660 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
661 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
662 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
663 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
666 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
667 enum {
668 /* MIPS DSP Arithmetic Sub-class */
669 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
670 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
671 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
672 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
673 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
674 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
675 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
676 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
677 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
678 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
679 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
680 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
681 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
682 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
683 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
684 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
685 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
686 /* DSP Bit/Manipulation Sub-class */
687 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
688 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
689 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
690 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
691 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
692 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
695 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
696 enum {
697 /* MIPS DSP Multiply Sub-class insns */
698 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
699 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
700 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
701 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
702 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
703 /* MIPS DSP Arithmetic Sub-class */
704 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
705 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
706 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
707 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
708 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
709 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
710 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
711 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
712 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
713 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
714 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
715 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
716 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
717 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
718 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
719 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
720 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
721 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
722 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
723 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
724 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
727 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
728 enum {
729 /* DSP Compare-Pick Sub-class */
730 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
731 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
732 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
733 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
734 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
735 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
736 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
737 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
738 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
739 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
740 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
741 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
742 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
743 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
744 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
745 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
746 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
747 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
748 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
749 /* MIPS DSP Arithmetic Sub-class */
750 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
751 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
752 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
753 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
754 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
755 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
756 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
757 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
760 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
761 enum {
762 /* DSP Append Sub-class */
763 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
764 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
765 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
766 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
769 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
770 enum {
771 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
772 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
773 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
774 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
775 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
776 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
777 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
778 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
779 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
780 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
781 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
782 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
783 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
784 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
785 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
786 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
787 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
788 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
789 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
790 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
791 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
792 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
795 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
796 enum {
797 /* DSP Bit/Manipulation Sub-class */
798 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
801 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
802 enum {
803 /* MIPS DSP Multiply Sub-class insns */
804 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
805 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
806 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
807 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
808 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
809 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
810 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
811 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
812 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
813 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
814 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
815 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
816 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
817 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
818 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
819 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
820 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
821 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
822 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
823 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
824 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
825 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
826 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
827 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
828 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
829 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
832 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
833 enum {
834 /* MIPS DSP GPR-Based Shift Sub-class */
835 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
836 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
837 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
838 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
839 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
840 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
841 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
842 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
843 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
844 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
845 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
846 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
847 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
848 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
849 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
850 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
851 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
852 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
853 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
854 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
855 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
856 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
857 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
858 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
859 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
860 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
863 /* Coprocessor 0 (rs field) */
864 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
866 enum {
867 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
868 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
869 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
870 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
871 OPC_MFTR = (0x08 << 21) | OPC_CP0,
872 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
873 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
874 OPC_MTTR = (0x0C << 21) | OPC_CP0,
875 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
876 OPC_C0 = (0x10 << 21) | OPC_CP0,
877 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
878 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
881 /* MFMC0 opcodes */
882 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
884 enum {
885 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
886 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
887 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
888 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
889 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
890 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
893 /* Coprocessor 0 (with rs == C0) */
894 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
896 enum {
897 OPC_TLBR = 0x01 | OPC_C0,
898 OPC_TLBWI = 0x02 | OPC_C0,
899 OPC_TLBWR = 0x06 | OPC_C0,
900 OPC_TLBP = 0x08 | OPC_C0,
901 OPC_RFE = 0x10 | OPC_C0,
902 OPC_ERET = 0x18 | OPC_C0,
903 OPC_DERET = 0x1F | OPC_C0,
904 OPC_WAIT = 0x20 | OPC_C0,
907 /* Coprocessor 1 (rs field) */
908 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
910 /* Values for the fmt field in FP instructions */
911 enum {
912 /* 0 - 15 are reserved */
913 FMT_S = 16, /* single fp */
914 FMT_D = 17, /* double fp */
915 FMT_E = 18, /* extended fp */
916 FMT_Q = 19, /* quad fp */
917 FMT_W = 20, /* 32-bit fixed */
918 FMT_L = 21, /* 64-bit fixed */
919 FMT_PS = 22, /* paired single fp */
920 /* 23 - 31 are reserved */
923 enum {
924 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
925 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
926 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
927 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
928 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
929 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
930 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
931 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
932 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
933 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
934 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
935 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
936 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
937 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
938 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
939 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
940 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
941 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
942 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
943 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
946 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
947 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
949 enum {
950 OPC_BC1F = (0x00 << 16) | OPC_BC1,
951 OPC_BC1T = (0x01 << 16) | OPC_BC1,
952 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
953 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
956 enum {
957 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
958 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
961 enum {
962 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
963 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
966 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
968 enum {
969 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
970 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
971 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
972 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
973 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
974 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
975 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
976 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
977 OPC_BC2 = (0x08 << 21) | OPC_CP2,
978 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
979 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
982 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
984 enum {
985 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
986 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
987 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
988 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
989 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
990 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
991 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
992 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
994 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
995 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
996 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
997 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
998 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
999 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1000 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1001 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1003 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1004 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1005 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1006 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1007 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1008 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1009 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1010 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1012 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1013 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1014 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1015 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1016 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1017 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1018 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1019 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1021 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1022 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1023 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1024 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1025 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1026 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1028 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1029 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1030 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1031 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1032 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1033 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1035 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1036 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1037 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1038 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1039 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1040 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1042 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1043 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1044 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1045 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1046 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1047 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1049 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1050 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1051 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1052 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1053 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1054 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1056 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1057 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1058 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1059 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1060 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1061 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1063 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1064 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1065 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1066 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1067 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1068 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1070 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1071 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1072 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1073 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1074 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1075 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1079 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1081 enum {
1082 OPC_LWXC1 = 0x00 | OPC_CP3,
1083 OPC_LDXC1 = 0x01 | OPC_CP3,
1084 OPC_LUXC1 = 0x05 | OPC_CP3,
1085 OPC_SWXC1 = 0x08 | OPC_CP3,
1086 OPC_SDXC1 = 0x09 | OPC_CP3,
1087 OPC_SUXC1 = 0x0D | OPC_CP3,
1088 OPC_PREFX = 0x0F | OPC_CP3,
1089 OPC_ALNV_PS = 0x1E | OPC_CP3,
1090 OPC_MADD_S = 0x20 | OPC_CP3,
1091 OPC_MADD_D = 0x21 | OPC_CP3,
1092 OPC_MADD_PS = 0x26 | OPC_CP3,
1093 OPC_MSUB_S = 0x28 | OPC_CP3,
1094 OPC_MSUB_D = 0x29 | OPC_CP3,
1095 OPC_MSUB_PS = 0x2E | OPC_CP3,
1096 OPC_NMADD_S = 0x30 | OPC_CP3,
1097 OPC_NMADD_D = 0x31 | OPC_CP3,
1098 OPC_NMADD_PS= 0x36 | OPC_CP3,
1099 OPC_NMSUB_S = 0x38 | OPC_CP3,
1100 OPC_NMSUB_D = 0x39 | OPC_CP3,
1101 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1104 /* global register indices */
1105 static TCGv_ptr cpu_env;
1106 static TCGv cpu_gpr[32], cpu_PC;
1107 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1108 static TCGv cpu_dspctrl, btarget, bcond;
1109 static TCGv_i32 hflags;
1110 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1111 static TCGv_i64 fpu_f64[32];
1113 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1114 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1116 #include "exec/gen-icount.h"
1118 #define gen_helper_0e0i(name, arg) do { \
1119 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1120 gen_helper_##name(cpu_env, helper_tmp); \
1121 tcg_temp_free_i32(helper_tmp); \
1122 } while(0)
1124 #define gen_helper_0e1i(name, arg1, arg2) do { \
1125 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1126 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1127 tcg_temp_free_i32(helper_tmp); \
1128 } while(0)
1130 #define gen_helper_1e0i(name, ret, arg1) do { \
1131 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1132 gen_helper_##name(ret, cpu_env, helper_tmp); \
1133 tcg_temp_free_i32(helper_tmp); \
1134 } while(0)
1136 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1137 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1138 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1139 tcg_temp_free_i32(helper_tmp); \
1140 } while(0)
1142 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1143 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1144 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1145 tcg_temp_free_i32(helper_tmp); \
1146 } while(0)
1148 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1149 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1150 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1151 tcg_temp_free_i32(helper_tmp); \
1152 } while(0)
1154 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1155 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1156 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1157 tcg_temp_free_i32(helper_tmp); \
1158 } while(0)
1160 typedef struct DisasContext {
1161 struct TranslationBlock *tb;
1162 target_ulong pc, saved_pc;
1163 uint32_t opcode;
1164 int singlestep_enabled;
1165 int insn_flags;
1166 int32_t CP0_Config1;
1167 /* Routine used to access memory */
1168 int mem_idx;
1169 uint32_t hflags, saved_hflags;
1170 int bstate;
1171 target_ulong btarget;
1172 bool ulri;
1173 } DisasContext;
1175 enum {
1176 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1177 * exception condition */
1178 BS_STOP = 1, /* We want to stop translation for any reason */
1179 BS_BRANCH = 2, /* We reached a branch condition */
1180 BS_EXCP = 3, /* We reached an exception condition */
1183 static const char * const regnames[] = {
1184 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1185 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1186 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1187 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1190 static const char * const regnames_HI[] = {
1191 "HI0", "HI1", "HI2", "HI3",
1194 static const char * const regnames_LO[] = {
1195 "LO0", "LO1", "LO2", "LO3",
1198 static const char * const fregnames[] = {
1199 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1200 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1201 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1202 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1205 #define MIPS_DEBUG(fmt, ...) \
1206 do { \
1207 if (MIPS_DEBUG_DISAS) { \
1208 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1209 TARGET_FMT_lx ": %08x " fmt "\n", \
1210 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1212 } while (0)
1214 #define LOG_DISAS(...) \
1215 do { \
1216 if (MIPS_DEBUG_DISAS) { \
1217 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1219 } while (0)
1221 #define MIPS_INVAL(op) \
1222 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1223 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1225 /* General purpose registers moves. */
1226 static inline void gen_load_gpr (TCGv t, int reg)
1228 if (reg == 0)
1229 tcg_gen_movi_tl(t, 0);
1230 else
1231 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1234 static inline void gen_store_gpr (TCGv t, int reg)
1236 if (reg != 0)
1237 tcg_gen_mov_tl(cpu_gpr[reg], t);
1240 /* Moves to/from shadow registers. */
1241 static inline void gen_load_srsgpr (int from, int to)
1243 TCGv t0 = tcg_temp_new();
1245 if (from == 0)
1246 tcg_gen_movi_tl(t0, 0);
1247 else {
1248 TCGv_i32 t2 = tcg_temp_new_i32();
1249 TCGv_ptr addr = tcg_temp_new_ptr();
1251 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1252 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1253 tcg_gen_andi_i32(t2, t2, 0xf);
1254 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1255 tcg_gen_ext_i32_ptr(addr, t2);
1256 tcg_gen_add_ptr(addr, cpu_env, addr);
1258 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1259 tcg_temp_free_ptr(addr);
1260 tcg_temp_free_i32(t2);
1262 gen_store_gpr(t0, to);
1263 tcg_temp_free(t0);
1266 static inline void gen_store_srsgpr (int from, int to)
1268 if (to != 0) {
1269 TCGv t0 = tcg_temp_new();
1270 TCGv_i32 t2 = tcg_temp_new_i32();
1271 TCGv_ptr addr = tcg_temp_new_ptr();
1273 gen_load_gpr(t0, from);
1274 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1275 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1276 tcg_gen_andi_i32(t2, t2, 0xf);
1277 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1278 tcg_gen_ext_i32_ptr(addr, t2);
1279 tcg_gen_add_ptr(addr, cpu_env, addr);
1281 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1282 tcg_temp_free_ptr(addr);
1283 tcg_temp_free_i32(t2);
1284 tcg_temp_free(t0);
1288 /* Floating point register moves. */
1289 static void gen_load_fpr32(TCGv_i32 t, int reg)
1291 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1294 static void gen_store_fpr32(TCGv_i32 t, int reg)
1296 TCGv_i64 t64 = tcg_temp_new_i64();
1297 tcg_gen_extu_i32_i64(t64, t);
1298 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1299 tcg_temp_free_i64(t64);
1302 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1304 if (ctx->hflags & MIPS_HFLAG_F64) {
1305 TCGv_i64 t64 = tcg_temp_new_i64();
1306 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1307 tcg_gen_trunc_i64_i32(t, t64);
1308 tcg_temp_free_i64(t64);
1309 } else {
1310 gen_load_fpr32(t, reg | 1);
1314 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1316 if (ctx->hflags & MIPS_HFLAG_F64) {
1317 TCGv_i64 t64 = tcg_temp_new_i64();
1318 tcg_gen_extu_i32_i64(t64, t);
1319 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1320 tcg_temp_free_i64(t64);
1321 } else {
1322 gen_store_fpr32(t, reg | 1);
1326 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1328 if (ctx->hflags & MIPS_HFLAG_F64) {
1329 tcg_gen_mov_i64(t, fpu_f64[reg]);
1330 } else {
1331 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1335 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1337 if (ctx->hflags & MIPS_HFLAG_F64) {
1338 tcg_gen_mov_i64(fpu_f64[reg], t);
1339 } else {
1340 TCGv_i64 t0;
1341 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1342 t0 = tcg_temp_new_i64();
1343 tcg_gen_shri_i64(t0, t, 32);
1344 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1345 tcg_temp_free_i64(t0);
1349 static inline int get_fp_bit (int cc)
1351 if (cc)
1352 return 24 + cc;
1353 else
1354 return 23;
1357 /* Tests */
1358 static inline void gen_save_pc(target_ulong pc)
1360 tcg_gen_movi_tl(cpu_PC, pc);
1363 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1365 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1366 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1367 gen_save_pc(ctx->pc);
1368 ctx->saved_pc = ctx->pc;
1370 if (ctx->hflags != ctx->saved_hflags) {
1371 tcg_gen_movi_i32(hflags, ctx->hflags);
1372 ctx->saved_hflags = ctx->hflags;
1373 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1374 case MIPS_HFLAG_BR:
1375 break;
1376 case MIPS_HFLAG_BC:
1377 case MIPS_HFLAG_BL:
1378 case MIPS_HFLAG_B:
1379 tcg_gen_movi_tl(btarget, ctx->btarget);
1380 break;
1385 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1387 ctx->saved_hflags = ctx->hflags;
1388 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1389 case MIPS_HFLAG_BR:
1390 break;
1391 case MIPS_HFLAG_BC:
1392 case MIPS_HFLAG_BL:
1393 case MIPS_HFLAG_B:
1394 ctx->btarget = env->btarget;
1395 break;
1399 static inline void
1400 generate_exception_err (DisasContext *ctx, int excp, int err)
1402 TCGv_i32 texcp = tcg_const_i32(excp);
1403 TCGv_i32 terr = tcg_const_i32(err);
1404 save_cpu_state(ctx, 1);
1405 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1406 tcg_temp_free_i32(terr);
1407 tcg_temp_free_i32(texcp);
1410 static inline void
1411 generate_exception (DisasContext *ctx, int excp)
1413 save_cpu_state(ctx, 1);
1414 gen_helper_0e0i(raise_exception, excp);
1417 /* Addresses computation */
1418 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1420 tcg_gen_add_tl(ret, arg0, arg1);
1422 #if defined(TARGET_MIPS64)
1423 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1424 tcg_gen_ext32s_i64(ret, ret);
1426 #endif
1429 /* Addresses computation (translation time) */
1430 static target_long addr_add(DisasContext *ctx, target_long base,
1431 target_long offset)
1433 target_long sum = base + offset;
1435 #if defined(TARGET_MIPS64)
1436 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1437 sum = (int32_t)sum;
1439 #endif
1440 return sum;
1443 static inline void check_cp0_enabled(DisasContext *ctx)
1445 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1446 generate_exception_err(ctx, EXCP_CpU, 0);
1449 static inline void check_cp1_enabled(DisasContext *ctx)
1451 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1452 generate_exception_err(ctx, EXCP_CpU, 1);
1455 /* Verify that the processor is running with COP1X instructions enabled.
1456 This is associated with the nabla symbol in the MIPS32 and MIPS64
1457 opcode tables. */
1459 static inline void check_cop1x(DisasContext *ctx)
1461 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1462 generate_exception(ctx, EXCP_RI);
1465 /* Verify that the processor is running with 64-bit floating-point
1466 operations enabled. */
1468 static inline void check_cp1_64bitmode(DisasContext *ctx)
1470 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1471 generate_exception(ctx, EXCP_RI);
1475 * Verify if floating point register is valid; an operation is not defined
1476 * if bit 0 of any register specification is set and the FR bit in the
1477 * Status register equals zero, since the register numbers specify an
1478 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1479 * in the Status register equals one, both even and odd register numbers
1480 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1482 * Multiple 64 bit wide registers can be checked by calling
1483 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1485 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1487 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1488 generate_exception(ctx, EXCP_RI);
1491 /* Verify that the processor is running with DSP instructions enabled.
1492 This is enabled by CP0 Status register MX(24) bit.
1495 static inline void check_dsp(DisasContext *ctx)
1497 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1498 if (ctx->insn_flags & ASE_DSP) {
1499 generate_exception(ctx, EXCP_DSPDIS);
1500 } else {
1501 generate_exception(ctx, EXCP_RI);
1506 static inline void check_dspr2(DisasContext *ctx)
1508 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1509 if (ctx->insn_flags & ASE_DSP) {
1510 generate_exception(ctx, EXCP_DSPDIS);
1511 } else {
1512 generate_exception(ctx, EXCP_RI);
1517 /* This code generates a "reserved instruction" exception if the
1518 CPU does not support the instruction set corresponding to flags. */
1519 static inline void check_insn(DisasContext *ctx, int flags)
1521 if (unlikely(!(ctx->insn_flags & flags))) {
1522 generate_exception(ctx, EXCP_RI);
1526 /* This code generates a "reserved instruction" exception if the
1527 CPU has corresponding flag set which indicates that the instruction
1528 has been removed. */
1529 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1531 if (unlikely(ctx->insn_flags & flags)) {
1532 generate_exception(ctx, EXCP_RI);
1536 #ifdef TARGET_MIPS64
1537 /* This code generates a "reserved instruction" exception if 64-bit
1538 instructions are not enabled. */
1539 static inline void check_mips_64(DisasContext *ctx)
1541 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1542 generate_exception(ctx, EXCP_RI);
1544 #endif
1546 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1547 calling interface for 32 and 64-bit FPRs. No sense in changing
1548 all callers for gen_load_fpr32 when we need the CTX parameter for
1549 this one use. */
1550 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1551 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1552 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1553 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1554 int ft, int fs, int cc) \
1556 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1557 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1558 switch (ifmt) { \
1559 case FMT_PS: \
1560 check_cp1_64bitmode(ctx); \
1561 break; \
1562 case FMT_D: \
1563 if (abs) { \
1564 check_cop1x(ctx); \
1566 check_cp1_registers(ctx, fs | ft); \
1567 break; \
1568 case FMT_S: \
1569 if (abs) { \
1570 check_cop1x(ctx); \
1572 break; \
1574 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1575 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1576 switch (n) { \
1577 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1578 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1579 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1580 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1581 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1582 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1583 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1584 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1585 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1586 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1587 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1588 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1589 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1590 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1591 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1592 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1593 default: abort(); \
1595 tcg_temp_free_i##bits (fp0); \
1596 tcg_temp_free_i##bits (fp1); \
1599 FOP_CONDS(, 0, d, FMT_D, 64)
1600 FOP_CONDS(abs, 1, d, FMT_D, 64)
1601 FOP_CONDS(, 0, s, FMT_S, 32)
1602 FOP_CONDS(abs, 1, s, FMT_S, 32)
1603 FOP_CONDS(, 0, ps, FMT_PS, 64)
1604 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1605 #undef FOP_CONDS
1607 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1608 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1609 int ft, int fs, int fd) \
1611 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1612 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1613 switch (ifmt) { \
1614 case FMT_D: \
1615 check_cp1_registers(ctx, fs | ft | fd); \
1616 break; \
1618 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1619 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1620 switch (n) { \
1621 case 0: \
1622 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1623 break; \
1624 case 1: \
1625 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1626 break; \
1627 case 2: \
1628 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1629 break; \
1630 case 3: \
1631 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1632 break; \
1633 case 4: \
1634 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1635 break; \
1636 case 5: \
1637 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1638 break; \
1639 case 6: \
1640 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1641 break; \
1642 case 7: \
1643 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1644 break; \
1645 case 8: \
1646 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1647 break; \
1648 case 9: \
1649 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1650 break; \
1651 case 10: \
1652 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1653 break; \
1654 case 11: \
1655 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1656 break; \
1657 case 12: \
1658 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1659 break; \
1660 case 13: \
1661 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1662 break; \
1663 case 14: \
1664 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1665 break; \
1666 case 15: \
1667 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1668 break; \
1669 case 17: \
1670 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1671 break; \
1672 case 18: \
1673 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1674 break; \
1675 case 19: \
1676 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1677 break; \
1678 case 25: \
1679 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1680 break; \
1681 case 26: \
1682 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1683 break; \
1684 case 27: \
1685 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1686 break; \
1687 default: \
1688 abort(); \
1690 STORE; \
1691 tcg_temp_free_i ## bits (fp0); \
1692 tcg_temp_free_i ## bits (fp1); \
1695 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1696 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(fp0, fd))
1697 #undef FOP_CONDNS
1698 #undef gen_ldcmp_fpr32
1699 #undef gen_ldcmp_fpr64
1701 /* load/store instructions. */
1702 #ifdef CONFIG_USER_ONLY
1703 #define OP_LD_ATOMIC(insn,fname) \
1704 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1706 TCGv t0 = tcg_temp_new(); \
1707 tcg_gen_mov_tl(t0, arg1); \
1708 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1709 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1710 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1711 tcg_temp_free(t0); \
1713 #else
1714 #define OP_LD_ATOMIC(insn,fname) \
1715 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1717 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1719 #endif
1720 OP_LD_ATOMIC(ll,ld32s);
1721 #if defined(TARGET_MIPS64)
1722 OP_LD_ATOMIC(lld,ld64);
1723 #endif
1724 #undef OP_LD_ATOMIC
1726 #ifdef CONFIG_USER_ONLY
1727 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1728 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1730 TCGv t0 = tcg_temp_new(); \
1731 int l1 = gen_new_label(); \
1732 int l2 = gen_new_label(); \
1734 tcg_gen_andi_tl(t0, arg2, almask); \
1735 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
1736 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
1737 generate_exception(ctx, EXCP_AdES); \
1738 gen_set_label(l1); \
1739 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1740 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1741 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
1742 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1743 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
1744 gen_helper_0e0i(raise_exception, EXCP_SC); \
1745 gen_set_label(l2); \
1746 tcg_gen_movi_tl(t0, 0); \
1747 gen_store_gpr(t0, rt); \
1748 tcg_temp_free(t0); \
1750 #else
1751 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1752 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1754 TCGv t0 = tcg_temp_new(); \
1755 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
1756 gen_store_gpr(t0, rt); \
1757 tcg_temp_free(t0); \
1759 #endif
1760 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1761 #if defined(TARGET_MIPS64)
1762 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1763 #endif
1764 #undef OP_ST_ATOMIC
1766 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1767 int base, int16_t offset)
1769 if (base == 0) {
1770 tcg_gen_movi_tl(addr, offset);
1771 } else if (offset == 0) {
1772 gen_load_gpr(addr, base);
1773 } else {
1774 tcg_gen_movi_tl(addr, offset);
1775 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1779 static target_ulong pc_relative_pc (DisasContext *ctx)
1781 target_ulong pc = ctx->pc;
1783 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1784 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1786 pc -= branch_bytes;
1789 pc &= ~(target_ulong)3;
1790 return pc;
1793 /* Load */
1794 static void gen_ld(DisasContext *ctx, uint32_t opc,
1795 int rt, int base, int16_t offset)
1797 const char *opn = "ld";
1798 TCGv t0, t1, t2;
1800 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1801 /* Loongson CPU uses a load to zero register for prefetch.
1802 We emulate it as a NOP. On other CPU we must perform the
1803 actual memory access. */
1804 MIPS_DEBUG("NOP");
1805 return;
1808 t0 = tcg_temp_new();
1809 gen_base_offset_addr(ctx, t0, base, offset);
1811 switch (opc) {
1812 #if defined(TARGET_MIPS64)
1813 case OPC_LWU:
1814 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1815 gen_store_gpr(t0, rt);
1816 opn = "lwu";
1817 break;
1818 case OPC_LD:
1819 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1820 gen_store_gpr(t0, rt);
1821 opn = "ld";
1822 break;
1823 case OPC_LLD:
1824 case R6_OPC_LLD:
1825 save_cpu_state(ctx, 1);
1826 op_ld_lld(t0, t0, ctx);
1827 gen_store_gpr(t0, rt);
1828 opn = "lld";
1829 break;
1830 case OPC_LDL:
1831 t1 = tcg_temp_new();
1832 tcg_gen_andi_tl(t1, t0, 7);
1833 #ifndef TARGET_WORDS_BIGENDIAN
1834 tcg_gen_xori_tl(t1, t1, 7);
1835 #endif
1836 tcg_gen_shli_tl(t1, t1, 3);
1837 tcg_gen_andi_tl(t0, t0, ~7);
1838 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1839 tcg_gen_shl_tl(t0, t0, t1);
1840 tcg_gen_xori_tl(t1, t1, 63);
1841 t2 = tcg_const_tl(0x7fffffffffffffffull);
1842 tcg_gen_shr_tl(t2, t2, t1);
1843 gen_load_gpr(t1, rt);
1844 tcg_gen_and_tl(t1, t1, t2);
1845 tcg_temp_free(t2);
1846 tcg_gen_or_tl(t0, t0, t1);
1847 tcg_temp_free(t1);
1848 gen_store_gpr(t0, rt);
1849 opn = "ldl";
1850 break;
1851 case OPC_LDR:
1852 t1 = tcg_temp_new();
1853 tcg_gen_andi_tl(t1, t0, 7);
1854 #ifdef TARGET_WORDS_BIGENDIAN
1855 tcg_gen_xori_tl(t1, t1, 7);
1856 #endif
1857 tcg_gen_shli_tl(t1, t1, 3);
1858 tcg_gen_andi_tl(t0, t0, ~7);
1859 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1860 tcg_gen_shr_tl(t0, t0, t1);
1861 tcg_gen_xori_tl(t1, t1, 63);
1862 t2 = tcg_const_tl(0xfffffffffffffffeull);
1863 tcg_gen_shl_tl(t2, t2, t1);
1864 gen_load_gpr(t1, rt);
1865 tcg_gen_and_tl(t1, t1, t2);
1866 tcg_temp_free(t2);
1867 tcg_gen_or_tl(t0, t0, t1);
1868 tcg_temp_free(t1);
1869 gen_store_gpr(t0, rt);
1870 opn = "ldr";
1871 break;
1872 case OPC_LDPC:
1873 t1 = tcg_const_tl(pc_relative_pc(ctx));
1874 gen_op_addr_add(ctx, t0, t0, t1);
1875 tcg_temp_free(t1);
1876 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1877 gen_store_gpr(t0, rt);
1878 opn = "ldpc";
1879 break;
1880 #endif
1881 case OPC_LWPC:
1882 t1 = tcg_const_tl(pc_relative_pc(ctx));
1883 gen_op_addr_add(ctx, t0, t0, t1);
1884 tcg_temp_free(t1);
1885 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1886 gen_store_gpr(t0, rt);
1887 opn = "lwpc";
1888 break;
1889 case OPC_LW:
1890 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1891 gen_store_gpr(t0, rt);
1892 opn = "lw";
1893 break;
1894 case OPC_LH:
1895 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
1896 gen_store_gpr(t0, rt);
1897 opn = "lh";
1898 break;
1899 case OPC_LHU:
1900 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
1901 gen_store_gpr(t0, rt);
1902 opn = "lhu";
1903 break;
1904 case OPC_LB:
1905 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
1906 gen_store_gpr(t0, rt);
1907 opn = "lb";
1908 break;
1909 case OPC_LBU:
1910 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
1911 gen_store_gpr(t0, rt);
1912 opn = "lbu";
1913 break;
1914 case OPC_LWL:
1915 t1 = tcg_temp_new();
1916 tcg_gen_andi_tl(t1, t0, 3);
1917 #ifndef TARGET_WORDS_BIGENDIAN
1918 tcg_gen_xori_tl(t1, t1, 3);
1919 #endif
1920 tcg_gen_shli_tl(t1, t1, 3);
1921 tcg_gen_andi_tl(t0, t0, ~3);
1922 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1923 tcg_gen_shl_tl(t0, t0, t1);
1924 tcg_gen_xori_tl(t1, t1, 31);
1925 t2 = tcg_const_tl(0x7fffffffull);
1926 tcg_gen_shr_tl(t2, t2, t1);
1927 gen_load_gpr(t1, rt);
1928 tcg_gen_and_tl(t1, t1, t2);
1929 tcg_temp_free(t2);
1930 tcg_gen_or_tl(t0, t0, t1);
1931 tcg_temp_free(t1);
1932 tcg_gen_ext32s_tl(t0, t0);
1933 gen_store_gpr(t0, rt);
1934 opn = "lwl";
1935 break;
1936 case OPC_LWR:
1937 t1 = tcg_temp_new();
1938 tcg_gen_andi_tl(t1, t0, 3);
1939 #ifdef TARGET_WORDS_BIGENDIAN
1940 tcg_gen_xori_tl(t1, t1, 3);
1941 #endif
1942 tcg_gen_shli_tl(t1, t1, 3);
1943 tcg_gen_andi_tl(t0, t0, ~3);
1944 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1945 tcg_gen_shr_tl(t0, t0, t1);
1946 tcg_gen_xori_tl(t1, t1, 31);
1947 t2 = tcg_const_tl(0xfffffffeull);
1948 tcg_gen_shl_tl(t2, t2, t1);
1949 gen_load_gpr(t1, rt);
1950 tcg_gen_and_tl(t1, t1, t2);
1951 tcg_temp_free(t2);
1952 tcg_gen_or_tl(t0, t0, t1);
1953 tcg_temp_free(t1);
1954 tcg_gen_ext32s_tl(t0, t0);
1955 gen_store_gpr(t0, rt);
1956 opn = "lwr";
1957 break;
1958 case OPC_LL:
1959 case R6_OPC_LL:
1960 save_cpu_state(ctx, 1);
1961 op_ld_ll(t0, t0, ctx);
1962 gen_store_gpr(t0, rt);
1963 opn = "ll";
1964 break;
1966 (void)opn; /* avoid a compiler warning */
1967 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1968 tcg_temp_free(t0);
1971 /* Store */
1972 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1973 int base, int16_t offset)
1975 const char *opn = "st";
1976 TCGv t0 = tcg_temp_new();
1977 TCGv t1 = tcg_temp_new();
1979 gen_base_offset_addr(ctx, t0, base, offset);
1980 gen_load_gpr(t1, rt);
1981 switch (opc) {
1982 #if defined(TARGET_MIPS64)
1983 case OPC_SD:
1984 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
1985 opn = "sd";
1986 break;
1987 case OPC_SDL:
1988 save_cpu_state(ctx, 1);
1989 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
1990 opn = "sdl";
1991 break;
1992 case OPC_SDR:
1993 save_cpu_state(ctx, 1);
1994 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
1995 opn = "sdr";
1996 break;
1997 #endif
1998 case OPC_SW:
1999 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
2000 opn = "sw";
2001 break;
2002 case OPC_SH:
2003 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
2004 opn = "sh";
2005 break;
2006 case OPC_SB:
2007 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2008 opn = "sb";
2009 break;
2010 case OPC_SWL:
2011 save_cpu_state(ctx, 1);
2012 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2013 opn = "swl";
2014 break;
2015 case OPC_SWR:
2016 save_cpu_state(ctx, 1);
2017 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2018 opn = "swr";
2019 break;
2021 (void)opn; /* avoid a compiler warning */
2022 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2023 tcg_temp_free(t0);
2024 tcg_temp_free(t1);
2028 /* Store conditional */
2029 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2030 int base, int16_t offset)
2032 const char *opn = "st_cond";
2033 TCGv t0, t1;
2035 #ifdef CONFIG_USER_ONLY
2036 t0 = tcg_temp_local_new();
2037 t1 = tcg_temp_local_new();
2038 #else
2039 t0 = tcg_temp_new();
2040 t1 = tcg_temp_new();
2041 #endif
2042 gen_base_offset_addr(ctx, t0, base, offset);
2043 gen_load_gpr(t1, rt);
2044 switch (opc) {
2045 #if defined(TARGET_MIPS64)
2046 case OPC_SCD:
2047 case R6_OPC_SCD:
2048 save_cpu_state(ctx, 1);
2049 op_st_scd(t1, t0, rt, ctx);
2050 opn = "scd";
2051 break;
2052 #endif
2053 case OPC_SC:
2054 case R6_OPC_SC:
2055 save_cpu_state(ctx, 1);
2056 op_st_sc(t1, t0, rt, ctx);
2057 opn = "sc";
2058 break;
2060 (void)opn; /* avoid a compiler warning */
2061 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2062 tcg_temp_free(t1);
2063 tcg_temp_free(t0);
2066 /* Load and store */
2067 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2068 int base, int16_t offset)
2070 const char *opn = "flt_ldst";
2071 TCGv t0 = tcg_temp_new();
2073 gen_base_offset_addr(ctx, t0, base, offset);
2074 /* Don't do NOP if destination is zero: we must perform the actual
2075 memory access. */
2076 switch (opc) {
2077 case OPC_LWC1:
2079 TCGv_i32 fp0 = tcg_temp_new_i32();
2080 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
2081 gen_store_fpr32(fp0, ft);
2082 tcg_temp_free_i32(fp0);
2084 opn = "lwc1";
2085 break;
2086 case OPC_SWC1:
2088 TCGv_i32 fp0 = tcg_temp_new_i32();
2089 gen_load_fpr32(fp0, ft);
2090 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
2091 tcg_temp_free_i32(fp0);
2093 opn = "swc1";
2094 break;
2095 case OPC_LDC1:
2097 TCGv_i64 fp0 = tcg_temp_new_i64();
2098 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2099 gen_store_fpr64(ctx, fp0, ft);
2100 tcg_temp_free_i64(fp0);
2102 opn = "ldc1";
2103 break;
2104 case OPC_SDC1:
2106 TCGv_i64 fp0 = tcg_temp_new_i64();
2107 gen_load_fpr64(ctx, fp0, ft);
2108 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2109 tcg_temp_free_i64(fp0);
2111 opn = "sdc1";
2112 break;
2113 default:
2114 MIPS_INVAL(opn);
2115 generate_exception(ctx, EXCP_RI);
2116 goto out;
2118 (void)opn; /* avoid a compiler warning */
2119 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2120 out:
2121 tcg_temp_free(t0);
2124 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2125 int rs, int16_t imm)
2127 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2128 check_cp1_enabled(ctx);
2129 gen_flt_ldst(ctx, op, rt, rs, imm);
2130 } else {
2131 generate_exception_err(ctx, EXCP_CpU, 1);
2135 /* Arithmetic with immediate operand */
2136 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2137 int rt, int rs, int16_t imm)
2139 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2140 const char *opn = "imm arith";
2142 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2143 /* If no destination, treat it as a NOP.
2144 For addi, we must generate the overflow exception when needed. */
2145 MIPS_DEBUG("NOP");
2146 return;
2148 switch (opc) {
2149 case OPC_ADDI:
2151 TCGv t0 = tcg_temp_local_new();
2152 TCGv t1 = tcg_temp_new();
2153 TCGv t2 = tcg_temp_new();
2154 int l1 = gen_new_label();
2156 gen_load_gpr(t1, rs);
2157 tcg_gen_addi_tl(t0, t1, uimm);
2158 tcg_gen_ext32s_tl(t0, t0);
2160 tcg_gen_xori_tl(t1, t1, ~uimm);
2161 tcg_gen_xori_tl(t2, t0, uimm);
2162 tcg_gen_and_tl(t1, t1, t2);
2163 tcg_temp_free(t2);
2164 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2165 tcg_temp_free(t1);
2166 /* operands of same sign, result different sign */
2167 generate_exception(ctx, EXCP_OVERFLOW);
2168 gen_set_label(l1);
2169 tcg_gen_ext32s_tl(t0, t0);
2170 gen_store_gpr(t0, rt);
2171 tcg_temp_free(t0);
2173 opn = "addi";
2174 break;
2175 case OPC_ADDIU:
2176 if (rs != 0) {
2177 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2178 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2179 } else {
2180 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2182 opn = "addiu";
2183 break;
2184 #if defined(TARGET_MIPS64)
2185 case OPC_DADDI:
2187 TCGv t0 = tcg_temp_local_new();
2188 TCGv t1 = tcg_temp_new();
2189 TCGv t2 = tcg_temp_new();
2190 int l1 = gen_new_label();
2192 gen_load_gpr(t1, rs);
2193 tcg_gen_addi_tl(t0, t1, uimm);
2195 tcg_gen_xori_tl(t1, t1, ~uimm);
2196 tcg_gen_xori_tl(t2, t0, uimm);
2197 tcg_gen_and_tl(t1, t1, t2);
2198 tcg_temp_free(t2);
2199 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2200 tcg_temp_free(t1);
2201 /* operands of same sign, result different sign */
2202 generate_exception(ctx, EXCP_OVERFLOW);
2203 gen_set_label(l1);
2204 gen_store_gpr(t0, rt);
2205 tcg_temp_free(t0);
2207 opn = "daddi";
2208 break;
2209 case OPC_DADDIU:
2210 if (rs != 0) {
2211 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2212 } else {
2213 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2215 opn = "daddiu";
2216 break;
2217 #endif
2219 (void)opn; /* avoid a compiler warning */
2220 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2223 /* Logic with immediate operand */
2224 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2225 int rt, int rs, int16_t imm)
2227 target_ulong uimm;
2229 if (rt == 0) {
2230 /* If no destination, treat it as a NOP. */
2231 MIPS_DEBUG("NOP");
2232 return;
2234 uimm = (uint16_t)imm;
2235 switch (opc) {
2236 case OPC_ANDI:
2237 if (likely(rs != 0))
2238 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2239 else
2240 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2241 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2242 regnames[rs], uimm);
2243 break;
2244 case OPC_ORI:
2245 if (rs != 0)
2246 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2247 else
2248 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2249 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2250 regnames[rs], uimm);
2251 break;
2252 case OPC_XORI:
2253 if (likely(rs != 0))
2254 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2255 else
2256 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2257 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2258 regnames[rs], uimm);
2259 break;
2260 case OPC_LUI:
2261 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2262 /* OPC_AUI */
2263 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2264 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2265 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2266 } else {
2267 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2268 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2270 break;
2272 default:
2273 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2274 break;
2278 /* Set on less than with immediate operand */
2279 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2280 int rt, int rs, int16_t imm)
2282 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2283 const char *opn = "imm arith";
2284 TCGv t0;
2286 if (rt == 0) {
2287 /* If no destination, treat it as a NOP. */
2288 MIPS_DEBUG("NOP");
2289 return;
2291 t0 = tcg_temp_new();
2292 gen_load_gpr(t0, rs);
2293 switch (opc) {
2294 case OPC_SLTI:
2295 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2296 opn = "slti";
2297 break;
2298 case OPC_SLTIU:
2299 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2300 opn = "sltiu";
2301 break;
2303 (void)opn; /* avoid a compiler warning */
2304 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2305 tcg_temp_free(t0);
2308 /* Shifts with immediate operand */
2309 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2310 int rt, int rs, int16_t imm)
2312 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2313 const char *opn = "imm shift";
2314 TCGv t0;
2316 if (rt == 0) {
2317 /* If no destination, treat it as a NOP. */
2318 MIPS_DEBUG("NOP");
2319 return;
2322 t0 = tcg_temp_new();
2323 gen_load_gpr(t0, rs);
2324 switch (opc) {
2325 case OPC_SLL:
2326 tcg_gen_shli_tl(t0, t0, uimm);
2327 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2328 opn = "sll";
2329 break;
2330 case OPC_SRA:
2331 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2332 opn = "sra";
2333 break;
2334 case OPC_SRL:
2335 if (uimm != 0) {
2336 tcg_gen_ext32u_tl(t0, t0);
2337 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2338 } else {
2339 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2341 opn = "srl";
2342 break;
2343 case OPC_ROTR:
2344 if (uimm != 0) {
2345 TCGv_i32 t1 = tcg_temp_new_i32();
2347 tcg_gen_trunc_tl_i32(t1, t0);
2348 tcg_gen_rotri_i32(t1, t1, uimm);
2349 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2350 tcg_temp_free_i32(t1);
2351 } else {
2352 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2354 opn = "rotr";
2355 break;
2356 #if defined(TARGET_MIPS64)
2357 case OPC_DSLL:
2358 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2359 opn = "dsll";
2360 break;
2361 case OPC_DSRA:
2362 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2363 opn = "dsra";
2364 break;
2365 case OPC_DSRL:
2366 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2367 opn = "dsrl";
2368 break;
2369 case OPC_DROTR:
2370 if (uimm != 0) {
2371 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2372 } else {
2373 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2375 opn = "drotr";
2376 break;
2377 case OPC_DSLL32:
2378 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2379 opn = "dsll32";
2380 break;
2381 case OPC_DSRA32:
2382 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2383 opn = "dsra32";
2384 break;
2385 case OPC_DSRL32:
2386 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2387 opn = "dsrl32";
2388 break;
2389 case OPC_DROTR32:
2390 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2391 opn = "drotr32";
2392 break;
2393 #endif
2395 (void)opn; /* avoid a compiler warning */
2396 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2397 tcg_temp_free(t0);
2400 /* Arithmetic */
2401 static void gen_arith(DisasContext *ctx, uint32_t opc,
2402 int rd, int rs, int rt)
2404 const char *opn = "arith";
2406 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2407 && opc != OPC_DADD && opc != OPC_DSUB) {
2408 /* If no destination, treat it as a NOP.
2409 For add & sub, we must generate the overflow exception when needed. */
2410 MIPS_DEBUG("NOP");
2411 return;
2414 switch (opc) {
2415 case OPC_ADD:
2417 TCGv t0 = tcg_temp_local_new();
2418 TCGv t1 = tcg_temp_new();
2419 TCGv t2 = tcg_temp_new();
2420 int l1 = gen_new_label();
2422 gen_load_gpr(t1, rs);
2423 gen_load_gpr(t2, rt);
2424 tcg_gen_add_tl(t0, t1, t2);
2425 tcg_gen_ext32s_tl(t0, t0);
2426 tcg_gen_xor_tl(t1, t1, t2);
2427 tcg_gen_xor_tl(t2, t0, t2);
2428 tcg_gen_andc_tl(t1, t2, t1);
2429 tcg_temp_free(t2);
2430 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2431 tcg_temp_free(t1);
2432 /* operands of same sign, result different sign */
2433 generate_exception(ctx, EXCP_OVERFLOW);
2434 gen_set_label(l1);
2435 gen_store_gpr(t0, rd);
2436 tcg_temp_free(t0);
2438 opn = "add";
2439 break;
2440 case OPC_ADDU:
2441 if (rs != 0 && rt != 0) {
2442 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2443 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2444 } else if (rs == 0 && rt != 0) {
2445 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2446 } else if (rs != 0 && rt == 0) {
2447 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2448 } else {
2449 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2451 opn = "addu";
2452 break;
2453 case OPC_SUB:
2455 TCGv t0 = tcg_temp_local_new();
2456 TCGv t1 = tcg_temp_new();
2457 TCGv t2 = tcg_temp_new();
2458 int l1 = gen_new_label();
2460 gen_load_gpr(t1, rs);
2461 gen_load_gpr(t2, rt);
2462 tcg_gen_sub_tl(t0, t1, t2);
2463 tcg_gen_ext32s_tl(t0, t0);
2464 tcg_gen_xor_tl(t2, t1, t2);
2465 tcg_gen_xor_tl(t1, t0, t1);
2466 tcg_gen_and_tl(t1, t1, t2);
2467 tcg_temp_free(t2);
2468 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2469 tcg_temp_free(t1);
2470 /* operands of different sign, first operand and result different sign */
2471 generate_exception(ctx, EXCP_OVERFLOW);
2472 gen_set_label(l1);
2473 gen_store_gpr(t0, rd);
2474 tcg_temp_free(t0);
2476 opn = "sub";
2477 break;
2478 case OPC_SUBU:
2479 if (rs != 0 && rt != 0) {
2480 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2481 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2482 } else if (rs == 0 && rt != 0) {
2483 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2484 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2485 } else if (rs != 0 && rt == 0) {
2486 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2487 } else {
2488 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2490 opn = "subu";
2491 break;
2492 #if defined(TARGET_MIPS64)
2493 case OPC_DADD:
2495 TCGv t0 = tcg_temp_local_new();
2496 TCGv t1 = tcg_temp_new();
2497 TCGv t2 = tcg_temp_new();
2498 int l1 = gen_new_label();
2500 gen_load_gpr(t1, rs);
2501 gen_load_gpr(t2, rt);
2502 tcg_gen_add_tl(t0, t1, t2);
2503 tcg_gen_xor_tl(t1, t1, t2);
2504 tcg_gen_xor_tl(t2, t0, t2);
2505 tcg_gen_andc_tl(t1, t2, t1);
2506 tcg_temp_free(t2);
2507 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2508 tcg_temp_free(t1);
2509 /* operands of same sign, result different sign */
2510 generate_exception(ctx, EXCP_OVERFLOW);
2511 gen_set_label(l1);
2512 gen_store_gpr(t0, rd);
2513 tcg_temp_free(t0);
2515 opn = "dadd";
2516 break;
2517 case OPC_DADDU:
2518 if (rs != 0 && rt != 0) {
2519 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2520 } else if (rs == 0 && rt != 0) {
2521 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2522 } else if (rs != 0 && rt == 0) {
2523 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2524 } else {
2525 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2527 opn = "daddu";
2528 break;
2529 case OPC_DSUB:
2531 TCGv t0 = tcg_temp_local_new();
2532 TCGv t1 = tcg_temp_new();
2533 TCGv t2 = tcg_temp_new();
2534 int l1 = gen_new_label();
2536 gen_load_gpr(t1, rs);
2537 gen_load_gpr(t2, rt);
2538 tcg_gen_sub_tl(t0, t1, t2);
2539 tcg_gen_xor_tl(t2, t1, t2);
2540 tcg_gen_xor_tl(t1, t0, t1);
2541 tcg_gen_and_tl(t1, t1, t2);
2542 tcg_temp_free(t2);
2543 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2544 tcg_temp_free(t1);
2545 /* operands of different sign, first operand and result different sign */
2546 generate_exception(ctx, EXCP_OVERFLOW);
2547 gen_set_label(l1);
2548 gen_store_gpr(t0, rd);
2549 tcg_temp_free(t0);
2551 opn = "dsub";
2552 break;
2553 case OPC_DSUBU:
2554 if (rs != 0 && rt != 0) {
2555 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2556 } else if (rs == 0 && rt != 0) {
2557 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2558 } else if (rs != 0 && rt == 0) {
2559 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2560 } else {
2561 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2563 opn = "dsubu";
2564 break;
2565 #endif
2566 case OPC_MUL:
2567 if (likely(rs != 0 && rt != 0)) {
2568 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2569 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2570 } else {
2571 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2573 opn = "mul";
2574 break;
2576 (void)opn; /* avoid a compiler warning */
2577 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2580 /* Conditional move */
2581 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2582 int rd, int rs, int rt)
2584 const char *opn = "cond move";
2585 TCGv t0, t1, t2;
2587 if (rd == 0) {
2588 /* If no destination, treat it as a NOP. */
2589 MIPS_DEBUG("NOP");
2590 return;
2593 t0 = tcg_temp_new();
2594 gen_load_gpr(t0, rt);
2595 t1 = tcg_const_tl(0);
2596 t2 = tcg_temp_new();
2597 gen_load_gpr(t2, rs);
2598 switch (opc) {
2599 case OPC_MOVN:
2600 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2601 opn = "movn";
2602 break;
2603 case OPC_MOVZ:
2604 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2605 opn = "movz";
2606 break;
2607 case OPC_SELNEZ:
2608 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2609 opn = "selnez";
2610 break;
2611 case OPC_SELEQZ:
2612 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2613 opn = "seleqz";
2614 break;
2616 tcg_temp_free(t2);
2617 tcg_temp_free(t1);
2618 tcg_temp_free(t0);
2620 (void)opn; /* avoid a compiler warning */
2621 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2624 /* Logic */
2625 static void gen_logic(DisasContext *ctx, uint32_t opc,
2626 int rd, int rs, int rt)
2628 const char *opn = "logic";
2630 if (rd == 0) {
2631 /* If no destination, treat it as a NOP. */
2632 MIPS_DEBUG("NOP");
2633 return;
2636 switch (opc) {
2637 case OPC_AND:
2638 if (likely(rs != 0 && rt != 0)) {
2639 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2640 } else {
2641 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2643 opn = "and";
2644 break;
2645 case OPC_NOR:
2646 if (rs != 0 && rt != 0) {
2647 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2648 } else if (rs == 0 && rt != 0) {
2649 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2650 } else if (rs != 0 && rt == 0) {
2651 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2652 } else {
2653 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2655 opn = "nor";
2656 break;
2657 case OPC_OR:
2658 if (likely(rs != 0 && rt != 0)) {
2659 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2660 } else if (rs == 0 && rt != 0) {
2661 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2662 } else if (rs != 0 && rt == 0) {
2663 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2664 } else {
2665 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2667 opn = "or";
2668 break;
2669 case OPC_XOR:
2670 if (likely(rs != 0 && rt != 0)) {
2671 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2672 } else if (rs == 0 && rt != 0) {
2673 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2674 } else if (rs != 0 && rt == 0) {
2675 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2676 } else {
2677 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2679 opn = "xor";
2680 break;
2682 (void)opn; /* avoid a compiler warning */
2683 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2686 /* Set on lower than */
2687 static void gen_slt(DisasContext *ctx, uint32_t opc,
2688 int rd, int rs, int rt)
2690 const char *opn = "slt";
2691 TCGv t0, t1;
2693 if (rd == 0) {
2694 /* If no destination, treat it as a NOP. */
2695 MIPS_DEBUG("NOP");
2696 return;
2699 t0 = tcg_temp_new();
2700 t1 = tcg_temp_new();
2701 gen_load_gpr(t0, rs);
2702 gen_load_gpr(t1, rt);
2703 switch (opc) {
2704 case OPC_SLT:
2705 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2706 opn = "slt";
2707 break;
2708 case OPC_SLTU:
2709 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2710 opn = "sltu";
2711 break;
2713 (void)opn; /* avoid a compiler warning */
2714 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2715 tcg_temp_free(t0);
2716 tcg_temp_free(t1);
2719 /* Shifts */
2720 static void gen_shift(DisasContext *ctx, uint32_t opc,
2721 int rd, int rs, int rt)
2723 const char *opn = "shifts";
2724 TCGv t0, t1;
2726 if (rd == 0) {
2727 /* If no destination, treat it as a NOP.
2728 For add & sub, we must generate the overflow exception when needed. */
2729 MIPS_DEBUG("NOP");
2730 return;
2733 t0 = tcg_temp_new();
2734 t1 = tcg_temp_new();
2735 gen_load_gpr(t0, rs);
2736 gen_load_gpr(t1, rt);
2737 switch (opc) {
2738 case OPC_SLLV:
2739 tcg_gen_andi_tl(t0, t0, 0x1f);
2740 tcg_gen_shl_tl(t0, t1, t0);
2741 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2742 opn = "sllv";
2743 break;
2744 case OPC_SRAV:
2745 tcg_gen_andi_tl(t0, t0, 0x1f);
2746 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2747 opn = "srav";
2748 break;
2749 case OPC_SRLV:
2750 tcg_gen_ext32u_tl(t1, t1);
2751 tcg_gen_andi_tl(t0, t0, 0x1f);
2752 tcg_gen_shr_tl(t0, t1, t0);
2753 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2754 opn = "srlv";
2755 break;
2756 case OPC_ROTRV:
2758 TCGv_i32 t2 = tcg_temp_new_i32();
2759 TCGv_i32 t3 = tcg_temp_new_i32();
2761 tcg_gen_trunc_tl_i32(t2, t0);
2762 tcg_gen_trunc_tl_i32(t3, t1);
2763 tcg_gen_andi_i32(t2, t2, 0x1f);
2764 tcg_gen_rotr_i32(t2, t3, t2);
2765 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2766 tcg_temp_free_i32(t2);
2767 tcg_temp_free_i32(t3);
2768 opn = "rotrv";
2770 break;
2771 #if defined(TARGET_MIPS64)
2772 case OPC_DSLLV:
2773 tcg_gen_andi_tl(t0, t0, 0x3f);
2774 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2775 opn = "dsllv";
2776 break;
2777 case OPC_DSRAV:
2778 tcg_gen_andi_tl(t0, t0, 0x3f);
2779 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2780 opn = "dsrav";
2781 break;
2782 case OPC_DSRLV:
2783 tcg_gen_andi_tl(t0, t0, 0x3f);
2784 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2785 opn = "dsrlv";
2786 break;
2787 case OPC_DROTRV:
2788 tcg_gen_andi_tl(t0, t0, 0x3f);
2789 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2790 opn = "drotrv";
2791 break;
2792 #endif
2794 (void)opn; /* avoid a compiler warning */
2795 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2796 tcg_temp_free(t0);
2797 tcg_temp_free(t1);
2800 /* Arithmetic on HI/LO registers */
2801 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2803 const char *opn = "hilo";
2805 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2806 /* Treat as NOP. */
2807 MIPS_DEBUG("NOP");
2808 return;
2811 if (acc != 0) {
2812 check_dsp(ctx);
2815 switch (opc) {
2816 case OPC_MFHI:
2817 #if defined(TARGET_MIPS64)
2818 if (acc != 0) {
2819 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2820 } else
2821 #endif
2823 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2825 opn = "mfhi";
2826 break;
2827 case OPC_MFLO:
2828 #if defined(TARGET_MIPS64)
2829 if (acc != 0) {
2830 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2831 } else
2832 #endif
2834 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2836 opn = "mflo";
2837 break;
2838 case OPC_MTHI:
2839 if (reg != 0) {
2840 #if defined(TARGET_MIPS64)
2841 if (acc != 0) {
2842 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2843 } else
2844 #endif
2846 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2848 } else {
2849 tcg_gen_movi_tl(cpu_HI[acc], 0);
2851 opn = "mthi";
2852 break;
2853 case OPC_MTLO:
2854 if (reg != 0) {
2855 #if defined(TARGET_MIPS64)
2856 if (acc != 0) {
2857 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2858 } else
2859 #endif
2861 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2863 } else {
2864 tcg_gen_movi_tl(cpu_LO[acc], 0);
2866 opn = "mtlo";
2867 break;
2869 (void)opn; /* avoid a compiler warning */
2870 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2873 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
2874 TCGMemOp memop)
2876 TCGv t0 = tcg_const_tl(addr);
2877 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
2878 gen_store_gpr(t0, reg);
2879 tcg_temp_free(t0);
2882 static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
2884 target_long offset;
2885 target_long addr;
2887 switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
2888 case OPC_ADDIUPC:
2889 if (rs != 0) {
2890 offset = sextract32(ctx->opcode << 2, 0, 21);
2891 addr = addr_add(ctx, ctx->pc, offset);
2892 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2894 break;
2895 case R6_OPC_LWPC:
2896 offset = sextract32(ctx->opcode << 2, 0, 21);
2897 addr = addr_add(ctx, ctx->pc, offset);
2898 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
2899 break;
2900 #if defined(TARGET_MIPS64)
2901 case OPC_LWUPC:
2902 check_mips_64(ctx);
2903 offset = sextract32(ctx->opcode << 2, 0, 21);
2904 addr = addr_add(ctx, ctx->pc, offset);
2905 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
2906 break;
2907 #endif
2908 default:
2909 switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
2910 case OPC_AUIPC:
2911 if (rs != 0) {
2912 offset = imm << 16;
2913 addr = addr_add(ctx, ctx->pc, offset);
2914 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2916 break;
2917 case OPC_ALUIPC:
2918 if (rs != 0) {
2919 offset = imm << 16;
2920 addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
2921 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2923 break;
2924 #if defined(TARGET_MIPS64)
2925 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
2926 case R6_OPC_LDPC + (1 << 16):
2927 case R6_OPC_LDPC + (2 << 16):
2928 case R6_OPC_LDPC + (3 << 16):
2929 check_mips_64(ctx);
2930 offset = sextract32(ctx->opcode << 3, 0, 21);
2931 addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
2932 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
2933 break;
2934 #endif
2935 default:
2936 MIPS_INVAL("OPC_PCREL");
2937 generate_exception(ctx, EXCP_RI);
2938 break;
2940 break;
2944 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
2946 const char *opn = "r6 mul/div";
2947 TCGv t0, t1;
2949 if (rd == 0) {
2950 /* Treat as NOP. */
2951 MIPS_DEBUG("NOP");
2952 return;
2955 t0 = tcg_temp_new();
2956 t1 = tcg_temp_new();
2958 gen_load_gpr(t0, rs);
2959 gen_load_gpr(t1, rt);
2961 switch (opc) {
2962 case R6_OPC_DIV:
2964 TCGv t2 = tcg_temp_new();
2965 TCGv t3 = tcg_temp_new();
2966 tcg_gen_ext32s_tl(t0, t0);
2967 tcg_gen_ext32s_tl(t1, t1);
2968 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2969 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2970 tcg_gen_and_tl(t2, t2, t3);
2971 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2972 tcg_gen_or_tl(t2, t2, t3);
2973 tcg_gen_movi_tl(t3, 0);
2974 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2975 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2976 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2977 tcg_temp_free(t3);
2978 tcg_temp_free(t2);
2980 opn = "div";
2981 break;
2982 case R6_OPC_MOD:
2984 TCGv t2 = tcg_temp_new();
2985 TCGv t3 = tcg_temp_new();
2986 tcg_gen_ext32s_tl(t0, t0);
2987 tcg_gen_ext32s_tl(t1, t1);
2988 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2989 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2990 tcg_gen_and_tl(t2, t2, t3);
2991 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2992 tcg_gen_or_tl(t2, t2, t3);
2993 tcg_gen_movi_tl(t3, 0);
2994 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2995 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2996 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2997 tcg_temp_free(t3);
2998 tcg_temp_free(t2);
3000 opn = "mod";
3001 break;
3002 case R6_OPC_DIVU:
3004 TCGv t2 = tcg_const_tl(0);
3005 TCGv t3 = tcg_const_tl(1);
3006 tcg_gen_ext32u_tl(t0, t0);
3007 tcg_gen_ext32u_tl(t1, t1);
3008 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3009 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3010 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3011 tcg_temp_free(t3);
3012 tcg_temp_free(t2);
3014 opn = "divu";
3015 break;
3016 case R6_OPC_MODU:
3018 TCGv t2 = tcg_const_tl(0);
3019 TCGv t3 = tcg_const_tl(1);
3020 tcg_gen_ext32u_tl(t0, t0);
3021 tcg_gen_ext32u_tl(t1, t1);
3022 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3023 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3024 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3025 tcg_temp_free(t3);
3026 tcg_temp_free(t2);
3028 opn = "modu";
3029 break;
3030 case R6_OPC_MUL:
3032 TCGv_i32 t2 = tcg_temp_new_i32();
3033 TCGv_i32 t3 = tcg_temp_new_i32();
3034 tcg_gen_trunc_tl_i32(t2, t0);
3035 tcg_gen_trunc_tl_i32(t3, t1);
3036 tcg_gen_mul_i32(t2, t2, t3);
3037 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3038 tcg_temp_free_i32(t2);
3039 tcg_temp_free_i32(t3);
3041 opn = "mul";
3042 break;
3043 case R6_OPC_MUH:
3045 TCGv_i32 t2 = tcg_temp_new_i32();
3046 TCGv_i32 t3 = tcg_temp_new_i32();
3047 tcg_gen_trunc_tl_i32(t2, t0);
3048 tcg_gen_trunc_tl_i32(t3, t1);
3049 tcg_gen_muls2_i32(t2, t3, t2, t3);
3050 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3051 tcg_temp_free_i32(t2);
3052 tcg_temp_free_i32(t3);
3054 opn = "muh";
3055 break;
3056 case R6_OPC_MULU:
3058 TCGv_i32 t2 = tcg_temp_new_i32();
3059 TCGv_i32 t3 = tcg_temp_new_i32();
3060 tcg_gen_trunc_tl_i32(t2, t0);
3061 tcg_gen_trunc_tl_i32(t3, t1);
3062 tcg_gen_mul_i32(t2, t2, t3);
3063 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3064 tcg_temp_free_i32(t2);
3065 tcg_temp_free_i32(t3);
3067 opn = "mulu";
3068 break;
3069 case R6_OPC_MUHU:
3071 TCGv_i32 t2 = tcg_temp_new_i32();
3072 TCGv_i32 t3 = tcg_temp_new_i32();
3073 tcg_gen_trunc_tl_i32(t2, t0);
3074 tcg_gen_trunc_tl_i32(t3, t1);
3075 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3076 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3077 tcg_temp_free_i32(t2);
3078 tcg_temp_free_i32(t3);
3080 opn = "muhu";
3081 break;
3082 #if defined(TARGET_MIPS64)
3083 case R6_OPC_DDIV:
3085 TCGv t2 = tcg_temp_new();
3086 TCGv t3 = tcg_temp_new();
3087 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3088 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3089 tcg_gen_and_tl(t2, t2, t3);
3090 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3091 tcg_gen_or_tl(t2, t2, t3);
3092 tcg_gen_movi_tl(t3, 0);
3093 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3094 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3095 tcg_temp_free(t3);
3096 tcg_temp_free(t2);
3098 opn = "ddiv";
3099 break;
3100 case R6_OPC_DMOD:
3102 TCGv t2 = tcg_temp_new();
3103 TCGv t3 = tcg_temp_new();
3104 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3105 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3106 tcg_gen_and_tl(t2, t2, t3);
3107 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3108 tcg_gen_or_tl(t2, t2, t3);
3109 tcg_gen_movi_tl(t3, 0);
3110 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3111 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3112 tcg_temp_free(t3);
3113 tcg_temp_free(t2);
3115 opn = "dmod";
3116 break;
3117 case R6_OPC_DDIVU:
3119 TCGv t2 = tcg_const_tl(0);
3120 TCGv t3 = tcg_const_tl(1);
3121 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3122 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3123 tcg_temp_free(t3);
3124 tcg_temp_free(t2);
3126 opn = "ddivu";
3127 break;
3128 case R6_OPC_DMODU:
3130 TCGv t2 = tcg_const_tl(0);
3131 TCGv t3 = tcg_const_tl(1);
3132 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3133 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3134 tcg_temp_free(t3);
3135 tcg_temp_free(t2);
3137 opn = "dmodu";
3138 break;
3139 case R6_OPC_DMUL:
3140 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3141 opn = "dmul";
3142 break;
3143 case R6_OPC_DMUH:
3145 TCGv t2 = tcg_temp_new();
3146 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3147 tcg_temp_free(t2);
3149 opn = "dmuh";
3150 break;
3151 case R6_OPC_DMULU:
3152 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3153 opn = "dmulu";
3154 break;
3155 case R6_OPC_DMUHU:
3157 TCGv t2 = tcg_temp_new();
3158 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3159 tcg_temp_free(t2);
3161 opn = "dmuhu";
3162 break;
3163 #endif
3164 default:
3165 MIPS_INVAL(opn);
3166 generate_exception(ctx, EXCP_RI);
3167 goto out;
3169 (void)opn; /* avoid a compiler warning */
3170 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3171 out:
3172 tcg_temp_free(t0);
3173 tcg_temp_free(t1);
3176 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3177 int acc, int rs, int rt)
3179 const char *opn = "mul/div";
3180 TCGv t0, t1;
3182 t0 = tcg_temp_new();
3183 t1 = tcg_temp_new();
3185 gen_load_gpr(t0, rs);
3186 gen_load_gpr(t1, rt);
3188 if (acc != 0) {
3189 check_dsp(ctx);
3192 switch (opc) {
3193 case OPC_DIV:
3195 TCGv t2 = tcg_temp_new();
3196 TCGv t3 = tcg_temp_new();
3197 tcg_gen_ext32s_tl(t0, t0);
3198 tcg_gen_ext32s_tl(t1, t1);
3199 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3200 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3201 tcg_gen_and_tl(t2, t2, t3);
3202 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3203 tcg_gen_or_tl(t2, t2, t3);
3204 tcg_gen_movi_tl(t3, 0);
3205 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3206 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3207 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3208 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3209 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3210 tcg_temp_free(t3);
3211 tcg_temp_free(t2);
3213 opn = "div";
3214 break;
3215 case OPC_DIVU:
3217 TCGv t2 = tcg_const_tl(0);
3218 TCGv t3 = tcg_const_tl(1);
3219 tcg_gen_ext32u_tl(t0, t0);
3220 tcg_gen_ext32u_tl(t1, t1);
3221 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3222 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3223 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3224 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3225 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3226 tcg_temp_free(t3);
3227 tcg_temp_free(t2);
3229 opn = "divu";
3230 break;
3231 case OPC_MULT:
3233 TCGv_i32 t2 = tcg_temp_new_i32();
3234 TCGv_i32 t3 = tcg_temp_new_i32();
3235 tcg_gen_trunc_tl_i32(t2, t0);
3236 tcg_gen_trunc_tl_i32(t3, t1);
3237 tcg_gen_muls2_i32(t2, t3, t2, t3);
3238 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3239 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3240 tcg_temp_free_i32(t2);
3241 tcg_temp_free_i32(t3);
3243 opn = "mult";
3244 break;
3245 case OPC_MULTU:
3247 TCGv_i32 t2 = tcg_temp_new_i32();
3248 TCGv_i32 t3 = tcg_temp_new_i32();
3249 tcg_gen_trunc_tl_i32(t2, t0);
3250 tcg_gen_trunc_tl_i32(t3, t1);
3251 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3252 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3253 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3254 tcg_temp_free_i32(t2);
3255 tcg_temp_free_i32(t3);
3257 opn = "multu";
3258 break;
3259 #if defined(TARGET_MIPS64)
3260 case OPC_DDIV:
3262 TCGv t2 = tcg_temp_new();
3263 TCGv t3 = tcg_temp_new();
3264 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3265 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3266 tcg_gen_and_tl(t2, t2, t3);
3267 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3268 tcg_gen_or_tl(t2, t2, t3);
3269 tcg_gen_movi_tl(t3, 0);
3270 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3271 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3272 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3273 tcg_temp_free(t3);
3274 tcg_temp_free(t2);
3276 opn = "ddiv";
3277 break;
3278 case OPC_DDIVU:
3280 TCGv t2 = tcg_const_tl(0);
3281 TCGv t3 = tcg_const_tl(1);
3282 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3283 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3284 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3285 tcg_temp_free(t3);
3286 tcg_temp_free(t2);
3288 opn = "ddivu";
3289 break;
3290 case OPC_DMULT:
3291 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3292 opn = "dmult";
3293 break;
3294 case OPC_DMULTU:
3295 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3296 opn = "dmultu";
3297 break;
3298 #endif
3299 case OPC_MADD:
3301 TCGv_i64 t2 = tcg_temp_new_i64();
3302 TCGv_i64 t3 = tcg_temp_new_i64();
3304 tcg_gen_ext_tl_i64(t2, t0);
3305 tcg_gen_ext_tl_i64(t3, t1);
3306 tcg_gen_mul_i64(t2, t2, t3);
3307 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3308 tcg_gen_add_i64(t2, t2, t3);
3309 tcg_temp_free_i64(t3);
3310 tcg_gen_trunc_i64_tl(t0, t2);
3311 tcg_gen_shri_i64(t2, t2, 32);
3312 tcg_gen_trunc_i64_tl(t1, t2);
3313 tcg_temp_free_i64(t2);
3314 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3315 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3317 opn = "madd";
3318 break;
3319 case OPC_MADDU:
3321 TCGv_i64 t2 = tcg_temp_new_i64();
3322 TCGv_i64 t3 = tcg_temp_new_i64();
3324 tcg_gen_ext32u_tl(t0, t0);
3325 tcg_gen_ext32u_tl(t1, t1);
3326 tcg_gen_extu_tl_i64(t2, t0);
3327 tcg_gen_extu_tl_i64(t3, t1);
3328 tcg_gen_mul_i64(t2, t2, t3);
3329 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3330 tcg_gen_add_i64(t2, t2, t3);
3331 tcg_temp_free_i64(t3);
3332 tcg_gen_trunc_i64_tl(t0, t2);
3333 tcg_gen_shri_i64(t2, t2, 32);
3334 tcg_gen_trunc_i64_tl(t1, t2);
3335 tcg_temp_free_i64(t2);
3336 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3337 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3339 opn = "maddu";
3340 break;
3341 case OPC_MSUB:
3343 TCGv_i64 t2 = tcg_temp_new_i64();
3344 TCGv_i64 t3 = tcg_temp_new_i64();
3346 tcg_gen_ext_tl_i64(t2, t0);
3347 tcg_gen_ext_tl_i64(t3, t1);
3348 tcg_gen_mul_i64(t2, t2, t3);
3349 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3350 tcg_gen_sub_i64(t2, t3, t2);
3351 tcg_temp_free_i64(t3);
3352 tcg_gen_trunc_i64_tl(t0, t2);
3353 tcg_gen_shri_i64(t2, t2, 32);
3354 tcg_gen_trunc_i64_tl(t1, t2);
3355 tcg_temp_free_i64(t2);
3356 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3357 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3359 opn = "msub";
3360 break;
3361 case OPC_MSUBU:
3363 TCGv_i64 t2 = tcg_temp_new_i64();
3364 TCGv_i64 t3 = tcg_temp_new_i64();
3366 tcg_gen_ext32u_tl(t0, t0);
3367 tcg_gen_ext32u_tl(t1, t1);
3368 tcg_gen_extu_tl_i64(t2, t0);
3369 tcg_gen_extu_tl_i64(t3, t1);
3370 tcg_gen_mul_i64(t2, t2, t3);
3371 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3372 tcg_gen_sub_i64(t2, t3, t2);
3373 tcg_temp_free_i64(t3);
3374 tcg_gen_trunc_i64_tl(t0, t2);
3375 tcg_gen_shri_i64(t2, t2, 32);
3376 tcg_gen_trunc_i64_tl(t1, t2);
3377 tcg_temp_free_i64(t2);
3378 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3379 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3381 opn = "msubu";
3382 break;
3383 default:
3384 MIPS_INVAL(opn);
3385 generate_exception(ctx, EXCP_RI);
3386 goto out;
3388 (void)opn; /* avoid a compiler warning */
3389 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3390 out:
3391 tcg_temp_free(t0);
3392 tcg_temp_free(t1);
3395 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3396 int rd, int rs, int rt)
3398 const char *opn = "mul vr54xx";
3399 TCGv t0 = tcg_temp_new();
3400 TCGv t1 = tcg_temp_new();
3402 gen_load_gpr(t0, rs);
3403 gen_load_gpr(t1, rt);
3405 switch (opc) {
3406 case OPC_VR54XX_MULS:
3407 gen_helper_muls(t0, cpu_env, t0, t1);
3408 opn = "muls";
3409 break;
3410 case OPC_VR54XX_MULSU:
3411 gen_helper_mulsu(t0, cpu_env, t0, t1);
3412 opn = "mulsu";
3413 break;
3414 case OPC_VR54XX_MACC:
3415 gen_helper_macc(t0, cpu_env, t0, t1);
3416 opn = "macc";
3417 break;
3418 case OPC_VR54XX_MACCU:
3419 gen_helper_maccu(t0, cpu_env, t0, t1);
3420 opn = "maccu";
3421 break;
3422 case OPC_VR54XX_MSAC:
3423 gen_helper_msac(t0, cpu_env, t0, t1);
3424 opn = "msac";
3425 break;
3426 case OPC_VR54XX_MSACU:
3427 gen_helper_msacu(t0, cpu_env, t0, t1);
3428 opn = "msacu";
3429 break;
3430 case OPC_VR54XX_MULHI:
3431 gen_helper_mulhi(t0, cpu_env, t0, t1);
3432 opn = "mulhi";
3433 break;
3434 case OPC_VR54XX_MULHIU:
3435 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3436 opn = "mulhiu";
3437 break;
3438 case OPC_VR54XX_MULSHI:
3439 gen_helper_mulshi(t0, cpu_env, t0, t1);
3440 opn = "mulshi";
3441 break;
3442 case OPC_VR54XX_MULSHIU:
3443 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3444 opn = "mulshiu";
3445 break;
3446 case OPC_VR54XX_MACCHI:
3447 gen_helper_macchi(t0, cpu_env, t0, t1);
3448 opn = "macchi";
3449 break;
3450 case OPC_VR54XX_MACCHIU:
3451 gen_helper_macchiu(t0, cpu_env, t0, t1);
3452 opn = "macchiu";
3453 break;
3454 case OPC_VR54XX_MSACHI:
3455 gen_helper_msachi(t0, cpu_env, t0, t1);
3456 opn = "msachi";
3457 break;
3458 case OPC_VR54XX_MSACHIU:
3459 gen_helper_msachiu(t0, cpu_env, t0, t1);
3460 opn = "msachiu";
3461 break;
3462 default:
3463 MIPS_INVAL("mul vr54xx");
3464 generate_exception(ctx, EXCP_RI);
3465 goto out;
3467 gen_store_gpr(t0, rd);
3468 (void)opn; /* avoid a compiler warning */
3469 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3471 out:
3472 tcg_temp_free(t0);
3473 tcg_temp_free(t1);
3476 static void gen_cl (DisasContext *ctx, uint32_t opc,
3477 int rd, int rs)
3479 const char *opn = "CLx";
3480 TCGv t0;
3482 if (rd == 0) {
3483 /* Treat as NOP. */
3484 MIPS_DEBUG("NOP");
3485 return;
3487 t0 = tcg_temp_new();
3488 gen_load_gpr(t0, rs);
3489 switch (opc) {
3490 case OPC_CLO:
3491 case R6_OPC_CLO:
3492 gen_helper_clo(cpu_gpr[rd], t0);
3493 opn = "clo";
3494 break;
3495 case OPC_CLZ:
3496 case R6_OPC_CLZ:
3497 gen_helper_clz(cpu_gpr[rd], t0);
3498 opn = "clz";
3499 break;
3500 #if defined(TARGET_MIPS64)
3501 case OPC_DCLO:
3502 case R6_OPC_DCLO:
3503 gen_helper_dclo(cpu_gpr[rd], t0);
3504 opn = "dclo";
3505 break;
3506 case OPC_DCLZ:
3507 case R6_OPC_DCLZ:
3508 gen_helper_dclz(cpu_gpr[rd], t0);
3509 opn = "dclz";
3510 break;
3511 #endif
3513 (void)opn; /* avoid a compiler warning */
3514 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3515 tcg_temp_free(t0);
3518 /* Godson integer instructions */
3519 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3520 int rd, int rs, int rt)
3522 const char *opn = "loongson";
3523 TCGv t0, t1;
3525 if (rd == 0) {
3526 /* Treat as NOP. */
3527 MIPS_DEBUG("NOP");
3528 return;
3531 switch (opc) {
3532 case OPC_MULT_G_2E:
3533 case OPC_MULT_G_2F:
3534 case OPC_MULTU_G_2E:
3535 case OPC_MULTU_G_2F:
3536 #if defined(TARGET_MIPS64)
3537 case OPC_DMULT_G_2E:
3538 case OPC_DMULT_G_2F:
3539 case OPC_DMULTU_G_2E:
3540 case OPC_DMULTU_G_2F:
3541 #endif
3542 t0 = tcg_temp_new();
3543 t1 = tcg_temp_new();
3544 break;
3545 default:
3546 t0 = tcg_temp_local_new();
3547 t1 = tcg_temp_local_new();
3548 break;
3551 gen_load_gpr(t0, rs);
3552 gen_load_gpr(t1, rt);
3554 switch (opc) {
3555 case OPC_MULT_G_2E:
3556 case OPC_MULT_G_2F:
3557 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3558 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3559 opn = "mult.g";
3560 break;
3561 case OPC_MULTU_G_2E:
3562 case OPC_MULTU_G_2F:
3563 tcg_gen_ext32u_tl(t0, t0);
3564 tcg_gen_ext32u_tl(t1, t1);
3565 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3566 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3567 opn = "multu.g";
3568 break;
3569 case OPC_DIV_G_2E:
3570 case OPC_DIV_G_2F:
3572 int l1 = gen_new_label();
3573 int l2 = gen_new_label();
3574 int l3 = gen_new_label();
3575 tcg_gen_ext32s_tl(t0, t0);
3576 tcg_gen_ext32s_tl(t1, t1);
3577 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3578 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3579 tcg_gen_br(l3);
3580 gen_set_label(l1);
3581 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3582 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3583 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3584 tcg_gen_br(l3);
3585 gen_set_label(l2);
3586 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3587 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3588 gen_set_label(l3);
3590 opn = "div.g";
3591 break;
3592 case OPC_DIVU_G_2E:
3593 case OPC_DIVU_G_2F:
3595 int l1 = gen_new_label();
3596 int l2 = gen_new_label();
3597 tcg_gen_ext32u_tl(t0, t0);
3598 tcg_gen_ext32u_tl(t1, t1);
3599 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3600 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3601 tcg_gen_br(l2);
3602 gen_set_label(l1);
3603 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3604 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3605 gen_set_label(l2);
3607 opn = "divu.g";
3608 break;
3609 case OPC_MOD_G_2E:
3610 case OPC_MOD_G_2F:
3612 int l1 = gen_new_label();
3613 int l2 = gen_new_label();
3614 int l3 = gen_new_label();
3615 tcg_gen_ext32u_tl(t0, t0);
3616 tcg_gen_ext32u_tl(t1, t1);
3617 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3618 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3619 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3620 gen_set_label(l1);
3621 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3622 tcg_gen_br(l3);
3623 gen_set_label(l2);
3624 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3625 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3626 gen_set_label(l3);
3628 opn = "mod.g";
3629 break;
3630 case OPC_MODU_G_2E:
3631 case OPC_MODU_G_2F:
3633 int l1 = gen_new_label();
3634 int l2 = gen_new_label();
3635 tcg_gen_ext32u_tl(t0, t0);
3636 tcg_gen_ext32u_tl(t1, t1);
3637 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3638 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3639 tcg_gen_br(l2);
3640 gen_set_label(l1);
3641 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3642 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3643 gen_set_label(l2);
3645 opn = "modu.g";
3646 break;
3647 #if defined(TARGET_MIPS64)
3648 case OPC_DMULT_G_2E:
3649 case OPC_DMULT_G_2F:
3650 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3651 opn = "dmult.g";
3652 break;
3653 case OPC_DMULTU_G_2E:
3654 case OPC_DMULTU_G_2F:
3655 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3656 opn = "dmultu.g";
3657 break;
3658 case OPC_DDIV_G_2E:
3659 case OPC_DDIV_G_2F:
3661 int l1 = gen_new_label();
3662 int l2 = gen_new_label();
3663 int l3 = gen_new_label();
3664 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3665 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3666 tcg_gen_br(l3);
3667 gen_set_label(l1);
3668 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3669 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3670 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3671 tcg_gen_br(l3);
3672 gen_set_label(l2);
3673 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3674 gen_set_label(l3);
3676 opn = "ddiv.g";
3677 break;
3678 case OPC_DDIVU_G_2E:
3679 case OPC_DDIVU_G_2F:
3681 int l1 = gen_new_label();
3682 int l2 = gen_new_label();
3683 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3684 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3685 tcg_gen_br(l2);
3686 gen_set_label(l1);
3687 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3688 gen_set_label(l2);
3690 opn = "ddivu.g";
3691 break;
3692 case OPC_DMOD_G_2E:
3693 case OPC_DMOD_G_2F:
3695 int l1 = gen_new_label();
3696 int l2 = gen_new_label();
3697 int l3 = gen_new_label();
3698 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3699 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3700 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3701 gen_set_label(l1);
3702 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3703 tcg_gen_br(l3);
3704 gen_set_label(l2);
3705 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3706 gen_set_label(l3);
3708 opn = "dmod.g";
3709 break;
3710 case OPC_DMODU_G_2E:
3711 case OPC_DMODU_G_2F:
3713 int l1 = gen_new_label();
3714 int l2 = gen_new_label();
3715 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3716 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3717 tcg_gen_br(l2);
3718 gen_set_label(l1);
3719 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3720 gen_set_label(l2);
3722 opn = "dmodu.g";
3723 break;
3724 #endif
3727 (void)opn; /* avoid a compiler warning */
3728 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3729 tcg_temp_free(t0);
3730 tcg_temp_free(t1);
3733 /* Loongson multimedia instructions */
3734 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3736 const char *opn = "loongson_cp2";
3737 uint32_t opc, shift_max;
3738 TCGv_i64 t0, t1;
3740 opc = MASK_LMI(ctx->opcode);
3741 switch (opc) {
3742 case OPC_ADD_CP2:
3743 case OPC_SUB_CP2:
3744 case OPC_DADD_CP2:
3745 case OPC_DSUB_CP2:
3746 t0 = tcg_temp_local_new_i64();
3747 t1 = tcg_temp_local_new_i64();
3748 break;
3749 default:
3750 t0 = tcg_temp_new_i64();
3751 t1 = tcg_temp_new_i64();
3752 break;
3755 gen_load_fpr64(ctx, t0, rs);
3756 gen_load_fpr64(ctx, t1, rt);
3758 #define LMI_HELPER(UP, LO) \
3759 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3760 #define LMI_HELPER_1(UP, LO) \
3761 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3762 #define LMI_DIRECT(UP, LO, OP) \
3763 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3765 switch (opc) {
3766 LMI_HELPER(PADDSH, paddsh);
3767 LMI_HELPER(PADDUSH, paddush);
3768 LMI_HELPER(PADDH, paddh);
3769 LMI_HELPER(PADDW, paddw);
3770 LMI_HELPER(PADDSB, paddsb);
3771 LMI_HELPER(PADDUSB, paddusb);
3772 LMI_HELPER(PADDB, paddb);
3774 LMI_HELPER(PSUBSH, psubsh);
3775 LMI_HELPER(PSUBUSH, psubush);
3776 LMI_HELPER(PSUBH, psubh);
3777 LMI_HELPER(PSUBW, psubw);
3778 LMI_HELPER(PSUBSB, psubsb);
3779 LMI_HELPER(PSUBUSB, psubusb);
3780 LMI_HELPER(PSUBB, psubb);
3782 LMI_HELPER(PSHUFH, pshufh);
3783 LMI_HELPER(PACKSSWH, packsswh);
3784 LMI_HELPER(PACKSSHB, packsshb);
3785 LMI_HELPER(PACKUSHB, packushb);
3787 LMI_HELPER(PUNPCKLHW, punpcklhw);
3788 LMI_HELPER(PUNPCKHHW, punpckhhw);
3789 LMI_HELPER(PUNPCKLBH, punpcklbh);
3790 LMI_HELPER(PUNPCKHBH, punpckhbh);
3791 LMI_HELPER(PUNPCKLWD, punpcklwd);
3792 LMI_HELPER(PUNPCKHWD, punpckhwd);
3794 LMI_HELPER(PAVGH, pavgh);
3795 LMI_HELPER(PAVGB, pavgb);
3796 LMI_HELPER(PMAXSH, pmaxsh);
3797 LMI_HELPER(PMINSH, pminsh);
3798 LMI_HELPER(PMAXUB, pmaxub);
3799 LMI_HELPER(PMINUB, pminub);
3801 LMI_HELPER(PCMPEQW, pcmpeqw);
3802 LMI_HELPER(PCMPGTW, pcmpgtw);
3803 LMI_HELPER(PCMPEQH, pcmpeqh);
3804 LMI_HELPER(PCMPGTH, pcmpgth);
3805 LMI_HELPER(PCMPEQB, pcmpeqb);
3806 LMI_HELPER(PCMPGTB, pcmpgtb);
3808 LMI_HELPER(PSLLW, psllw);
3809 LMI_HELPER(PSLLH, psllh);
3810 LMI_HELPER(PSRLW, psrlw);
3811 LMI_HELPER(PSRLH, psrlh);
3812 LMI_HELPER(PSRAW, psraw);
3813 LMI_HELPER(PSRAH, psrah);
3815 LMI_HELPER(PMULLH, pmullh);
3816 LMI_HELPER(PMULHH, pmulhh);
3817 LMI_HELPER(PMULHUH, pmulhuh);
3818 LMI_HELPER(PMADDHW, pmaddhw);
3820 LMI_HELPER(PASUBUB, pasubub);
3821 LMI_HELPER_1(BIADD, biadd);
3822 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3824 LMI_DIRECT(PADDD, paddd, add);
3825 LMI_DIRECT(PSUBD, psubd, sub);
3826 LMI_DIRECT(XOR_CP2, xor, xor);
3827 LMI_DIRECT(NOR_CP2, nor, nor);
3828 LMI_DIRECT(AND_CP2, and, and);
3829 LMI_DIRECT(PANDN, pandn, andc);
3830 LMI_DIRECT(OR, or, or);
3832 case OPC_PINSRH_0:
3833 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3834 opn = "pinsrh_0";
3835 break;
3836 case OPC_PINSRH_1:
3837 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3838 opn = "pinsrh_1";
3839 break;
3840 case OPC_PINSRH_2:
3841 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3842 opn = "pinsrh_2";
3843 break;
3844 case OPC_PINSRH_3:
3845 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3846 opn = "pinsrh_3";
3847 break;
3849 case OPC_PEXTRH:
3850 tcg_gen_andi_i64(t1, t1, 3);
3851 tcg_gen_shli_i64(t1, t1, 4);
3852 tcg_gen_shr_i64(t0, t0, t1);
3853 tcg_gen_ext16u_i64(t0, t0);
3854 opn = "pextrh";
3855 break;
3857 case OPC_ADDU_CP2:
3858 tcg_gen_add_i64(t0, t0, t1);
3859 tcg_gen_ext32s_i64(t0, t0);
3860 opn = "addu";
3861 break;
3862 case OPC_SUBU_CP2:
3863 tcg_gen_sub_i64(t0, t0, t1);
3864 tcg_gen_ext32s_i64(t0, t0);
3865 opn = "addu";
3866 break;
3868 case OPC_SLL_CP2:
3869 opn = "sll";
3870 shift_max = 32;
3871 goto do_shift;
3872 case OPC_SRL_CP2:
3873 opn = "srl";
3874 shift_max = 32;
3875 goto do_shift;
3876 case OPC_SRA_CP2:
3877 opn = "sra";
3878 shift_max = 32;
3879 goto do_shift;
3880 case OPC_DSLL_CP2:
3881 opn = "dsll";
3882 shift_max = 64;
3883 goto do_shift;
3884 case OPC_DSRL_CP2:
3885 opn = "dsrl";
3886 shift_max = 64;
3887 goto do_shift;
3888 case OPC_DSRA_CP2:
3889 opn = "dsra";
3890 shift_max = 64;
3891 goto do_shift;
3892 do_shift:
3893 /* Make sure shift count isn't TCG undefined behaviour. */
3894 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3896 switch (opc) {
3897 case OPC_SLL_CP2:
3898 case OPC_DSLL_CP2:
3899 tcg_gen_shl_i64(t0, t0, t1);
3900 break;
3901 case OPC_SRA_CP2:
3902 case OPC_DSRA_CP2:
3903 /* Since SRA is UndefinedResult without sign-extended inputs,
3904 we can treat SRA and DSRA the same. */
3905 tcg_gen_sar_i64(t0, t0, t1);
3906 break;
3907 case OPC_SRL_CP2:
3908 /* We want to shift in zeros for SRL; zero-extend first. */
3909 tcg_gen_ext32u_i64(t0, t0);
3910 /* FALLTHRU */
3911 case OPC_DSRL_CP2:
3912 tcg_gen_shr_i64(t0, t0, t1);
3913 break;
3916 if (shift_max == 32) {
3917 tcg_gen_ext32s_i64(t0, t0);
3920 /* Shifts larger than MAX produce zero. */
3921 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3922 tcg_gen_neg_i64(t1, t1);
3923 tcg_gen_and_i64(t0, t0, t1);
3924 break;
3926 case OPC_ADD_CP2:
3927 case OPC_DADD_CP2:
3929 TCGv_i64 t2 = tcg_temp_new_i64();
3930 int lab = gen_new_label();
3932 tcg_gen_mov_i64(t2, t0);
3933 tcg_gen_add_i64(t0, t1, t2);
3934 if (opc == OPC_ADD_CP2) {
3935 tcg_gen_ext32s_i64(t0, t0);
3937 tcg_gen_xor_i64(t1, t1, t2);
3938 tcg_gen_xor_i64(t2, t2, t0);
3939 tcg_gen_andc_i64(t1, t2, t1);
3940 tcg_temp_free_i64(t2);
3941 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3942 generate_exception(ctx, EXCP_OVERFLOW);
3943 gen_set_label(lab);
3945 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3946 break;
3949 case OPC_SUB_CP2:
3950 case OPC_DSUB_CP2:
3952 TCGv_i64 t2 = tcg_temp_new_i64();
3953 int lab = gen_new_label();
3955 tcg_gen_mov_i64(t2, t0);
3956 tcg_gen_sub_i64(t0, t1, t2);
3957 if (opc == OPC_SUB_CP2) {
3958 tcg_gen_ext32s_i64(t0, t0);
3960 tcg_gen_xor_i64(t1, t1, t2);
3961 tcg_gen_xor_i64(t2, t2, t0);
3962 tcg_gen_and_i64(t1, t1, t2);
3963 tcg_temp_free_i64(t2);
3964 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3965 generate_exception(ctx, EXCP_OVERFLOW);
3966 gen_set_label(lab);
3968 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3969 break;
3972 case OPC_PMULUW:
3973 tcg_gen_ext32u_i64(t0, t0);
3974 tcg_gen_ext32u_i64(t1, t1);
3975 tcg_gen_mul_i64(t0, t0, t1);
3976 opn = "pmuluw";
3977 break;
3979 case OPC_SEQU_CP2:
3980 case OPC_SEQ_CP2:
3981 case OPC_SLTU_CP2:
3982 case OPC_SLT_CP2:
3983 case OPC_SLEU_CP2:
3984 case OPC_SLE_CP2:
3985 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3986 FD field is the CC field? */
3987 default:
3988 MIPS_INVAL(opn);
3989 generate_exception(ctx, EXCP_RI);
3990 return;
3993 #undef LMI_HELPER
3994 #undef LMI_DIRECT
3996 gen_store_fpr64(ctx, t0, rd);
3998 (void)opn; /* avoid a compiler warning */
3999 MIPS_DEBUG("%s %s, %s, %s", opn,
4000 fregnames[rd], fregnames[rs], fregnames[rt]);
4001 tcg_temp_free_i64(t0);
4002 tcg_temp_free_i64(t1);
4005 /* Traps */
4006 static void gen_trap (DisasContext *ctx, uint32_t opc,
4007 int rs, int rt, int16_t imm)
4009 int cond;
4010 TCGv t0 = tcg_temp_new();
4011 TCGv t1 = tcg_temp_new();
4013 cond = 0;
4014 /* Load needed operands */
4015 switch (opc) {
4016 case OPC_TEQ:
4017 case OPC_TGE:
4018 case OPC_TGEU:
4019 case OPC_TLT:
4020 case OPC_TLTU:
4021 case OPC_TNE:
4022 /* Compare two registers */
4023 if (rs != rt) {
4024 gen_load_gpr(t0, rs);
4025 gen_load_gpr(t1, rt);
4026 cond = 1;
4028 break;
4029 case OPC_TEQI:
4030 case OPC_TGEI:
4031 case OPC_TGEIU:
4032 case OPC_TLTI:
4033 case OPC_TLTIU:
4034 case OPC_TNEI:
4035 /* Compare register to immediate */
4036 if (rs != 0 || imm != 0) {
4037 gen_load_gpr(t0, rs);
4038 tcg_gen_movi_tl(t1, (int32_t)imm);
4039 cond = 1;
4041 break;
4043 if (cond == 0) {
4044 switch (opc) {
4045 case OPC_TEQ: /* rs == rs */
4046 case OPC_TEQI: /* r0 == 0 */
4047 case OPC_TGE: /* rs >= rs */
4048 case OPC_TGEI: /* r0 >= 0 */
4049 case OPC_TGEU: /* rs >= rs unsigned */
4050 case OPC_TGEIU: /* r0 >= 0 unsigned */
4051 /* Always trap */
4052 generate_exception(ctx, EXCP_TRAP);
4053 break;
4054 case OPC_TLT: /* rs < rs */
4055 case OPC_TLTI: /* r0 < 0 */
4056 case OPC_TLTU: /* rs < rs unsigned */
4057 case OPC_TLTIU: /* r0 < 0 unsigned */
4058 case OPC_TNE: /* rs != rs */
4059 case OPC_TNEI: /* r0 != 0 */
4060 /* Never trap: treat as NOP. */
4061 break;
4063 } else {
4064 int l1 = gen_new_label();
4066 switch (opc) {
4067 case OPC_TEQ:
4068 case OPC_TEQI:
4069 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4070 break;
4071 case OPC_TGE:
4072 case OPC_TGEI:
4073 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4074 break;
4075 case OPC_TGEU:
4076 case OPC_TGEIU:
4077 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4078 break;
4079 case OPC_TLT:
4080 case OPC_TLTI:
4081 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4082 break;
4083 case OPC_TLTU:
4084 case OPC_TLTIU:
4085 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4086 break;
4087 case OPC_TNE:
4088 case OPC_TNEI:
4089 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4090 break;
4092 generate_exception(ctx, EXCP_TRAP);
4093 gen_set_label(l1);
4095 tcg_temp_free(t0);
4096 tcg_temp_free(t1);
4099 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4101 TranslationBlock *tb;
4102 tb = ctx->tb;
4103 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4104 likely(!ctx->singlestep_enabled)) {
4105 tcg_gen_goto_tb(n);
4106 gen_save_pc(dest);
4107 tcg_gen_exit_tb((uintptr_t)tb + n);
4108 } else {
4109 gen_save_pc(dest);
4110 if (ctx->singlestep_enabled) {
4111 save_cpu_state(ctx, 0);
4112 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4114 tcg_gen_exit_tb(0);
4118 /* Branches (before delay slot) */
4119 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4120 int insn_bytes,
4121 int rs, int rt, int32_t offset,
4122 int delayslot_size)
4124 target_ulong btgt = -1;
4125 int blink = 0;
4126 int bcond_compute = 0;
4127 TCGv t0 = tcg_temp_new();
4128 TCGv t1 = tcg_temp_new();
4130 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4131 #ifdef MIPS_DEBUG_DISAS
4132 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
4133 #endif
4134 generate_exception(ctx, EXCP_RI);
4135 goto out;
4138 /* Load needed operands */
4139 switch (opc) {
4140 case OPC_BEQ:
4141 case OPC_BEQL:
4142 case OPC_BNE:
4143 case OPC_BNEL:
4144 /* Compare two registers */
4145 if (rs != rt) {
4146 gen_load_gpr(t0, rs);
4147 gen_load_gpr(t1, rt);
4148 bcond_compute = 1;
4150 btgt = ctx->pc + insn_bytes + offset;
4151 break;
4152 case OPC_BGEZ:
4153 case OPC_BGEZAL:
4154 case OPC_BGEZALL:
4155 case OPC_BGEZL:
4156 case OPC_BGTZ:
4157 case OPC_BGTZL:
4158 case OPC_BLEZ:
4159 case OPC_BLEZL:
4160 case OPC_BLTZ:
4161 case OPC_BLTZAL:
4162 case OPC_BLTZALL:
4163 case OPC_BLTZL:
4164 /* Compare to zero */
4165 if (rs != 0) {
4166 gen_load_gpr(t0, rs);
4167 bcond_compute = 1;
4169 btgt = ctx->pc + insn_bytes + offset;
4170 break;
4171 case OPC_BPOSGE32:
4172 #if defined(TARGET_MIPS64)
4173 case OPC_BPOSGE64:
4174 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4175 #else
4176 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4177 #endif
4178 bcond_compute = 1;
4179 btgt = ctx->pc + insn_bytes + offset;
4180 break;
4181 case OPC_J:
4182 case OPC_JAL:
4183 case OPC_JALX:
4184 /* Jump to immediate */
4185 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4186 break;
4187 case OPC_JR:
4188 case OPC_JALR:
4189 /* Jump to register */
4190 if (offset != 0 && offset != 16) {
4191 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4192 others are reserved. */
4193 MIPS_INVAL("jump hint");
4194 generate_exception(ctx, EXCP_RI);
4195 goto out;
4197 gen_load_gpr(btarget, rs);
4198 break;
4199 default:
4200 MIPS_INVAL("branch/jump");
4201 generate_exception(ctx, EXCP_RI);
4202 goto out;
4204 if (bcond_compute == 0) {
4205 /* No condition to be computed */
4206 switch (opc) {
4207 case OPC_BEQ: /* rx == rx */
4208 case OPC_BEQL: /* rx == rx likely */
4209 case OPC_BGEZ: /* 0 >= 0 */
4210 case OPC_BGEZL: /* 0 >= 0 likely */
4211 case OPC_BLEZ: /* 0 <= 0 */
4212 case OPC_BLEZL: /* 0 <= 0 likely */
4213 /* Always take */
4214 ctx->hflags |= MIPS_HFLAG_B;
4215 MIPS_DEBUG("balways");
4216 break;
4217 case OPC_BGEZAL: /* 0 >= 0 */
4218 case OPC_BGEZALL: /* 0 >= 0 likely */
4219 /* Always take and link */
4220 blink = 31;
4221 ctx->hflags |= MIPS_HFLAG_B;
4222 MIPS_DEBUG("balways and link");
4223 break;
4224 case OPC_BNE: /* rx != rx */
4225 case OPC_BGTZ: /* 0 > 0 */
4226 case OPC_BLTZ: /* 0 < 0 */
4227 /* Treat as NOP. */
4228 MIPS_DEBUG("bnever (NOP)");
4229 goto out;
4230 case OPC_BLTZAL: /* 0 < 0 */
4231 /* Handle as an unconditional branch to get correct delay
4232 slot checking. */
4233 blink = 31;
4234 btgt = ctx->pc + insn_bytes + delayslot_size;
4235 ctx->hflags |= MIPS_HFLAG_B;
4236 MIPS_DEBUG("bnever and link");
4237 break;
4238 case OPC_BLTZALL: /* 0 < 0 likely */
4239 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4240 /* Skip the instruction in the delay slot */
4241 MIPS_DEBUG("bnever, link and skip");
4242 ctx->pc += 4;
4243 goto out;
4244 case OPC_BNEL: /* rx != rx likely */
4245 case OPC_BGTZL: /* 0 > 0 likely */
4246 case OPC_BLTZL: /* 0 < 0 likely */
4247 /* Skip the instruction in the delay slot */
4248 MIPS_DEBUG("bnever and skip");
4249 ctx->pc += 4;
4250 goto out;
4251 case OPC_J:
4252 ctx->hflags |= MIPS_HFLAG_B;
4253 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4254 break;
4255 case OPC_JALX:
4256 ctx->hflags |= MIPS_HFLAG_BX;
4257 /* Fallthrough */
4258 case OPC_JAL:
4259 blink = 31;
4260 ctx->hflags |= MIPS_HFLAG_B;
4261 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4262 break;
4263 case OPC_JR:
4264 ctx->hflags |= MIPS_HFLAG_BR;
4265 MIPS_DEBUG("jr %s", regnames[rs]);
4266 break;
4267 case OPC_JALR:
4268 blink = rt;
4269 ctx->hflags |= MIPS_HFLAG_BR;
4270 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4271 break;
4272 default:
4273 MIPS_INVAL("branch/jump");
4274 generate_exception(ctx, EXCP_RI);
4275 goto out;
4277 } else {
4278 switch (opc) {
4279 case OPC_BEQ:
4280 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4281 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4282 regnames[rs], regnames[rt], btgt);
4283 goto not_likely;
4284 case OPC_BEQL:
4285 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4286 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4287 regnames[rs], regnames[rt], btgt);
4288 goto likely;
4289 case OPC_BNE:
4290 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4291 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4292 regnames[rs], regnames[rt], btgt);
4293 goto not_likely;
4294 case OPC_BNEL:
4295 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4296 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4297 regnames[rs], regnames[rt], btgt);
4298 goto likely;
4299 case OPC_BGEZ:
4300 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4301 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4302 goto not_likely;
4303 case OPC_BGEZL:
4304 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4305 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4306 goto likely;
4307 case OPC_BGEZAL:
4308 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4309 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4310 blink = 31;
4311 goto not_likely;
4312 case OPC_BGEZALL:
4313 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4314 blink = 31;
4315 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4316 goto likely;
4317 case OPC_BGTZ:
4318 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4319 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4320 goto not_likely;
4321 case OPC_BGTZL:
4322 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4323 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4324 goto likely;
4325 case OPC_BLEZ:
4326 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4327 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4328 goto not_likely;
4329 case OPC_BLEZL:
4330 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4331 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4332 goto likely;
4333 case OPC_BLTZ:
4334 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4335 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4336 goto not_likely;
4337 case OPC_BLTZL:
4338 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4339 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4340 goto likely;
4341 case OPC_BPOSGE32:
4342 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4343 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4344 goto not_likely;
4345 #if defined(TARGET_MIPS64)
4346 case OPC_BPOSGE64:
4347 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4348 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4349 goto not_likely;
4350 #endif
4351 case OPC_BLTZAL:
4352 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4353 blink = 31;
4354 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4355 not_likely:
4356 ctx->hflags |= MIPS_HFLAG_BC;
4357 break;
4358 case OPC_BLTZALL:
4359 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4360 blink = 31;
4361 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4362 likely:
4363 ctx->hflags |= MIPS_HFLAG_BL;
4364 break;
4365 default:
4366 MIPS_INVAL("conditional branch/jump");
4367 generate_exception(ctx, EXCP_RI);
4368 goto out;
4371 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4372 blink, ctx->hflags, btgt);
4374 ctx->btarget = btgt;
4376 switch (delayslot_size) {
4377 case 2:
4378 ctx->hflags |= MIPS_HFLAG_BDS16;
4379 break;
4380 case 4:
4381 ctx->hflags |= MIPS_HFLAG_BDS32;
4382 break;
4385 if (blink > 0) {
4386 int post_delay = insn_bytes + delayslot_size;
4387 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4389 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4392 out:
4393 if (insn_bytes == 2)
4394 ctx->hflags |= MIPS_HFLAG_B16;
4395 tcg_temp_free(t0);
4396 tcg_temp_free(t1);
4399 /* special3 bitfield operations */
4400 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4401 int rs, int lsb, int msb)
4403 TCGv t0 = tcg_temp_new();
4404 TCGv t1 = tcg_temp_new();
4406 gen_load_gpr(t1, rs);
4407 switch (opc) {
4408 case OPC_EXT:
4409 if (lsb + msb > 31)
4410 goto fail;
4411 tcg_gen_shri_tl(t0, t1, lsb);
4412 if (msb != 31) {
4413 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4414 } else {
4415 tcg_gen_ext32s_tl(t0, t0);
4417 break;
4418 #if defined(TARGET_MIPS64)
4419 case OPC_DEXTM:
4420 tcg_gen_shri_tl(t0, t1, lsb);
4421 if (msb != 31) {
4422 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4424 break;
4425 case OPC_DEXTU:
4426 tcg_gen_shri_tl(t0, t1, lsb + 32);
4427 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4428 break;
4429 case OPC_DEXT:
4430 tcg_gen_shri_tl(t0, t1, lsb);
4431 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4432 break;
4433 #endif
4434 case OPC_INS:
4435 if (lsb > msb)
4436 goto fail;
4437 gen_load_gpr(t0, rt);
4438 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4439 tcg_gen_ext32s_tl(t0, t0);
4440 break;
4441 #if defined(TARGET_MIPS64)
4442 case OPC_DINSM:
4443 gen_load_gpr(t0, rt);
4444 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
4445 break;
4446 case OPC_DINSU:
4447 gen_load_gpr(t0, rt);
4448 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
4449 break;
4450 case OPC_DINS:
4451 gen_load_gpr(t0, rt);
4452 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4453 break;
4454 #endif
4455 default:
4456 fail:
4457 MIPS_INVAL("bitops");
4458 generate_exception(ctx, EXCP_RI);
4459 tcg_temp_free(t0);
4460 tcg_temp_free(t1);
4461 return;
4463 gen_store_gpr(t0, rt);
4464 tcg_temp_free(t0);
4465 tcg_temp_free(t1);
4468 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4470 TCGv t0;
4472 if (rd == 0) {
4473 /* If no destination, treat it as a NOP. */
4474 MIPS_DEBUG("NOP");
4475 return;
4478 t0 = tcg_temp_new();
4479 gen_load_gpr(t0, rt);
4480 switch (op2) {
4481 case OPC_WSBH:
4483 TCGv t1 = tcg_temp_new();
4485 tcg_gen_shri_tl(t1, t0, 8);
4486 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4487 tcg_gen_shli_tl(t0, t0, 8);
4488 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4489 tcg_gen_or_tl(t0, t0, t1);
4490 tcg_temp_free(t1);
4491 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4493 break;
4494 case OPC_SEB:
4495 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4496 break;
4497 case OPC_SEH:
4498 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4499 break;
4500 #if defined(TARGET_MIPS64)
4501 case OPC_DSBH:
4503 TCGv t1 = tcg_temp_new();
4505 tcg_gen_shri_tl(t1, t0, 8);
4506 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4507 tcg_gen_shli_tl(t0, t0, 8);
4508 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4509 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4510 tcg_temp_free(t1);
4512 break;
4513 case OPC_DSHD:
4515 TCGv t1 = tcg_temp_new();
4517 tcg_gen_shri_tl(t1, t0, 16);
4518 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4519 tcg_gen_shli_tl(t0, t0, 16);
4520 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4521 tcg_gen_or_tl(t0, t0, t1);
4522 tcg_gen_shri_tl(t1, t0, 32);
4523 tcg_gen_shli_tl(t0, t0, 32);
4524 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4525 tcg_temp_free(t1);
4527 break;
4528 #endif
4529 default:
4530 MIPS_INVAL("bsfhl");
4531 generate_exception(ctx, EXCP_RI);
4532 tcg_temp_free(t0);
4533 return;
4535 tcg_temp_free(t0);
4538 #ifndef CONFIG_USER_ONLY
4539 /* CP0 (MMU and control) */
4540 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4542 TCGv_i32 t0 = tcg_temp_new_i32();
4544 tcg_gen_ld_i32(t0, cpu_env, off);
4545 tcg_gen_ext_i32_tl(arg, t0);
4546 tcg_temp_free_i32(t0);
4549 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4551 tcg_gen_ld_tl(arg, cpu_env, off);
4552 tcg_gen_ext32s_tl(arg, arg);
4555 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4557 TCGv_i32 t0 = tcg_temp_new_i32();
4559 tcg_gen_trunc_tl_i32(t0, arg);
4560 tcg_gen_st_i32(t0, cpu_env, off);
4561 tcg_temp_free_i32(t0);
4564 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
4566 tcg_gen_ext32s_tl(arg, arg);
4567 tcg_gen_st_tl(arg, cpu_env, off);
4570 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4572 const char *rn = "invalid";
4574 if (sel != 0)
4575 check_insn(ctx, ISA_MIPS32);
4577 switch (reg) {
4578 case 0:
4579 switch (sel) {
4580 case 0:
4581 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4582 rn = "Index";
4583 break;
4584 case 1:
4585 check_insn(ctx, ASE_MT);
4586 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4587 rn = "MVPControl";
4588 break;
4589 case 2:
4590 check_insn(ctx, ASE_MT);
4591 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4592 rn = "MVPConf0";
4593 break;
4594 case 3:
4595 check_insn(ctx, ASE_MT);
4596 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4597 rn = "MVPConf1";
4598 break;
4599 default:
4600 goto die;
4602 break;
4603 case 1:
4604 switch (sel) {
4605 case 0:
4606 gen_helper_mfc0_random(arg, cpu_env);
4607 rn = "Random";
4608 break;
4609 case 1:
4610 check_insn(ctx, ASE_MT);
4611 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4612 rn = "VPEControl";
4613 break;
4614 case 2:
4615 check_insn(ctx, ASE_MT);
4616 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4617 rn = "VPEConf0";
4618 break;
4619 case 3:
4620 check_insn(ctx, ASE_MT);
4621 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4622 rn = "VPEConf1";
4623 break;
4624 case 4:
4625 check_insn(ctx, ASE_MT);
4626 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4627 rn = "YQMask";
4628 break;
4629 case 5:
4630 check_insn(ctx, ASE_MT);
4631 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4632 rn = "VPESchedule";
4633 break;
4634 case 6:
4635 check_insn(ctx, ASE_MT);
4636 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4637 rn = "VPEScheFBack";
4638 break;
4639 case 7:
4640 check_insn(ctx, ASE_MT);
4641 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4642 rn = "VPEOpt";
4643 break;
4644 default:
4645 goto die;
4647 break;
4648 case 2:
4649 switch (sel) {
4650 case 0:
4651 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4652 tcg_gen_ext32s_tl(arg, arg);
4653 rn = "EntryLo0";
4654 break;
4655 case 1:
4656 check_insn(ctx, ASE_MT);
4657 gen_helper_mfc0_tcstatus(arg, cpu_env);
4658 rn = "TCStatus";
4659 break;
4660 case 2:
4661 check_insn(ctx, ASE_MT);
4662 gen_helper_mfc0_tcbind(arg, cpu_env);
4663 rn = "TCBind";
4664 break;
4665 case 3:
4666 check_insn(ctx, ASE_MT);
4667 gen_helper_mfc0_tcrestart(arg, cpu_env);
4668 rn = "TCRestart";
4669 break;
4670 case 4:
4671 check_insn(ctx, ASE_MT);
4672 gen_helper_mfc0_tchalt(arg, cpu_env);
4673 rn = "TCHalt";
4674 break;
4675 case 5:
4676 check_insn(ctx, ASE_MT);
4677 gen_helper_mfc0_tccontext(arg, cpu_env);
4678 rn = "TCContext";
4679 break;
4680 case 6:
4681 check_insn(ctx, ASE_MT);
4682 gen_helper_mfc0_tcschedule(arg, cpu_env);
4683 rn = "TCSchedule";
4684 break;
4685 case 7:
4686 check_insn(ctx, ASE_MT);
4687 gen_helper_mfc0_tcschefback(arg, cpu_env);
4688 rn = "TCScheFBack";
4689 break;
4690 default:
4691 goto die;
4693 break;
4694 case 3:
4695 switch (sel) {
4696 case 0:
4697 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4698 tcg_gen_ext32s_tl(arg, arg);
4699 rn = "EntryLo1";
4700 break;
4701 default:
4702 goto die;
4704 break;
4705 case 4:
4706 switch (sel) {
4707 case 0:
4708 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
4709 tcg_gen_ext32s_tl(arg, arg);
4710 rn = "Context";
4711 break;
4712 case 1:
4713 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
4714 rn = "ContextConfig";
4715 goto die;
4716 // break;
4717 case 2:
4718 if (ctx->ulri) {
4719 tcg_gen_ld32s_tl(arg, cpu_env,
4720 offsetof(CPUMIPSState,
4721 active_tc.CP0_UserLocal));
4722 rn = "UserLocal";
4723 } else {
4724 tcg_gen_movi_tl(arg, 0);
4726 break;
4727 default:
4728 goto die;
4730 break;
4731 case 5:
4732 switch (sel) {
4733 case 0:
4734 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
4735 rn = "PageMask";
4736 break;
4737 case 1:
4738 check_insn(ctx, ISA_MIPS32R2);
4739 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
4740 rn = "PageGrain";
4741 break;
4742 default:
4743 goto die;
4745 break;
4746 case 6:
4747 switch (sel) {
4748 case 0:
4749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
4750 rn = "Wired";
4751 break;
4752 case 1:
4753 check_insn(ctx, ISA_MIPS32R2);
4754 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
4755 rn = "SRSConf0";
4756 break;
4757 case 2:
4758 check_insn(ctx, ISA_MIPS32R2);
4759 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
4760 rn = "SRSConf1";
4761 break;
4762 case 3:
4763 check_insn(ctx, ISA_MIPS32R2);
4764 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
4765 rn = "SRSConf2";
4766 break;
4767 case 4:
4768 check_insn(ctx, ISA_MIPS32R2);
4769 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
4770 rn = "SRSConf3";
4771 break;
4772 case 5:
4773 check_insn(ctx, ISA_MIPS32R2);
4774 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
4775 rn = "SRSConf4";
4776 break;
4777 default:
4778 goto die;
4780 break;
4781 case 7:
4782 switch (sel) {
4783 case 0:
4784 check_insn(ctx, ISA_MIPS32R2);
4785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
4786 rn = "HWREna";
4787 break;
4788 default:
4789 goto die;
4791 break;
4792 case 8:
4793 switch (sel) {
4794 case 0:
4795 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
4796 tcg_gen_ext32s_tl(arg, arg);
4797 rn = "BadVAddr";
4798 break;
4799 default:
4800 goto die;
4802 break;
4803 case 9:
4804 switch (sel) {
4805 case 0:
4806 /* Mark as an IO operation because we read the time. */
4807 if (use_icount)
4808 gen_io_start();
4809 gen_helper_mfc0_count(arg, cpu_env);
4810 if (use_icount) {
4811 gen_io_end();
4813 /* Break the TB to be able to take timer interrupts immediately
4814 after reading count. */
4815 ctx->bstate = BS_STOP;
4816 rn = "Count";
4817 break;
4818 /* 6,7 are implementation dependent */
4819 default:
4820 goto die;
4822 break;
4823 case 10:
4824 switch (sel) {
4825 case 0:
4826 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
4827 tcg_gen_ext32s_tl(arg, arg);
4828 rn = "EntryHi";
4829 break;
4830 default:
4831 goto die;
4833 break;
4834 case 11:
4835 switch (sel) {
4836 case 0:
4837 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
4838 rn = "Compare";
4839 break;
4840 /* 6,7 are implementation dependent */
4841 default:
4842 goto die;
4844 break;
4845 case 12:
4846 switch (sel) {
4847 case 0:
4848 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
4849 rn = "Status";
4850 break;
4851 case 1:
4852 check_insn(ctx, ISA_MIPS32R2);
4853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
4854 rn = "IntCtl";
4855 break;
4856 case 2:
4857 check_insn(ctx, ISA_MIPS32R2);
4858 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
4859 rn = "SRSCtl";
4860 break;
4861 case 3:
4862 check_insn(ctx, ISA_MIPS32R2);
4863 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4864 rn = "SRSMap";
4865 break;
4866 default:
4867 goto die;
4869 break;
4870 case 13:
4871 switch (sel) {
4872 case 0:
4873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
4874 rn = "Cause";
4875 break;
4876 default:
4877 goto die;
4879 break;
4880 case 14:
4881 switch (sel) {
4882 case 0:
4883 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
4884 tcg_gen_ext32s_tl(arg, arg);
4885 rn = "EPC";
4886 break;
4887 default:
4888 goto die;
4890 break;
4891 case 15:
4892 switch (sel) {
4893 case 0:
4894 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
4895 rn = "PRid";
4896 break;
4897 case 1:
4898 check_insn(ctx, ISA_MIPS32R2);
4899 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
4900 rn = "EBase";
4901 break;
4902 default:
4903 goto die;
4905 break;
4906 case 16:
4907 switch (sel) {
4908 case 0:
4909 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
4910 rn = "Config";
4911 break;
4912 case 1:
4913 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
4914 rn = "Config1";
4915 break;
4916 case 2:
4917 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
4918 rn = "Config2";
4919 break;
4920 case 3:
4921 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
4922 rn = "Config3";
4923 break;
4924 case 4:
4925 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
4926 rn = "Config4";
4927 break;
4928 case 5:
4929 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
4930 rn = "Config5";
4931 break;
4932 /* 6,7 are implementation dependent */
4933 case 6:
4934 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
4935 rn = "Config6";
4936 break;
4937 case 7:
4938 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
4939 rn = "Config7";
4940 break;
4941 default:
4942 goto die;
4944 break;
4945 case 17:
4946 switch (sel) {
4947 case 0:
4948 gen_helper_mfc0_lladdr(arg, cpu_env);
4949 rn = "LLAddr";
4950 break;
4951 default:
4952 goto die;
4954 break;
4955 case 18:
4956 switch (sel) {
4957 case 0 ... 7:
4958 gen_helper_1e0i(mfc0_watchlo, arg, sel);
4959 rn = "WatchLo";
4960 break;
4961 default:
4962 goto die;
4964 break;
4965 case 19:
4966 switch (sel) {
4967 case 0 ...7:
4968 gen_helper_1e0i(mfc0_watchhi, arg, sel);
4969 rn = "WatchHi";
4970 break;
4971 default:
4972 goto die;
4974 break;
4975 case 20:
4976 switch (sel) {
4977 case 0:
4978 #if defined(TARGET_MIPS64)
4979 check_insn(ctx, ISA_MIPS3);
4980 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
4981 tcg_gen_ext32s_tl(arg, arg);
4982 rn = "XContext";
4983 break;
4984 #endif
4985 default:
4986 goto die;
4988 break;
4989 case 21:
4990 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4991 switch (sel) {
4992 case 0:
4993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
4994 rn = "Framemask";
4995 break;
4996 default:
4997 goto die;
4999 break;
5000 case 22:
5001 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5002 rn = "'Diagnostic"; /* implementation dependent */
5003 break;
5004 case 23:
5005 switch (sel) {
5006 case 0:
5007 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5008 rn = "Debug";
5009 break;
5010 case 1:
5011 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5012 rn = "TraceControl";
5013 // break;
5014 case 2:
5015 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5016 rn = "TraceControl2";
5017 // break;
5018 case 3:
5019 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5020 rn = "UserTraceData";
5021 // break;
5022 case 4:
5023 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5024 rn = "TraceBPC";
5025 // break;
5026 default:
5027 goto die;
5029 break;
5030 case 24:
5031 switch (sel) {
5032 case 0:
5033 /* EJTAG support */
5034 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5035 tcg_gen_ext32s_tl(arg, arg);
5036 rn = "DEPC";
5037 break;
5038 default:
5039 goto die;
5041 break;
5042 case 25:
5043 switch (sel) {
5044 case 0:
5045 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5046 rn = "Performance0";
5047 break;
5048 case 1:
5049 // gen_helper_mfc0_performance1(arg);
5050 rn = "Performance1";
5051 // break;
5052 case 2:
5053 // gen_helper_mfc0_performance2(arg);
5054 rn = "Performance2";
5055 // break;
5056 case 3:
5057 // gen_helper_mfc0_performance3(arg);
5058 rn = "Performance3";
5059 // break;
5060 case 4:
5061 // gen_helper_mfc0_performance4(arg);
5062 rn = "Performance4";
5063 // break;
5064 case 5:
5065 // gen_helper_mfc0_performance5(arg);
5066 rn = "Performance5";
5067 // break;
5068 case 6:
5069 // gen_helper_mfc0_performance6(arg);
5070 rn = "Performance6";
5071 // break;
5072 case 7:
5073 // gen_helper_mfc0_performance7(arg);
5074 rn = "Performance7";
5075 // break;
5076 default:
5077 goto die;
5079 break;
5080 case 26:
5081 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5082 rn = "ECC";
5083 break;
5084 case 27:
5085 switch (sel) {
5086 case 0 ... 3:
5087 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5088 rn = "CacheErr";
5089 break;
5090 default:
5091 goto die;
5093 break;
5094 case 28:
5095 switch (sel) {
5096 case 0:
5097 case 2:
5098 case 4:
5099 case 6:
5100 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
5101 rn = "TagLo";
5102 break;
5103 case 1:
5104 case 3:
5105 case 5:
5106 case 7:
5107 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5108 rn = "DataLo";
5109 break;
5110 default:
5111 goto die;
5113 break;
5114 case 29:
5115 switch (sel) {
5116 case 0:
5117 case 2:
5118 case 4:
5119 case 6:
5120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5121 rn = "TagHi";
5122 break;
5123 case 1:
5124 case 3:
5125 case 5:
5126 case 7:
5127 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5128 rn = "DataHi";
5129 break;
5130 default:
5131 goto die;
5133 break;
5134 case 30:
5135 switch (sel) {
5136 case 0:
5137 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5138 tcg_gen_ext32s_tl(arg, arg);
5139 rn = "ErrorEPC";
5140 break;
5141 default:
5142 goto die;
5144 break;
5145 case 31:
5146 switch (sel) {
5147 case 0:
5148 /* EJTAG support */
5149 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5150 rn = "DESAVE";
5151 break;
5152 default:
5153 goto die;
5155 break;
5156 default:
5157 goto die;
5159 (void)rn; /* avoid a compiler warning */
5160 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5161 return;
5163 die:
5164 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5165 generate_exception(ctx, EXCP_RI);
5168 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5170 const char *rn = "invalid";
5172 if (sel != 0)
5173 check_insn(ctx, ISA_MIPS32);
5175 if (use_icount)
5176 gen_io_start();
5178 switch (reg) {
5179 case 0:
5180 switch (sel) {
5181 case 0:
5182 gen_helper_mtc0_index(cpu_env, arg);
5183 rn = "Index";
5184 break;
5185 case 1:
5186 check_insn(ctx, ASE_MT);
5187 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5188 rn = "MVPControl";
5189 break;
5190 case 2:
5191 check_insn(ctx, ASE_MT);
5192 /* ignored */
5193 rn = "MVPConf0";
5194 break;
5195 case 3:
5196 check_insn(ctx, ASE_MT);
5197 /* ignored */
5198 rn = "MVPConf1";
5199 break;
5200 default:
5201 goto die;
5203 break;
5204 case 1:
5205 switch (sel) {
5206 case 0:
5207 /* ignored */
5208 rn = "Random";
5209 break;
5210 case 1:
5211 check_insn(ctx, ASE_MT);
5212 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5213 rn = "VPEControl";
5214 break;
5215 case 2:
5216 check_insn(ctx, ASE_MT);
5217 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5218 rn = "VPEConf0";
5219 break;
5220 case 3:
5221 check_insn(ctx, ASE_MT);
5222 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5223 rn = "VPEConf1";
5224 break;
5225 case 4:
5226 check_insn(ctx, ASE_MT);
5227 gen_helper_mtc0_yqmask(cpu_env, arg);
5228 rn = "YQMask";
5229 break;
5230 case 5:
5231 check_insn(ctx, ASE_MT);
5232 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5233 rn = "VPESchedule";
5234 break;
5235 case 6:
5236 check_insn(ctx, ASE_MT);
5237 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5238 rn = "VPEScheFBack";
5239 break;
5240 case 7:
5241 check_insn(ctx, ASE_MT);
5242 gen_helper_mtc0_vpeopt(cpu_env, arg);
5243 rn = "VPEOpt";
5244 break;
5245 default:
5246 goto die;
5248 break;
5249 case 2:
5250 switch (sel) {
5251 case 0:
5252 gen_helper_mtc0_entrylo0(cpu_env, arg);
5253 rn = "EntryLo0";
5254 break;
5255 case 1:
5256 check_insn(ctx, ASE_MT);
5257 gen_helper_mtc0_tcstatus(cpu_env, arg);
5258 rn = "TCStatus";
5259 break;
5260 case 2:
5261 check_insn(ctx, ASE_MT);
5262 gen_helper_mtc0_tcbind(cpu_env, arg);
5263 rn = "TCBind";
5264 break;
5265 case 3:
5266 check_insn(ctx, ASE_MT);
5267 gen_helper_mtc0_tcrestart(cpu_env, arg);
5268 rn = "TCRestart";
5269 break;
5270 case 4:
5271 check_insn(ctx, ASE_MT);
5272 gen_helper_mtc0_tchalt(cpu_env, arg);
5273 rn = "TCHalt";
5274 break;
5275 case 5:
5276 check_insn(ctx, ASE_MT);
5277 gen_helper_mtc0_tccontext(cpu_env, arg);
5278 rn = "TCContext";
5279 break;
5280 case 6:
5281 check_insn(ctx, ASE_MT);
5282 gen_helper_mtc0_tcschedule(cpu_env, arg);
5283 rn = "TCSchedule";
5284 break;
5285 case 7:
5286 check_insn(ctx, ASE_MT);
5287 gen_helper_mtc0_tcschefback(cpu_env, arg);
5288 rn = "TCScheFBack";
5289 break;
5290 default:
5291 goto die;
5293 break;
5294 case 3:
5295 switch (sel) {
5296 case 0:
5297 gen_helper_mtc0_entrylo1(cpu_env, arg);
5298 rn = "EntryLo1";
5299 break;
5300 default:
5301 goto die;
5303 break;
5304 case 4:
5305 switch (sel) {
5306 case 0:
5307 gen_helper_mtc0_context(cpu_env, arg);
5308 rn = "Context";
5309 break;
5310 case 1:
5311 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5312 rn = "ContextConfig";
5313 goto die;
5314 // break;
5315 case 2:
5316 if (ctx->ulri) {
5317 tcg_gen_st_tl(arg, cpu_env,
5318 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5319 rn = "UserLocal";
5321 break;
5322 default:
5323 goto die;
5325 break;
5326 case 5:
5327 switch (sel) {
5328 case 0:
5329 gen_helper_mtc0_pagemask(cpu_env, arg);
5330 rn = "PageMask";
5331 break;
5332 case 1:
5333 check_insn(ctx, ISA_MIPS32R2);
5334 gen_helper_mtc0_pagegrain(cpu_env, arg);
5335 rn = "PageGrain";
5336 break;
5337 default:
5338 goto die;
5340 break;
5341 case 6:
5342 switch (sel) {
5343 case 0:
5344 gen_helper_mtc0_wired(cpu_env, arg);
5345 rn = "Wired";
5346 break;
5347 case 1:
5348 check_insn(ctx, ISA_MIPS32R2);
5349 gen_helper_mtc0_srsconf0(cpu_env, arg);
5350 rn = "SRSConf0";
5351 break;
5352 case 2:
5353 check_insn(ctx, ISA_MIPS32R2);
5354 gen_helper_mtc0_srsconf1(cpu_env, arg);
5355 rn = "SRSConf1";
5356 break;
5357 case 3:
5358 check_insn(ctx, ISA_MIPS32R2);
5359 gen_helper_mtc0_srsconf2(cpu_env, arg);
5360 rn = "SRSConf2";
5361 break;
5362 case 4:
5363 check_insn(ctx, ISA_MIPS32R2);
5364 gen_helper_mtc0_srsconf3(cpu_env, arg);
5365 rn = "SRSConf3";
5366 break;
5367 case 5:
5368 check_insn(ctx, ISA_MIPS32R2);
5369 gen_helper_mtc0_srsconf4(cpu_env, arg);
5370 rn = "SRSConf4";
5371 break;
5372 default:
5373 goto die;
5375 break;
5376 case 7:
5377 switch (sel) {
5378 case 0:
5379 check_insn(ctx, ISA_MIPS32R2);
5380 gen_helper_mtc0_hwrena(cpu_env, arg);
5381 ctx->bstate = BS_STOP;
5382 rn = "HWREna";
5383 break;
5384 default:
5385 goto die;
5387 break;
5388 case 8:
5389 /* ignored */
5390 rn = "BadVAddr";
5391 break;
5392 case 9:
5393 switch (sel) {
5394 case 0:
5395 gen_helper_mtc0_count(cpu_env, arg);
5396 rn = "Count";
5397 break;
5398 /* 6,7 are implementation dependent */
5399 default:
5400 goto die;
5402 break;
5403 case 10:
5404 switch (sel) {
5405 case 0:
5406 gen_helper_mtc0_entryhi(cpu_env, arg);
5407 rn = "EntryHi";
5408 break;
5409 default:
5410 goto die;
5412 break;
5413 case 11:
5414 switch (sel) {
5415 case 0:
5416 gen_helper_mtc0_compare(cpu_env, arg);
5417 rn = "Compare";
5418 break;
5419 /* 6,7 are implementation dependent */
5420 default:
5421 goto die;
5423 break;
5424 case 12:
5425 switch (sel) {
5426 case 0:
5427 save_cpu_state(ctx, 1);
5428 gen_helper_mtc0_status(cpu_env, arg);
5429 /* BS_STOP isn't good enough here, hflags may have changed. */
5430 gen_save_pc(ctx->pc + 4);
5431 ctx->bstate = BS_EXCP;
5432 rn = "Status";
5433 break;
5434 case 1:
5435 check_insn(ctx, ISA_MIPS32R2);
5436 gen_helper_mtc0_intctl(cpu_env, arg);
5437 /* Stop translation as we may have switched the execution mode */
5438 ctx->bstate = BS_STOP;
5439 rn = "IntCtl";
5440 break;
5441 case 2:
5442 check_insn(ctx, ISA_MIPS32R2);
5443 gen_helper_mtc0_srsctl(cpu_env, arg);
5444 /* Stop translation as we may have switched the execution mode */
5445 ctx->bstate = BS_STOP;
5446 rn = "SRSCtl";
5447 break;
5448 case 3:
5449 check_insn(ctx, ISA_MIPS32R2);
5450 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5451 /* Stop translation as we may have switched the execution mode */
5452 ctx->bstate = BS_STOP;
5453 rn = "SRSMap";
5454 break;
5455 default:
5456 goto die;
5458 break;
5459 case 13:
5460 switch (sel) {
5461 case 0:
5462 save_cpu_state(ctx, 1);
5463 gen_helper_mtc0_cause(cpu_env, arg);
5464 rn = "Cause";
5465 break;
5466 default:
5467 goto die;
5469 break;
5470 case 14:
5471 switch (sel) {
5472 case 0:
5473 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
5474 rn = "EPC";
5475 break;
5476 default:
5477 goto die;
5479 break;
5480 case 15:
5481 switch (sel) {
5482 case 0:
5483 /* ignored */
5484 rn = "PRid";
5485 break;
5486 case 1:
5487 check_insn(ctx, ISA_MIPS32R2);
5488 gen_helper_mtc0_ebase(cpu_env, arg);
5489 rn = "EBase";
5490 break;
5491 default:
5492 goto die;
5494 break;
5495 case 16:
5496 switch (sel) {
5497 case 0:
5498 gen_helper_mtc0_config0(cpu_env, arg);
5499 rn = "Config";
5500 /* Stop translation as we may have switched the execution mode */
5501 ctx->bstate = BS_STOP;
5502 break;
5503 case 1:
5504 /* ignored, read only */
5505 rn = "Config1";
5506 break;
5507 case 2:
5508 gen_helper_mtc0_config2(cpu_env, arg);
5509 rn = "Config2";
5510 /* Stop translation as we may have switched the execution mode */
5511 ctx->bstate = BS_STOP;
5512 break;
5513 case 3:
5514 /* ignored, read only */
5515 rn = "Config3";
5516 break;
5517 case 4:
5518 gen_helper_mtc0_config4(cpu_env, arg);
5519 rn = "Config4";
5520 ctx->bstate = BS_STOP;
5521 break;
5522 case 5:
5523 gen_helper_mtc0_config5(cpu_env, arg);
5524 rn = "Config5";
5525 /* Stop translation as we may have switched the execution mode */
5526 ctx->bstate = BS_STOP;
5527 break;
5528 /* 6,7 are implementation dependent */
5529 case 6:
5530 /* ignored */
5531 rn = "Config6";
5532 break;
5533 case 7:
5534 /* ignored */
5535 rn = "Config7";
5536 break;
5537 default:
5538 rn = "Invalid config selector";
5539 goto die;
5541 break;
5542 case 17:
5543 switch (sel) {
5544 case 0:
5545 gen_helper_mtc0_lladdr(cpu_env, arg);
5546 rn = "LLAddr";
5547 break;
5548 default:
5549 goto die;
5551 break;
5552 case 18:
5553 switch (sel) {
5554 case 0 ... 7:
5555 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5556 rn = "WatchLo";
5557 break;
5558 default:
5559 goto die;
5561 break;
5562 case 19:
5563 switch (sel) {
5564 case 0 ... 7:
5565 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5566 rn = "WatchHi";
5567 break;
5568 default:
5569 goto die;
5571 break;
5572 case 20:
5573 switch (sel) {
5574 case 0:
5575 #if defined(TARGET_MIPS64)
5576 check_insn(ctx, ISA_MIPS3);
5577 gen_helper_mtc0_xcontext(cpu_env, arg);
5578 rn = "XContext";
5579 break;
5580 #endif
5581 default:
5582 goto die;
5584 break;
5585 case 21:
5586 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5587 switch (sel) {
5588 case 0:
5589 gen_helper_mtc0_framemask(cpu_env, arg);
5590 rn = "Framemask";
5591 break;
5592 default:
5593 goto die;
5595 break;
5596 case 22:
5597 /* ignored */
5598 rn = "Diagnostic"; /* implementation dependent */
5599 break;
5600 case 23:
5601 switch (sel) {
5602 case 0:
5603 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5604 /* BS_STOP isn't good enough here, hflags may have changed. */
5605 gen_save_pc(ctx->pc + 4);
5606 ctx->bstate = BS_EXCP;
5607 rn = "Debug";
5608 break;
5609 case 1:
5610 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5611 rn = "TraceControl";
5612 /* Stop translation as we may have switched the execution mode */
5613 ctx->bstate = BS_STOP;
5614 // break;
5615 case 2:
5616 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5617 rn = "TraceControl2";
5618 /* Stop translation as we may have switched the execution mode */
5619 ctx->bstate = BS_STOP;
5620 // break;
5621 case 3:
5622 /* Stop translation as we may have switched the execution mode */
5623 ctx->bstate = BS_STOP;
5624 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5625 rn = "UserTraceData";
5626 /* Stop translation as we may have switched the execution mode */
5627 ctx->bstate = BS_STOP;
5628 // break;
5629 case 4:
5630 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5631 /* Stop translation as we may have switched the execution mode */
5632 ctx->bstate = BS_STOP;
5633 rn = "TraceBPC";
5634 // break;
5635 default:
5636 goto die;
5638 break;
5639 case 24:
5640 switch (sel) {
5641 case 0:
5642 /* EJTAG support */
5643 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
5644 rn = "DEPC";
5645 break;
5646 default:
5647 goto die;
5649 break;
5650 case 25:
5651 switch (sel) {
5652 case 0:
5653 gen_helper_mtc0_performance0(cpu_env, arg);
5654 rn = "Performance0";
5655 break;
5656 case 1:
5657 // gen_helper_mtc0_performance1(arg);
5658 rn = "Performance1";
5659 // break;
5660 case 2:
5661 // gen_helper_mtc0_performance2(arg);
5662 rn = "Performance2";
5663 // break;
5664 case 3:
5665 // gen_helper_mtc0_performance3(arg);
5666 rn = "Performance3";
5667 // break;
5668 case 4:
5669 // gen_helper_mtc0_performance4(arg);
5670 rn = "Performance4";
5671 // break;
5672 case 5:
5673 // gen_helper_mtc0_performance5(arg);
5674 rn = "Performance5";
5675 // break;
5676 case 6:
5677 // gen_helper_mtc0_performance6(arg);
5678 rn = "Performance6";
5679 // break;
5680 case 7:
5681 // gen_helper_mtc0_performance7(arg);
5682 rn = "Performance7";
5683 // break;
5684 default:
5685 goto die;
5687 break;
5688 case 26:
5689 /* ignored */
5690 rn = "ECC";
5691 break;
5692 case 27:
5693 switch (sel) {
5694 case 0 ... 3:
5695 /* ignored */
5696 rn = "CacheErr";
5697 break;
5698 default:
5699 goto die;
5701 break;
5702 case 28:
5703 switch (sel) {
5704 case 0:
5705 case 2:
5706 case 4:
5707 case 6:
5708 gen_helper_mtc0_taglo(cpu_env, arg);
5709 rn = "TagLo";
5710 break;
5711 case 1:
5712 case 3:
5713 case 5:
5714 case 7:
5715 gen_helper_mtc0_datalo(cpu_env, arg);
5716 rn = "DataLo";
5717 break;
5718 default:
5719 goto die;
5721 break;
5722 case 29:
5723 switch (sel) {
5724 case 0:
5725 case 2:
5726 case 4:
5727 case 6:
5728 gen_helper_mtc0_taghi(cpu_env, arg);
5729 rn = "TagHi";
5730 break;
5731 case 1:
5732 case 3:
5733 case 5:
5734 case 7:
5735 gen_helper_mtc0_datahi(cpu_env, arg);
5736 rn = "DataHi";
5737 break;
5738 default:
5739 rn = "invalid sel";
5740 goto die;
5742 break;
5743 case 30:
5744 switch (sel) {
5745 case 0:
5746 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
5747 rn = "ErrorEPC";
5748 break;
5749 default:
5750 goto die;
5752 break;
5753 case 31:
5754 switch (sel) {
5755 case 0:
5756 /* EJTAG support */
5757 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5758 rn = "DESAVE";
5759 break;
5760 default:
5761 goto die;
5763 /* Stop translation as we may have switched the execution mode */
5764 ctx->bstate = BS_STOP;
5765 break;
5766 default:
5767 goto die;
5769 (void)rn; /* avoid a compiler warning */
5770 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5771 /* For simplicity assume that all writes can cause interrupts. */
5772 if (use_icount) {
5773 gen_io_end();
5774 ctx->bstate = BS_STOP;
5776 return;
5778 die:
5779 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5780 generate_exception(ctx, EXCP_RI);
5783 #if defined(TARGET_MIPS64)
5784 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5786 const char *rn = "invalid";
5788 if (sel != 0)
5789 check_insn(ctx, ISA_MIPS64);
5791 switch (reg) {
5792 case 0:
5793 switch (sel) {
5794 case 0:
5795 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5796 rn = "Index";
5797 break;
5798 case 1:
5799 check_insn(ctx, ASE_MT);
5800 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5801 rn = "MVPControl";
5802 break;
5803 case 2:
5804 check_insn(ctx, ASE_MT);
5805 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5806 rn = "MVPConf0";
5807 break;
5808 case 3:
5809 check_insn(ctx, ASE_MT);
5810 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5811 rn = "MVPConf1";
5812 break;
5813 default:
5814 goto die;
5816 break;
5817 case 1:
5818 switch (sel) {
5819 case 0:
5820 gen_helper_mfc0_random(arg, cpu_env);
5821 rn = "Random";
5822 break;
5823 case 1:
5824 check_insn(ctx, ASE_MT);
5825 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5826 rn = "VPEControl";
5827 break;
5828 case 2:
5829 check_insn(ctx, ASE_MT);
5830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5831 rn = "VPEConf0";
5832 break;
5833 case 3:
5834 check_insn(ctx, ASE_MT);
5835 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5836 rn = "VPEConf1";
5837 break;
5838 case 4:
5839 check_insn(ctx, ASE_MT);
5840 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
5841 rn = "YQMask";
5842 break;
5843 case 5:
5844 check_insn(ctx, ASE_MT);
5845 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5846 rn = "VPESchedule";
5847 break;
5848 case 6:
5849 check_insn(ctx, ASE_MT);
5850 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5851 rn = "VPEScheFBack";
5852 break;
5853 case 7:
5854 check_insn(ctx, ASE_MT);
5855 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5856 rn = "VPEOpt";
5857 break;
5858 default:
5859 goto die;
5861 break;
5862 case 2:
5863 switch (sel) {
5864 case 0:
5865 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
5866 rn = "EntryLo0";
5867 break;
5868 case 1:
5869 check_insn(ctx, ASE_MT);
5870 gen_helper_mfc0_tcstatus(arg, cpu_env);
5871 rn = "TCStatus";
5872 break;
5873 case 2:
5874 check_insn(ctx, ASE_MT);
5875 gen_helper_mfc0_tcbind(arg, cpu_env);
5876 rn = "TCBind";
5877 break;
5878 case 3:
5879 check_insn(ctx, ASE_MT);
5880 gen_helper_dmfc0_tcrestart(arg, cpu_env);
5881 rn = "TCRestart";
5882 break;
5883 case 4:
5884 check_insn(ctx, ASE_MT);
5885 gen_helper_dmfc0_tchalt(arg, cpu_env);
5886 rn = "TCHalt";
5887 break;
5888 case 5:
5889 check_insn(ctx, ASE_MT);
5890 gen_helper_dmfc0_tccontext(arg, cpu_env);
5891 rn = "TCContext";
5892 break;
5893 case 6:
5894 check_insn(ctx, ASE_MT);
5895 gen_helper_dmfc0_tcschedule(arg, cpu_env);
5896 rn = "TCSchedule";
5897 break;
5898 case 7:
5899 check_insn(ctx, ASE_MT);
5900 gen_helper_dmfc0_tcschefback(arg, cpu_env);
5901 rn = "TCScheFBack";
5902 break;
5903 default:
5904 goto die;
5906 break;
5907 case 3:
5908 switch (sel) {
5909 case 0:
5910 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
5911 rn = "EntryLo1";
5912 break;
5913 default:
5914 goto die;
5916 break;
5917 case 4:
5918 switch (sel) {
5919 case 0:
5920 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5921 rn = "Context";
5922 break;
5923 case 1:
5924 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
5925 rn = "ContextConfig";
5926 goto die;
5927 // break;
5928 case 2:
5929 if (ctx->ulri) {
5930 tcg_gen_ld_tl(arg, cpu_env,
5931 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5932 rn = "UserLocal";
5933 } else {
5934 tcg_gen_movi_tl(arg, 0);
5936 break;
5937 default:
5938 goto die;
5940 break;
5941 case 5:
5942 switch (sel) {
5943 case 0:
5944 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5945 rn = "PageMask";
5946 break;
5947 case 1:
5948 check_insn(ctx, ISA_MIPS32R2);
5949 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5950 rn = "PageGrain";
5951 break;
5952 default:
5953 goto die;
5955 break;
5956 case 6:
5957 switch (sel) {
5958 case 0:
5959 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5960 rn = "Wired";
5961 break;
5962 case 1:
5963 check_insn(ctx, ISA_MIPS32R2);
5964 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5965 rn = "SRSConf0";
5966 break;
5967 case 2:
5968 check_insn(ctx, ISA_MIPS32R2);
5969 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5970 rn = "SRSConf1";
5971 break;
5972 case 3:
5973 check_insn(ctx, ISA_MIPS32R2);
5974 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5975 rn = "SRSConf2";
5976 break;
5977 case 4:
5978 check_insn(ctx, ISA_MIPS32R2);
5979 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5980 rn = "SRSConf3";
5981 break;
5982 case 5:
5983 check_insn(ctx, ISA_MIPS32R2);
5984 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5985 rn = "SRSConf4";
5986 break;
5987 default:
5988 goto die;
5990 break;
5991 case 7:
5992 switch (sel) {
5993 case 0:
5994 check_insn(ctx, ISA_MIPS32R2);
5995 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5996 rn = "HWREna";
5997 break;
5998 default:
5999 goto die;
6001 break;
6002 case 8:
6003 switch (sel) {
6004 case 0:
6005 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6006 rn = "BadVAddr";
6007 break;
6008 default:
6009 goto die;
6011 break;
6012 case 9:
6013 switch (sel) {
6014 case 0:
6015 /* Mark as an IO operation because we read the time. */
6016 if (use_icount)
6017 gen_io_start();
6018 gen_helper_mfc0_count(arg, cpu_env);
6019 if (use_icount) {
6020 gen_io_end();
6022 /* Break the TB to be able to take timer interrupts immediately
6023 after reading count. */
6024 ctx->bstate = BS_STOP;
6025 rn = "Count";
6026 break;
6027 /* 6,7 are implementation dependent */
6028 default:
6029 goto die;
6031 break;
6032 case 10:
6033 switch (sel) {
6034 case 0:
6035 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6036 rn = "EntryHi";
6037 break;
6038 default:
6039 goto die;
6041 break;
6042 case 11:
6043 switch (sel) {
6044 case 0:
6045 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6046 rn = "Compare";
6047 break;
6048 /* 6,7 are implementation dependent */
6049 default:
6050 goto die;
6052 break;
6053 case 12:
6054 switch (sel) {
6055 case 0:
6056 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6057 rn = "Status";
6058 break;
6059 case 1:
6060 check_insn(ctx, ISA_MIPS32R2);
6061 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6062 rn = "IntCtl";
6063 break;
6064 case 2:
6065 check_insn(ctx, ISA_MIPS32R2);
6066 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6067 rn = "SRSCtl";
6068 break;
6069 case 3:
6070 check_insn(ctx, ISA_MIPS32R2);
6071 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6072 rn = "SRSMap";
6073 break;
6074 default:
6075 goto die;
6077 break;
6078 case 13:
6079 switch (sel) {
6080 case 0:
6081 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6082 rn = "Cause";
6083 break;
6084 default:
6085 goto die;
6087 break;
6088 case 14:
6089 switch (sel) {
6090 case 0:
6091 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6092 rn = "EPC";
6093 break;
6094 default:
6095 goto die;
6097 break;
6098 case 15:
6099 switch (sel) {
6100 case 0:
6101 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6102 rn = "PRid";
6103 break;
6104 case 1:
6105 check_insn(ctx, ISA_MIPS32R2);
6106 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6107 rn = "EBase";
6108 break;
6109 default:
6110 goto die;
6112 break;
6113 case 16:
6114 switch (sel) {
6115 case 0:
6116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6117 rn = "Config";
6118 break;
6119 case 1:
6120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6121 rn = "Config1";
6122 break;
6123 case 2:
6124 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6125 rn = "Config2";
6126 break;
6127 case 3:
6128 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6129 rn = "Config3";
6130 break;
6131 /* 6,7 are implementation dependent */
6132 case 6:
6133 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6134 rn = "Config6";
6135 break;
6136 case 7:
6137 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6138 rn = "Config7";
6139 break;
6140 default:
6141 goto die;
6143 break;
6144 case 17:
6145 switch (sel) {
6146 case 0:
6147 gen_helper_dmfc0_lladdr(arg, cpu_env);
6148 rn = "LLAddr";
6149 break;
6150 default:
6151 goto die;
6153 break;
6154 case 18:
6155 switch (sel) {
6156 case 0 ... 7:
6157 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6158 rn = "WatchLo";
6159 break;
6160 default:
6161 goto die;
6163 break;
6164 case 19:
6165 switch (sel) {
6166 case 0 ... 7:
6167 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6168 rn = "WatchHi";
6169 break;
6170 default:
6171 goto die;
6173 break;
6174 case 20:
6175 switch (sel) {
6176 case 0:
6177 check_insn(ctx, ISA_MIPS3);
6178 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6179 rn = "XContext";
6180 break;
6181 default:
6182 goto die;
6184 break;
6185 case 21:
6186 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6187 switch (sel) {
6188 case 0:
6189 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6190 rn = "Framemask";
6191 break;
6192 default:
6193 goto die;
6195 break;
6196 case 22:
6197 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6198 rn = "'Diagnostic"; /* implementation dependent */
6199 break;
6200 case 23:
6201 switch (sel) {
6202 case 0:
6203 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6204 rn = "Debug";
6205 break;
6206 case 1:
6207 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6208 rn = "TraceControl";
6209 // break;
6210 case 2:
6211 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6212 rn = "TraceControl2";
6213 // break;
6214 case 3:
6215 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6216 rn = "UserTraceData";
6217 // break;
6218 case 4:
6219 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6220 rn = "TraceBPC";
6221 // break;
6222 default:
6223 goto die;
6225 break;
6226 case 24:
6227 switch (sel) {
6228 case 0:
6229 /* EJTAG support */
6230 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6231 rn = "DEPC";
6232 break;
6233 default:
6234 goto die;
6236 break;
6237 case 25:
6238 switch (sel) {
6239 case 0:
6240 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6241 rn = "Performance0";
6242 break;
6243 case 1:
6244 // gen_helper_dmfc0_performance1(arg);
6245 rn = "Performance1";
6246 // break;
6247 case 2:
6248 // gen_helper_dmfc0_performance2(arg);
6249 rn = "Performance2";
6250 // break;
6251 case 3:
6252 // gen_helper_dmfc0_performance3(arg);
6253 rn = "Performance3";
6254 // break;
6255 case 4:
6256 // gen_helper_dmfc0_performance4(arg);
6257 rn = "Performance4";
6258 // break;
6259 case 5:
6260 // gen_helper_dmfc0_performance5(arg);
6261 rn = "Performance5";
6262 // break;
6263 case 6:
6264 // gen_helper_dmfc0_performance6(arg);
6265 rn = "Performance6";
6266 // break;
6267 case 7:
6268 // gen_helper_dmfc0_performance7(arg);
6269 rn = "Performance7";
6270 // break;
6271 default:
6272 goto die;
6274 break;
6275 case 26:
6276 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6277 rn = "ECC";
6278 break;
6279 case 27:
6280 switch (sel) {
6281 /* ignored */
6282 case 0 ... 3:
6283 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6284 rn = "CacheErr";
6285 break;
6286 default:
6287 goto die;
6289 break;
6290 case 28:
6291 switch (sel) {
6292 case 0:
6293 case 2:
6294 case 4:
6295 case 6:
6296 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6297 rn = "TagLo";
6298 break;
6299 case 1:
6300 case 3:
6301 case 5:
6302 case 7:
6303 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6304 rn = "DataLo";
6305 break;
6306 default:
6307 goto die;
6309 break;
6310 case 29:
6311 switch (sel) {
6312 case 0:
6313 case 2:
6314 case 4:
6315 case 6:
6316 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6317 rn = "TagHi";
6318 break;
6319 case 1:
6320 case 3:
6321 case 5:
6322 case 7:
6323 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6324 rn = "DataHi";
6325 break;
6326 default:
6327 goto die;
6329 break;
6330 case 30:
6331 switch (sel) {
6332 case 0:
6333 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6334 rn = "ErrorEPC";
6335 break;
6336 default:
6337 goto die;
6339 break;
6340 case 31:
6341 switch (sel) {
6342 case 0:
6343 /* EJTAG support */
6344 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6345 rn = "DESAVE";
6346 break;
6347 default:
6348 goto die;
6350 break;
6351 default:
6352 goto die;
6354 (void)rn; /* avoid a compiler warning */
6355 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6356 return;
6358 die:
6359 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6360 generate_exception(ctx, EXCP_RI);
6363 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6365 const char *rn = "invalid";
6367 if (sel != 0)
6368 check_insn(ctx, ISA_MIPS64);
6370 if (use_icount)
6371 gen_io_start();
6373 switch (reg) {
6374 case 0:
6375 switch (sel) {
6376 case 0:
6377 gen_helper_mtc0_index(cpu_env, arg);
6378 rn = "Index";
6379 break;
6380 case 1:
6381 check_insn(ctx, ASE_MT);
6382 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6383 rn = "MVPControl";
6384 break;
6385 case 2:
6386 check_insn(ctx, ASE_MT);
6387 /* ignored */
6388 rn = "MVPConf0";
6389 break;
6390 case 3:
6391 check_insn(ctx, ASE_MT);
6392 /* ignored */
6393 rn = "MVPConf1";
6394 break;
6395 default:
6396 goto die;
6398 break;
6399 case 1:
6400 switch (sel) {
6401 case 0:
6402 /* ignored */
6403 rn = "Random";
6404 break;
6405 case 1:
6406 check_insn(ctx, ASE_MT);
6407 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6408 rn = "VPEControl";
6409 break;
6410 case 2:
6411 check_insn(ctx, ASE_MT);
6412 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6413 rn = "VPEConf0";
6414 break;
6415 case 3:
6416 check_insn(ctx, ASE_MT);
6417 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6418 rn = "VPEConf1";
6419 break;
6420 case 4:
6421 check_insn(ctx, ASE_MT);
6422 gen_helper_mtc0_yqmask(cpu_env, arg);
6423 rn = "YQMask";
6424 break;
6425 case 5:
6426 check_insn(ctx, ASE_MT);
6427 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6428 rn = "VPESchedule";
6429 break;
6430 case 6:
6431 check_insn(ctx, ASE_MT);
6432 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6433 rn = "VPEScheFBack";
6434 break;
6435 case 7:
6436 check_insn(ctx, ASE_MT);
6437 gen_helper_mtc0_vpeopt(cpu_env, arg);
6438 rn = "VPEOpt";
6439 break;
6440 default:
6441 goto die;
6443 break;
6444 case 2:
6445 switch (sel) {
6446 case 0:
6447 gen_helper_mtc0_entrylo0(cpu_env, arg);
6448 rn = "EntryLo0";
6449 break;
6450 case 1:
6451 check_insn(ctx, ASE_MT);
6452 gen_helper_mtc0_tcstatus(cpu_env, arg);
6453 rn = "TCStatus";
6454 break;
6455 case 2:
6456 check_insn(ctx, ASE_MT);
6457 gen_helper_mtc0_tcbind(cpu_env, arg);
6458 rn = "TCBind";
6459 break;
6460 case 3:
6461 check_insn(ctx, ASE_MT);
6462 gen_helper_mtc0_tcrestart(cpu_env, arg);
6463 rn = "TCRestart";
6464 break;
6465 case 4:
6466 check_insn(ctx, ASE_MT);
6467 gen_helper_mtc0_tchalt(cpu_env, arg);
6468 rn = "TCHalt";
6469 break;
6470 case 5:
6471 check_insn(ctx, ASE_MT);
6472 gen_helper_mtc0_tccontext(cpu_env, arg);
6473 rn = "TCContext";
6474 break;
6475 case 6:
6476 check_insn(ctx, ASE_MT);
6477 gen_helper_mtc0_tcschedule(cpu_env, arg);
6478 rn = "TCSchedule";
6479 break;
6480 case 7:
6481 check_insn(ctx, ASE_MT);
6482 gen_helper_mtc0_tcschefback(cpu_env, arg);
6483 rn = "TCScheFBack";
6484 break;
6485 default:
6486 goto die;
6488 break;
6489 case 3:
6490 switch (sel) {
6491 case 0:
6492 gen_helper_mtc0_entrylo1(cpu_env, arg);
6493 rn = "EntryLo1";
6494 break;
6495 default:
6496 goto die;
6498 break;
6499 case 4:
6500 switch (sel) {
6501 case 0:
6502 gen_helper_mtc0_context(cpu_env, arg);
6503 rn = "Context";
6504 break;
6505 case 1:
6506 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6507 rn = "ContextConfig";
6508 goto die;
6509 // break;
6510 case 2:
6511 if (ctx->ulri) {
6512 tcg_gen_st_tl(arg, cpu_env,
6513 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6514 rn = "UserLocal";
6516 break;
6517 default:
6518 goto die;
6520 break;
6521 case 5:
6522 switch (sel) {
6523 case 0:
6524 gen_helper_mtc0_pagemask(cpu_env, arg);
6525 rn = "PageMask";
6526 break;
6527 case 1:
6528 check_insn(ctx, ISA_MIPS32R2);
6529 gen_helper_mtc0_pagegrain(cpu_env, arg);
6530 rn = "PageGrain";
6531 break;
6532 default:
6533 goto die;
6535 break;
6536 case 6:
6537 switch (sel) {
6538 case 0:
6539 gen_helper_mtc0_wired(cpu_env, arg);
6540 rn = "Wired";
6541 break;
6542 case 1:
6543 check_insn(ctx, ISA_MIPS32R2);
6544 gen_helper_mtc0_srsconf0(cpu_env, arg);
6545 rn = "SRSConf0";
6546 break;
6547 case 2:
6548 check_insn(ctx, ISA_MIPS32R2);
6549 gen_helper_mtc0_srsconf1(cpu_env, arg);
6550 rn = "SRSConf1";
6551 break;
6552 case 3:
6553 check_insn(ctx, ISA_MIPS32R2);
6554 gen_helper_mtc0_srsconf2(cpu_env, arg);
6555 rn = "SRSConf2";
6556 break;
6557 case 4:
6558 check_insn(ctx, ISA_MIPS32R2);
6559 gen_helper_mtc0_srsconf3(cpu_env, arg);
6560 rn = "SRSConf3";
6561 break;
6562 case 5:
6563 check_insn(ctx, ISA_MIPS32R2);
6564 gen_helper_mtc0_srsconf4(cpu_env, arg);
6565 rn = "SRSConf4";
6566 break;
6567 default:
6568 goto die;
6570 break;
6571 case 7:
6572 switch (sel) {
6573 case 0:
6574 check_insn(ctx, ISA_MIPS32R2);
6575 gen_helper_mtc0_hwrena(cpu_env, arg);
6576 ctx->bstate = BS_STOP;
6577 rn = "HWREna";
6578 break;
6579 default:
6580 goto die;
6582 break;
6583 case 8:
6584 /* ignored */
6585 rn = "BadVAddr";
6586 break;
6587 case 9:
6588 switch (sel) {
6589 case 0:
6590 gen_helper_mtc0_count(cpu_env, arg);
6591 rn = "Count";
6592 break;
6593 /* 6,7 are implementation dependent */
6594 default:
6595 goto die;
6597 /* Stop translation as we may have switched the execution mode */
6598 ctx->bstate = BS_STOP;
6599 break;
6600 case 10:
6601 switch (sel) {
6602 case 0:
6603 gen_helper_mtc0_entryhi(cpu_env, arg);
6604 rn = "EntryHi";
6605 break;
6606 default:
6607 goto die;
6609 break;
6610 case 11:
6611 switch (sel) {
6612 case 0:
6613 gen_helper_mtc0_compare(cpu_env, arg);
6614 rn = "Compare";
6615 break;
6616 /* 6,7 are implementation dependent */
6617 default:
6618 goto die;
6620 /* Stop translation as we may have switched the execution mode */
6621 ctx->bstate = BS_STOP;
6622 break;
6623 case 12:
6624 switch (sel) {
6625 case 0:
6626 save_cpu_state(ctx, 1);
6627 gen_helper_mtc0_status(cpu_env, arg);
6628 /* BS_STOP isn't good enough here, hflags may have changed. */
6629 gen_save_pc(ctx->pc + 4);
6630 ctx->bstate = BS_EXCP;
6631 rn = "Status";
6632 break;
6633 case 1:
6634 check_insn(ctx, ISA_MIPS32R2);
6635 gen_helper_mtc0_intctl(cpu_env, arg);
6636 /* Stop translation as we may have switched the execution mode */
6637 ctx->bstate = BS_STOP;
6638 rn = "IntCtl";
6639 break;
6640 case 2:
6641 check_insn(ctx, ISA_MIPS32R2);
6642 gen_helper_mtc0_srsctl(cpu_env, arg);
6643 /* Stop translation as we may have switched the execution mode */
6644 ctx->bstate = BS_STOP;
6645 rn = "SRSCtl";
6646 break;
6647 case 3:
6648 check_insn(ctx, ISA_MIPS32R2);
6649 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6650 /* Stop translation as we may have switched the execution mode */
6651 ctx->bstate = BS_STOP;
6652 rn = "SRSMap";
6653 break;
6654 default:
6655 goto die;
6657 break;
6658 case 13:
6659 switch (sel) {
6660 case 0:
6661 save_cpu_state(ctx, 1);
6662 /* Mark as an IO operation because we may trigger a software
6663 interrupt. */
6664 if (use_icount) {
6665 gen_io_start();
6667 gen_helper_mtc0_cause(cpu_env, arg);
6668 if (use_icount) {
6669 gen_io_end();
6671 /* Stop translation as we may have triggered an intetrupt */
6672 ctx->bstate = BS_STOP;
6673 rn = "Cause";
6674 break;
6675 default:
6676 goto die;
6678 break;
6679 case 14:
6680 switch (sel) {
6681 case 0:
6682 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6683 rn = "EPC";
6684 break;
6685 default:
6686 goto die;
6688 break;
6689 case 15:
6690 switch (sel) {
6691 case 0:
6692 /* ignored */
6693 rn = "PRid";
6694 break;
6695 case 1:
6696 check_insn(ctx, ISA_MIPS32R2);
6697 gen_helper_mtc0_ebase(cpu_env, arg);
6698 rn = "EBase";
6699 break;
6700 default:
6701 goto die;
6703 break;
6704 case 16:
6705 switch (sel) {
6706 case 0:
6707 gen_helper_mtc0_config0(cpu_env, arg);
6708 rn = "Config";
6709 /* Stop translation as we may have switched the execution mode */
6710 ctx->bstate = BS_STOP;
6711 break;
6712 case 1:
6713 /* ignored, read only */
6714 rn = "Config1";
6715 break;
6716 case 2:
6717 gen_helper_mtc0_config2(cpu_env, arg);
6718 rn = "Config2";
6719 /* Stop translation as we may have switched the execution mode */
6720 ctx->bstate = BS_STOP;
6721 break;
6722 case 3:
6723 /* ignored */
6724 rn = "Config3";
6725 break;
6726 /* 6,7 are implementation dependent */
6727 default:
6728 rn = "Invalid config selector";
6729 goto die;
6731 break;
6732 case 17:
6733 switch (sel) {
6734 case 0:
6735 gen_helper_mtc0_lladdr(cpu_env, arg);
6736 rn = "LLAddr";
6737 break;
6738 default:
6739 goto die;
6741 break;
6742 case 18:
6743 switch (sel) {
6744 case 0 ... 7:
6745 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6746 rn = "WatchLo";
6747 break;
6748 default:
6749 goto die;
6751 break;
6752 case 19:
6753 switch (sel) {
6754 case 0 ... 7:
6755 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6756 rn = "WatchHi";
6757 break;
6758 default:
6759 goto die;
6761 break;
6762 case 20:
6763 switch (sel) {
6764 case 0:
6765 check_insn(ctx, ISA_MIPS3);
6766 gen_helper_mtc0_xcontext(cpu_env, arg);
6767 rn = "XContext";
6768 break;
6769 default:
6770 goto die;
6772 break;
6773 case 21:
6774 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6775 switch (sel) {
6776 case 0:
6777 gen_helper_mtc0_framemask(cpu_env, arg);
6778 rn = "Framemask";
6779 break;
6780 default:
6781 goto die;
6783 break;
6784 case 22:
6785 /* ignored */
6786 rn = "Diagnostic"; /* implementation dependent */
6787 break;
6788 case 23:
6789 switch (sel) {
6790 case 0:
6791 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6792 /* BS_STOP isn't good enough here, hflags may have changed. */
6793 gen_save_pc(ctx->pc + 4);
6794 ctx->bstate = BS_EXCP;
6795 rn = "Debug";
6796 break;
6797 case 1:
6798 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6799 /* Stop translation as we may have switched the execution mode */
6800 ctx->bstate = BS_STOP;
6801 rn = "TraceControl";
6802 // break;
6803 case 2:
6804 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6805 /* Stop translation as we may have switched the execution mode */
6806 ctx->bstate = BS_STOP;
6807 rn = "TraceControl2";
6808 // break;
6809 case 3:
6810 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6811 /* Stop translation as we may have switched the execution mode */
6812 ctx->bstate = BS_STOP;
6813 rn = "UserTraceData";
6814 // break;
6815 case 4:
6816 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6817 /* Stop translation as we may have switched the execution mode */
6818 ctx->bstate = BS_STOP;
6819 rn = "TraceBPC";
6820 // break;
6821 default:
6822 goto die;
6824 break;
6825 case 24:
6826 switch (sel) {
6827 case 0:
6828 /* EJTAG support */
6829 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6830 rn = "DEPC";
6831 break;
6832 default:
6833 goto die;
6835 break;
6836 case 25:
6837 switch (sel) {
6838 case 0:
6839 gen_helper_mtc0_performance0(cpu_env, arg);
6840 rn = "Performance0";
6841 break;
6842 case 1:
6843 // gen_helper_mtc0_performance1(cpu_env, arg);
6844 rn = "Performance1";
6845 // break;
6846 case 2:
6847 // gen_helper_mtc0_performance2(cpu_env, arg);
6848 rn = "Performance2";
6849 // break;
6850 case 3:
6851 // gen_helper_mtc0_performance3(cpu_env, arg);
6852 rn = "Performance3";
6853 // break;
6854 case 4:
6855 // gen_helper_mtc0_performance4(cpu_env, arg);
6856 rn = "Performance4";
6857 // break;
6858 case 5:
6859 // gen_helper_mtc0_performance5(cpu_env, arg);
6860 rn = "Performance5";
6861 // break;
6862 case 6:
6863 // gen_helper_mtc0_performance6(cpu_env, arg);
6864 rn = "Performance6";
6865 // break;
6866 case 7:
6867 // gen_helper_mtc0_performance7(cpu_env, arg);
6868 rn = "Performance7";
6869 // break;
6870 default:
6871 goto die;
6873 break;
6874 case 26:
6875 /* ignored */
6876 rn = "ECC";
6877 break;
6878 case 27:
6879 switch (sel) {
6880 case 0 ... 3:
6881 /* ignored */
6882 rn = "CacheErr";
6883 break;
6884 default:
6885 goto die;
6887 break;
6888 case 28:
6889 switch (sel) {
6890 case 0:
6891 case 2:
6892 case 4:
6893 case 6:
6894 gen_helper_mtc0_taglo(cpu_env, arg);
6895 rn = "TagLo";
6896 break;
6897 case 1:
6898 case 3:
6899 case 5:
6900 case 7:
6901 gen_helper_mtc0_datalo(cpu_env, arg);
6902 rn = "DataLo";
6903 break;
6904 default:
6905 goto die;
6907 break;
6908 case 29:
6909 switch (sel) {
6910 case 0:
6911 case 2:
6912 case 4:
6913 case 6:
6914 gen_helper_mtc0_taghi(cpu_env, arg);
6915 rn = "TagHi";
6916 break;
6917 case 1:
6918 case 3:
6919 case 5:
6920 case 7:
6921 gen_helper_mtc0_datahi(cpu_env, arg);
6922 rn = "DataHi";
6923 break;
6924 default:
6925 rn = "invalid sel";
6926 goto die;
6928 break;
6929 case 30:
6930 switch (sel) {
6931 case 0:
6932 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6933 rn = "ErrorEPC";
6934 break;
6935 default:
6936 goto die;
6938 break;
6939 case 31:
6940 switch (sel) {
6941 case 0:
6942 /* EJTAG support */
6943 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6944 rn = "DESAVE";
6945 break;
6946 default:
6947 goto die;
6949 /* Stop translation as we may have switched the execution mode */
6950 ctx->bstate = BS_STOP;
6951 break;
6952 default:
6953 goto die;
6955 (void)rn; /* avoid a compiler warning */
6956 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6957 /* For simplicity assume that all writes can cause interrupts. */
6958 if (use_icount) {
6959 gen_io_end();
6960 ctx->bstate = BS_STOP;
6962 return;
6964 die:
6965 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6966 generate_exception(ctx, EXCP_RI);
6968 #endif /* TARGET_MIPS64 */
6970 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
6971 int u, int sel, int h)
6973 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6974 TCGv t0 = tcg_temp_local_new();
6976 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
6977 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6978 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
6979 tcg_gen_movi_tl(t0, -1);
6980 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6981 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6982 tcg_gen_movi_tl(t0, -1);
6983 else if (u == 0) {
6984 switch (rt) {
6985 case 1:
6986 switch (sel) {
6987 case 1:
6988 gen_helper_mftc0_vpecontrol(t0, cpu_env);
6989 break;
6990 case 2:
6991 gen_helper_mftc0_vpeconf0(t0, cpu_env);
6992 break;
6993 default:
6994 goto die;
6995 break;
6997 break;
6998 case 2:
6999 switch (sel) {
7000 case 1:
7001 gen_helper_mftc0_tcstatus(t0, cpu_env);
7002 break;
7003 case 2:
7004 gen_helper_mftc0_tcbind(t0, cpu_env);
7005 break;
7006 case 3:
7007 gen_helper_mftc0_tcrestart(t0, cpu_env);
7008 break;
7009 case 4:
7010 gen_helper_mftc0_tchalt(t0, cpu_env);
7011 break;
7012 case 5:
7013 gen_helper_mftc0_tccontext(t0, cpu_env);
7014 break;
7015 case 6:
7016 gen_helper_mftc0_tcschedule(t0, cpu_env);
7017 break;
7018 case 7:
7019 gen_helper_mftc0_tcschefback(t0, cpu_env);
7020 break;
7021 default:
7022 gen_mfc0(ctx, t0, rt, sel);
7023 break;
7025 break;
7026 case 10:
7027 switch (sel) {
7028 case 0:
7029 gen_helper_mftc0_entryhi(t0, cpu_env);
7030 break;
7031 default:
7032 gen_mfc0(ctx, t0, rt, sel);
7033 break;
7035 case 12:
7036 switch (sel) {
7037 case 0:
7038 gen_helper_mftc0_status(t0, cpu_env);
7039 break;
7040 default:
7041 gen_mfc0(ctx, t0, rt, sel);
7042 break;
7044 case 13:
7045 switch (sel) {
7046 case 0:
7047 gen_helper_mftc0_cause(t0, cpu_env);
7048 break;
7049 default:
7050 goto die;
7051 break;
7053 break;
7054 case 14:
7055 switch (sel) {
7056 case 0:
7057 gen_helper_mftc0_epc(t0, cpu_env);
7058 break;
7059 default:
7060 goto die;
7061 break;
7063 break;
7064 case 15:
7065 switch (sel) {
7066 case 1:
7067 gen_helper_mftc0_ebase(t0, cpu_env);
7068 break;
7069 default:
7070 goto die;
7071 break;
7073 break;
7074 case 16:
7075 switch (sel) {
7076 case 0 ... 7:
7077 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7078 break;
7079 default:
7080 goto die;
7081 break;
7083 break;
7084 case 23:
7085 switch (sel) {
7086 case 0:
7087 gen_helper_mftc0_debug(t0, cpu_env);
7088 break;
7089 default:
7090 gen_mfc0(ctx, t0, rt, sel);
7091 break;
7093 break;
7094 default:
7095 gen_mfc0(ctx, t0, rt, sel);
7097 } else switch (sel) {
7098 /* GPR registers. */
7099 case 0:
7100 gen_helper_1e0i(mftgpr, t0, rt);
7101 break;
7102 /* Auxiliary CPU registers */
7103 case 1:
7104 switch (rt) {
7105 case 0:
7106 gen_helper_1e0i(mftlo, t0, 0);
7107 break;
7108 case 1:
7109 gen_helper_1e0i(mfthi, t0, 0);
7110 break;
7111 case 2:
7112 gen_helper_1e0i(mftacx, t0, 0);
7113 break;
7114 case 4:
7115 gen_helper_1e0i(mftlo, t0, 1);
7116 break;
7117 case 5:
7118 gen_helper_1e0i(mfthi, t0, 1);
7119 break;
7120 case 6:
7121 gen_helper_1e0i(mftacx, t0, 1);
7122 break;
7123 case 8:
7124 gen_helper_1e0i(mftlo, t0, 2);
7125 break;
7126 case 9:
7127 gen_helper_1e0i(mfthi, t0, 2);
7128 break;
7129 case 10:
7130 gen_helper_1e0i(mftacx, t0, 2);
7131 break;
7132 case 12:
7133 gen_helper_1e0i(mftlo, t0, 3);
7134 break;
7135 case 13:
7136 gen_helper_1e0i(mfthi, t0, 3);
7137 break;
7138 case 14:
7139 gen_helper_1e0i(mftacx, t0, 3);
7140 break;
7141 case 16:
7142 gen_helper_mftdsp(t0, cpu_env);
7143 break;
7144 default:
7145 goto die;
7147 break;
7148 /* Floating point (COP1). */
7149 case 2:
7150 /* XXX: For now we support only a single FPU context. */
7151 if (h == 0) {
7152 TCGv_i32 fp0 = tcg_temp_new_i32();
7154 gen_load_fpr32(fp0, rt);
7155 tcg_gen_ext_i32_tl(t0, fp0);
7156 tcg_temp_free_i32(fp0);
7157 } else {
7158 TCGv_i32 fp0 = tcg_temp_new_i32();
7160 gen_load_fpr32h(ctx, fp0, rt);
7161 tcg_gen_ext_i32_tl(t0, fp0);
7162 tcg_temp_free_i32(fp0);
7164 break;
7165 case 3:
7166 /* XXX: For now we support only a single FPU context. */
7167 gen_helper_1e0i(cfc1, t0, rt);
7168 break;
7169 /* COP2: Not implemented. */
7170 case 4:
7171 case 5:
7172 /* fall through */
7173 default:
7174 goto die;
7176 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7177 gen_store_gpr(t0, rd);
7178 tcg_temp_free(t0);
7179 return;
7181 die:
7182 tcg_temp_free(t0);
7183 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7184 generate_exception(ctx, EXCP_RI);
7187 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7188 int u, int sel, int h)
7190 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7191 TCGv t0 = tcg_temp_local_new();
7193 gen_load_gpr(t0, rt);
7194 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7195 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7196 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7197 /* NOP */ ;
7198 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7199 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7200 /* NOP */ ;
7201 else if (u == 0) {
7202 switch (rd) {
7203 case 1:
7204 switch (sel) {
7205 case 1:
7206 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7207 break;
7208 case 2:
7209 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7210 break;
7211 default:
7212 goto die;
7213 break;
7215 break;
7216 case 2:
7217 switch (sel) {
7218 case 1:
7219 gen_helper_mttc0_tcstatus(cpu_env, t0);
7220 break;
7221 case 2:
7222 gen_helper_mttc0_tcbind(cpu_env, t0);
7223 break;
7224 case 3:
7225 gen_helper_mttc0_tcrestart(cpu_env, t0);
7226 break;
7227 case 4:
7228 gen_helper_mttc0_tchalt(cpu_env, t0);
7229 break;
7230 case 5:
7231 gen_helper_mttc0_tccontext(cpu_env, t0);
7232 break;
7233 case 6:
7234 gen_helper_mttc0_tcschedule(cpu_env, t0);
7235 break;
7236 case 7:
7237 gen_helper_mttc0_tcschefback(cpu_env, t0);
7238 break;
7239 default:
7240 gen_mtc0(ctx, t0, rd, sel);
7241 break;
7243 break;
7244 case 10:
7245 switch (sel) {
7246 case 0:
7247 gen_helper_mttc0_entryhi(cpu_env, t0);
7248 break;
7249 default:
7250 gen_mtc0(ctx, t0, rd, sel);
7251 break;
7253 case 12:
7254 switch (sel) {
7255 case 0:
7256 gen_helper_mttc0_status(cpu_env, t0);
7257 break;
7258 default:
7259 gen_mtc0(ctx, t0, rd, sel);
7260 break;
7262 case 13:
7263 switch (sel) {
7264 case 0:
7265 gen_helper_mttc0_cause(cpu_env, t0);
7266 break;
7267 default:
7268 goto die;
7269 break;
7271 break;
7272 case 15:
7273 switch (sel) {
7274 case 1:
7275 gen_helper_mttc0_ebase(cpu_env, t0);
7276 break;
7277 default:
7278 goto die;
7279 break;
7281 break;
7282 case 23:
7283 switch (sel) {
7284 case 0:
7285 gen_helper_mttc0_debug(cpu_env, t0);
7286 break;
7287 default:
7288 gen_mtc0(ctx, t0, rd, sel);
7289 break;
7291 break;
7292 default:
7293 gen_mtc0(ctx, t0, rd, sel);
7295 } else switch (sel) {
7296 /* GPR registers. */
7297 case 0:
7298 gen_helper_0e1i(mttgpr, t0, rd);
7299 break;
7300 /* Auxiliary CPU registers */
7301 case 1:
7302 switch (rd) {
7303 case 0:
7304 gen_helper_0e1i(mttlo, t0, 0);
7305 break;
7306 case 1:
7307 gen_helper_0e1i(mtthi, t0, 0);
7308 break;
7309 case 2:
7310 gen_helper_0e1i(mttacx, t0, 0);
7311 break;
7312 case 4:
7313 gen_helper_0e1i(mttlo, t0, 1);
7314 break;
7315 case 5:
7316 gen_helper_0e1i(mtthi, t0, 1);
7317 break;
7318 case 6:
7319 gen_helper_0e1i(mttacx, t0, 1);
7320 break;
7321 case 8:
7322 gen_helper_0e1i(mttlo, t0, 2);
7323 break;
7324 case 9:
7325 gen_helper_0e1i(mtthi, t0, 2);
7326 break;
7327 case 10:
7328 gen_helper_0e1i(mttacx, t0, 2);
7329 break;
7330 case 12:
7331 gen_helper_0e1i(mttlo, t0, 3);
7332 break;
7333 case 13:
7334 gen_helper_0e1i(mtthi, t0, 3);
7335 break;
7336 case 14:
7337 gen_helper_0e1i(mttacx, t0, 3);
7338 break;
7339 case 16:
7340 gen_helper_mttdsp(cpu_env, t0);
7341 break;
7342 default:
7343 goto die;
7345 break;
7346 /* Floating point (COP1). */
7347 case 2:
7348 /* XXX: For now we support only a single FPU context. */
7349 if (h == 0) {
7350 TCGv_i32 fp0 = tcg_temp_new_i32();
7352 tcg_gen_trunc_tl_i32(fp0, t0);
7353 gen_store_fpr32(fp0, rd);
7354 tcg_temp_free_i32(fp0);
7355 } else {
7356 TCGv_i32 fp0 = tcg_temp_new_i32();
7358 tcg_gen_trunc_tl_i32(fp0, t0);
7359 gen_store_fpr32h(ctx, fp0, rd);
7360 tcg_temp_free_i32(fp0);
7362 break;
7363 case 3:
7364 /* XXX: For now we support only a single FPU context. */
7366 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7368 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7369 tcg_temp_free_i32(fs_tmp);
7371 break;
7372 /* COP2: Not implemented. */
7373 case 4:
7374 case 5:
7375 /* fall through */
7376 default:
7377 goto die;
7379 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7380 tcg_temp_free(t0);
7381 return;
7383 die:
7384 tcg_temp_free(t0);
7385 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7386 generate_exception(ctx, EXCP_RI);
7389 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
7391 const char *opn = "ldst";
7393 check_cp0_enabled(ctx);
7394 switch (opc) {
7395 case OPC_MFC0:
7396 if (rt == 0) {
7397 /* Treat as NOP. */
7398 return;
7400 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7401 opn = "mfc0";
7402 break;
7403 case OPC_MTC0:
7405 TCGv t0 = tcg_temp_new();
7407 gen_load_gpr(t0, rt);
7408 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
7409 tcg_temp_free(t0);
7411 opn = "mtc0";
7412 break;
7413 #if defined(TARGET_MIPS64)
7414 case OPC_DMFC0:
7415 check_insn(ctx, ISA_MIPS3);
7416 if (rt == 0) {
7417 /* Treat as NOP. */
7418 return;
7420 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7421 opn = "dmfc0";
7422 break;
7423 case OPC_DMTC0:
7424 check_insn(ctx, ISA_MIPS3);
7426 TCGv t0 = tcg_temp_new();
7428 gen_load_gpr(t0, rt);
7429 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
7430 tcg_temp_free(t0);
7432 opn = "dmtc0";
7433 break;
7434 #endif
7435 case OPC_MFTR:
7436 check_insn(ctx, ASE_MT);
7437 if (rd == 0) {
7438 /* Treat as NOP. */
7439 return;
7441 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
7442 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7443 opn = "mftr";
7444 break;
7445 case OPC_MTTR:
7446 check_insn(ctx, ASE_MT);
7447 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
7448 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7449 opn = "mttr";
7450 break;
7451 case OPC_TLBWI:
7452 opn = "tlbwi";
7453 if (!env->tlb->helper_tlbwi)
7454 goto die;
7455 gen_helper_tlbwi(cpu_env);
7456 break;
7457 case OPC_TLBWR:
7458 opn = "tlbwr";
7459 if (!env->tlb->helper_tlbwr)
7460 goto die;
7461 gen_helper_tlbwr(cpu_env);
7462 break;
7463 case OPC_TLBP:
7464 opn = "tlbp";
7465 if (!env->tlb->helper_tlbp)
7466 goto die;
7467 gen_helper_tlbp(cpu_env);
7468 break;
7469 case OPC_TLBR:
7470 opn = "tlbr";
7471 if (!env->tlb->helper_tlbr)
7472 goto die;
7473 gen_helper_tlbr(cpu_env);
7474 break;
7475 case OPC_ERET:
7476 opn = "eret";
7477 check_insn(ctx, ISA_MIPS2);
7478 gen_helper_eret(cpu_env);
7479 ctx->bstate = BS_EXCP;
7480 break;
7481 case OPC_DERET:
7482 opn = "deret";
7483 check_insn(ctx, ISA_MIPS32);
7484 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7485 MIPS_INVAL(opn);
7486 generate_exception(ctx, EXCP_RI);
7487 } else {
7488 gen_helper_deret(cpu_env);
7489 ctx->bstate = BS_EXCP;
7491 break;
7492 case OPC_WAIT:
7493 opn = "wait";
7494 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
7495 /* If we get an exception, we want to restart at next instruction */
7496 ctx->pc += 4;
7497 save_cpu_state(ctx, 1);
7498 ctx->pc -= 4;
7499 gen_helper_wait(cpu_env);
7500 ctx->bstate = BS_EXCP;
7501 break;
7502 default:
7503 die:
7504 MIPS_INVAL(opn);
7505 generate_exception(ctx, EXCP_RI);
7506 return;
7508 (void)opn; /* avoid a compiler warning */
7509 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
7511 #endif /* !CONFIG_USER_ONLY */
7513 /* CP1 Branches (before delay slot) */
7514 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7515 int32_t cc, int32_t offset)
7517 target_ulong btarget;
7518 const char *opn = "cp1 cond branch";
7519 TCGv_i32 t0 = tcg_temp_new_i32();
7521 if (cc != 0)
7522 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
7524 btarget = ctx->pc + 4 + offset;
7526 switch (op) {
7527 case OPC_BC1F:
7528 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7529 tcg_gen_not_i32(t0, t0);
7530 tcg_gen_andi_i32(t0, t0, 1);
7531 tcg_gen_extu_i32_tl(bcond, t0);
7532 opn = "bc1f";
7533 goto not_likely;
7534 case OPC_BC1FL:
7535 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7536 tcg_gen_not_i32(t0, t0);
7537 tcg_gen_andi_i32(t0, t0, 1);
7538 tcg_gen_extu_i32_tl(bcond, t0);
7539 opn = "bc1fl";
7540 goto likely;
7541 case OPC_BC1T:
7542 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7543 tcg_gen_andi_i32(t0, t0, 1);
7544 tcg_gen_extu_i32_tl(bcond, t0);
7545 opn = "bc1t";
7546 goto not_likely;
7547 case OPC_BC1TL:
7548 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7549 tcg_gen_andi_i32(t0, t0, 1);
7550 tcg_gen_extu_i32_tl(bcond, t0);
7551 opn = "bc1tl";
7552 likely:
7553 ctx->hflags |= MIPS_HFLAG_BL;
7554 break;
7555 case OPC_BC1FANY2:
7557 TCGv_i32 t1 = tcg_temp_new_i32();
7558 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7559 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7560 tcg_gen_nand_i32(t0, t0, t1);
7561 tcg_temp_free_i32(t1);
7562 tcg_gen_andi_i32(t0, t0, 1);
7563 tcg_gen_extu_i32_tl(bcond, t0);
7565 opn = "bc1any2f";
7566 goto not_likely;
7567 case OPC_BC1TANY2:
7569 TCGv_i32 t1 = tcg_temp_new_i32();
7570 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7571 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7572 tcg_gen_or_i32(t0, t0, t1);
7573 tcg_temp_free_i32(t1);
7574 tcg_gen_andi_i32(t0, t0, 1);
7575 tcg_gen_extu_i32_tl(bcond, t0);
7577 opn = "bc1any2t";
7578 goto not_likely;
7579 case OPC_BC1FANY4:
7581 TCGv_i32 t1 = tcg_temp_new_i32();
7582 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7583 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7584 tcg_gen_and_i32(t0, t0, t1);
7585 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7586 tcg_gen_and_i32(t0, t0, t1);
7587 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7588 tcg_gen_nand_i32(t0, t0, t1);
7589 tcg_temp_free_i32(t1);
7590 tcg_gen_andi_i32(t0, t0, 1);
7591 tcg_gen_extu_i32_tl(bcond, t0);
7593 opn = "bc1any4f";
7594 goto not_likely;
7595 case OPC_BC1TANY4:
7597 TCGv_i32 t1 = tcg_temp_new_i32();
7598 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7599 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7600 tcg_gen_or_i32(t0, t0, t1);
7601 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7602 tcg_gen_or_i32(t0, t0, t1);
7603 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7604 tcg_gen_or_i32(t0, t0, t1);
7605 tcg_temp_free_i32(t1);
7606 tcg_gen_andi_i32(t0, t0, 1);
7607 tcg_gen_extu_i32_tl(bcond, t0);
7609 opn = "bc1any4t";
7610 not_likely:
7611 ctx->hflags |= MIPS_HFLAG_BC;
7612 break;
7613 default:
7614 MIPS_INVAL(opn);
7615 generate_exception (ctx, EXCP_RI);
7616 goto out;
7618 (void)opn; /* avoid a compiler warning */
7619 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
7620 ctx->hflags, btarget);
7621 ctx->btarget = btarget;
7622 ctx->hflags |= MIPS_HFLAG_BDS32;
7623 out:
7624 tcg_temp_free_i32(t0);
7627 /* R6 CP1 Branches */
7628 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
7629 int32_t ft, int32_t offset)
7631 target_ulong btarget;
7632 const char *opn = "cp1 cond branch";
7633 TCGv_i64 t0 = tcg_temp_new_i64();
7635 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7636 #ifdef MIPS_DEBUG_DISAS
7637 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
7638 #endif
7639 generate_exception(ctx, EXCP_RI);
7640 goto out;
7643 gen_load_fpr64(ctx, t0, ft);
7644 tcg_gen_andi_i64(t0, t0, 1);
7646 btarget = addr_add(ctx, ctx->pc + 4, offset);
7648 switch (op) {
7649 case OPC_BC1EQZ:
7650 tcg_gen_xori_i64(t0, t0, 1);
7651 opn = "bc1eqz";
7652 ctx->hflags |= MIPS_HFLAG_BC;
7653 break;
7654 case OPC_BC1NEZ:
7655 /* t0 already set */
7656 opn = "bc1nez";
7657 ctx->hflags |= MIPS_HFLAG_BC;
7658 break;
7659 default:
7660 MIPS_INVAL(opn);
7661 generate_exception(ctx, EXCP_RI);
7662 goto out;
7665 tcg_gen_trunc_i64_tl(bcond, t0);
7667 (void)opn; /* avoid a compiler warning */
7668 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
7669 ctx->hflags, btarget);
7670 ctx->btarget = btarget;
7672 out:
7673 tcg_temp_free_i64(t0);
7676 /* Coprocessor 1 (FPU) */
7678 #define FOP(func, fmt) (((fmt) << 21) | (func))
7680 enum fopcode {
7681 OPC_ADD_S = FOP(0, FMT_S),
7682 OPC_SUB_S = FOP(1, FMT_S),
7683 OPC_MUL_S = FOP(2, FMT_S),
7684 OPC_DIV_S = FOP(3, FMT_S),
7685 OPC_SQRT_S = FOP(4, FMT_S),
7686 OPC_ABS_S = FOP(5, FMT_S),
7687 OPC_MOV_S = FOP(6, FMT_S),
7688 OPC_NEG_S = FOP(7, FMT_S),
7689 OPC_ROUND_L_S = FOP(8, FMT_S),
7690 OPC_TRUNC_L_S = FOP(9, FMT_S),
7691 OPC_CEIL_L_S = FOP(10, FMT_S),
7692 OPC_FLOOR_L_S = FOP(11, FMT_S),
7693 OPC_ROUND_W_S = FOP(12, FMT_S),
7694 OPC_TRUNC_W_S = FOP(13, FMT_S),
7695 OPC_CEIL_W_S = FOP(14, FMT_S),
7696 OPC_FLOOR_W_S = FOP(15, FMT_S),
7697 OPC_SEL_S = FOP(16, FMT_S),
7698 OPC_MOVCF_S = FOP(17, FMT_S),
7699 OPC_MOVZ_S = FOP(18, FMT_S),
7700 OPC_MOVN_S = FOP(19, FMT_S),
7701 OPC_SELEQZ_S = FOP(20, FMT_S),
7702 OPC_RECIP_S = FOP(21, FMT_S),
7703 OPC_RSQRT_S = FOP(22, FMT_S),
7704 OPC_SELNEZ_S = FOP(23, FMT_S),
7705 OPC_MADDF_S = FOP(24, FMT_S),
7706 OPC_MSUBF_S = FOP(25, FMT_S),
7707 OPC_RINT_S = FOP(26, FMT_S),
7708 OPC_CLASS_S = FOP(27, FMT_S),
7709 OPC_MIN_S = FOP(28, FMT_S),
7710 OPC_RECIP2_S = FOP(28, FMT_S),
7711 OPC_MINA_S = FOP(29, FMT_S),
7712 OPC_RECIP1_S = FOP(29, FMT_S),
7713 OPC_MAX_S = FOP(30, FMT_S),
7714 OPC_RSQRT1_S = FOP(30, FMT_S),
7715 OPC_MAXA_S = FOP(31, FMT_S),
7716 OPC_RSQRT2_S = FOP(31, FMT_S),
7717 OPC_CVT_D_S = FOP(33, FMT_S),
7718 OPC_CVT_W_S = FOP(36, FMT_S),
7719 OPC_CVT_L_S = FOP(37, FMT_S),
7720 OPC_CVT_PS_S = FOP(38, FMT_S),
7721 OPC_CMP_F_S = FOP (48, FMT_S),
7722 OPC_CMP_UN_S = FOP (49, FMT_S),
7723 OPC_CMP_EQ_S = FOP (50, FMT_S),
7724 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7725 OPC_CMP_OLT_S = FOP (52, FMT_S),
7726 OPC_CMP_ULT_S = FOP (53, FMT_S),
7727 OPC_CMP_OLE_S = FOP (54, FMT_S),
7728 OPC_CMP_ULE_S = FOP (55, FMT_S),
7729 OPC_CMP_SF_S = FOP (56, FMT_S),
7730 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7731 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7732 OPC_CMP_NGL_S = FOP (59, FMT_S),
7733 OPC_CMP_LT_S = FOP (60, FMT_S),
7734 OPC_CMP_NGE_S = FOP (61, FMT_S),
7735 OPC_CMP_LE_S = FOP (62, FMT_S),
7736 OPC_CMP_NGT_S = FOP (63, FMT_S),
7738 OPC_ADD_D = FOP(0, FMT_D),
7739 OPC_SUB_D = FOP(1, FMT_D),
7740 OPC_MUL_D = FOP(2, FMT_D),
7741 OPC_DIV_D = FOP(3, FMT_D),
7742 OPC_SQRT_D = FOP(4, FMT_D),
7743 OPC_ABS_D = FOP(5, FMT_D),
7744 OPC_MOV_D = FOP(6, FMT_D),
7745 OPC_NEG_D = FOP(7, FMT_D),
7746 OPC_ROUND_L_D = FOP(8, FMT_D),
7747 OPC_TRUNC_L_D = FOP(9, FMT_D),
7748 OPC_CEIL_L_D = FOP(10, FMT_D),
7749 OPC_FLOOR_L_D = FOP(11, FMT_D),
7750 OPC_ROUND_W_D = FOP(12, FMT_D),
7751 OPC_TRUNC_W_D = FOP(13, FMT_D),
7752 OPC_CEIL_W_D = FOP(14, FMT_D),
7753 OPC_FLOOR_W_D = FOP(15, FMT_D),
7754 OPC_SEL_D = FOP(16, FMT_D),
7755 OPC_MOVCF_D = FOP(17, FMT_D),
7756 OPC_MOVZ_D = FOP(18, FMT_D),
7757 OPC_MOVN_D = FOP(19, FMT_D),
7758 OPC_SELEQZ_D = FOP(20, FMT_D),
7759 OPC_RECIP_D = FOP(21, FMT_D),
7760 OPC_RSQRT_D = FOP(22, FMT_D),
7761 OPC_SELNEZ_D = FOP(23, FMT_D),
7762 OPC_MADDF_D = FOP(24, FMT_D),
7763 OPC_MSUBF_D = FOP(25, FMT_D),
7764 OPC_RINT_D = FOP(26, FMT_D),
7765 OPC_CLASS_D = FOP(27, FMT_D),
7766 OPC_MIN_D = FOP(28, FMT_D),
7767 OPC_RECIP2_D = FOP(28, FMT_D),
7768 OPC_MINA_D = FOP(29, FMT_D),
7769 OPC_RECIP1_D = FOP(29, FMT_D),
7770 OPC_MAX_D = FOP(30, FMT_D),
7771 OPC_RSQRT1_D = FOP(30, FMT_D),
7772 OPC_MAXA_D = FOP(31, FMT_D),
7773 OPC_RSQRT2_D = FOP(31, FMT_D),
7774 OPC_CVT_S_D = FOP(32, FMT_D),
7775 OPC_CVT_W_D = FOP(36, FMT_D),
7776 OPC_CVT_L_D = FOP(37, FMT_D),
7777 OPC_CMP_F_D = FOP (48, FMT_D),
7778 OPC_CMP_UN_D = FOP (49, FMT_D),
7779 OPC_CMP_EQ_D = FOP (50, FMT_D),
7780 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7781 OPC_CMP_OLT_D = FOP (52, FMT_D),
7782 OPC_CMP_ULT_D = FOP (53, FMT_D),
7783 OPC_CMP_OLE_D = FOP (54, FMT_D),
7784 OPC_CMP_ULE_D = FOP (55, FMT_D),
7785 OPC_CMP_SF_D = FOP (56, FMT_D),
7786 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7787 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7788 OPC_CMP_NGL_D = FOP (59, FMT_D),
7789 OPC_CMP_LT_D = FOP (60, FMT_D),
7790 OPC_CMP_NGE_D = FOP (61, FMT_D),
7791 OPC_CMP_LE_D = FOP (62, FMT_D),
7792 OPC_CMP_NGT_D = FOP (63, FMT_D),
7794 OPC_CVT_S_W = FOP(32, FMT_W),
7795 OPC_CVT_D_W = FOP(33, FMT_W),
7796 OPC_CVT_S_L = FOP(32, FMT_L),
7797 OPC_CVT_D_L = FOP(33, FMT_L),
7798 OPC_CVT_PS_PW = FOP(38, FMT_W),
7800 OPC_ADD_PS = FOP(0, FMT_PS),
7801 OPC_SUB_PS = FOP(1, FMT_PS),
7802 OPC_MUL_PS = FOP(2, FMT_PS),
7803 OPC_DIV_PS = FOP(3, FMT_PS),
7804 OPC_ABS_PS = FOP(5, FMT_PS),
7805 OPC_MOV_PS = FOP(6, FMT_PS),
7806 OPC_NEG_PS = FOP(7, FMT_PS),
7807 OPC_MOVCF_PS = FOP(17, FMT_PS),
7808 OPC_MOVZ_PS = FOP(18, FMT_PS),
7809 OPC_MOVN_PS = FOP(19, FMT_PS),
7810 OPC_ADDR_PS = FOP(24, FMT_PS),
7811 OPC_MULR_PS = FOP(26, FMT_PS),
7812 OPC_RECIP2_PS = FOP(28, FMT_PS),
7813 OPC_RECIP1_PS = FOP(29, FMT_PS),
7814 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7815 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7817 OPC_CVT_S_PU = FOP(32, FMT_PS),
7818 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7819 OPC_CVT_S_PL = FOP(40, FMT_PS),
7820 OPC_PLL_PS = FOP(44, FMT_PS),
7821 OPC_PLU_PS = FOP(45, FMT_PS),
7822 OPC_PUL_PS = FOP(46, FMT_PS),
7823 OPC_PUU_PS = FOP(47, FMT_PS),
7824 OPC_CMP_F_PS = FOP (48, FMT_PS),
7825 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7826 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7827 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7828 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7829 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7830 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7831 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7832 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7833 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7834 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7835 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7836 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7837 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7838 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7839 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7842 enum r6_f_cmp_op {
7843 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
7844 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
7845 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
7846 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
7847 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
7848 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
7849 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
7850 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
7851 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
7852 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
7853 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
7854 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
7855 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
7856 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
7857 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
7858 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
7859 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
7860 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
7861 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
7862 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
7863 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
7864 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
7866 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
7867 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
7868 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
7869 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
7870 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
7871 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
7872 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
7873 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
7874 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
7875 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
7876 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
7877 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
7878 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
7879 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
7880 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
7881 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
7882 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
7883 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
7884 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
7885 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
7886 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
7887 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
7889 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
7891 const char *opn = "cp1 move";
7892 TCGv t0 = tcg_temp_new();
7894 switch (opc) {
7895 case OPC_MFC1:
7897 TCGv_i32 fp0 = tcg_temp_new_i32();
7899 gen_load_fpr32(fp0, fs);
7900 tcg_gen_ext_i32_tl(t0, fp0);
7901 tcg_temp_free_i32(fp0);
7903 gen_store_gpr(t0, rt);
7904 opn = "mfc1";
7905 break;
7906 case OPC_MTC1:
7907 gen_load_gpr(t0, rt);
7909 TCGv_i32 fp0 = tcg_temp_new_i32();
7911 tcg_gen_trunc_tl_i32(fp0, t0);
7912 gen_store_fpr32(fp0, fs);
7913 tcg_temp_free_i32(fp0);
7915 opn = "mtc1";
7916 break;
7917 case OPC_CFC1:
7918 gen_helper_1e0i(cfc1, t0, fs);
7919 gen_store_gpr(t0, rt);
7920 opn = "cfc1";
7921 break;
7922 case OPC_CTC1:
7923 gen_load_gpr(t0, rt);
7925 TCGv_i32 fs_tmp = tcg_const_i32(fs);
7927 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7928 tcg_temp_free_i32(fs_tmp);
7930 opn = "ctc1";
7931 break;
7932 #if defined(TARGET_MIPS64)
7933 case OPC_DMFC1:
7934 gen_load_fpr64(ctx, t0, fs);
7935 gen_store_gpr(t0, rt);
7936 opn = "dmfc1";
7937 break;
7938 case OPC_DMTC1:
7939 gen_load_gpr(t0, rt);
7940 gen_store_fpr64(ctx, t0, fs);
7941 opn = "dmtc1";
7942 break;
7943 #endif
7944 case OPC_MFHC1:
7946 TCGv_i32 fp0 = tcg_temp_new_i32();
7948 gen_load_fpr32h(ctx, fp0, fs);
7949 tcg_gen_ext_i32_tl(t0, fp0);
7950 tcg_temp_free_i32(fp0);
7952 gen_store_gpr(t0, rt);
7953 opn = "mfhc1";
7954 break;
7955 case OPC_MTHC1:
7956 gen_load_gpr(t0, rt);
7958 TCGv_i32 fp0 = tcg_temp_new_i32();
7960 tcg_gen_trunc_tl_i32(fp0, t0);
7961 gen_store_fpr32h(ctx, fp0, fs);
7962 tcg_temp_free_i32(fp0);
7964 opn = "mthc1";
7965 break;
7966 default:
7967 MIPS_INVAL(opn);
7968 generate_exception (ctx, EXCP_RI);
7969 goto out;
7971 (void)opn; /* avoid a compiler warning */
7972 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
7974 out:
7975 tcg_temp_free(t0);
7978 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
7980 int l1;
7981 TCGCond cond;
7982 TCGv_i32 t0;
7984 if (rd == 0) {
7985 /* Treat as NOP. */
7986 return;
7989 if (tf)
7990 cond = TCG_COND_EQ;
7991 else
7992 cond = TCG_COND_NE;
7994 l1 = gen_new_label();
7995 t0 = tcg_temp_new_i32();
7996 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7997 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7998 tcg_temp_free_i32(t0);
7999 if (rs == 0) {
8000 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8001 } else {
8002 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8004 gen_set_label(l1);
8007 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
8009 int cond;
8010 TCGv_i32 t0 = tcg_temp_new_i32();
8011 int l1 = gen_new_label();
8013 if (tf)
8014 cond = TCG_COND_EQ;
8015 else
8016 cond = TCG_COND_NE;
8018 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8019 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8020 gen_load_fpr32(t0, fs);
8021 gen_store_fpr32(t0, fd);
8022 gen_set_label(l1);
8023 tcg_temp_free_i32(t0);
8026 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8028 int cond;
8029 TCGv_i32 t0 = tcg_temp_new_i32();
8030 TCGv_i64 fp0;
8031 int l1 = gen_new_label();
8033 if (tf)
8034 cond = TCG_COND_EQ;
8035 else
8036 cond = TCG_COND_NE;
8038 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8039 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8040 tcg_temp_free_i32(t0);
8041 fp0 = tcg_temp_new_i64();
8042 gen_load_fpr64(ctx, fp0, fs);
8043 gen_store_fpr64(ctx, fp0, fd);
8044 tcg_temp_free_i64(fp0);
8045 gen_set_label(l1);
8048 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8049 int cc, int tf)
8051 int cond;
8052 TCGv_i32 t0 = tcg_temp_new_i32();
8053 int l1 = gen_new_label();
8054 int l2 = gen_new_label();
8056 if (tf)
8057 cond = TCG_COND_EQ;
8058 else
8059 cond = TCG_COND_NE;
8061 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8062 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8063 gen_load_fpr32(t0, fs);
8064 gen_store_fpr32(t0, fd);
8065 gen_set_label(l1);
8067 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8068 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8069 gen_load_fpr32h(ctx, t0, fs);
8070 gen_store_fpr32h(ctx, t0, fd);
8071 tcg_temp_free_i32(t0);
8072 gen_set_label(l2);
8075 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8076 int fs)
8078 TCGv_i32 t1 = tcg_const_i32(0);
8079 TCGv_i32 fp0 = tcg_temp_new_i32();
8080 TCGv_i32 fp1 = tcg_temp_new_i32();
8081 TCGv_i32 fp2 = tcg_temp_new_i32();
8082 gen_load_fpr32(fp0, fd);
8083 gen_load_fpr32(fp1, ft);
8084 gen_load_fpr32(fp2, fs);
8086 switch (op1) {
8087 case OPC_SEL_S:
8088 tcg_gen_andi_i32(fp0, fp0, 1);
8089 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8090 break;
8091 case OPC_SELEQZ_S:
8092 tcg_gen_andi_i32(fp1, fp1, 1);
8093 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8094 break;
8095 case OPC_SELNEZ_S:
8096 tcg_gen_andi_i32(fp1, fp1, 1);
8097 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8098 break;
8099 default:
8100 MIPS_INVAL("gen_sel_s");
8101 generate_exception (ctx, EXCP_RI);
8102 break;
8105 gen_store_fpr32(fp0, fd);
8106 tcg_temp_free_i32(fp2);
8107 tcg_temp_free_i32(fp1);
8108 tcg_temp_free_i32(fp0);
8109 tcg_temp_free_i32(t1);
8112 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8113 int fs)
8115 TCGv_i64 t1 = tcg_const_i64(0);
8116 TCGv_i64 fp0 = tcg_temp_new_i64();
8117 TCGv_i64 fp1 = tcg_temp_new_i64();
8118 TCGv_i64 fp2 = tcg_temp_new_i64();
8119 gen_load_fpr64(ctx, fp0, fd);
8120 gen_load_fpr64(ctx, fp1, ft);
8121 gen_load_fpr64(ctx, fp2, fs);
8123 switch (op1) {
8124 case OPC_SEL_D:
8125 tcg_gen_andi_i64(fp0, fp0, 1);
8126 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8127 break;
8128 case OPC_SELEQZ_D:
8129 tcg_gen_andi_i64(fp1, fp1, 1);
8130 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8131 break;
8132 case OPC_SELNEZ_D:
8133 tcg_gen_andi_i64(fp1, fp1, 1);
8134 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8135 break;
8136 default:
8137 MIPS_INVAL("gen_sel_d");
8138 generate_exception (ctx, EXCP_RI);
8139 break;
8142 gen_store_fpr64(ctx, fp0, fd);
8143 tcg_temp_free_i64(fp2);
8144 tcg_temp_free_i64(fp1);
8145 tcg_temp_free_i64(fp0);
8146 tcg_temp_free_i64(t1);
8149 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8150 int ft, int fs, int fd, int cc)
8152 const char *opn = "farith";
8153 const char *condnames[] = {
8154 "c.f",
8155 "c.un",
8156 "c.eq",
8157 "c.ueq",
8158 "c.olt",
8159 "c.ult",
8160 "c.ole",
8161 "c.ule",
8162 "c.sf",
8163 "c.ngle",
8164 "c.seq",
8165 "c.ngl",
8166 "c.lt",
8167 "c.nge",
8168 "c.le",
8169 "c.ngt",
8171 const char *condnames_abs[] = {
8172 "cabs.f",
8173 "cabs.un",
8174 "cabs.eq",
8175 "cabs.ueq",
8176 "cabs.olt",
8177 "cabs.ult",
8178 "cabs.ole",
8179 "cabs.ule",
8180 "cabs.sf",
8181 "cabs.ngle",
8182 "cabs.seq",
8183 "cabs.ngl",
8184 "cabs.lt",
8185 "cabs.nge",
8186 "cabs.le",
8187 "cabs.ngt",
8189 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
8190 uint32_t func = ctx->opcode & 0x3f;
8192 switch (op1) {
8193 case OPC_ADD_S:
8195 TCGv_i32 fp0 = tcg_temp_new_i32();
8196 TCGv_i32 fp1 = tcg_temp_new_i32();
8198 gen_load_fpr32(fp0, fs);
8199 gen_load_fpr32(fp1, ft);
8200 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8201 tcg_temp_free_i32(fp1);
8202 gen_store_fpr32(fp0, fd);
8203 tcg_temp_free_i32(fp0);
8205 opn = "add.s";
8206 optype = BINOP;
8207 break;
8208 case OPC_SUB_S:
8210 TCGv_i32 fp0 = tcg_temp_new_i32();
8211 TCGv_i32 fp1 = tcg_temp_new_i32();
8213 gen_load_fpr32(fp0, fs);
8214 gen_load_fpr32(fp1, ft);
8215 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8216 tcg_temp_free_i32(fp1);
8217 gen_store_fpr32(fp0, fd);
8218 tcg_temp_free_i32(fp0);
8220 opn = "sub.s";
8221 optype = BINOP;
8222 break;
8223 case OPC_MUL_S:
8225 TCGv_i32 fp0 = tcg_temp_new_i32();
8226 TCGv_i32 fp1 = tcg_temp_new_i32();
8228 gen_load_fpr32(fp0, fs);
8229 gen_load_fpr32(fp1, ft);
8230 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8231 tcg_temp_free_i32(fp1);
8232 gen_store_fpr32(fp0, fd);
8233 tcg_temp_free_i32(fp0);
8235 opn = "mul.s";
8236 optype = BINOP;
8237 break;
8238 case OPC_DIV_S:
8240 TCGv_i32 fp0 = tcg_temp_new_i32();
8241 TCGv_i32 fp1 = tcg_temp_new_i32();
8243 gen_load_fpr32(fp0, fs);
8244 gen_load_fpr32(fp1, ft);
8245 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8246 tcg_temp_free_i32(fp1);
8247 gen_store_fpr32(fp0, fd);
8248 tcg_temp_free_i32(fp0);
8250 opn = "div.s";
8251 optype = BINOP;
8252 break;
8253 case OPC_SQRT_S:
8255 TCGv_i32 fp0 = tcg_temp_new_i32();
8257 gen_load_fpr32(fp0, fs);
8258 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8259 gen_store_fpr32(fp0, fd);
8260 tcg_temp_free_i32(fp0);
8262 opn = "sqrt.s";
8263 break;
8264 case OPC_ABS_S:
8266 TCGv_i32 fp0 = tcg_temp_new_i32();
8268 gen_load_fpr32(fp0, fs);
8269 gen_helper_float_abs_s(fp0, fp0);
8270 gen_store_fpr32(fp0, fd);
8271 tcg_temp_free_i32(fp0);
8273 opn = "abs.s";
8274 break;
8275 case OPC_MOV_S:
8277 TCGv_i32 fp0 = tcg_temp_new_i32();
8279 gen_load_fpr32(fp0, fs);
8280 gen_store_fpr32(fp0, fd);
8281 tcg_temp_free_i32(fp0);
8283 opn = "mov.s";
8284 break;
8285 case OPC_NEG_S:
8287 TCGv_i32 fp0 = tcg_temp_new_i32();
8289 gen_load_fpr32(fp0, fs);
8290 gen_helper_float_chs_s(fp0, fp0);
8291 gen_store_fpr32(fp0, fd);
8292 tcg_temp_free_i32(fp0);
8294 opn = "neg.s";
8295 break;
8296 case OPC_ROUND_L_S:
8297 check_cp1_64bitmode(ctx);
8299 TCGv_i32 fp32 = tcg_temp_new_i32();
8300 TCGv_i64 fp64 = tcg_temp_new_i64();
8302 gen_load_fpr32(fp32, fs);
8303 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8304 tcg_temp_free_i32(fp32);
8305 gen_store_fpr64(ctx, fp64, fd);
8306 tcg_temp_free_i64(fp64);
8308 opn = "round.l.s";
8309 break;
8310 case OPC_TRUNC_L_S:
8311 check_cp1_64bitmode(ctx);
8313 TCGv_i32 fp32 = tcg_temp_new_i32();
8314 TCGv_i64 fp64 = tcg_temp_new_i64();
8316 gen_load_fpr32(fp32, fs);
8317 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8318 tcg_temp_free_i32(fp32);
8319 gen_store_fpr64(ctx, fp64, fd);
8320 tcg_temp_free_i64(fp64);
8322 opn = "trunc.l.s";
8323 break;
8324 case OPC_CEIL_L_S:
8325 check_cp1_64bitmode(ctx);
8327 TCGv_i32 fp32 = tcg_temp_new_i32();
8328 TCGv_i64 fp64 = tcg_temp_new_i64();
8330 gen_load_fpr32(fp32, fs);
8331 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8332 tcg_temp_free_i32(fp32);
8333 gen_store_fpr64(ctx, fp64, fd);
8334 tcg_temp_free_i64(fp64);
8336 opn = "ceil.l.s";
8337 break;
8338 case OPC_FLOOR_L_S:
8339 check_cp1_64bitmode(ctx);
8341 TCGv_i32 fp32 = tcg_temp_new_i32();
8342 TCGv_i64 fp64 = tcg_temp_new_i64();
8344 gen_load_fpr32(fp32, fs);
8345 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8346 tcg_temp_free_i32(fp32);
8347 gen_store_fpr64(ctx, fp64, fd);
8348 tcg_temp_free_i64(fp64);
8350 opn = "floor.l.s";
8351 break;
8352 case OPC_ROUND_W_S:
8354 TCGv_i32 fp0 = tcg_temp_new_i32();
8356 gen_load_fpr32(fp0, fs);
8357 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8358 gen_store_fpr32(fp0, fd);
8359 tcg_temp_free_i32(fp0);
8361 opn = "round.w.s";
8362 break;
8363 case OPC_TRUNC_W_S:
8365 TCGv_i32 fp0 = tcg_temp_new_i32();
8367 gen_load_fpr32(fp0, fs);
8368 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8369 gen_store_fpr32(fp0, fd);
8370 tcg_temp_free_i32(fp0);
8372 opn = "trunc.w.s";
8373 break;
8374 case OPC_CEIL_W_S:
8376 TCGv_i32 fp0 = tcg_temp_new_i32();
8378 gen_load_fpr32(fp0, fs);
8379 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8380 gen_store_fpr32(fp0, fd);
8381 tcg_temp_free_i32(fp0);
8383 opn = "ceil.w.s";
8384 break;
8385 case OPC_FLOOR_W_S:
8387 TCGv_i32 fp0 = tcg_temp_new_i32();
8389 gen_load_fpr32(fp0, fs);
8390 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
8391 gen_store_fpr32(fp0, fd);
8392 tcg_temp_free_i32(fp0);
8394 opn = "floor.w.s";
8395 break;
8396 case OPC_SEL_S:
8397 check_insn(ctx, ISA_MIPS32R6);
8398 gen_sel_s(ctx, op1, fd, ft, fs);
8399 opn = "sel.s";
8400 break;
8401 case OPC_SELEQZ_S:
8402 check_insn(ctx, ISA_MIPS32R6);
8403 gen_sel_s(ctx, op1, fd, ft, fs);
8404 opn = "seleqz.s";
8405 break;
8406 case OPC_SELNEZ_S:
8407 check_insn(ctx, ISA_MIPS32R6);
8408 gen_sel_s(ctx, op1, fd, ft, fs);
8409 opn = "selnez.s";
8410 break;
8411 case OPC_MOVCF_S:
8412 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8413 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8414 opn = "movcf.s";
8415 break;
8416 case OPC_MOVZ_S:
8417 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8419 int l1 = gen_new_label();
8420 TCGv_i32 fp0;
8422 if (ft != 0) {
8423 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8425 fp0 = tcg_temp_new_i32();
8426 gen_load_fpr32(fp0, fs);
8427 gen_store_fpr32(fp0, fd);
8428 tcg_temp_free_i32(fp0);
8429 gen_set_label(l1);
8431 opn = "movz.s";
8432 break;
8433 case OPC_MOVN_S:
8434 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8436 int l1 = gen_new_label();
8437 TCGv_i32 fp0;
8439 if (ft != 0) {
8440 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8441 fp0 = tcg_temp_new_i32();
8442 gen_load_fpr32(fp0, fs);
8443 gen_store_fpr32(fp0, fd);
8444 tcg_temp_free_i32(fp0);
8445 gen_set_label(l1);
8448 opn = "movn.s";
8449 break;
8450 case OPC_RECIP_S:
8451 check_cop1x(ctx);
8453 TCGv_i32 fp0 = tcg_temp_new_i32();
8455 gen_load_fpr32(fp0, fs);
8456 gen_helper_float_recip_s(fp0, cpu_env, fp0);
8457 gen_store_fpr32(fp0, fd);
8458 tcg_temp_free_i32(fp0);
8460 opn = "recip.s";
8461 break;
8462 case OPC_RSQRT_S:
8463 check_cop1x(ctx);
8465 TCGv_i32 fp0 = tcg_temp_new_i32();
8467 gen_load_fpr32(fp0, fs);
8468 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
8469 gen_store_fpr32(fp0, fd);
8470 tcg_temp_free_i32(fp0);
8472 opn = "rsqrt.s";
8473 break;
8474 case OPC_MADDF_S:
8475 check_insn(ctx, ISA_MIPS32R6);
8477 TCGv_i32 fp0 = tcg_temp_new_i32();
8478 TCGv_i32 fp1 = tcg_temp_new_i32();
8479 TCGv_i32 fp2 = tcg_temp_new_i32();
8480 gen_load_fpr32(fp0, fs);
8481 gen_load_fpr32(fp1, ft);
8482 gen_load_fpr32(fp2, fd);
8483 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
8484 gen_store_fpr32(fp2, fd);
8485 tcg_temp_free_i32(fp2);
8486 tcg_temp_free_i32(fp1);
8487 tcg_temp_free_i32(fp0);
8488 opn = "maddf.s";
8490 break;
8491 case OPC_MSUBF_S:
8492 check_insn(ctx, ISA_MIPS32R6);
8494 TCGv_i32 fp0 = tcg_temp_new_i32();
8495 TCGv_i32 fp1 = tcg_temp_new_i32();
8496 TCGv_i32 fp2 = tcg_temp_new_i32();
8497 gen_load_fpr32(fp0, fs);
8498 gen_load_fpr32(fp1, ft);
8499 gen_load_fpr32(fp2, fd);
8500 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
8501 gen_store_fpr32(fp2, fd);
8502 tcg_temp_free_i32(fp2);
8503 tcg_temp_free_i32(fp1);
8504 tcg_temp_free_i32(fp0);
8505 opn = "msubf.s";
8507 break;
8508 case OPC_RINT_S:
8509 check_insn(ctx, ISA_MIPS32R6);
8511 TCGv_i32 fp0 = tcg_temp_new_i32();
8512 gen_load_fpr32(fp0, fs);
8513 gen_helper_float_rint_s(fp0, cpu_env, fp0);
8514 gen_store_fpr32(fp0, fd);
8515 tcg_temp_free_i32(fp0);
8516 opn = "rint.s";
8518 break;
8519 case OPC_CLASS_S:
8520 check_insn(ctx, ISA_MIPS32R6);
8522 TCGv_i32 fp0 = tcg_temp_new_i32();
8523 gen_load_fpr32(fp0, fs);
8524 gen_helper_float_class_s(fp0, fp0);
8525 gen_store_fpr32(fp0, fd);
8526 tcg_temp_free_i32(fp0);
8527 opn = "class.s";
8529 break;
8530 case OPC_MIN_S: /* OPC_RECIP2_S */
8531 if (ctx->insn_flags & ISA_MIPS32R6) {
8532 /* OPC_MIN_S */
8533 TCGv_i32 fp0 = tcg_temp_new_i32();
8534 TCGv_i32 fp1 = tcg_temp_new_i32();
8535 TCGv_i32 fp2 = tcg_temp_new_i32();
8536 gen_load_fpr32(fp0, fs);
8537 gen_load_fpr32(fp1, ft);
8538 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
8539 gen_store_fpr32(fp2, fd);
8540 tcg_temp_free_i32(fp2);
8541 tcg_temp_free_i32(fp1);
8542 tcg_temp_free_i32(fp0);
8543 opn = "min.s";
8544 } else {
8545 /* OPC_RECIP2_S */
8546 check_cp1_64bitmode(ctx);
8548 TCGv_i32 fp0 = tcg_temp_new_i32();
8549 TCGv_i32 fp1 = tcg_temp_new_i32();
8551 gen_load_fpr32(fp0, fs);
8552 gen_load_fpr32(fp1, ft);
8553 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
8554 tcg_temp_free_i32(fp1);
8555 gen_store_fpr32(fp0, fd);
8556 tcg_temp_free_i32(fp0);
8558 opn = "recip2.s";
8560 break;
8561 case OPC_MINA_S: /* OPC_RECIP1_S */
8562 if (ctx->insn_flags & ISA_MIPS32R6) {
8563 /* OPC_MINA_S */
8564 TCGv_i32 fp0 = tcg_temp_new_i32();
8565 TCGv_i32 fp1 = tcg_temp_new_i32();
8566 TCGv_i32 fp2 = tcg_temp_new_i32();
8567 gen_load_fpr32(fp0, fs);
8568 gen_load_fpr32(fp1, ft);
8569 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
8570 gen_store_fpr32(fp2, fd);
8571 tcg_temp_free_i32(fp2);
8572 tcg_temp_free_i32(fp1);
8573 tcg_temp_free_i32(fp0);
8574 opn = "mina.s";
8575 } else {
8576 /* OPC_RECIP1_S */
8577 check_cp1_64bitmode(ctx);
8579 TCGv_i32 fp0 = tcg_temp_new_i32();
8581 gen_load_fpr32(fp0, fs);
8582 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
8583 gen_store_fpr32(fp0, fd);
8584 tcg_temp_free_i32(fp0);
8586 opn = "recip1.s";
8588 break;
8589 case OPC_MAX_S: /* OPC_RSQRT1_S */
8590 if (ctx->insn_flags & ISA_MIPS32R6) {
8591 /* OPC_MAX_S */
8592 TCGv_i32 fp0 = tcg_temp_new_i32();
8593 TCGv_i32 fp1 = tcg_temp_new_i32();
8594 gen_load_fpr32(fp0, fs);
8595 gen_load_fpr32(fp1, ft);
8596 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
8597 gen_store_fpr32(fp1, fd);
8598 tcg_temp_free_i32(fp1);
8599 tcg_temp_free_i32(fp0);
8600 opn = "max.s";
8601 } else {
8602 /* OPC_RSQRT1_S */
8603 check_cp1_64bitmode(ctx);
8605 TCGv_i32 fp0 = tcg_temp_new_i32();
8607 gen_load_fpr32(fp0, fs);
8608 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
8609 gen_store_fpr32(fp0, fd);
8610 tcg_temp_free_i32(fp0);
8612 opn = "rsqrt1.s";
8614 break;
8615 case OPC_MAXA_S: /* OPC_RSQRT2_S */
8616 if (ctx->insn_flags & ISA_MIPS32R6) {
8617 /* OPC_MAXA_S */
8618 TCGv_i32 fp0 = tcg_temp_new_i32();
8619 TCGv_i32 fp1 = tcg_temp_new_i32();
8620 gen_load_fpr32(fp0, fs);
8621 gen_load_fpr32(fp1, ft);
8622 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
8623 gen_store_fpr32(fp1, fd);
8624 tcg_temp_free_i32(fp1);
8625 tcg_temp_free_i32(fp0);
8626 opn = "maxa.s";
8627 } else {
8628 /* OPC_RSQRT2_S */
8629 check_cp1_64bitmode(ctx);
8631 TCGv_i32 fp0 = tcg_temp_new_i32();
8632 TCGv_i32 fp1 = tcg_temp_new_i32();
8634 gen_load_fpr32(fp0, fs);
8635 gen_load_fpr32(fp1, ft);
8636 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
8637 tcg_temp_free_i32(fp1);
8638 gen_store_fpr32(fp0, fd);
8639 tcg_temp_free_i32(fp0);
8641 opn = "rsqrt2.s";
8643 break;
8644 case OPC_CVT_D_S:
8645 check_cp1_registers(ctx, fd);
8647 TCGv_i32 fp32 = tcg_temp_new_i32();
8648 TCGv_i64 fp64 = tcg_temp_new_i64();
8650 gen_load_fpr32(fp32, fs);
8651 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
8652 tcg_temp_free_i32(fp32);
8653 gen_store_fpr64(ctx, fp64, fd);
8654 tcg_temp_free_i64(fp64);
8656 opn = "cvt.d.s";
8657 break;
8658 case OPC_CVT_W_S:
8660 TCGv_i32 fp0 = tcg_temp_new_i32();
8662 gen_load_fpr32(fp0, fs);
8663 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
8664 gen_store_fpr32(fp0, fd);
8665 tcg_temp_free_i32(fp0);
8667 opn = "cvt.w.s";
8668 break;
8669 case OPC_CVT_L_S:
8670 check_cp1_64bitmode(ctx);
8672 TCGv_i32 fp32 = tcg_temp_new_i32();
8673 TCGv_i64 fp64 = tcg_temp_new_i64();
8675 gen_load_fpr32(fp32, fs);
8676 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
8677 tcg_temp_free_i32(fp32);
8678 gen_store_fpr64(ctx, fp64, fd);
8679 tcg_temp_free_i64(fp64);
8681 opn = "cvt.l.s";
8682 break;
8683 case OPC_CVT_PS_S:
8684 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8685 check_cp1_64bitmode(ctx);
8687 TCGv_i64 fp64 = tcg_temp_new_i64();
8688 TCGv_i32 fp32_0 = tcg_temp_new_i32();
8689 TCGv_i32 fp32_1 = tcg_temp_new_i32();
8691 gen_load_fpr32(fp32_0, fs);
8692 gen_load_fpr32(fp32_1, ft);
8693 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
8694 tcg_temp_free_i32(fp32_1);
8695 tcg_temp_free_i32(fp32_0);
8696 gen_store_fpr64(ctx, fp64, fd);
8697 tcg_temp_free_i64(fp64);
8699 opn = "cvt.ps.s";
8700 break;
8701 case OPC_CMP_F_S:
8702 case OPC_CMP_UN_S:
8703 case OPC_CMP_EQ_S:
8704 case OPC_CMP_UEQ_S:
8705 case OPC_CMP_OLT_S:
8706 case OPC_CMP_ULT_S:
8707 case OPC_CMP_OLE_S:
8708 case OPC_CMP_ULE_S:
8709 case OPC_CMP_SF_S:
8710 case OPC_CMP_NGLE_S:
8711 case OPC_CMP_SEQ_S:
8712 case OPC_CMP_NGL_S:
8713 case OPC_CMP_LT_S:
8714 case OPC_CMP_NGE_S:
8715 case OPC_CMP_LE_S:
8716 case OPC_CMP_NGT_S:
8717 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8718 if (ctx->opcode & (1 << 6)) {
8719 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
8720 opn = condnames_abs[func-48];
8721 } else {
8722 gen_cmp_s(ctx, func-48, ft, fs, cc);
8723 opn = condnames[func-48];
8725 break;
8726 case OPC_ADD_D:
8727 check_cp1_registers(ctx, fs | ft | fd);
8729 TCGv_i64 fp0 = tcg_temp_new_i64();
8730 TCGv_i64 fp1 = tcg_temp_new_i64();
8732 gen_load_fpr64(ctx, fp0, fs);
8733 gen_load_fpr64(ctx, fp1, ft);
8734 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
8735 tcg_temp_free_i64(fp1);
8736 gen_store_fpr64(ctx, fp0, fd);
8737 tcg_temp_free_i64(fp0);
8739 opn = "add.d";
8740 optype = BINOP;
8741 break;
8742 case OPC_SUB_D:
8743 check_cp1_registers(ctx, fs | ft | fd);
8745 TCGv_i64 fp0 = tcg_temp_new_i64();
8746 TCGv_i64 fp1 = tcg_temp_new_i64();
8748 gen_load_fpr64(ctx, fp0, fs);
8749 gen_load_fpr64(ctx, fp1, ft);
8750 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
8751 tcg_temp_free_i64(fp1);
8752 gen_store_fpr64(ctx, fp0, fd);
8753 tcg_temp_free_i64(fp0);
8755 opn = "sub.d";
8756 optype = BINOP;
8757 break;
8758 case OPC_MUL_D:
8759 check_cp1_registers(ctx, fs | ft | fd);
8761 TCGv_i64 fp0 = tcg_temp_new_i64();
8762 TCGv_i64 fp1 = tcg_temp_new_i64();
8764 gen_load_fpr64(ctx, fp0, fs);
8765 gen_load_fpr64(ctx, fp1, ft);
8766 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
8767 tcg_temp_free_i64(fp1);
8768 gen_store_fpr64(ctx, fp0, fd);
8769 tcg_temp_free_i64(fp0);
8771 opn = "mul.d";
8772 optype = BINOP;
8773 break;
8774 case OPC_DIV_D:
8775 check_cp1_registers(ctx, fs | ft | fd);
8777 TCGv_i64 fp0 = tcg_temp_new_i64();
8778 TCGv_i64 fp1 = tcg_temp_new_i64();
8780 gen_load_fpr64(ctx, fp0, fs);
8781 gen_load_fpr64(ctx, fp1, ft);
8782 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
8783 tcg_temp_free_i64(fp1);
8784 gen_store_fpr64(ctx, fp0, fd);
8785 tcg_temp_free_i64(fp0);
8787 opn = "div.d";
8788 optype = BINOP;
8789 break;
8790 case OPC_SQRT_D:
8791 check_cp1_registers(ctx, fs | fd);
8793 TCGv_i64 fp0 = tcg_temp_new_i64();
8795 gen_load_fpr64(ctx, fp0, fs);
8796 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
8797 gen_store_fpr64(ctx, fp0, fd);
8798 tcg_temp_free_i64(fp0);
8800 opn = "sqrt.d";
8801 break;
8802 case OPC_ABS_D:
8803 check_cp1_registers(ctx, fs | fd);
8805 TCGv_i64 fp0 = tcg_temp_new_i64();
8807 gen_load_fpr64(ctx, fp0, fs);
8808 gen_helper_float_abs_d(fp0, fp0);
8809 gen_store_fpr64(ctx, fp0, fd);
8810 tcg_temp_free_i64(fp0);
8812 opn = "abs.d";
8813 break;
8814 case OPC_MOV_D:
8815 check_cp1_registers(ctx, fs | fd);
8817 TCGv_i64 fp0 = tcg_temp_new_i64();
8819 gen_load_fpr64(ctx, fp0, fs);
8820 gen_store_fpr64(ctx, fp0, fd);
8821 tcg_temp_free_i64(fp0);
8823 opn = "mov.d";
8824 break;
8825 case OPC_NEG_D:
8826 check_cp1_registers(ctx, fs | fd);
8828 TCGv_i64 fp0 = tcg_temp_new_i64();
8830 gen_load_fpr64(ctx, fp0, fs);
8831 gen_helper_float_chs_d(fp0, fp0);
8832 gen_store_fpr64(ctx, fp0, fd);
8833 tcg_temp_free_i64(fp0);
8835 opn = "neg.d";
8836 break;
8837 case OPC_ROUND_L_D:
8838 check_cp1_64bitmode(ctx);
8840 TCGv_i64 fp0 = tcg_temp_new_i64();
8842 gen_load_fpr64(ctx, fp0, fs);
8843 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
8844 gen_store_fpr64(ctx, fp0, fd);
8845 tcg_temp_free_i64(fp0);
8847 opn = "round.l.d";
8848 break;
8849 case OPC_TRUNC_L_D:
8850 check_cp1_64bitmode(ctx);
8852 TCGv_i64 fp0 = tcg_temp_new_i64();
8854 gen_load_fpr64(ctx, fp0, fs);
8855 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
8856 gen_store_fpr64(ctx, fp0, fd);
8857 tcg_temp_free_i64(fp0);
8859 opn = "trunc.l.d";
8860 break;
8861 case OPC_CEIL_L_D:
8862 check_cp1_64bitmode(ctx);
8864 TCGv_i64 fp0 = tcg_temp_new_i64();
8866 gen_load_fpr64(ctx, fp0, fs);
8867 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
8868 gen_store_fpr64(ctx, fp0, fd);
8869 tcg_temp_free_i64(fp0);
8871 opn = "ceil.l.d";
8872 break;
8873 case OPC_FLOOR_L_D:
8874 check_cp1_64bitmode(ctx);
8876 TCGv_i64 fp0 = tcg_temp_new_i64();
8878 gen_load_fpr64(ctx, fp0, fs);
8879 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
8880 gen_store_fpr64(ctx, fp0, fd);
8881 tcg_temp_free_i64(fp0);
8883 opn = "floor.l.d";
8884 break;
8885 case OPC_ROUND_W_D:
8886 check_cp1_registers(ctx, fs);
8888 TCGv_i32 fp32 = tcg_temp_new_i32();
8889 TCGv_i64 fp64 = tcg_temp_new_i64();
8891 gen_load_fpr64(ctx, fp64, fs);
8892 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
8893 tcg_temp_free_i64(fp64);
8894 gen_store_fpr32(fp32, fd);
8895 tcg_temp_free_i32(fp32);
8897 opn = "round.w.d";
8898 break;
8899 case OPC_TRUNC_W_D:
8900 check_cp1_registers(ctx, fs);
8902 TCGv_i32 fp32 = tcg_temp_new_i32();
8903 TCGv_i64 fp64 = tcg_temp_new_i64();
8905 gen_load_fpr64(ctx, fp64, fs);
8906 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
8907 tcg_temp_free_i64(fp64);
8908 gen_store_fpr32(fp32, fd);
8909 tcg_temp_free_i32(fp32);
8911 opn = "trunc.w.d";
8912 break;
8913 case OPC_CEIL_W_D:
8914 check_cp1_registers(ctx, fs);
8916 TCGv_i32 fp32 = tcg_temp_new_i32();
8917 TCGv_i64 fp64 = tcg_temp_new_i64();
8919 gen_load_fpr64(ctx, fp64, fs);
8920 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
8921 tcg_temp_free_i64(fp64);
8922 gen_store_fpr32(fp32, fd);
8923 tcg_temp_free_i32(fp32);
8925 opn = "ceil.w.d";
8926 break;
8927 case OPC_FLOOR_W_D:
8928 check_cp1_registers(ctx, fs);
8930 TCGv_i32 fp32 = tcg_temp_new_i32();
8931 TCGv_i64 fp64 = tcg_temp_new_i64();
8933 gen_load_fpr64(ctx, fp64, fs);
8934 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
8935 tcg_temp_free_i64(fp64);
8936 gen_store_fpr32(fp32, fd);
8937 tcg_temp_free_i32(fp32);
8939 opn = "floor.w.d";
8940 break;
8941 case OPC_SEL_D:
8942 check_insn(ctx, ISA_MIPS32R6);
8943 gen_sel_d(ctx, op1, fd, ft, fs);
8944 opn = "sel.d";
8945 break;
8946 case OPC_SELEQZ_D:
8947 check_insn(ctx, ISA_MIPS32R6);
8948 gen_sel_d(ctx, op1, fd, ft, fs);
8949 opn = "seleqz.d";
8950 break;
8951 case OPC_SELNEZ_D:
8952 check_insn(ctx, ISA_MIPS32R6);
8953 gen_sel_d(ctx, op1, fd, ft, fs);
8954 opn = "selnez.d";
8955 break;
8956 case OPC_MOVCF_D:
8957 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8958 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8959 opn = "movcf.d";
8960 break;
8961 case OPC_MOVZ_D:
8962 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8964 int l1 = gen_new_label();
8965 TCGv_i64 fp0;
8967 if (ft != 0) {
8968 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8970 fp0 = tcg_temp_new_i64();
8971 gen_load_fpr64(ctx, fp0, fs);
8972 gen_store_fpr64(ctx, fp0, fd);
8973 tcg_temp_free_i64(fp0);
8974 gen_set_label(l1);
8976 opn = "movz.d";
8977 break;
8978 case OPC_MOVN_D:
8979 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8981 int l1 = gen_new_label();
8982 TCGv_i64 fp0;
8984 if (ft != 0) {
8985 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8986 fp0 = tcg_temp_new_i64();
8987 gen_load_fpr64(ctx, fp0, fs);
8988 gen_store_fpr64(ctx, fp0, fd);
8989 tcg_temp_free_i64(fp0);
8990 gen_set_label(l1);
8993 opn = "movn.d";
8994 break;
8995 case OPC_RECIP_D:
8996 check_cp1_64bitmode(ctx);
8998 TCGv_i64 fp0 = tcg_temp_new_i64();
9000 gen_load_fpr64(ctx, fp0, fs);
9001 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9002 gen_store_fpr64(ctx, fp0, fd);
9003 tcg_temp_free_i64(fp0);
9005 opn = "recip.d";
9006 break;
9007 case OPC_RSQRT_D:
9008 check_cp1_64bitmode(ctx);
9010 TCGv_i64 fp0 = tcg_temp_new_i64();
9012 gen_load_fpr64(ctx, fp0, fs);
9013 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9014 gen_store_fpr64(ctx, fp0, fd);
9015 tcg_temp_free_i64(fp0);
9017 opn = "rsqrt.d";
9018 break;
9019 case OPC_MADDF_D:
9020 check_insn(ctx, ISA_MIPS32R6);
9022 TCGv_i64 fp0 = tcg_temp_new_i64();
9023 TCGv_i64 fp1 = tcg_temp_new_i64();
9024 TCGv_i64 fp2 = tcg_temp_new_i64();
9025 gen_load_fpr64(ctx, fp0, fs);
9026 gen_load_fpr64(ctx, fp1, ft);
9027 gen_load_fpr64(ctx, fp2, fd);
9028 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9029 gen_store_fpr64(ctx, fp2, fd);
9030 tcg_temp_free_i64(fp2);
9031 tcg_temp_free_i64(fp1);
9032 tcg_temp_free_i64(fp0);
9033 opn = "maddf.d";
9035 break;
9036 case OPC_MSUBF_D:
9037 check_insn(ctx, ISA_MIPS32R6);
9039 TCGv_i64 fp0 = tcg_temp_new_i64();
9040 TCGv_i64 fp1 = tcg_temp_new_i64();
9041 TCGv_i64 fp2 = tcg_temp_new_i64();
9042 gen_load_fpr64(ctx, fp0, fs);
9043 gen_load_fpr64(ctx, fp1, ft);
9044 gen_load_fpr64(ctx, fp2, fd);
9045 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9046 gen_store_fpr64(ctx, fp2, fd);
9047 tcg_temp_free_i64(fp2);
9048 tcg_temp_free_i64(fp1);
9049 tcg_temp_free_i64(fp0);
9050 opn = "msubf.d";
9052 break;
9053 case OPC_RINT_D:
9054 check_insn(ctx, ISA_MIPS32R6);
9056 TCGv_i64 fp0 = tcg_temp_new_i64();
9057 gen_load_fpr64(ctx, fp0, fs);
9058 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9059 gen_store_fpr64(ctx, fp0, fd);
9060 tcg_temp_free_i64(fp0);
9061 opn = "rint.d";
9063 break;
9064 case OPC_CLASS_D:
9065 check_insn(ctx, ISA_MIPS32R6);
9067 TCGv_i64 fp0 = tcg_temp_new_i64();
9068 gen_load_fpr64(ctx, fp0, fs);
9069 gen_helper_float_class_d(fp0, fp0);
9070 gen_store_fpr64(ctx, fp0, fd);
9071 tcg_temp_free_i64(fp0);
9072 opn = "class.d";
9074 break;
9075 case OPC_MIN_D: /* OPC_RECIP2_D */
9076 if (ctx->insn_flags & ISA_MIPS32R6) {
9077 /* OPC_MIN_D */
9078 TCGv_i64 fp0 = tcg_temp_new_i64();
9079 TCGv_i64 fp1 = tcg_temp_new_i64();
9080 gen_load_fpr64(ctx, fp0, fs);
9081 gen_load_fpr64(ctx, fp1, ft);
9082 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9083 gen_store_fpr64(ctx, fp1, fd);
9084 tcg_temp_free_i64(fp1);
9085 tcg_temp_free_i64(fp0);
9086 opn = "min.d";
9087 } else {
9088 /* OPC_RECIP2_D */
9089 check_cp1_64bitmode(ctx);
9091 TCGv_i64 fp0 = tcg_temp_new_i64();
9092 TCGv_i64 fp1 = tcg_temp_new_i64();
9094 gen_load_fpr64(ctx, fp0, fs);
9095 gen_load_fpr64(ctx, fp1, ft);
9096 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9097 tcg_temp_free_i64(fp1);
9098 gen_store_fpr64(ctx, fp0, fd);
9099 tcg_temp_free_i64(fp0);
9101 opn = "recip2.d";
9103 break;
9104 case OPC_MINA_D: /* OPC_RECIP1_D */
9105 if (ctx->insn_flags & ISA_MIPS32R6) {
9106 /* OPC_MINA_D */
9107 TCGv_i64 fp0 = tcg_temp_new_i64();
9108 TCGv_i64 fp1 = tcg_temp_new_i64();
9109 gen_load_fpr64(ctx, fp0, fs);
9110 gen_load_fpr64(ctx, fp1, ft);
9111 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9112 gen_store_fpr64(ctx, fp1, fd);
9113 tcg_temp_free_i64(fp1);
9114 tcg_temp_free_i64(fp0);
9115 opn = "mina.d";
9116 } else {
9117 /* OPC_RECIP1_D */
9118 check_cp1_64bitmode(ctx);
9120 TCGv_i64 fp0 = tcg_temp_new_i64();
9122 gen_load_fpr64(ctx, fp0, fs);
9123 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9124 gen_store_fpr64(ctx, fp0, fd);
9125 tcg_temp_free_i64(fp0);
9127 opn = "recip1.d";
9129 break;
9130 case OPC_MAX_D: /* OPC_RSQRT1_D */
9131 if (ctx->insn_flags & ISA_MIPS32R6) {
9132 /* OPC_MAX_D */
9133 TCGv_i64 fp0 = tcg_temp_new_i64();
9134 TCGv_i64 fp1 = tcg_temp_new_i64();
9135 gen_load_fpr64(ctx, fp0, fs);
9136 gen_load_fpr64(ctx, fp1, ft);
9137 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9138 gen_store_fpr64(ctx, fp1, fd);
9139 tcg_temp_free_i64(fp1);
9140 tcg_temp_free_i64(fp0);
9141 opn = "max.d";
9142 } else {
9143 /* OPC_RSQRT1_D */
9144 check_cp1_64bitmode(ctx);
9146 TCGv_i64 fp0 = tcg_temp_new_i64();
9148 gen_load_fpr64(ctx, fp0, fs);
9149 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9150 gen_store_fpr64(ctx, fp0, fd);
9151 tcg_temp_free_i64(fp0);
9153 opn = "rsqrt1.d";
9155 break;
9156 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9157 if (ctx->insn_flags & ISA_MIPS32R6) {
9158 /* OPC_MAXA_D */
9159 TCGv_i64 fp0 = tcg_temp_new_i64();
9160 TCGv_i64 fp1 = tcg_temp_new_i64();
9161 gen_load_fpr64(ctx, fp0, fs);
9162 gen_load_fpr64(ctx, fp1, ft);
9163 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9164 gen_store_fpr64(ctx, fp1, fd);
9165 tcg_temp_free_i64(fp1);
9166 tcg_temp_free_i64(fp0);
9167 opn = "maxa.d";
9168 } else {
9169 /* OPC_RSQRT2_D */
9170 check_cp1_64bitmode(ctx);
9172 TCGv_i64 fp0 = tcg_temp_new_i64();
9173 TCGv_i64 fp1 = tcg_temp_new_i64();
9175 gen_load_fpr64(ctx, fp0, fs);
9176 gen_load_fpr64(ctx, fp1, ft);
9177 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9178 tcg_temp_free_i64(fp1);
9179 gen_store_fpr64(ctx, fp0, fd);
9180 tcg_temp_free_i64(fp0);
9182 opn = "rsqrt2.d";
9184 break;
9185 case OPC_CMP_F_D:
9186 case OPC_CMP_UN_D:
9187 case OPC_CMP_EQ_D:
9188 case OPC_CMP_UEQ_D:
9189 case OPC_CMP_OLT_D:
9190 case OPC_CMP_ULT_D:
9191 case OPC_CMP_OLE_D:
9192 case OPC_CMP_ULE_D:
9193 case OPC_CMP_SF_D:
9194 case OPC_CMP_NGLE_D:
9195 case OPC_CMP_SEQ_D:
9196 case OPC_CMP_NGL_D:
9197 case OPC_CMP_LT_D:
9198 case OPC_CMP_NGE_D:
9199 case OPC_CMP_LE_D:
9200 case OPC_CMP_NGT_D:
9201 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9202 if (ctx->opcode & (1 << 6)) {
9203 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9204 opn = condnames_abs[func-48];
9205 } else {
9206 gen_cmp_d(ctx, func-48, ft, fs, cc);
9207 opn = condnames[func-48];
9209 break;
9210 case OPC_CVT_S_D:
9211 check_cp1_registers(ctx, fs);
9213 TCGv_i32 fp32 = tcg_temp_new_i32();
9214 TCGv_i64 fp64 = tcg_temp_new_i64();
9216 gen_load_fpr64(ctx, fp64, fs);
9217 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9218 tcg_temp_free_i64(fp64);
9219 gen_store_fpr32(fp32, fd);
9220 tcg_temp_free_i32(fp32);
9222 opn = "cvt.s.d";
9223 break;
9224 case OPC_CVT_W_D:
9225 check_cp1_registers(ctx, fs);
9227 TCGv_i32 fp32 = tcg_temp_new_i32();
9228 TCGv_i64 fp64 = tcg_temp_new_i64();
9230 gen_load_fpr64(ctx, fp64, fs);
9231 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9232 tcg_temp_free_i64(fp64);
9233 gen_store_fpr32(fp32, fd);
9234 tcg_temp_free_i32(fp32);
9236 opn = "cvt.w.d";
9237 break;
9238 case OPC_CVT_L_D:
9239 check_cp1_64bitmode(ctx);
9241 TCGv_i64 fp0 = tcg_temp_new_i64();
9243 gen_load_fpr64(ctx, fp0, fs);
9244 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9245 gen_store_fpr64(ctx, fp0, fd);
9246 tcg_temp_free_i64(fp0);
9248 opn = "cvt.l.d";
9249 break;
9250 case OPC_CVT_S_W:
9252 TCGv_i32 fp0 = tcg_temp_new_i32();
9254 gen_load_fpr32(fp0, fs);
9255 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9256 gen_store_fpr32(fp0, fd);
9257 tcg_temp_free_i32(fp0);
9259 opn = "cvt.s.w";
9260 break;
9261 case OPC_CVT_D_W:
9262 check_cp1_registers(ctx, fd);
9264 TCGv_i32 fp32 = tcg_temp_new_i32();
9265 TCGv_i64 fp64 = tcg_temp_new_i64();
9267 gen_load_fpr32(fp32, fs);
9268 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9269 tcg_temp_free_i32(fp32);
9270 gen_store_fpr64(ctx, fp64, fd);
9271 tcg_temp_free_i64(fp64);
9273 opn = "cvt.d.w";
9274 break;
9275 case OPC_CVT_S_L:
9276 check_cp1_64bitmode(ctx);
9278 TCGv_i32 fp32 = tcg_temp_new_i32();
9279 TCGv_i64 fp64 = tcg_temp_new_i64();
9281 gen_load_fpr64(ctx, fp64, fs);
9282 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9283 tcg_temp_free_i64(fp64);
9284 gen_store_fpr32(fp32, fd);
9285 tcg_temp_free_i32(fp32);
9287 opn = "cvt.s.l";
9288 break;
9289 case OPC_CVT_D_L:
9290 check_cp1_64bitmode(ctx);
9292 TCGv_i64 fp0 = tcg_temp_new_i64();
9294 gen_load_fpr64(ctx, fp0, fs);
9295 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9296 gen_store_fpr64(ctx, fp0, fd);
9297 tcg_temp_free_i64(fp0);
9299 opn = "cvt.d.l";
9300 break;
9301 case OPC_CVT_PS_PW:
9302 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9303 check_cp1_64bitmode(ctx);
9305 TCGv_i64 fp0 = tcg_temp_new_i64();
9307 gen_load_fpr64(ctx, fp0, fs);
9308 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9309 gen_store_fpr64(ctx, fp0, fd);
9310 tcg_temp_free_i64(fp0);
9312 opn = "cvt.ps.pw";
9313 break;
9314 case OPC_ADD_PS:
9315 check_cp1_64bitmode(ctx);
9317 TCGv_i64 fp0 = tcg_temp_new_i64();
9318 TCGv_i64 fp1 = tcg_temp_new_i64();
9320 gen_load_fpr64(ctx, fp0, fs);
9321 gen_load_fpr64(ctx, fp1, ft);
9322 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9323 tcg_temp_free_i64(fp1);
9324 gen_store_fpr64(ctx, fp0, fd);
9325 tcg_temp_free_i64(fp0);
9327 opn = "add.ps";
9328 break;
9329 case OPC_SUB_PS:
9330 check_cp1_64bitmode(ctx);
9332 TCGv_i64 fp0 = tcg_temp_new_i64();
9333 TCGv_i64 fp1 = tcg_temp_new_i64();
9335 gen_load_fpr64(ctx, fp0, fs);
9336 gen_load_fpr64(ctx, fp1, ft);
9337 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9338 tcg_temp_free_i64(fp1);
9339 gen_store_fpr64(ctx, fp0, fd);
9340 tcg_temp_free_i64(fp0);
9342 opn = "sub.ps";
9343 break;
9344 case OPC_MUL_PS:
9345 check_cp1_64bitmode(ctx);
9347 TCGv_i64 fp0 = tcg_temp_new_i64();
9348 TCGv_i64 fp1 = tcg_temp_new_i64();
9350 gen_load_fpr64(ctx, fp0, fs);
9351 gen_load_fpr64(ctx, fp1, ft);
9352 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9353 tcg_temp_free_i64(fp1);
9354 gen_store_fpr64(ctx, fp0, fd);
9355 tcg_temp_free_i64(fp0);
9357 opn = "mul.ps";
9358 break;
9359 case OPC_ABS_PS:
9360 check_cp1_64bitmode(ctx);
9362 TCGv_i64 fp0 = tcg_temp_new_i64();
9364 gen_load_fpr64(ctx, fp0, fs);
9365 gen_helper_float_abs_ps(fp0, fp0);
9366 gen_store_fpr64(ctx, fp0, fd);
9367 tcg_temp_free_i64(fp0);
9369 opn = "abs.ps";
9370 break;
9371 case OPC_MOV_PS:
9372 check_cp1_64bitmode(ctx);
9374 TCGv_i64 fp0 = tcg_temp_new_i64();
9376 gen_load_fpr64(ctx, fp0, fs);
9377 gen_store_fpr64(ctx, fp0, fd);
9378 tcg_temp_free_i64(fp0);
9380 opn = "mov.ps";
9381 break;
9382 case OPC_NEG_PS:
9383 check_cp1_64bitmode(ctx);
9385 TCGv_i64 fp0 = tcg_temp_new_i64();
9387 gen_load_fpr64(ctx, fp0, fs);
9388 gen_helper_float_chs_ps(fp0, fp0);
9389 gen_store_fpr64(ctx, fp0, fd);
9390 tcg_temp_free_i64(fp0);
9392 opn = "neg.ps";
9393 break;
9394 case OPC_MOVCF_PS:
9395 check_cp1_64bitmode(ctx);
9396 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9397 opn = "movcf.ps";
9398 break;
9399 case OPC_MOVZ_PS:
9400 check_cp1_64bitmode(ctx);
9402 int l1 = gen_new_label();
9403 TCGv_i64 fp0;
9405 if (ft != 0)
9406 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9407 fp0 = tcg_temp_new_i64();
9408 gen_load_fpr64(ctx, fp0, fs);
9409 gen_store_fpr64(ctx, fp0, fd);
9410 tcg_temp_free_i64(fp0);
9411 gen_set_label(l1);
9413 opn = "movz.ps";
9414 break;
9415 case OPC_MOVN_PS:
9416 check_cp1_64bitmode(ctx);
9418 int l1 = gen_new_label();
9419 TCGv_i64 fp0;
9421 if (ft != 0) {
9422 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9423 fp0 = tcg_temp_new_i64();
9424 gen_load_fpr64(ctx, fp0, fs);
9425 gen_store_fpr64(ctx, fp0, fd);
9426 tcg_temp_free_i64(fp0);
9427 gen_set_label(l1);
9430 opn = "movn.ps";
9431 break;
9432 case OPC_ADDR_PS:
9433 check_cp1_64bitmode(ctx);
9435 TCGv_i64 fp0 = tcg_temp_new_i64();
9436 TCGv_i64 fp1 = tcg_temp_new_i64();
9438 gen_load_fpr64(ctx, fp0, ft);
9439 gen_load_fpr64(ctx, fp1, fs);
9440 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9441 tcg_temp_free_i64(fp1);
9442 gen_store_fpr64(ctx, fp0, fd);
9443 tcg_temp_free_i64(fp0);
9445 opn = "addr.ps";
9446 break;
9447 case OPC_MULR_PS:
9448 check_cp1_64bitmode(ctx);
9450 TCGv_i64 fp0 = tcg_temp_new_i64();
9451 TCGv_i64 fp1 = tcg_temp_new_i64();
9453 gen_load_fpr64(ctx, fp0, ft);
9454 gen_load_fpr64(ctx, fp1, fs);
9455 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9456 tcg_temp_free_i64(fp1);
9457 gen_store_fpr64(ctx, fp0, fd);
9458 tcg_temp_free_i64(fp0);
9460 opn = "mulr.ps";
9461 break;
9462 case OPC_RECIP2_PS:
9463 check_cp1_64bitmode(ctx);
9465 TCGv_i64 fp0 = tcg_temp_new_i64();
9466 TCGv_i64 fp1 = tcg_temp_new_i64();
9468 gen_load_fpr64(ctx, fp0, fs);
9469 gen_load_fpr64(ctx, fp1, ft);
9470 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9471 tcg_temp_free_i64(fp1);
9472 gen_store_fpr64(ctx, fp0, fd);
9473 tcg_temp_free_i64(fp0);
9475 opn = "recip2.ps";
9476 break;
9477 case OPC_RECIP1_PS:
9478 check_cp1_64bitmode(ctx);
9480 TCGv_i64 fp0 = tcg_temp_new_i64();
9482 gen_load_fpr64(ctx, fp0, fs);
9483 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
9484 gen_store_fpr64(ctx, fp0, fd);
9485 tcg_temp_free_i64(fp0);
9487 opn = "recip1.ps";
9488 break;
9489 case OPC_RSQRT1_PS:
9490 check_cp1_64bitmode(ctx);
9492 TCGv_i64 fp0 = tcg_temp_new_i64();
9494 gen_load_fpr64(ctx, fp0, fs);
9495 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
9496 gen_store_fpr64(ctx, fp0, fd);
9497 tcg_temp_free_i64(fp0);
9499 opn = "rsqrt1.ps";
9500 break;
9501 case OPC_RSQRT2_PS:
9502 check_cp1_64bitmode(ctx);
9504 TCGv_i64 fp0 = tcg_temp_new_i64();
9505 TCGv_i64 fp1 = tcg_temp_new_i64();
9507 gen_load_fpr64(ctx, fp0, fs);
9508 gen_load_fpr64(ctx, fp1, ft);
9509 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
9510 tcg_temp_free_i64(fp1);
9511 gen_store_fpr64(ctx, fp0, fd);
9512 tcg_temp_free_i64(fp0);
9514 opn = "rsqrt2.ps";
9515 break;
9516 case OPC_CVT_S_PU:
9517 check_cp1_64bitmode(ctx);
9519 TCGv_i32 fp0 = tcg_temp_new_i32();
9521 gen_load_fpr32h(ctx, fp0, fs);
9522 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
9523 gen_store_fpr32(fp0, fd);
9524 tcg_temp_free_i32(fp0);
9526 opn = "cvt.s.pu";
9527 break;
9528 case OPC_CVT_PW_PS:
9529 check_cp1_64bitmode(ctx);
9531 TCGv_i64 fp0 = tcg_temp_new_i64();
9533 gen_load_fpr64(ctx, fp0, fs);
9534 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
9535 gen_store_fpr64(ctx, fp0, fd);
9536 tcg_temp_free_i64(fp0);
9538 opn = "cvt.pw.ps";
9539 break;
9540 case OPC_CVT_S_PL:
9541 check_cp1_64bitmode(ctx);
9543 TCGv_i32 fp0 = tcg_temp_new_i32();
9545 gen_load_fpr32(fp0, fs);
9546 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
9547 gen_store_fpr32(fp0, fd);
9548 tcg_temp_free_i32(fp0);
9550 opn = "cvt.s.pl";
9551 break;
9552 case OPC_PLL_PS:
9553 check_cp1_64bitmode(ctx);
9555 TCGv_i32 fp0 = tcg_temp_new_i32();
9556 TCGv_i32 fp1 = tcg_temp_new_i32();
9558 gen_load_fpr32(fp0, fs);
9559 gen_load_fpr32(fp1, ft);
9560 gen_store_fpr32h(ctx, fp0, fd);
9561 gen_store_fpr32(fp1, fd);
9562 tcg_temp_free_i32(fp0);
9563 tcg_temp_free_i32(fp1);
9565 opn = "pll.ps";
9566 break;
9567 case OPC_PLU_PS:
9568 check_cp1_64bitmode(ctx);
9570 TCGv_i32 fp0 = tcg_temp_new_i32();
9571 TCGv_i32 fp1 = tcg_temp_new_i32();
9573 gen_load_fpr32(fp0, fs);
9574 gen_load_fpr32h(ctx, fp1, ft);
9575 gen_store_fpr32(fp1, fd);
9576 gen_store_fpr32h(ctx, fp0, fd);
9577 tcg_temp_free_i32(fp0);
9578 tcg_temp_free_i32(fp1);
9580 opn = "plu.ps";
9581 break;
9582 case OPC_PUL_PS:
9583 check_cp1_64bitmode(ctx);
9585 TCGv_i32 fp0 = tcg_temp_new_i32();
9586 TCGv_i32 fp1 = tcg_temp_new_i32();
9588 gen_load_fpr32h(ctx, fp0, fs);
9589 gen_load_fpr32(fp1, ft);
9590 gen_store_fpr32(fp1, fd);
9591 gen_store_fpr32h(ctx, fp0, fd);
9592 tcg_temp_free_i32(fp0);
9593 tcg_temp_free_i32(fp1);
9595 opn = "pul.ps";
9596 break;
9597 case OPC_PUU_PS:
9598 check_cp1_64bitmode(ctx);
9600 TCGv_i32 fp0 = tcg_temp_new_i32();
9601 TCGv_i32 fp1 = tcg_temp_new_i32();
9603 gen_load_fpr32h(ctx, fp0, fs);
9604 gen_load_fpr32h(ctx, fp1, ft);
9605 gen_store_fpr32(fp1, fd);
9606 gen_store_fpr32h(ctx, fp0, fd);
9607 tcg_temp_free_i32(fp0);
9608 tcg_temp_free_i32(fp1);
9610 opn = "puu.ps";
9611 break;
9612 case OPC_CMP_F_PS:
9613 case OPC_CMP_UN_PS:
9614 case OPC_CMP_EQ_PS:
9615 case OPC_CMP_UEQ_PS:
9616 case OPC_CMP_OLT_PS:
9617 case OPC_CMP_ULT_PS:
9618 case OPC_CMP_OLE_PS:
9619 case OPC_CMP_ULE_PS:
9620 case OPC_CMP_SF_PS:
9621 case OPC_CMP_NGLE_PS:
9622 case OPC_CMP_SEQ_PS:
9623 case OPC_CMP_NGL_PS:
9624 case OPC_CMP_LT_PS:
9625 case OPC_CMP_NGE_PS:
9626 case OPC_CMP_LE_PS:
9627 case OPC_CMP_NGT_PS:
9628 if (ctx->opcode & (1 << 6)) {
9629 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
9630 opn = condnames_abs[func-48];
9631 } else {
9632 gen_cmp_ps(ctx, func-48, ft, fs, cc);
9633 opn = condnames[func-48];
9635 break;
9636 default:
9637 MIPS_INVAL(opn);
9638 generate_exception (ctx, EXCP_RI);
9639 return;
9641 (void)opn; /* avoid a compiler warning */
9642 switch (optype) {
9643 case BINOP:
9644 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
9645 break;
9646 case CMPOP:
9647 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
9648 break;
9649 default:
9650 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
9651 break;
9655 /* Coprocessor 3 (FPU) */
9656 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
9657 int fd, int fs, int base, int index)
9659 const char *opn = "extended float load/store";
9660 int store = 0;
9661 TCGv t0 = tcg_temp_new();
9663 if (base == 0) {
9664 gen_load_gpr(t0, index);
9665 } else if (index == 0) {
9666 gen_load_gpr(t0, base);
9667 } else {
9668 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
9670 /* Don't do NOP if destination is zero: we must perform the actual
9671 memory access. */
9672 switch (opc) {
9673 case OPC_LWXC1:
9674 check_cop1x(ctx);
9676 TCGv_i32 fp0 = tcg_temp_new_i32();
9678 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9679 tcg_gen_trunc_tl_i32(fp0, t0);
9680 gen_store_fpr32(fp0, fd);
9681 tcg_temp_free_i32(fp0);
9683 opn = "lwxc1";
9684 break;
9685 case OPC_LDXC1:
9686 check_cop1x(ctx);
9687 check_cp1_registers(ctx, fd);
9689 TCGv_i64 fp0 = tcg_temp_new_i64();
9690 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9691 gen_store_fpr64(ctx, fp0, fd);
9692 tcg_temp_free_i64(fp0);
9694 opn = "ldxc1";
9695 break;
9696 case OPC_LUXC1:
9697 check_cp1_64bitmode(ctx);
9698 tcg_gen_andi_tl(t0, t0, ~0x7);
9700 TCGv_i64 fp0 = tcg_temp_new_i64();
9702 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9703 gen_store_fpr64(ctx, fp0, fd);
9704 tcg_temp_free_i64(fp0);
9706 opn = "luxc1";
9707 break;
9708 case OPC_SWXC1:
9709 check_cop1x(ctx);
9711 TCGv_i32 fp0 = tcg_temp_new_i32();
9712 gen_load_fpr32(fp0, fs);
9713 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
9714 tcg_temp_free_i32(fp0);
9716 opn = "swxc1";
9717 store = 1;
9718 break;
9719 case OPC_SDXC1:
9720 check_cop1x(ctx);
9721 check_cp1_registers(ctx, fs);
9723 TCGv_i64 fp0 = tcg_temp_new_i64();
9724 gen_load_fpr64(ctx, fp0, fs);
9725 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9726 tcg_temp_free_i64(fp0);
9728 opn = "sdxc1";
9729 store = 1;
9730 break;
9731 case OPC_SUXC1:
9732 check_cp1_64bitmode(ctx);
9733 tcg_gen_andi_tl(t0, t0, ~0x7);
9735 TCGv_i64 fp0 = tcg_temp_new_i64();
9736 gen_load_fpr64(ctx, fp0, fs);
9737 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9738 tcg_temp_free_i64(fp0);
9740 opn = "suxc1";
9741 store = 1;
9742 break;
9744 tcg_temp_free(t0);
9745 (void)opn; (void)store; /* avoid compiler warnings */
9746 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
9747 regnames[index], regnames[base]);
9750 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
9751 int fd, int fr, int fs, int ft)
9753 const char *opn = "flt3_arith";
9755 switch (opc) {
9756 case OPC_ALNV_PS:
9757 check_cp1_64bitmode(ctx);
9759 TCGv t0 = tcg_temp_local_new();
9760 TCGv_i32 fp = tcg_temp_new_i32();
9761 TCGv_i32 fph = tcg_temp_new_i32();
9762 int l1 = gen_new_label();
9763 int l2 = gen_new_label();
9765 gen_load_gpr(t0, fr);
9766 tcg_gen_andi_tl(t0, t0, 0x7);
9768 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
9769 gen_load_fpr32(fp, fs);
9770 gen_load_fpr32h(ctx, fph, fs);
9771 gen_store_fpr32(fp, fd);
9772 gen_store_fpr32h(ctx, fph, fd);
9773 tcg_gen_br(l2);
9774 gen_set_label(l1);
9775 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
9776 tcg_temp_free(t0);
9777 #ifdef TARGET_WORDS_BIGENDIAN
9778 gen_load_fpr32(fp, fs);
9779 gen_load_fpr32h(ctx, fph, ft);
9780 gen_store_fpr32h(ctx, fp, fd);
9781 gen_store_fpr32(fph, fd);
9782 #else
9783 gen_load_fpr32h(ctx, fph, fs);
9784 gen_load_fpr32(fp, ft);
9785 gen_store_fpr32(fph, fd);
9786 gen_store_fpr32h(ctx, fp, fd);
9787 #endif
9788 gen_set_label(l2);
9789 tcg_temp_free_i32(fp);
9790 tcg_temp_free_i32(fph);
9792 opn = "alnv.ps";
9793 break;
9794 case OPC_MADD_S:
9795 check_cop1x(ctx);
9797 TCGv_i32 fp0 = tcg_temp_new_i32();
9798 TCGv_i32 fp1 = tcg_temp_new_i32();
9799 TCGv_i32 fp2 = tcg_temp_new_i32();
9801 gen_load_fpr32(fp0, fs);
9802 gen_load_fpr32(fp1, ft);
9803 gen_load_fpr32(fp2, fr);
9804 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
9805 tcg_temp_free_i32(fp0);
9806 tcg_temp_free_i32(fp1);
9807 gen_store_fpr32(fp2, fd);
9808 tcg_temp_free_i32(fp2);
9810 opn = "madd.s";
9811 break;
9812 case OPC_MADD_D:
9813 check_cop1x(ctx);
9814 check_cp1_registers(ctx, fd | fs | ft | fr);
9816 TCGv_i64 fp0 = tcg_temp_new_i64();
9817 TCGv_i64 fp1 = tcg_temp_new_i64();
9818 TCGv_i64 fp2 = tcg_temp_new_i64();
9820 gen_load_fpr64(ctx, fp0, fs);
9821 gen_load_fpr64(ctx, fp1, ft);
9822 gen_load_fpr64(ctx, fp2, fr);
9823 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
9824 tcg_temp_free_i64(fp0);
9825 tcg_temp_free_i64(fp1);
9826 gen_store_fpr64(ctx, fp2, fd);
9827 tcg_temp_free_i64(fp2);
9829 opn = "madd.d";
9830 break;
9831 case OPC_MADD_PS:
9832 check_cp1_64bitmode(ctx);
9834 TCGv_i64 fp0 = tcg_temp_new_i64();
9835 TCGv_i64 fp1 = tcg_temp_new_i64();
9836 TCGv_i64 fp2 = tcg_temp_new_i64();
9838 gen_load_fpr64(ctx, fp0, fs);
9839 gen_load_fpr64(ctx, fp1, ft);
9840 gen_load_fpr64(ctx, fp2, fr);
9841 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
9842 tcg_temp_free_i64(fp0);
9843 tcg_temp_free_i64(fp1);
9844 gen_store_fpr64(ctx, fp2, fd);
9845 tcg_temp_free_i64(fp2);
9847 opn = "madd.ps";
9848 break;
9849 case OPC_MSUB_S:
9850 check_cop1x(ctx);
9852 TCGv_i32 fp0 = tcg_temp_new_i32();
9853 TCGv_i32 fp1 = tcg_temp_new_i32();
9854 TCGv_i32 fp2 = tcg_temp_new_i32();
9856 gen_load_fpr32(fp0, fs);
9857 gen_load_fpr32(fp1, ft);
9858 gen_load_fpr32(fp2, fr);
9859 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
9860 tcg_temp_free_i32(fp0);
9861 tcg_temp_free_i32(fp1);
9862 gen_store_fpr32(fp2, fd);
9863 tcg_temp_free_i32(fp2);
9865 opn = "msub.s";
9866 break;
9867 case OPC_MSUB_D:
9868 check_cop1x(ctx);
9869 check_cp1_registers(ctx, fd | fs | ft | fr);
9871 TCGv_i64 fp0 = tcg_temp_new_i64();
9872 TCGv_i64 fp1 = tcg_temp_new_i64();
9873 TCGv_i64 fp2 = tcg_temp_new_i64();
9875 gen_load_fpr64(ctx, fp0, fs);
9876 gen_load_fpr64(ctx, fp1, ft);
9877 gen_load_fpr64(ctx, fp2, fr);
9878 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
9879 tcg_temp_free_i64(fp0);
9880 tcg_temp_free_i64(fp1);
9881 gen_store_fpr64(ctx, fp2, fd);
9882 tcg_temp_free_i64(fp2);
9884 opn = "msub.d";
9885 break;
9886 case OPC_MSUB_PS:
9887 check_cp1_64bitmode(ctx);
9889 TCGv_i64 fp0 = tcg_temp_new_i64();
9890 TCGv_i64 fp1 = tcg_temp_new_i64();
9891 TCGv_i64 fp2 = tcg_temp_new_i64();
9893 gen_load_fpr64(ctx, fp0, fs);
9894 gen_load_fpr64(ctx, fp1, ft);
9895 gen_load_fpr64(ctx, fp2, fr);
9896 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
9897 tcg_temp_free_i64(fp0);
9898 tcg_temp_free_i64(fp1);
9899 gen_store_fpr64(ctx, fp2, fd);
9900 tcg_temp_free_i64(fp2);
9902 opn = "msub.ps";
9903 break;
9904 case OPC_NMADD_S:
9905 check_cop1x(ctx);
9907 TCGv_i32 fp0 = tcg_temp_new_i32();
9908 TCGv_i32 fp1 = tcg_temp_new_i32();
9909 TCGv_i32 fp2 = tcg_temp_new_i32();
9911 gen_load_fpr32(fp0, fs);
9912 gen_load_fpr32(fp1, ft);
9913 gen_load_fpr32(fp2, fr);
9914 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
9915 tcg_temp_free_i32(fp0);
9916 tcg_temp_free_i32(fp1);
9917 gen_store_fpr32(fp2, fd);
9918 tcg_temp_free_i32(fp2);
9920 opn = "nmadd.s";
9921 break;
9922 case OPC_NMADD_D:
9923 check_cop1x(ctx);
9924 check_cp1_registers(ctx, fd | fs | ft | fr);
9926 TCGv_i64 fp0 = tcg_temp_new_i64();
9927 TCGv_i64 fp1 = tcg_temp_new_i64();
9928 TCGv_i64 fp2 = tcg_temp_new_i64();
9930 gen_load_fpr64(ctx, fp0, fs);
9931 gen_load_fpr64(ctx, fp1, ft);
9932 gen_load_fpr64(ctx, fp2, fr);
9933 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
9934 tcg_temp_free_i64(fp0);
9935 tcg_temp_free_i64(fp1);
9936 gen_store_fpr64(ctx, fp2, fd);
9937 tcg_temp_free_i64(fp2);
9939 opn = "nmadd.d";
9940 break;
9941 case OPC_NMADD_PS:
9942 check_cp1_64bitmode(ctx);
9944 TCGv_i64 fp0 = tcg_temp_new_i64();
9945 TCGv_i64 fp1 = tcg_temp_new_i64();
9946 TCGv_i64 fp2 = tcg_temp_new_i64();
9948 gen_load_fpr64(ctx, fp0, fs);
9949 gen_load_fpr64(ctx, fp1, ft);
9950 gen_load_fpr64(ctx, fp2, fr);
9951 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
9952 tcg_temp_free_i64(fp0);
9953 tcg_temp_free_i64(fp1);
9954 gen_store_fpr64(ctx, fp2, fd);
9955 tcg_temp_free_i64(fp2);
9957 opn = "nmadd.ps";
9958 break;
9959 case OPC_NMSUB_S:
9960 check_cop1x(ctx);
9962 TCGv_i32 fp0 = tcg_temp_new_i32();
9963 TCGv_i32 fp1 = tcg_temp_new_i32();
9964 TCGv_i32 fp2 = tcg_temp_new_i32();
9966 gen_load_fpr32(fp0, fs);
9967 gen_load_fpr32(fp1, ft);
9968 gen_load_fpr32(fp2, fr);
9969 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
9970 tcg_temp_free_i32(fp0);
9971 tcg_temp_free_i32(fp1);
9972 gen_store_fpr32(fp2, fd);
9973 tcg_temp_free_i32(fp2);
9975 opn = "nmsub.s";
9976 break;
9977 case OPC_NMSUB_D:
9978 check_cop1x(ctx);
9979 check_cp1_registers(ctx, fd | fs | ft | fr);
9981 TCGv_i64 fp0 = tcg_temp_new_i64();
9982 TCGv_i64 fp1 = tcg_temp_new_i64();
9983 TCGv_i64 fp2 = tcg_temp_new_i64();
9985 gen_load_fpr64(ctx, fp0, fs);
9986 gen_load_fpr64(ctx, fp1, ft);
9987 gen_load_fpr64(ctx, fp2, fr);
9988 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
9989 tcg_temp_free_i64(fp0);
9990 tcg_temp_free_i64(fp1);
9991 gen_store_fpr64(ctx, fp2, fd);
9992 tcg_temp_free_i64(fp2);
9994 opn = "nmsub.d";
9995 break;
9996 case OPC_NMSUB_PS:
9997 check_cp1_64bitmode(ctx);
9999 TCGv_i64 fp0 = tcg_temp_new_i64();
10000 TCGv_i64 fp1 = tcg_temp_new_i64();
10001 TCGv_i64 fp2 = tcg_temp_new_i64();
10003 gen_load_fpr64(ctx, fp0, fs);
10004 gen_load_fpr64(ctx, fp1, ft);
10005 gen_load_fpr64(ctx, fp2, fr);
10006 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10007 tcg_temp_free_i64(fp0);
10008 tcg_temp_free_i64(fp1);
10009 gen_store_fpr64(ctx, fp2, fd);
10010 tcg_temp_free_i64(fp2);
10012 opn = "nmsub.ps";
10013 break;
10014 default:
10015 MIPS_INVAL(opn);
10016 generate_exception (ctx, EXCP_RI);
10017 return;
10019 (void)opn; /* avoid a compiler warning */
10020 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10021 fregnames[fs], fregnames[ft]);
10024 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10026 TCGv t0;
10028 #if !defined(CONFIG_USER_ONLY)
10029 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10030 Therefore only check the ISA in system mode. */
10031 check_insn(ctx, ISA_MIPS32R2);
10032 #endif
10033 t0 = tcg_temp_new();
10035 switch (rd) {
10036 case 0:
10037 save_cpu_state(ctx, 1);
10038 gen_helper_rdhwr_cpunum(t0, cpu_env);
10039 gen_store_gpr(t0, rt);
10040 break;
10041 case 1:
10042 save_cpu_state(ctx, 1);
10043 gen_helper_rdhwr_synci_step(t0, cpu_env);
10044 gen_store_gpr(t0, rt);
10045 break;
10046 case 2:
10047 save_cpu_state(ctx, 1);
10048 gen_helper_rdhwr_cc(t0, cpu_env);
10049 gen_store_gpr(t0, rt);
10050 break;
10051 case 3:
10052 save_cpu_state(ctx, 1);
10053 gen_helper_rdhwr_ccres(t0, cpu_env);
10054 gen_store_gpr(t0, rt);
10055 break;
10056 case 29:
10057 #if defined(CONFIG_USER_ONLY)
10058 tcg_gen_ld_tl(t0, cpu_env,
10059 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10060 gen_store_gpr(t0, rt);
10061 break;
10062 #else
10063 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10064 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10065 tcg_gen_ld_tl(t0, cpu_env,
10066 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10067 gen_store_gpr(t0, rt);
10068 } else {
10069 generate_exception(ctx, EXCP_RI);
10071 break;
10072 #endif
10073 default: /* Invalid */
10074 MIPS_INVAL("rdhwr");
10075 generate_exception(ctx, EXCP_RI);
10076 break;
10078 tcg_temp_free(t0);
10081 static void gen_branch(DisasContext *ctx, int insn_bytes)
10083 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10084 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10085 /* Branches completion */
10086 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10087 ctx->bstate = BS_BRANCH;
10088 save_cpu_state(ctx, 0);
10089 /* FIXME: Need to clear can_do_io. */
10090 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10091 case MIPS_HFLAG_B:
10092 /* unconditional branch */
10093 MIPS_DEBUG("unconditional branch");
10094 if (proc_hflags & MIPS_HFLAG_BX) {
10095 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10097 gen_goto_tb(ctx, 0, ctx->btarget);
10098 break;
10099 case MIPS_HFLAG_BL:
10100 /* blikely taken case */
10101 MIPS_DEBUG("blikely branch taken");
10102 gen_goto_tb(ctx, 0, ctx->btarget);
10103 break;
10104 case MIPS_HFLAG_BC:
10105 /* Conditional branch */
10106 MIPS_DEBUG("conditional branch");
10108 int l1 = gen_new_label();
10110 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10111 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10112 gen_set_label(l1);
10113 gen_goto_tb(ctx, 0, ctx->btarget);
10115 break;
10116 case MIPS_HFLAG_BR:
10117 /* unconditional branch to register */
10118 MIPS_DEBUG("branch to register");
10119 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10120 TCGv t0 = tcg_temp_new();
10121 TCGv_i32 t1 = tcg_temp_new_i32();
10123 tcg_gen_andi_tl(t0, btarget, 0x1);
10124 tcg_gen_trunc_tl_i32(t1, t0);
10125 tcg_temp_free(t0);
10126 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10127 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10128 tcg_gen_or_i32(hflags, hflags, t1);
10129 tcg_temp_free_i32(t1);
10131 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10132 } else {
10133 tcg_gen_mov_tl(cpu_PC, btarget);
10135 if (ctx->singlestep_enabled) {
10136 save_cpu_state(ctx, 0);
10137 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
10139 tcg_gen_exit_tb(0);
10140 break;
10141 default:
10142 MIPS_DEBUG("unknown branch");
10143 break;
10148 /* ISA extensions (ASEs) */
10149 /* MIPS16 extension to MIPS32 */
10151 /* MIPS16 major opcodes */
10152 enum {
10153 M16_OPC_ADDIUSP = 0x00,
10154 M16_OPC_ADDIUPC = 0x01,
10155 M16_OPC_B = 0x02,
10156 M16_OPC_JAL = 0x03,
10157 M16_OPC_BEQZ = 0x04,
10158 M16_OPC_BNEQZ = 0x05,
10159 M16_OPC_SHIFT = 0x06,
10160 M16_OPC_LD = 0x07,
10161 M16_OPC_RRIA = 0x08,
10162 M16_OPC_ADDIU8 = 0x09,
10163 M16_OPC_SLTI = 0x0a,
10164 M16_OPC_SLTIU = 0x0b,
10165 M16_OPC_I8 = 0x0c,
10166 M16_OPC_LI = 0x0d,
10167 M16_OPC_CMPI = 0x0e,
10168 M16_OPC_SD = 0x0f,
10169 M16_OPC_LB = 0x10,
10170 M16_OPC_LH = 0x11,
10171 M16_OPC_LWSP = 0x12,
10172 M16_OPC_LW = 0x13,
10173 M16_OPC_LBU = 0x14,
10174 M16_OPC_LHU = 0x15,
10175 M16_OPC_LWPC = 0x16,
10176 M16_OPC_LWU = 0x17,
10177 M16_OPC_SB = 0x18,
10178 M16_OPC_SH = 0x19,
10179 M16_OPC_SWSP = 0x1a,
10180 M16_OPC_SW = 0x1b,
10181 M16_OPC_RRR = 0x1c,
10182 M16_OPC_RR = 0x1d,
10183 M16_OPC_EXTEND = 0x1e,
10184 M16_OPC_I64 = 0x1f
10187 /* I8 funct field */
10188 enum {
10189 I8_BTEQZ = 0x0,
10190 I8_BTNEZ = 0x1,
10191 I8_SWRASP = 0x2,
10192 I8_ADJSP = 0x3,
10193 I8_SVRS = 0x4,
10194 I8_MOV32R = 0x5,
10195 I8_MOVR32 = 0x7
10198 /* RRR f field */
10199 enum {
10200 RRR_DADDU = 0x0,
10201 RRR_ADDU = 0x1,
10202 RRR_DSUBU = 0x2,
10203 RRR_SUBU = 0x3
10206 /* RR funct field */
10207 enum {
10208 RR_JR = 0x00,
10209 RR_SDBBP = 0x01,
10210 RR_SLT = 0x02,
10211 RR_SLTU = 0x03,
10212 RR_SLLV = 0x04,
10213 RR_BREAK = 0x05,
10214 RR_SRLV = 0x06,
10215 RR_SRAV = 0x07,
10216 RR_DSRL = 0x08,
10217 RR_CMP = 0x0a,
10218 RR_NEG = 0x0b,
10219 RR_AND = 0x0c,
10220 RR_OR = 0x0d,
10221 RR_XOR = 0x0e,
10222 RR_NOT = 0x0f,
10223 RR_MFHI = 0x10,
10224 RR_CNVT = 0x11,
10225 RR_MFLO = 0x12,
10226 RR_DSRA = 0x13,
10227 RR_DSLLV = 0x14,
10228 RR_DSRLV = 0x16,
10229 RR_DSRAV = 0x17,
10230 RR_MULT = 0x18,
10231 RR_MULTU = 0x19,
10232 RR_DIV = 0x1a,
10233 RR_DIVU = 0x1b,
10234 RR_DMULT = 0x1c,
10235 RR_DMULTU = 0x1d,
10236 RR_DDIV = 0x1e,
10237 RR_DDIVU = 0x1f
10240 /* I64 funct field */
10241 enum {
10242 I64_LDSP = 0x0,
10243 I64_SDSP = 0x1,
10244 I64_SDRASP = 0x2,
10245 I64_DADJSP = 0x3,
10246 I64_LDPC = 0x4,
10247 I64_DADDIU5 = 0x5,
10248 I64_DADDIUPC = 0x6,
10249 I64_DADDIUSP = 0x7
10252 /* RR ry field for CNVT */
10253 enum {
10254 RR_RY_CNVT_ZEB = 0x0,
10255 RR_RY_CNVT_ZEH = 0x1,
10256 RR_RY_CNVT_ZEW = 0x2,
10257 RR_RY_CNVT_SEB = 0x4,
10258 RR_RY_CNVT_SEH = 0x5,
10259 RR_RY_CNVT_SEW = 0x6,
10262 static int xlat (int r)
10264 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10266 return map[r];
10269 static void gen_mips16_save (DisasContext *ctx,
10270 int xsregs, int aregs,
10271 int do_ra, int do_s0, int do_s1,
10272 int framesize)
10274 TCGv t0 = tcg_temp_new();
10275 TCGv t1 = tcg_temp_new();
10276 int args, astatic;
10278 switch (aregs) {
10279 case 0:
10280 case 1:
10281 case 2:
10282 case 3:
10283 case 11:
10284 args = 0;
10285 break;
10286 case 4:
10287 case 5:
10288 case 6:
10289 case 7:
10290 args = 1;
10291 break;
10292 case 8:
10293 case 9:
10294 case 10:
10295 args = 2;
10296 break;
10297 case 12:
10298 case 13:
10299 args = 3;
10300 break;
10301 case 14:
10302 args = 4;
10303 break;
10304 default:
10305 generate_exception(ctx, EXCP_RI);
10306 return;
10309 switch (args) {
10310 case 4:
10311 gen_base_offset_addr(ctx, t0, 29, 12);
10312 gen_load_gpr(t1, 7);
10313 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10314 /* Fall through */
10315 case 3:
10316 gen_base_offset_addr(ctx, t0, 29, 8);
10317 gen_load_gpr(t1, 6);
10318 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10319 /* Fall through */
10320 case 2:
10321 gen_base_offset_addr(ctx, t0, 29, 4);
10322 gen_load_gpr(t1, 5);
10323 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10324 /* Fall through */
10325 case 1:
10326 gen_base_offset_addr(ctx, t0, 29, 0);
10327 gen_load_gpr(t1, 4);
10328 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10331 gen_load_gpr(t0, 29);
10333 #define DECR_AND_STORE(reg) do { \
10334 tcg_gen_subi_tl(t0, t0, 4); \
10335 gen_load_gpr(t1, reg); \
10336 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
10337 } while (0)
10339 if (do_ra) {
10340 DECR_AND_STORE(31);
10343 switch (xsregs) {
10344 case 7:
10345 DECR_AND_STORE(30);
10346 /* Fall through */
10347 case 6:
10348 DECR_AND_STORE(23);
10349 /* Fall through */
10350 case 5:
10351 DECR_AND_STORE(22);
10352 /* Fall through */
10353 case 4:
10354 DECR_AND_STORE(21);
10355 /* Fall through */
10356 case 3:
10357 DECR_AND_STORE(20);
10358 /* Fall through */
10359 case 2:
10360 DECR_AND_STORE(19);
10361 /* Fall through */
10362 case 1:
10363 DECR_AND_STORE(18);
10366 if (do_s1) {
10367 DECR_AND_STORE(17);
10369 if (do_s0) {
10370 DECR_AND_STORE(16);
10373 switch (aregs) {
10374 case 0:
10375 case 4:
10376 case 8:
10377 case 12:
10378 case 14:
10379 astatic = 0;
10380 break;
10381 case 1:
10382 case 5:
10383 case 9:
10384 case 13:
10385 astatic = 1;
10386 break;
10387 case 2:
10388 case 6:
10389 case 10:
10390 astatic = 2;
10391 break;
10392 case 3:
10393 case 7:
10394 astatic = 3;
10395 break;
10396 case 11:
10397 astatic = 4;
10398 break;
10399 default:
10400 generate_exception(ctx, EXCP_RI);
10401 return;
10404 if (astatic > 0) {
10405 DECR_AND_STORE(7);
10406 if (astatic > 1) {
10407 DECR_AND_STORE(6);
10408 if (astatic > 2) {
10409 DECR_AND_STORE(5);
10410 if (astatic > 3) {
10411 DECR_AND_STORE(4);
10416 #undef DECR_AND_STORE
10418 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10419 tcg_temp_free(t0);
10420 tcg_temp_free(t1);
10423 static void gen_mips16_restore (DisasContext *ctx,
10424 int xsregs, int aregs,
10425 int do_ra, int do_s0, int do_s1,
10426 int framesize)
10428 int astatic;
10429 TCGv t0 = tcg_temp_new();
10430 TCGv t1 = tcg_temp_new();
10432 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
10434 #define DECR_AND_LOAD(reg) do { \
10435 tcg_gen_subi_tl(t0, t0, 4); \
10436 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
10437 gen_store_gpr(t1, reg); \
10438 } while (0)
10440 if (do_ra) {
10441 DECR_AND_LOAD(31);
10444 switch (xsregs) {
10445 case 7:
10446 DECR_AND_LOAD(30);
10447 /* Fall through */
10448 case 6:
10449 DECR_AND_LOAD(23);
10450 /* Fall through */
10451 case 5:
10452 DECR_AND_LOAD(22);
10453 /* Fall through */
10454 case 4:
10455 DECR_AND_LOAD(21);
10456 /* Fall through */
10457 case 3:
10458 DECR_AND_LOAD(20);
10459 /* Fall through */
10460 case 2:
10461 DECR_AND_LOAD(19);
10462 /* Fall through */
10463 case 1:
10464 DECR_AND_LOAD(18);
10467 if (do_s1) {
10468 DECR_AND_LOAD(17);
10470 if (do_s0) {
10471 DECR_AND_LOAD(16);
10474 switch (aregs) {
10475 case 0:
10476 case 4:
10477 case 8:
10478 case 12:
10479 case 14:
10480 astatic = 0;
10481 break;
10482 case 1:
10483 case 5:
10484 case 9:
10485 case 13:
10486 astatic = 1;
10487 break;
10488 case 2:
10489 case 6:
10490 case 10:
10491 astatic = 2;
10492 break;
10493 case 3:
10494 case 7:
10495 astatic = 3;
10496 break;
10497 case 11:
10498 astatic = 4;
10499 break;
10500 default:
10501 generate_exception(ctx, EXCP_RI);
10502 return;
10505 if (astatic > 0) {
10506 DECR_AND_LOAD(7);
10507 if (astatic > 1) {
10508 DECR_AND_LOAD(6);
10509 if (astatic > 2) {
10510 DECR_AND_LOAD(5);
10511 if (astatic > 3) {
10512 DECR_AND_LOAD(4);
10517 #undef DECR_AND_LOAD
10519 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10520 tcg_temp_free(t0);
10521 tcg_temp_free(t1);
10524 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
10525 int is_64_bit, int extended)
10527 TCGv t0;
10529 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10530 generate_exception(ctx, EXCP_RI);
10531 return;
10534 t0 = tcg_temp_new();
10536 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
10537 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
10538 if (!is_64_bit) {
10539 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10542 tcg_temp_free(t0);
10545 #if defined(TARGET_MIPS64)
10546 static void decode_i64_mips16 (DisasContext *ctx,
10547 int ry, int funct, int16_t offset,
10548 int extended)
10550 switch (funct) {
10551 case I64_LDSP:
10552 check_mips_64(ctx);
10553 offset = extended ? offset : offset << 3;
10554 gen_ld(ctx, OPC_LD, ry, 29, offset);
10555 break;
10556 case I64_SDSP:
10557 check_mips_64(ctx);
10558 offset = extended ? offset : offset << 3;
10559 gen_st(ctx, OPC_SD, ry, 29, offset);
10560 break;
10561 case I64_SDRASP:
10562 check_mips_64(ctx);
10563 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
10564 gen_st(ctx, OPC_SD, 31, 29, offset);
10565 break;
10566 case I64_DADJSP:
10567 check_mips_64(ctx);
10568 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
10569 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
10570 break;
10571 case I64_LDPC:
10572 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10573 generate_exception(ctx, EXCP_RI);
10574 } else {
10575 offset = extended ? offset : offset << 3;
10576 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
10578 break;
10579 case I64_DADDIU5:
10580 check_mips_64(ctx);
10581 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
10582 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
10583 break;
10584 case I64_DADDIUPC:
10585 check_mips_64(ctx);
10586 offset = extended ? offset : offset << 2;
10587 gen_addiupc(ctx, ry, offset, 1, extended);
10588 break;
10589 case I64_DADDIUSP:
10590 check_mips_64(ctx);
10591 offset = extended ? offset : offset << 2;
10592 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
10593 break;
10596 #endif
10598 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
10600 int extend = cpu_lduw_code(env, ctx->pc + 2);
10601 int op, rx, ry, funct, sa;
10602 int16_t imm, offset;
10604 ctx->opcode = (ctx->opcode << 16) | extend;
10605 op = (ctx->opcode >> 11) & 0x1f;
10606 sa = (ctx->opcode >> 22) & 0x1f;
10607 funct = (ctx->opcode >> 8) & 0x7;
10608 rx = xlat((ctx->opcode >> 8) & 0x7);
10609 ry = xlat((ctx->opcode >> 5) & 0x7);
10610 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
10611 | ((ctx->opcode >> 21) & 0x3f) << 5
10612 | (ctx->opcode & 0x1f));
10614 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
10615 counterparts. */
10616 switch (op) {
10617 case M16_OPC_ADDIUSP:
10618 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
10619 break;
10620 case M16_OPC_ADDIUPC:
10621 gen_addiupc(ctx, rx, imm, 0, 1);
10622 break;
10623 case M16_OPC_B:
10624 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
10625 /* No delay slot, so just process as a normal instruction */
10626 break;
10627 case M16_OPC_BEQZ:
10628 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
10629 /* No delay slot, so just process as a normal instruction */
10630 break;
10631 case M16_OPC_BNEQZ:
10632 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
10633 /* No delay slot, so just process as a normal instruction */
10634 break;
10635 case M16_OPC_SHIFT:
10636 switch (ctx->opcode & 0x3) {
10637 case 0x0:
10638 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
10639 break;
10640 case 0x1:
10641 #if defined(TARGET_MIPS64)
10642 check_mips_64(ctx);
10643 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
10644 #else
10645 generate_exception(ctx, EXCP_RI);
10646 #endif
10647 break;
10648 case 0x2:
10649 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
10650 break;
10651 case 0x3:
10652 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
10653 break;
10655 break;
10656 #if defined(TARGET_MIPS64)
10657 case M16_OPC_LD:
10658 check_mips_64(ctx);
10659 gen_ld(ctx, OPC_LD, ry, rx, offset);
10660 break;
10661 #endif
10662 case M16_OPC_RRIA:
10663 imm = ctx->opcode & 0xf;
10664 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
10665 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
10666 imm = (int16_t) (imm << 1) >> 1;
10667 if ((ctx->opcode >> 4) & 0x1) {
10668 #if defined(TARGET_MIPS64)
10669 check_mips_64(ctx);
10670 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
10671 #else
10672 generate_exception(ctx, EXCP_RI);
10673 #endif
10674 } else {
10675 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
10677 break;
10678 case M16_OPC_ADDIU8:
10679 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
10680 break;
10681 case M16_OPC_SLTI:
10682 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
10683 break;
10684 case M16_OPC_SLTIU:
10685 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
10686 break;
10687 case M16_OPC_I8:
10688 switch (funct) {
10689 case I8_BTEQZ:
10690 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
10691 break;
10692 case I8_BTNEZ:
10693 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
10694 break;
10695 case I8_SWRASP:
10696 gen_st(ctx, OPC_SW, 31, 29, imm);
10697 break;
10698 case I8_ADJSP:
10699 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
10700 break;
10701 case I8_SVRS:
10703 int xsregs = (ctx->opcode >> 24) & 0x7;
10704 int aregs = (ctx->opcode >> 16) & 0xf;
10705 int do_ra = (ctx->opcode >> 6) & 0x1;
10706 int do_s0 = (ctx->opcode >> 5) & 0x1;
10707 int do_s1 = (ctx->opcode >> 4) & 0x1;
10708 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
10709 | (ctx->opcode & 0xf)) << 3;
10711 if (ctx->opcode & (1 << 7)) {
10712 gen_mips16_save(ctx, xsregs, aregs,
10713 do_ra, do_s0, do_s1,
10714 framesize);
10715 } else {
10716 gen_mips16_restore(ctx, xsregs, aregs,
10717 do_ra, do_s0, do_s1,
10718 framesize);
10721 break;
10722 default:
10723 generate_exception(ctx, EXCP_RI);
10724 break;
10726 break;
10727 case M16_OPC_LI:
10728 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
10729 break;
10730 case M16_OPC_CMPI:
10731 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
10732 break;
10733 #if defined(TARGET_MIPS64)
10734 case M16_OPC_SD:
10735 gen_st(ctx, OPC_SD, ry, rx, offset);
10736 break;
10737 #endif
10738 case M16_OPC_LB:
10739 gen_ld(ctx, OPC_LB, ry, rx, offset);
10740 break;
10741 case M16_OPC_LH:
10742 gen_ld(ctx, OPC_LH, ry, rx, offset);
10743 break;
10744 case M16_OPC_LWSP:
10745 gen_ld(ctx, OPC_LW, rx, 29, offset);
10746 break;
10747 case M16_OPC_LW:
10748 gen_ld(ctx, OPC_LW, ry, rx, offset);
10749 break;
10750 case M16_OPC_LBU:
10751 gen_ld(ctx, OPC_LBU, ry, rx, offset);
10752 break;
10753 case M16_OPC_LHU:
10754 gen_ld(ctx, OPC_LHU, ry, rx, offset);
10755 break;
10756 case M16_OPC_LWPC:
10757 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
10758 break;
10759 #if defined(TARGET_MIPS64)
10760 case M16_OPC_LWU:
10761 gen_ld(ctx, OPC_LWU, ry, rx, offset);
10762 break;
10763 #endif
10764 case M16_OPC_SB:
10765 gen_st(ctx, OPC_SB, ry, rx, offset);
10766 break;
10767 case M16_OPC_SH:
10768 gen_st(ctx, OPC_SH, ry, rx, offset);
10769 break;
10770 case M16_OPC_SWSP:
10771 gen_st(ctx, OPC_SW, rx, 29, offset);
10772 break;
10773 case M16_OPC_SW:
10774 gen_st(ctx, OPC_SW, ry, rx, offset);
10775 break;
10776 #if defined(TARGET_MIPS64)
10777 case M16_OPC_I64:
10778 decode_i64_mips16(ctx, ry, funct, offset, 1);
10779 break;
10780 #endif
10781 default:
10782 generate_exception(ctx, EXCP_RI);
10783 break;
10786 return 4;
10789 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
10791 int rx, ry;
10792 int sa;
10793 int op, cnvt_op, op1, offset;
10794 int funct;
10795 int n_bytes;
10797 op = (ctx->opcode >> 11) & 0x1f;
10798 sa = (ctx->opcode >> 2) & 0x7;
10799 sa = sa == 0 ? 8 : sa;
10800 rx = xlat((ctx->opcode >> 8) & 0x7);
10801 cnvt_op = (ctx->opcode >> 5) & 0x7;
10802 ry = xlat((ctx->opcode >> 5) & 0x7);
10803 op1 = offset = ctx->opcode & 0x1f;
10805 n_bytes = 2;
10807 switch (op) {
10808 case M16_OPC_ADDIUSP:
10810 int16_t imm = ((uint8_t) ctx->opcode) << 2;
10812 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
10814 break;
10815 case M16_OPC_ADDIUPC:
10816 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
10817 break;
10818 case M16_OPC_B:
10819 offset = (ctx->opcode & 0x7ff) << 1;
10820 offset = (int16_t)(offset << 4) >> 4;
10821 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
10822 /* No delay slot, so just process as a normal instruction */
10823 break;
10824 case M16_OPC_JAL:
10825 offset = cpu_lduw_code(env, ctx->pc + 2);
10826 offset = (((ctx->opcode & 0x1f) << 21)
10827 | ((ctx->opcode >> 5) & 0x1f) << 16
10828 | offset) << 2;
10829 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
10830 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
10831 n_bytes = 4;
10832 break;
10833 case M16_OPC_BEQZ:
10834 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
10835 ((int8_t)ctx->opcode) << 1, 0);
10836 /* No delay slot, so just process as a normal instruction */
10837 break;
10838 case M16_OPC_BNEQZ:
10839 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
10840 ((int8_t)ctx->opcode) << 1, 0);
10841 /* No delay slot, so just process as a normal instruction */
10842 break;
10843 case M16_OPC_SHIFT:
10844 switch (ctx->opcode & 0x3) {
10845 case 0x0:
10846 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
10847 break;
10848 case 0x1:
10849 #if defined(TARGET_MIPS64)
10850 check_mips_64(ctx);
10851 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
10852 #else
10853 generate_exception(ctx, EXCP_RI);
10854 #endif
10855 break;
10856 case 0x2:
10857 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
10858 break;
10859 case 0x3:
10860 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
10861 break;
10863 break;
10864 #if defined(TARGET_MIPS64)
10865 case M16_OPC_LD:
10866 check_mips_64(ctx);
10867 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
10868 break;
10869 #endif
10870 case M16_OPC_RRIA:
10872 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
10874 if ((ctx->opcode >> 4) & 1) {
10875 #if defined(TARGET_MIPS64)
10876 check_mips_64(ctx);
10877 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
10878 #else
10879 generate_exception(ctx, EXCP_RI);
10880 #endif
10881 } else {
10882 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
10885 break;
10886 case M16_OPC_ADDIU8:
10888 int16_t imm = (int8_t) ctx->opcode;
10890 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
10892 break;
10893 case M16_OPC_SLTI:
10895 int16_t imm = (uint8_t) ctx->opcode;
10896 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
10898 break;
10899 case M16_OPC_SLTIU:
10901 int16_t imm = (uint8_t) ctx->opcode;
10902 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
10904 break;
10905 case M16_OPC_I8:
10907 int reg32;
10909 funct = (ctx->opcode >> 8) & 0x7;
10910 switch (funct) {
10911 case I8_BTEQZ:
10912 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
10913 ((int8_t)ctx->opcode) << 1, 0);
10914 break;
10915 case I8_BTNEZ:
10916 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
10917 ((int8_t)ctx->opcode) << 1, 0);
10918 break;
10919 case I8_SWRASP:
10920 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
10921 break;
10922 case I8_ADJSP:
10923 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
10924 ((int8_t)ctx->opcode) << 3);
10925 break;
10926 case I8_SVRS:
10928 int do_ra = ctx->opcode & (1 << 6);
10929 int do_s0 = ctx->opcode & (1 << 5);
10930 int do_s1 = ctx->opcode & (1 << 4);
10931 int framesize = ctx->opcode & 0xf;
10933 if (framesize == 0) {
10934 framesize = 128;
10935 } else {
10936 framesize = framesize << 3;
10939 if (ctx->opcode & (1 << 7)) {
10940 gen_mips16_save(ctx, 0, 0,
10941 do_ra, do_s0, do_s1, framesize);
10942 } else {
10943 gen_mips16_restore(ctx, 0, 0,
10944 do_ra, do_s0, do_s1, framesize);
10947 break;
10948 case I8_MOV32R:
10950 int rz = xlat(ctx->opcode & 0x7);
10952 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
10953 ((ctx->opcode >> 5) & 0x7);
10954 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
10956 break;
10957 case I8_MOVR32:
10958 reg32 = ctx->opcode & 0x1f;
10959 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
10960 break;
10961 default:
10962 generate_exception(ctx, EXCP_RI);
10963 break;
10966 break;
10967 case M16_OPC_LI:
10969 int16_t imm = (uint8_t) ctx->opcode;
10971 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
10973 break;
10974 case M16_OPC_CMPI:
10976 int16_t imm = (uint8_t) ctx->opcode;
10977 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
10979 break;
10980 #if defined(TARGET_MIPS64)
10981 case M16_OPC_SD:
10982 check_mips_64(ctx);
10983 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
10984 break;
10985 #endif
10986 case M16_OPC_LB:
10987 gen_ld(ctx, OPC_LB, ry, rx, offset);
10988 break;
10989 case M16_OPC_LH:
10990 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
10991 break;
10992 case M16_OPC_LWSP:
10993 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
10994 break;
10995 case M16_OPC_LW:
10996 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
10997 break;
10998 case M16_OPC_LBU:
10999 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11000 break;
11001 case M16_OPC_LHU:
11002 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11003 break;
11004 case M16_OPC_LWPC:
11005 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11006 break;
11007 #if defined (TARGET_MIPS64)
11008 case M16_OPC_LWU:
11009 check_mips_64(ctx);
11010 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11011 break;
11012 #endif
11013 case M16_OPC_SB:
11014 gen_st(ctx, OPC_SB, ry, rx, offset);
11015 break;
11016 case M16_OPC_SH:
11017 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11018 break;
11019 case M16_OPC_SWSP:
11020 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11021 break;
11022 case M16_OPC_SW:
11023 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11024 break;
11025 case M16_OPC_RRR:
11027 int rz = xlat((ctx->opcode >> 2) & 0x7);
11028 int mips32_op;
11030 switch (ctx->opcode & 0x3) {
11031 case RRR_ADDU:
11032 mips32_op = OPC_ADDU;
11033 break;
11034 case RRR_SUBU:
11035 mips32_op = OPC_SUBU;
11036 break;
11037 #if defined(TARGET_MIPS64)
11038 case RRR_DADDU:
11039 mips32_op = OPC_DADDU;
11040 check_mips_64(ctx);
11041 break;
11042 case RRR_DSUBU:
11043 mips32_op = OPC_DSUBU;
11044 check_mips_64(ctx);
11045 break;
11046 #endif
11047 default:
11048 generate_exception(ctx, EXCP_RI);
11049 goto done;
11052 gen_arith(ctx, mips32_op, rz, rx, ry);
11053 done:
11056 break;
11057 case M16_OPC_RR:
11058 switch (op1) {
11059 case RR_JR:
11061 int nd = (ctx->opcode >> 7) & 0x1;
11062 int link = (ctx->opcode >> 6) & 0x1;
11063 int ra = (ctx->opcode >> 5) & 0x1;
11065 if (link) {
11066 op = OPC_JALR;
11067 } else {
11068 op = OPC_JR;
11071 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11072 (nd ? 0 : 2));
11074 break;
11075 case RR_SDBBP:
11076 /* XXX: not clear which exception should be raised
11077 * when in debug mode...
11079 check_insn(ctx, ISA_MIPS32);
11080 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11081 generate_exception(ctx, EXCP_DBp);
11082 } else {
11083 generate_exception(ctx, EXCP_DBp);
11085 break;
11086 case RR_SLT:
11087 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11088 break;
11089 case RR_SLTU:
11090 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11091 break;
11092 case RR_BREAK:
11093 generate_exception(ctx, EXCP_BREAK);
11094 break;
11095 case RR_SLLV:
11096 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11097 break;
11098 case RR_SRLV:
11099 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11100 break;
11101 case RR_SRAV:
11102 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11103 break;
11104 #if defined (TARGET_MIPS64)
11105 case RR_DSRL:
11106 check_mips_64(ctx);
11107 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11108 break;
11109 #endif
11110 case RR_CMP:
11111 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11112 break;
11113 case RR_NEG:
11114 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11115 break;
11116 case RR_AND:
11117 gen_logic(ctx, OPC_AND, rx, rx, ry);
11118 break;
11119 case RR_OR:
11120 gen_logic(ctx, OPC_OR, rx, rx, ry);
11121 break;
11122 case RR_XOR:
11123 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11124 break;
11125 case RR_NOT:
11126 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11127 break;
11128 case RR_MFHI:
11129 gen_HILO(ctx, OPC_MFHI, 0, rx);
11130 break;
11131 case RR_CNVT:
11132 switch (cnvt_op) {
11133 case RR_RY_CNVT_ZEB:
11134 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11135 break;
11136 case RR_RY_CNVT_ZEH:
11137 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11138 break;
11139 case RR_RY_CNVT_SEB:
11140 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11141 break;
11142 case RR_RY_CNVT_SEH:
11143 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11144 break;
11145 #if defined (TARGET_MIPS64)
11146 case RR_RY_CNVT_ZEW:
11147 check_mips_64(ctx);
11148 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11149 break;
11150 case RR_RY_CNVT_SEW:
11151 check_mips_64(ctx);
11152 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11153 break;
11154 #endif
11155 default:
11156 generate_exception(ctx, EXCP_RI);
11157 break;
11159 break;
11160 case RR_MFLO:
11161 gen_HILO(ctx, OPC_MFLO, 0, rx);
11162 break;
11163 #if defined (TARGET_MIPS64)
11164 case RR_DSRA:
11165 check_mips_64(ctx);
11166 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11167 break;
11168 case RR_DSLLV:
11169 check_mips_64(ctx);
11170 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11171 break;
11172 case RR_DSRLV:
11173 check_mips_64(ctx);
11174 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11175 break;
11176 case RR_DSRAV:
11177 check_mips_64(ctx);
11178 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11179 break;
11180 #endif
11181 case RR_MULT:
11182 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11183 break;
11184 case RR_MULTU:
11185 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11186 break;
11187 case RR_DIV:
11188 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11189 break;
11190 case RR_DIVU:
11191 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11192 break;
11193 #if defined (TARGET_MIPS64)
11194 case RR_DMULT:
11195 check_mips_64(ctx);
11196 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11197 break;
11198 case RR_DMULTU:
11199 check_mips_64(ctx);
11200 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11201 break;
11202 case RR_DDIV:
11203 check_mips_64(ctx);
11204 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11205 break;
11206 case RR_DDIVU:
11207 check_mips_64(ctx);
11208 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11209 break;
11210 #endif
11211 default:
11212 generate_exception(ctx, EXCP_RI);
11213 break;
11215 break;
11216 case M16_OPC_EXTEND:
11217 decode_extended_mips16_opc(env, ctx);
11218 n_bytes = 4;
11219 break;
11220 #if defined(TARGET_MIPS64)
11221 case M16_OPC_I64:
11222 funct = (ctx->opcode >> 8) & 0x7;
11223 decode_i64_mips16(ctx, ry, funct, offset, 0);
11224 break;
11225 #endif
11226 default:
11227 generate_exception(ctx, EXCP_RI);
11228 break;
11231 return n_bytes;
11234 /* microMIPS extension to MIPS32/MIPS64 */
11237 * microMIPS32/microMIPS64 major opcodes
11239 * 1. MIPS Architecture for Programmers Volume II-B:
11240 * The microMIPS32 Instruction Set (Revision 3.05)
11242 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11244 * 2. MIPS Architecture For Programmers Volume II-A:
11245 * The MIPS64 Instruction Set (Revision 3.51)
11248 enum {
11249 POOL32A = 0x00,
11250 POOL16A = 0x01,
11251 LBU16 = 0x02,
11252 MOVE16 = 0x03,
11253 ADDI32 = 0x04,
11254 LBU32 = 0x05,
11255 SB32 = 0x06,
11256 LB32 = 0x07,
11258 POOL32B = 0x08,
11259 POOL16B = 0x09,
11260 LHU16 = 0x0a,
11261 ANDI16 = 0x0b,
11262 ADDIU32 = 0x0c,
11263 LHU32 = 0x0d,
11264 SH32 = 0x0e,
11265 LH32 = 0x0f,
11267 POOL32I = 0x10,
11268 POOL16C = 0x11,
11269 LWSP16 = 0x12,
11270 POOL16D = 0x13,
11271 ORI32 = 0x14,
11272 POOL32F = 0x15,
11273 POOL32S = 0x16, /* MIPS64 */
11274 DADDIU32 = 0x17, /* MIPS64 */
11276 /* 0x1f is reserved */
11277 POOL32C = 0x18,
11278 LWGP16 = 0x19,
11279 LW16 = 0x1a,
11280 POOL16E = 0x1b,
11281 XORI32 = 0x1c,
11282 JALS32 = 0x1d,
11283 ADDIUPC = 0x1e,
11285 /* 0x20 is reserved */
11286 RES_20 = 0x20,
11287 POOL16F = 0x21,
11288 SB16 = 0x22,
11289 BEQZ16 = 0x23,
11290 SLTI32 = 0x24,
11291 BEQ32 = 0x25,
11292 SWC132 = 0x26,
11293 LWC132 = 0x27,
11295 /* 0x28 and 0x29 are reserved */
11296 RES_28 = 0x28,
11297 RES_29 = 0x29,
11298 SH16 = 0x2a,
11299 BNEZ16 = 0x2b,
11300 SLTIU32 = 0x2c,
11301 BNE32 = 0x2d,
11302 SDC132 = 0x2e,
11303 LDC132 = 0x2f,
11305 /* 0x30 and 0x31 are reserved */
11306 RES_30 = 0x30,
11307 RES_31 = 0x31,
11308 SWSP16 = 0x32,
11309 B16 = 0x33,
11310 ANDI32 = 0x34,
11311 J32 = 0x35,
11312 SD32 = 0x36, /* MIPS64 */
11313 LD32 = 0x37, /* MIPS64 */
11315 /* 0x38 and 0x39 are reserved */
11316 RES_38 = 0x38,
11317 RES_39 = 0x39,
11318 SW16 = 0x3a,
11319 LI16 = 0x3b,
11320 JALX32 = 0x3c,
11321 JAL32 = 0x3d,
11322 SW32 = 0x3e,
11323 LW32 = 0x3f
11326 /* POOL32A encoding of minor opcode field */
11328 enum {
11329 /* These opcodes are distinguished only by bits 9..6; those bits are
11330 * what are recorded below. */
11331 SLL32 = 0x0,
11332 SRL32 = 0x1,
11333 SRA = 0x2,
11334 ROTR = 0x3,
11336 SLLV = 0x0,
11337 SRLV = 0x1,
11338 SRAV = 0x2,
11339 ROTRV = 0x3,
11340 ADD = 0x4,
11341 ADDU32 = 0x5,
11342 SUB = 0x6,
11343 SUBU32 = 0x7,
11344 MUL = 0x8,
11345 AND = 0x9,
11346 OR32 = 0xa,
11347 NOR = 0xb,
11348 XOR32 = 0xc,
11349 SLT = 0xd,
11350 SLTU = 0xe,
11352 MOVN = 0x0,
11353 MOVZ = 0x1,
11354 LWXS = 0x4,
11356 /* The following can be distinguished by their lower 6 bits. */
11357 INS = 0x0c,
11358 EXT = 0x2c,
11359 POOL32AXF = 0x3c
11362 /* POOL32AXF encoding of minor opcode field extension */
11365 * 1. MIPS Architecture for Programmers Volume II-B:
11366 * The microMIPS32 Instruction Set (Revision 3.05)
11368 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
11370 * 2. MIPS Architecture for Programmers VolumeIV-e:
11371 * The MIPS DSP Application-Specific Extension
11372 * to the microMIPS32 Architecture (Revision 2.34)
11374 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
11377 enum {
11378 /* bits 11..6 */
11379 TEQ = 0x00,
11380 TGE = 0x08,
11381 TGEU = 0x10,
11382 TLT = 0x20,
11383 TLTU = 0x28,
11384 TNE = 0x30,
11386 MFC0 = 0x03,
11387 MTC0 = 0x0b,
11389 /* begin of microMIPS32 DSP */
11391 /* bits 13..12 for 0x01 */
11392 MFHI_ACC = 0x0,
11393 MFLO_ACC = 0x1,
11394 MTHI_ACC = 0x2,
11395 MTLO_ACC = 0x3,
11397 /* bits 13..12 for 0x2a */
11398 MADD_ACC = 0x0,
11399 MADDU_ACC = 0x1,
11400 MSUB_ACC = 0x2,
11401 MSUBU_ACC = 0x3,
11403 /* bits 13..12 for 0x32 */
11404 MULT_ACC = 0x0,
11405 MULTU_ACC = 0x1,
11407 /* end of microMIPS32 DSP */
11409 /* bits 15..12 for 0x2c */
11410 SEB = 0x2,
11411 SEH = 0x3,
11412 CLO = 0x4,
11413 CLZ = 0x5,
11414 RDHWR = 0x6,
11415 WSBH = 0x7,
11416 MULT = 0x8,
11417 MULTU = 0x9,
11418 DIV = 0xa,
11419 DIVU = 0xb,
11420 MADD = 0xc,
11421 MADDU = 0xd,
11422 MSUB = 0xe,
11423 MSUBU = 0xf,
11425 /* bits 15..12 for 0x34 */
11426 MFC2 = 0x4,
11427 MTC2 = 0x5,
11428 MFHC2 = 0x8,
11429 MTHC2 = 0x9,
11430 CFC2 = 0xc,
11431 CTC2 = 0xd,
11433 /* bits 15..12 for 0x3c */
11434 JALR = 0x0,
11435 JR = 0x0, /* alias */
11436 JALR_HB = 0x1,
11437 JALRS = 0x4,
11438 JALRS_HB = 0x5,
11440 /* bits 15..12 for 0x05 */
11441 RDPGPR = 0xe,
11442 WRPGPR = 0xf,
11444 /* bits 15..12 for 0x0d */
11445 TLBP = 0x0,
11446 TLBR = 0x1,
11447 TLBWI = 0x2,
11448 TLBWR = 0x3,
11449 WAIT = 0x9,
11450 IRET = 0xd,
11451 DERET = 0xe,
11452 ERET = 0xf,
11454 /* bits 15..12 for 0x15 */
11455 DMT = 0x0,
11456 DVPE = 0x1,
11457 EMT = 0x2,
11458 EVPE = 0x3,
11460 /* bits 15..12 for 0x1d */
11461 DI = 0x4,
11462 EI = 0x5,
11464 /* bits 15..12 for 0x2d */
11465 SYNC = 0x6,
11466 SYSCALL = 0x8,
11467 SDBBP = 0xd,
11469 /* bits 15..12 for 0x35 */
11470 MFHI32 = 0x0,
11471 MFLO32 = 0x1,
11472 MTHI32 = 0x2,
11473 MTLO32 = 0x3,
11476 /* POOL32B encoding of minor opcode field (bits 15..12) */
11478 enum {
11479 LWC2 = 0x0,
11480 LWP = 0x1,
11481 LDP = 0x4,
11482 LWM32 = 0x5,
11483 CACHE = 0x6,
11484 LDM = 0x7,
11485 SWC2 = 0x8,
11486 SWP = 0x9,
11487 SDP = 0xc,
11488 SWM32 = 0xd,
11489 SDM = 0xf
11492 /* POOL32C encoding of minor opcode field (bits 15..12) */
11494 enum {
11495 LWL = 0x0,
11496 SWL = 0x8,
11497 LWR = 0x1,
11498 SWR = 0x9,
11499 PREF = 0x2,
11500 /* 0xa is reserved */
11501 LL = 0x3,
11502 SC = 0xb,
11503 LDL = 0x4,
11504 SDL = 0xc,
11505 LDR = 0x5,
11506 SDR = 0xd,
11507 /* 0x6 is reserved */
11508 LWU = 0xe,
11509 LLD = 0x7,
11510 SCD = 0xf
11513 /* POOL32F encoding of minor opcode field (bits 5..0) */
11515 enum {
11516 /* These are the bit 7..6 values */
11517 ADD_FMT = 0x0,
11518 MOVN_FMT = 0x0,
11520 SUB_FMT = 0x1,
11521 MOVZ_FMT = 0x1,
11523 MUL_FMT = 0x2,
11525 DIV_FMT = 0x3,
11527 /* These are the bit 8..6 values */
11528 RSQRT2_FMT = 0x0,
11529 MOVF_FMT = 0x0,
11531 LWXC1 = 0x1,
11532 MOVT_FMT = 0x1,
11534 PLL_PS = 0x2,
11535 SWXC1 = 0x2,
11537 PLU_PS = 0x3,
11538 LDXC1 = 0x3,
11540 PUL_PS = 0x4,
11541 SDXC1 = 0x4,
11542 RECIP2_FMT = 0x4,
11544 PUU_PS = 0x5,
11545 LUXC1 = 0x5,
11547 CVT_PS_S = 0x6,
11548 SUXC1 = 0x6,
11549 ADDR_PS = 0x6,
11550 PREFX = 0x6,
11552 MULR_PS = 0x7,
11554 MADD_S = 0x01,
11555 MADD_D = 0x09,
11556 MADD_PS = 0x11,
11557 ALNV_PS = 0x19,
11558 MSUB_S = 0x21,
11559 MSUB_D = 0x29,
11560 MSUB_PS = 0x31,
11562 NMADD_S = 0x02,
11563 NMADD_D = 0x0a,
11564 NMADD_PS = 0x12,
11565 NMSUB_S = 0x22,
11566 NMSUB_D = 0x2a,
11567 NMSUB_PS = 0x32,
11569 POOL32FXF = 0x3b,
11571 CABS_COND_FMT = 0x1c, /* MIPS3D */
11572 C_COND_FMT = 0x3c
11575 /* POOL32Fxf encoding of minor opcode extension field */
11577 enum {
11578 CVT_L = 0x04,
11579 RSQRT_FMT = 0x08,
11580 FLOOR_L = 0x0c,
11581 CVT_PW_PS = 0x1c,
11582 CVT_W = 0x24,
11583 SQRT_FMT = 0x28,
11584 FLOOR_W = 0x2c,
11585 CVT_PS_PW = 0x3c,
11586 CFC1 = 0x40,
11587 RECIP_FMT = 0x48,
11588 CEIL_L = 0x4c,
11589 CTC1 = 0x60,
11590 CEIL_W = 0x6c,
11591 MFC1 = 0x80,
11592 CVT_S_PL = 0x84,
11593 TRUNC_L = 0x8c,
11594 MTC1 = 0xa0,
11595 CVT_S_PU = 0xa4,
11596 TRUNC_W = 0xac,
11597 MFHC1 = 0xc0,
11598 ROUND_L = 0xcc,
11599 MTHC1 = 0xe0,
11600 ROUND_W = 0xec,
11602 MOV_FMT = 0x01,
11603 MOVF = 0x05,
11604 ABS_FMT = 0x0d,
11605 RSQRT1_FMT = 0x1d,
11606 MOVT = 0x25,
11607 NEG_FMT = 0x2d,
11608 CVT_D = 0x4d,
11609 RECIP1_FMT = 0x5d,
11610 CVT_S = 0x6d
11613 /* POOL32I encoding of minor opcode field (bits 25..21) */
11615 enum {
11616 BLTZ = 0x00,
11617 BLTZAL = 0x01,
11618 BGEZ = 0x02,
11619 BGEZAL = 0x03,
11620 BLEZ = 0x04,
11621 BNEZC = 0x05,
11622 BGTZ = 0x06,
11623 BEQZC = 0x07,
11624 TLTI = 0x08,
11625 TGEI = 0x09,
11626 TLTIU = 0x0a,
11627 TGEIU = 0x0b,
11628 TNEI = 0x0c,
11629 LUI = 0x0d,
11630 TEQI = 0x0e,
11631 SYNCI = 0x10,
11632 BLTZALS = 0x11,
11633 BGEZALS = 0x13,
11634 BC2F = 0x14,
11635 BC2T = 0x15,
11636 BPOSGE64 = 0x1a,
11637 BPOSGE32 = 0x1b,
11638 /* These overlap and are distinguished by bit16 of the instruction */
11639 BC1F = 0x1c,
11640 BC1T = 0x1d,
11641 BC1ANY2F = 0x1c,
11642 BC1ANY2T = 0x1d,
11643 BC1ANY4F = 0x1e,
11644 BC1ANY4T = 0x1f
11647 /* POOL16A encoding of minor opcode field */
11649 enum {
11650 ADDU16 = 0x0,
11651 SUBU16 = 0x1
11654 /* POOL16B encoding of minor opcode field */
11656 enum {
11657 SLL16 = 0x0,
11658 SRL16 = 0x1
11661 /* POOL16C encoding of minor opcode field */
11663 enum {
11664 NOT16 = 0x00,
11665 XOR16 = 0x04,
11666 AND16 = 0x08,
11667 OR16 = 0x0c,
11668 LWM16 = 0x10,
11669 SWM16 = 0x14,
11670 JR16 = 0x18,
11671 JRC16 = 0x1a,
11672 JALR16 = 0x1c,
11673 JALR16S = 0x1e,
11674 MFHI16 = 0x20,
11675 MFLO16 = 0x24,
11676 BREAK16 = 0x28,
11677 SDBBP16 = 0x2c,
11678 JRADDIUSP = 0x30
11681 /* POOL16D encoding of minor opcode field */
11683 enum {
11684 ADDIUS5 = 0x0,
11685 ADDIUSP = 0x1
11688 /* POOL16E encoding of minor opcode field */
11690 enum {
11691 ADDIUR2 = 0x0,
11692 ADDIUR1SP = 0x1
11695 static int mmreg (int r)
11697 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11699 return map[r];
11702 /* Used for 16-bit store instructions. */
11703 static int mmreg2 (int r)
11705 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
11707 return map[r];
11710 #define uMIPS_RD(op) ((op >> 7) & 0x7)
11711 #define uMIPS_RS(op) ((op >> 4) & 0x7)
11712 #define uMIPS_RS2(op) uMIPS_RS(op)
11713 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
11714 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
11715 #define uMIPS_RS5(op) (op & 0x1f)
11717 /* Signed immediate */
11718 #define SIMM(op, start, width) \
11719 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
11720 << (32-width)) \
11721 >> (32-width))
11722 /* Zero-extended immediate */
11723 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
11725 static void gen_addiur1sp(DisasContext *ctx)
11727 int rd = mmreg(uMIPS_RD(ctx->opcode));
11729 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
11732 static void gen_addiur2(DisasContext *ctx)
11734 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
11735 int rd = mmreg(uMIPS_RD(ctx->opcode));
11736 int rs = mmreg(uMIPS_RS(ctx->opcode));
11738 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
11741 static void gen_addiusp(DisasContext *ctx)
11743 int encoded = ZIMM(ctx->opcode, 1, 9);
11744 int decoded;
11746 if (encoded <= 1) {
11747 decoded = 256 + encoded;
11748 } else if (encoded <= 255) {
11749 decoded = encoded;
11750 } else if (encoded <= 509) {
11751 decoded = encoded - 512;
11752 } else {
11753 decoded = encoded - 768;
11756 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
11759 static void gen_addius5(DisasContext *ctx)
11761 int imm = SIMM(ctx->opcode, 1, 4);
11762 int rd = (ctx->opcode >> 5) & 0x1f;
11764 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
11767 static void gen_andi16(DisasContext *ctx)
11769 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
11770 31, 32, 63, 64, 255, 32768, 65535 };
11771 int rd = mmreg(uMIPS_RD(ctx->opcode));
11772 int rs = mmreg(uMIPS_RS(ctx->opcode));
11773 int encoded = ZIMM(ctx->opcode, 0, 4);
11775 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
11778 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
11779 int base, int16_t offset)
11781 const char *opn = "ldst_multiple";
11782 TCGv t0, t1;
11783 TCGv_i32 t2;
11785 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11786 generate_exception(ctx, EXCP_RI);
11787 return;
11790 t0 = tcg_temp_new();
11792 gen_base_offset_addr(ctx, t0, base, offset);
11794 t1 = tcg_const_tl(reglist);
11795 t2 = tcg_const_i32(ctx->mem_idx);
11797 save_cpu_state(ctx, 1);
11798 switch (opc) {
11799 case LWM32:
11800 gen_helper_lwm(cpu_env, t0, t1, t2);
11801 opn = "lwm";
11802 break;
11803 case SWM32:
11804 gen_helper_swm(cpu_env, t0, t1, t2);
11805 opn = "swm";
11806 break;
11807 #ifdef TARGET_MIPS64
11808 case LDM:
11809 gen_helper_ldm(cpu_env, t0, t1, t2);
11810 opn = "ldm";
11811 break;
11812 case SDM:
11813 gen_helper_sdm(cpu_env, t0, t1, t2);
11814 opn = "sdm";
11815 break;
11816 #endif
11818 (void)opn;
11819 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
11820 tcg_temp_free(t0);
11821 tcg_temp_free(t1);
11822 tcg_temp_free_i32(t2);
11826 static void gen_pool16c_insn(DisasContext *ctx)
11828 int rd = mmreg((ctx->opcode >> 3) & 0x7);
11829 int rs = mmreg(ctx->opcode & 0x7);
11831 switch (((ctx->opcode) >> 4) & 0x3f) {
11832 case NOT16 + 0:
11833 case NOT16 + 1:
11834 case NOT16 + 2:
11835 case NOT16 + 3:
11836 gen_logic(ctx, OPC_NOR, rd, rs, 0);
11837 break;
11838 case XOR16 + 0:
11839 case XOR16 + 1:
11840 case XOR16 + 2:
11841 case XOR16 + 3:
11842 gen_logic(ctx, OPC_XOR, rd, rd, rs);
11843 break;
11844 case AND16 + 0:
11845 case AND16 + 1:
11846 case AND16 + 2:
11847 case AND16 + 3:
11848 gen_logic(ctx, OPC_AND, rd, rd, rs);
11849 break;
11850 case OR16 + 0:
11851 case OR16 + 1:
11852 case OR16 + 2:
11853 case OR16 + 3:
11854 gen_logic(ctx, OPC_OR, rd, rd, rs);
11855 break;
11856 case LWM16 + 0:
11857 case LWM16 + 1:
11858 case LWM16 + 2:
11859 case LWM16 + 3:
11861 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
11862 int offset = ZIMM(ctx->opcode, 0, 4);
11864 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
11865 29, offset << 2);
11867 break;
11868 case SWM16 + 0:
11869 case SWM16 + 1:
11870 case SWM16 + 2:
11871 case SWM16 + 3:
11873 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
11874 int offset = ZIMM(ctx->opcode, 0, 4);
11876 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
11877 29, offset << 2);
11879 break;
11880 case JR16 + 0:
11881 case JR16 + 1:
11883 int reg = ctx->opcode & 0x1f;
11885 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
11887 break;
11888 case JRC16 + 0:
11889 case JRC16 + 1:
11891 int reg = ctx->opcode & 0x1f;
11892 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
11893 /* Let normal delay slot handling in our caller take us
11894 to the branch target. */
11896 break;
11897 case JALR16 + 0:
11898 case JALR16 + 1:
11899 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
11900 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
11901 break;
11902 case JALR16S + 0:
11903 case JALR16S + 1:
11904 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
11905 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
11906 break;
11907 case MFHI16 + 0:
11908 case MFHI16 + 1:
11909 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
11910 break;
11911 case MFLO16 + 0:
11912 case MFLO16 + 1:
11913 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
11914 break;
11915 case BREAK16:
11916 generate_exception(ctx, EXCP_BREAK);
11917 break;
11918 case SDBBP16:
11919 /* XXX: not clear which exception should be raised
11920 * when in debug mode...
11922 check_insn(ctx, ISA_MIPS32);
11923 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11924 generate_exception(ctx, EXCP_DBp);
11925 } else {
11926 generate_exception(ctx, EXCP_DBp);
11928 break;
11929 case JRADDIUSP + 0:
11930 case JRADDIUSP + 1:
11932 int imm = ZIMM(ctx->opcode, 0, 5);
11933 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
11934 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
11935 /* Let normal delay slot handling in our caller take us
11936 to the branch target. */
11938 break;
11939 default:
11940 generate_exception(ctx, EXCP_RI);
11941 break;
11945 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
11947 TCGv t0 = tcg_temp_new();
11948 TCGv t1 = tcg_temp_new();
11950 gen_load_gpr(t0, base);
11952 if (index != 0) {
11953 gen_load_gpr(t1, index);
11954 tcg_gen_shli_tl(t1, t1, 2);
11955 gen_op_addr_add(ctx, t0, t1, t0);
11958 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11959 gen_store_gpr(t1, rd);
11961 tcg_temp_free(t0);
11962 tcg_temp_free(t1);
11965 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
11966 int base, int16_t offset)
11968 const char *opn = "ldst_pair";
11969 TCGv t0, t1;
11971 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
11972 generate_exception(ctx, EXCP_RI);
11973 return;
11976 t0 = tcg_temp_new();
11977 t1 = tcg_temp_new();
11979 gen_base_offset_addr(ctx, t0, base, offset);
11981 switch (opc) {
11982 case LWP:
11983 if (rd == base) {
11984 generate_exception(ctx, EXCP_RI);
11985 return;
11987 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11988 gen_store_gpr(t1, rd);
11989 tcg_gen_movi_tl(t1, 4);
11990 gen_op_addr_add(ctx, t0, t0, t1);
11991 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11992 gen_store_gpr(t1, rd+1);
11993 opn = "lwp";
11994 break;
11995 case SWP:
11996 gen_load_gpr(t1, rd);
11997 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11998 tcg_gen_movi_tl(t1, 4);
11999 gen_op_addr_add(ctx, t0, t0, t1);
12000 gen_load_gpr(t1, rd+1);
12001 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12002 opn = "swp";
12003 break;
12004 #ifdef TARGET_MIPS64
12005 case LDP:
12006 if (rd == base) {
12007 generate_exception(ctx, EXCP_RI);
12008 return;
12010 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12011 gen_store_gpr(t1, rd);
12012 tcg_gen_movi_tl(t1, 8);
12013 gen_op_addr_add(ctx, t0, t0, t1);
12014 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12015 gen_store_gpr(t1, rd+1);
12016 opn = "ldp";
12017 break;
12018 case SDP:
12019 gen_load_gpr(t1, rd);
12020 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12021 tcg_gen_movi_tl(t1, 8);
12022 gen_op_addr_add(ctx, t0, t0, t1);
12023 gen_load_gpr(t1, rd+1);
12024 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12025 opn = "sdp";
12026 break;
12027 #endif
12029 (void)opn; /* avoid a compiler warning */
12030 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
12031 tcg_temp_free(t0);
12032 tcg_temp_free(t1);
12035 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12037 int extension = (ctx->opcode >> 6) & 0x3f;
12038 int minor = (ctx->opcode >> 12) & 0xf;
12039 uint32_t mips32_op;
12041 switch (extension) {
12042 case TEQ:
12043 mips32_op = OPC_TEQ;
12044 goto do_trap;
12045 case TGE:
12046 mips32_op = OPC_TGE;
12047 goto do_trap;
12048 case TGEU:
12049 mips32_op = OPC_TGEU;
12050 goto do_trap;
12051 case TLT:
12052 mips32_op = OPC_TLT;
12053 goto do_trap;
12054 case TLTU:
12055 mips32_op = OPC_TLTU;
12056 goto do_trap;
12057 case TNE:
12058 mips32_op = OPC_TNE;
12059 do_trap:
12060 gen_trap(ctx, mips32_op, rs, rt, -1);
12061 break;
12062 #ifndef CONFIG_USER_ONLY
12063 case MFC0:
12064 case MFC0 + 32:
12065 check_cp0_enabled(ctx);
12066 if (rt == 0) {
12067 /* Treat as NOP. */
12068 break;
12070 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12071 break;
12072 case MTC0:
12073 case MTC0 + 32:
12074 check_cp0_enabled(ctx);
12076 TCGv t0 = tcg_temp_new();
12078 gen_load_gpr(t0, rt);
12079 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
12080 tcg_temp_free(t0);
12082 break;
12083 #endif
12084 case 0x2a:
12085 switch (minor & 3) {
12086 case MADD_ACC:
12087 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12088 break;
12089 case MADDU_ACC:
12090 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12091 break;
12092 case MSUB_ACC:
12093 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12094 break;
12095 case MSUBU_ACC:
12096 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12097 break;
12098 default:
12099 goto pool32axf_invalid;
12101 break;
12102 case 0x32:
12103 switch (minor & 3) {
12104 case MULT_ACC:
12105 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12106 break;
12107 case MULTU_ACC:
12108 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12109 break;
12110 default:
12111 goto pool32axf_invalid;
12113 break;
12114 case 0x2c:
12115 switch (minor) {
12116 case SEB:
12117 gen_bshfl(ctx, OPC_SEB, rs, rt);
12118 break;
12119 case SEH:
12120 gen_bshfl(ctx, OPC_SEH, rs, rt);
12121 break;
12122 case CLO:
12123 mips32_op = OPC_CLO;
12124 goto do_cl;
12125 case CLZ:
12126 mips32_op = OPC_CLZ;
12127 do_cl:
12128 check_insn(ctx, ISA_MIPS32);
12129 gen_cl(ctx, mips32_op, rt, rs);
12130 break;
12131 case RDHWR:
12132 gen_rdhwr(ctx, rt, rs);
12133 break;
12134 case WSBH:
12135 gen_bshfl(ctx, OPC_WSBH, rs, rt);
12136 break;
12137 case MULT:
12138 mips32_op = OPC_MULT;
12139 goto do_mul;
12140 case MULTU:
12141 mips32_op = OPC_MULTU;
12142 goto do_mul;
12143 case DIV:
12144 mips32_op = OPC_DIV;
12145 goto do_div;
12146 case DIVU:
12147 mips32_op = OPC_DIVU;
12148 goto do_div;
12149 do_div:
12150 check_insn(ctx, ISA_MIPS32);
12151 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12152 break;
12153 case MADD:
12154 mips32_op = OPC_MADD;
12155 goto do_mul;
12156 case MADDU:
12157 mips32_op = OPC_MADDU;
12158 goto do_mul;
12159 case MSUB:
12160 mips32_op = OPC_MSUB;
12161 goto do_mul;
12162 case MSUBU:
12163 mips32_op = OPC_MSUBU;
12164 do_mul:
12165 check_insn(ctx, ISA_MIPS32);
12166 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12167 break;
12168 default:
12169 goto pool32axf_invalid;
12171 break;
12172 case 0x34:
12173 switch (minor) {
12174 case MFC2:
12175 case MTC2:
12176 case MFHC2:
12177 case MTHC2:
12178 case CFC2:
12179 case CTC2:
12180 generate_exception_err(ctx, EXCP_CpU, 2);
12181 break;
12182 default:
12183 goto pool32axf_invalid;
12185 break;
12186 case 0x3c:
12187 switch (minor) {
12188 case JALR:
12189 case JALR_HB:
12190 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
12191 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12192 break;
12193 case JALRS:
12194 case JALRS_HB:
12195 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
12196 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12197 break;
12198 default:
12199 goto pool32axf_invalid;
12201 break;
12202 case 0x05:
12203 switch (minor) {
12204 case RDPGPR:
12205 check_cp0_enabled(ctx);
12206 check_insn(ctx, ISA_MIPS32R2);
12207 gen_load_srsgpr(rt, rs);
12208 break;
12209 case WRPGPR:
12210 check_cp0_enabled(ctx);
12211 check_insn(ctx, ISA_MIPS32R2);
12212 gen_store_srsgpr(rt, rs);
12213 break;
12214 default:
12215 goto pool32axf_invalid;
12217 break;
12218 #ifndef CONFIG_USER_ONLY
12219 case 0x0d:
12220 switch (minor) {
12221 case TLBP:
12222 mips32_op = OPC_TLBP;
12223 goto do_cp0;
12224 case TLBR:
12225 mips32_op = OPC_TLBR;
12226 goto do_cp0;
12227 case TLBWI:
12228 mips32_op = OPC_TLBWI;
12229 goto do_cp0;
12230 case TLBWR:
12231 mips32_op = OPC_TLBWR;
12232 goto do_cp0;
12233 case WAIT:
12234 mips32_op = OPC_WAIT;
12235 goto do_cp0;
12236 case DERET:
12237 mips32_op = OPC_DERET;
12238 goto do_cp0;
12239 case ERET:
12240 mips32_op = OPC_ERET;
12241 do_cp0:
12242 gen_cp0(env, ctx, mips32_op, rt, rs);
12243 break;
12244 default:
12245 goto pool32axf_invalid;
12247 break;
12248 case 0x1d:
12249 switch (minor) {
12250 case DI:
12251 check_cp0_enabled(ctx);
12253 TCGv t0 = tcg_temp_new();
12255 save_cpu_state(ctx, 1);
12256 gen_helper_di(t0, cpu_env);
12257 gen_store_gpr(t0, rs);
12258 /* Stop translation as we may have switched the execution mode */
12259 ctx->bstate = BS_STOP;
12260 tcg_temp_free(t0);
12262 break;
12263 case EI:
12264 check_cp0_enabled(ctx);
12266 TCGv t0 = tcg_temp_new();
12268 save_cpu_state(ctx, 1);
12269 gen_helper_ei(t0, cpu_env);
12270 gen_store_gpr(t0, rs);
12271 /* Stop translation as we may have switched the execution mode */
12272 ctx->bstate = BS_STOP;
12273 tcg_temp_free(t0);
12275 break;
12276 default:
12277 goto pool32axf_invalid;
12279 break;
12280 #endif
12281 case 0x2d:
12282 switch (minor) {
12283 case SYNC:
12284 /* NOP */
12285 break;
12286 case SYSCALL:
12287 generate_exception(ctx, EXCP_SYSCALL);
12288 ctx->bstate = BS_STOP;
12289 break;
12290 case SDBBP:
12291 check_insn(ctx, ISA_MIPS32);
12292 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12293 generate_exception(ctx, EXCP_DBp);
12294 } else {
12295 generate_exception(ctx, EXCP_DBp);
12297 break;
12298 default:
12299 goto pool32axf_invalid;
12301 break;
12302 case 0x01:
12303 switch (minor & 3) {
12304 case MFHI_ACC:
12305 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
12306 break;
12307 case MFLO_ACC:
12308 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
12309 break;
12310 case MTHI_ACC:
12311 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
12312 break;
12313 case MTLO_ACC:
12314 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
12315 break;
12316 default:
12317 goto pool32axf_invalid;
12319 break;
12320 case 0x35:
12321 switch (minor) {
12322 case MFHI32:
12323 gen_HILO(ctx, OPC_MFHI, 0, rs);
12324 break;
12325 case MFLO32:
12326 gen_HILO(ctx, OPC_MFLO, 0, rs);
12327 break;
12328 case MTHI32:
12329 gen_HILO(ctx, OPC_MTHI, 0, rs);
12330 break;
12331 case MTLO32:
12332 gen_HILO(ctx, OPC_MTLO, 0, rs);
12333 break;
12334 default:
12335 goto pool32axf_invalid;
12337 break;
12338 default:
12339 pool32axf_invalid:
12340 MIPS_INVAL("pool32axf");
12341 generate_exception(ctx, EXCP_RI);
12342 break;
12346 /* Values for microMIPS fmt field. Variable-width, depending on which
12347 formats the instruction supports. */
12349 enum {
12350 FMT_SD_S = 0,
12351 FMT_SD_D = 1,
12353 FMT_SDPS_S = 0,
12354 FMT_SDPS_D = 1,
12355 FMT_SDPS_PS = 2,
12357 FMT_SWL_S = 0,
12358 FMT_SWL_W = 1,
12359 FMT_SWL_L = 2,
12361 FMT_DWL_D = 0,
12362 FMT_DWL_W = 1,
12363 FMT_DWL_L = 2
12366 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
12368 int extension = (ctx->opcode >> 6) & 0x3ff;
12369 uint32_t mips32_op;
12371 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
12372 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
12373 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
12375 switch (extension) {
12376 case FLOAT_1BIT_FMT(CFC1, 0):
12377 mips32_op = OPC_CFC1;
12378 goto do_cp1;
12379 case FLOAT_1BIT_FMT(CTC1, 0):
12380 mips32_op = OPC_CTC1;
12381 goto do_cp1;
12382 case FLOAT_1BIT_FMT(MFC1, 0):
12383 mips32_op = OPC_MFC1;
12384 goto do_cp1;
12385 case FLOAT_1BIT_FMT(MTC1, 0):
12386 mips32_op = OPC_MTC1;
12387 goto do_cp1;
12388 case FLOAT_1BIT_FMT(MFHC1, 0):
12389 mips32_op = OPC_MFHC1;
12390 goto do_cp1;
12391 case FLOAT_1BIT_FMT(MTHC1, 0):
12392 mips32_op = OPC_MTHC1;
12393 do_cp1:
12394 gen_cp1(ctx, mips32_op, rt, rs);
12395 break;
12397 /* Reciprocal square root */
12398 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
12399 mips32_op = OPC_RSQRT_S;
12400 goto do_unaryfp;
12401 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
12402 mips32_op = OPC_RSQRT_D;
12403 goto do_unaryfp;
12405 /* Square root */
12406 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
12407 mips32_op = OPC_SQRT_S;
12408 goto do_unaryfp;
12409 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
12410 mips32_op = OPC_SQRT_D;
12411 goto do_unaryfp;
12413 /* Reciprocal */
12414 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
12415 mips32_op = OPC_RECIP_S;
12416 goto do_unaryfp;
12417 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
12418 mips32_op = OPC_RECIP_D;
12419 goto do_unaryfp;
12421 /* Floor */
12422 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
12423 mips32_op = OPC_FLOOR_L_S;
12424 goto do_unaryfp;
12425 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
12426 mips32_op = OPC_FLOOR_L_D;
12427 goto do_unaryfp;
12428 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
12429 mips32_op = OPC_FLOOR_W_S;
12430 goto do_unaryfp;
12431 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
12432 mips32_op = OPC_FLOOR_W_D;
12433 goto do_unaryfp;
12435 /* Ceiling */
12436 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
12437 mips32_op = OPC_CEIL_L_S;
12438 goto do_unaryfp;
12439 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
12440 mips32_op = OPC_CEIL_L_D;
12441 goto do_unaryfp;
12442 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
12443 mips32_op = OPC_CEIL_W_S;
12444 goto do_unaryfp;
12445 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
12446 mips32_op = OPC_CEIL_W_D;
12447 goto do_unaryfp;
12449 /* Truncation */
12450 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
12451 mips32_op = OPC_TRUNC_L_S;
12452 goto do_unaryfp;
12453 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
12454 mips32_op = OPC_TRUNC_L_D;
12455 goto do_unaryfp;
12456 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
12457 mips32_op = OPC_TRUNC_W_S;
12458 goto do_unaryfp;
12459 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
12460 mips32_op = OPC_TRUNC_W_D;
12461 goto do_unaryfp;
12463 /* Round */
12464 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
12465 mips32_op = OPC_ROUND_L_S;
12466 goto do_unaryfp;
12467 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
12468 mips32_op = OPC_ROUND_L_D;
12469 goto do_unaryfp;
12470 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
12471 mips32_op = OPC_ROUND_W_S;
12472 goto do_unaryfp;
12473 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
12474 mips32_op = OPC_ROUND_W_D;
12475 goto do_unaryfp;
12477 /* Integer to floating-point conversion */
12478 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
12479 mips32_op = OPC_CVT_L_S;
12480 goto do_unaryfp;
12481 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
12482 mips32_op = OPC_CVT_L_D;
12483 goto do_unaryfp;
12484 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
12485 mips32_op = OPC_CVT_W_S;
12486 goto do_unaryfp;
12487 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
12488 mips32_op = OPC_CVT_W_D;
12489 goto do_unaryfp;
12491 /* Paired-foo conversions */
12492 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
12493 mips32_op = OPC_CVT_S_PL;
12494 goto do_unaryfp;
12495 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
12496 mips32_op = OPC_CVT_S_PU;
12497 goto do_unaryfp;
12498 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
12499 mips32_op = OPC_CVT_PW_PS;
12500 goto do_unaryfp;
12501 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
12502 mips32_op = OPC_CVT_PS_PW;
12503 goto do_unaryfp;
12505 /* Floating-point moves */
12506 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
12507 mips32_op = OPC_MOV_S;
12508 goto do_unaryfp;
12509 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
12510 mips32_op = OPC_MOV_D;
12511 goto do_unaryfp;
12512 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
12513 mips32_op = OPC_MOV_PS;
12514 goto do_unaryfp;
12516 /* Absolute value */
12517 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
12518 mips32_op = OPC_ABS_S;
12519 goto do_unaryfp;
12520 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
12521 mips32_op = OPC_ABS_D;
12522 goto do_unaryfp;
12523 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
12524 mips32_op = OPC_ABS_PS;
12525 goto do_unaryfp;
12527 /* Negation */
12528 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
12529 mips32_op = OPC_NEG_S;
12530 goto do_unaryfp;
12531 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
12532 mips32_op = OPC_NEG_D;
12533 goto do_unaryfp;
12534 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
12535 mips32_op = OPC_NEG_PS;
12536 goto do_unaryfp;
12538 /* Reciprocal square root step */
12539 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
12540 mips32_op = OPC_RSQRT1_S;
12541 goto do_unaryfp;
12542 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
12543 mips32_op = OPC_RSQRT1_D;
12544 goto do_unaryfp;
12545 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
12546 mips32_op = OPC_RSQRT1_PS;
12547 goto do_unaryfp;
12549 /* Reciprocal step */
12550 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
12551 mips32_op = OPC_RECIP1_S;
12552 goto do_unaryfp;
12553 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
12554 mips32_op = OPC_RECIP1_S;
12555 goto do_unaryfp;
12556 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
12557 mips32_op = OPC_RECIP1_PS;
12558 goto do_unaryfp;
12560 /* Conversions from double */
12561 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
12562 mips32_op = OPC_CVT_D_S;
12563 goto do_unaryfp;
12564 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
12565 mips32_op = OPC_CVT_D_W;
12566 goto do_unaryfp;
12567 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
12568 mips32_op = OPC_CVT_D_L;
12569 goto do_unaryfp;
12571 /* Conversions from single */
12572 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
12573 mips32_op = OPC_CVT_S_D;
12574 goto do_unaryfp;
12575 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
12576 mips32_op = OPC_CVT_S_W;
12577 goto do_unaryfp;
12578 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
12579 mips32_op = OPC_CVT_S_L;
12580 do_unaryfp:
12581 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
12582 break;
12584 /* Conditional moves on floating-point codes */
12585 case COND_FLOAT_MOV(MOVT, 0):
12586 case COND_FLOAT_MOV(MOVT, 1):
12587 case COND_FLOAT_MOV(MOVT, 2):
12588 case COND_FLOAT_MOV(MOVT, 3):
12589 case COND_FLOAT_MOV(MOVT, 4):
12590 case COND_FLOAT_MOV(MOVT, 5):
12591 case COND_FLOAT_MOV(MOVT, 6):
12592 case COND_FLOAT_MOV(MOVT, 7):
12593 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
12594 break;
12595 case COND_FLOAT_MOV(MOVF, 0):
12596 case COND_FLOAT_MOV(MOVF, 1):
12597 case COND_FLOAT_MOV(MOVF, 2):
12598 case COND_FLOAT_MOV(MOVF, 3):
12599 case COND_FLOAT_MOV(MOVF, 4):
12600 case COND_FLOAT_MOV(MOVF, 5):
12601 case COND_FLOAT_MOV(MOVF, 6):
12602 case COND_FLOAT_MOV(MOVF, 7):
12603 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
12604 break;
12605 default:
12606 MIPS_INVAL("pool32fxf");
12607 generate_exception(ctx, EXCP_RI);
12608 break;
12612 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
12613 uint16_t insn_hw1)
12615 int32_t offset;
12616 uint16_t insn;
12617 int rt, rs, rd, rr;
12618 int16_t imm;
12619 uint32_t op, minor, mips32_op;
12620 uint32_t cond, fmt, cc;
12622 insn = cpu_lduw_code(env, ctx->pc + 2);
12623 ctx->opcode = (ctx->opcode << 16) | insn;
12625 rt = (ctx->opcode >> 21) & 0x1f;
12626 rs = (ctx->opcode >> 16) & 0x1f;
12627 rd = (ctx->opcode >> 11) & 0x1f;
12628 rr = (ctx->opcode >> 6) & 0x1f;
12629 imm = (int16_t) ctx->opcode;
12631 op = (ctx->opcode >> 26) & 0x3f;
12632 switch (op) {
12633 case POOL32A:
12634 minor = ctx->opcode & 0x3f;
12635 switch (minor) {
12636 case 0x00:
12637 minor = (ctx->opcode >> 6) & 0xf;
12638 switch (minor) {
12639 case SLL32:
12640 mips32_op = OPC_SLL;
12641 goto do_shifti;
12642 case SRA:
12643 mips32_op = OPC_SRA;
12644 goto do_shifti;
12645 case SRL32:
12646 mips32_op = OPC_SRL;
12647 goto do_shifti;
12648 case ROTR:
12649 mips32_op = OPC_ROTR;
12650 do_shifti:
12651 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
12652 break;
12653 default:
12654 goto pool32a_invalid;
12656 break;
12657 case 0x10:
12658 minor = (ctx->opcode >> 6) & 0xf;
12659 switch (minor) {
12660 /* Arithmetic */
12661 case ADD:
12662 mips32_op = OPC_ADD;
12663 goto do_arith;
12664 case ADDU32:
12665 mips32_op = OPC_ADDU;
12666 goto do_arith;
12667 case SUB:
12668 mips32_op = OPC_SUB;
12669 goto do_arith;
12670 case SUBU32:
12671 mips32_op = OPC_SUBU;
12672 goto do_arith;
12673 case MUL:
12674 mips32_op = OPC_MUL;
12675 do_arith:
12676 gen_arith(ctx, mips32_op, rd, rs, rt);
12677 break;
12678 /* Shifts */
12679 case SLLV:
12680 mips32_op = OPC_SLLV;
12681 goto do_shift;
12682 case SRLV:
12683 mips32_op = OPC_SRLV;
12684 goto do_shift;
12685 case SRAV:
12686 mips32_op = OPC_SRAV;
12687 goto do_shift;
12688 case ROTRV:
12689 mips32_op = OPC_ROTRV;
12690 do_shift:
12691 gen_shift(ctx, mips32_op, rd, rs, rt);
12692 break;
12693 /* Logical operations */
12694 case AND:
12695 mips32_op = OPC_AND;
12696 goto do_logic;
12697 case OR32:
12698 mips32_op = OPC_OR;
12699 goto do_logic;
12700 case NOR:
12701 mips32_op = OPC_NOR;
12702 goto do_logic;
12703 case XOR32:
12704 mips32_op = OPC_XOR;
12705 do_logic:
12706 gen_logic(ctx, mips32_op, rd, rs, rt);
12707 break;
12708 /* Set less than */
12709 case SLT:
12710 mips32_op = OPC_SLT;
12711 goto do_slt;
12712 case SLTU:
12713 mips32_op = OPC_SLTU;
12714 do_slt:
12715 gen_slt(ctx, mips32_op, rd, rs, rt);
12716 break;
12717 default:
12718 goto pool32a_invalid;
12720 break;
12721 case 0x18:
12722 minor = (ctx->opcode >> 6) & 0xf;
12723 switch (minor) {
12724 /* Conditional moves */
12725 case MOVN:
12726 mips32_op = OPC_MOVN;
12727 goto do_cmov;
12728 case MOVZ:
12729 mips32_op = OPC_MOVZ;
12730 do_cmov:
12731 gen_cond_move(ctx, mips32_op, rd, rs, rt);
12732 break;
12733 case LWXS:
12734 gen_ldxs(ctx, rs, rt, rd);
12735 break;
12736 default:
12737 goto pool32a_invalid;
12739 break;
12740 case INS:
12741 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
12742 return;
12743 case EXT:
12744 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
12745 return;
12746 case POOL32AXF:
12747 gen_pool32axf(env, ctx, rt, rs);
12748 break;
12749 case 0x07:
12750 generate_exception(ctx, EXCP_BREAK);
12751 break;
12752 default:
12753 pool32a_invalid:
12754 MIPS_INVAL("pool32a");
12755 generate_exception(ctx, EXCP_RI);
12756 break;
12758 break;
12759 case POOL32B:
12760 minor = (ctx->opcode >> 12) & 0xf;
12761 switch (minor) {
12762 case CACHE:
12763 check_cp0_enabled(ctx);
12764 /* Treat as no-op. */
12765 break;
12766 case LWC2:
12767 case SWC2:
12768 /* COP2: Not implemented. */
12769 generate_exception_err(ctx, EXCP_CpU, 2);
12770 break;
12771 case LWP:
12772 case SWP:
12773 #ifdef TARGET_MIPS64
12774 case LDP:
12775 case SDP:
12776 #endif
12777 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
12778 break;
12779 case LWM32:
12780 case SWM32:
12781 #ifdef TARGET_MIPS64
12782 case LDM:
12783 case SDM:
12784 #endif
12785 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
12786 break;
12787 default:
12788 MIPS_INVAL("pool32b");
12789 generate_exception(ctx, EXCP_RI);
12790 break;
12792 break;
12793 case POOL32F:
12794 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
12795 minor = ctx->opcode & 0x3f;
12796 check_cp1_enabled(ctx);
12797 switch (minor) {
12798 case ALNV_PS:
12799 mips32_op = OPC_ALNV_PS;
12800 goto do_madd;
12801 case MADD_S:
12802 mips32_op = OPC_MADD_S;
12803 goto do_madd;
12804 case MADD_D:
12805 mips32_op = OPC_MADD_D;
12806 goto do_madd;
12807 case MADD_PS:
12808 mips32_op = OPC_MADD_PS;
12809 goto do_madd;
12810 case MSUB_S:
12811 mips32_op = OPC_MSUB_S;
12812 goto do_madd;
12813 case MSUB_D:
12814 mips32_op = OPC_MSUB_D;
12815 goto do_madd;
12816 case MSUB_PS:
12817 mips32_op = OPC_MSUB_PS;
12818 goto do_madd;
12819 case NMADD_S:
12820 mips32_op = OPC_NMADD_S;
12821 goto do_madd;
12822 case NMADD_D:
12823 mips32_op = OPC_NMADD_D;
12824 goto do_madd;
12825 case NMADD_PS:
12826 mips32_op = OPC_NMADD_PS;
12827 goto do_madd;
12828 case NMSUB_S:
12829 mips32_op = OPC_NMSUB_S;
12830 goto do_madd;
12831 case NMSUB_D:
12832 mips32_op = OPC_NMSUB_D;
12833 goto do_madd;
12834 case NMSUB_PS:
12835 mips32_op = OPC_NMSUB_PS;
12836 do_madd:
12837 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
12838 break;
12839 case CABS_COND_FMT:
12840 cond = (ctx->opcode >> 6) & 0xf;
12841 cc = (ctx->opcode >> 13) & 0x7;
12842 fmt = (ctx->opcode >> 10) & 0x3;
12843 switch (fmt) {
12844 case 0x0:
12845 gen_cmpabs_s(ctx, cond, rt, rs, cc);
12846 break;
12847 case 0x1:
12848 gen_cmpabs_d(ctx, cond, rt, rs, cc);
12849 break;
12850 case 0x2:
12851 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
12852 break;
12853 default:
12854 goto pool32f_invalid;
12856 break;
12857 case C_COND_FMT:
12858 cond = (ctx->opcode >> 6) & 0xf;
12859 cc = (ctx->opcode >> 13) & 0x7;
12860 fmt = (ctx->opcode >> 10) & 0x3;
12861 switch (fmt) {
12862 case 0x0:
12863 gen_cmp_s(ctx, cond, rt, rs, cc);
12864 break;
12865 case 0x1:
12866 gen_cmp_d(ctx, cond, rt, rs, cc);
12867 break;
12868 case 0x2:
12869 gen_cmp_ps(ctx, cond, rt, rs, cc);
12870 break;
12871 default:
12872 goto pool32f_invalid;
12874 break;
12875 case POOL32FXF:
12876 gen_pool32fxf(ctx, rt, rs);
12877 break;
12878 case 0x00:
12879 /* PLL foo */
12880 switch ((ctx->opcode >> 6) & 0x7) {
12881 case PLL_PS:
12882 mips32_op = OPC_PLL_PS;
12883 goto do_ps;
12884 case PLU_PS:
12885 mips32_op = OPC_PLU_PS;
12886 goto do_ps;
12887 case PUL_PS:
12888 mips32_op = OPC_PUL_PS;
12889 goto do_ps;
12890 case PUU_PS:
12891 mips32_op = OPC_PUU_PS;
12892 goto do_ps;
12893 case CVT_PS_S:
12894 mips32_op = OPC_CVT_PS_S;
12895 do_ps:
12896 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12897 break;
12898 default:
12899 goto pool32f_invalid;
12901 break;
12902 case 0x08:
12903 /* [LS][WDU]XC1 */
12904 switch ((ctx->opcode >> 6) & 0x7) {
12905 case LWXC1:
12906 mips32_op = OPC_LWXC1;
12907 goto do_ldst_cp1;
12908 case SWXC1:
12909 mips32_op = OPC_SWXC1;
12910 goto do_ldst_cp1;
12911 case LDXC1:
12912 mips32_op = OPC_LDXC1;
12913 goto do_ldst_cp1;
12914 case SDXC1:
12915 mips32_op = OPC_SDXC1;
12916 goto do_ldst_cp1;
12917 case LUXC1:
12918 mips32_op = OPC_LUXC1;
12919 goto do_ldst_cp1;
12920 case SUXC1:
12921 mips32_op = OPC_SUXC1;
12922 do_ldst_cp1:
12923 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
12924 break;
12925 default:
12926 goto pool32f_invalid;
12928 break;
12929 case 0x18:
12930 /* 3D insns */
12931 fmt = (ctx->opcode >> 9) & 0x3;
12932 switch ((ctx->opcode >> 6) & 0x7) {
12933 case RSQRT2_FMT:
12934 switch (fmt) {
12935 case FMT_SDPS_S:
12936 mips32_op = OPC_RSQRT2_S;
12937 goto do_3d;
12938 case FMT_SDPS_D:
12939 mips32_op = OPC_RSQRT2_D;
12940 goto do_3d;
12941 case FMT_SDPS_PS:
12942 mips32_op = OPC_RSQRT2_PS;
12943 goto do_3d;
12944 default:
12945 goto pool32f_invalid;
12947 break;
12948 case RECIP2_FMT:
12949 switch (fmt) {
12950 case FMT_SDPS_S:
12951 mips32_op = OPC_RECIP2_S;
12952 goto do_3d;
12953 case FMT_SDPS_D:
12954 mips32_op = OPC_RECIP2_D;
12955 goto do_3d;
12956 case FMT_SDPS_PS:
12957 mips32_op = OPC_RECIP2_PS;
12958 goto do_3d;
12959 default:
12960 goto pool32f_invalid;
12962 break;
12963 case ADDR_PS:
12964 mips32_op = OPC_ADDR_PS;
12965 goto do_3d;
12966 case MULR_PS:
12967 mips32_op = OPC_MULR_PS;
12968 do_3d:
12969 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12970 break;
12971 default:
12972 goto pool32f_invalid;
12974 break;
12975 case 0x20:
12976 /* MOV[FT].fmt and PREFX */
12977 cc = (ctx->opcode >> 13) & 0x7;
12978 fmt = (ctx->opcode >> 9) & 0x3;
12979 switch ((ctx->opcode >> 6) & 0x7) {
12980 case MOVF_FMT:
12981 switch (fmt) {
12982 case FMT_SDPS_S:
12983 gen_movcf_s(rs, rt, cc, 0);
12984 break;
12985 case FMT_SDPS_D:
12986 gen_movcf_d(ctx, rs, rt, cc, 0);
12987 break;
12988 case FMT_SDPS_PS:
12989 gen_movcf_ps(ctx, rs, rt, cc, 0);
12990 break;
12991 default:
12992 goto pool32f_invalid;
12994 break;
12995 case MOVT_FMT:
12996 switch (fmt) {
12997 case FMT_SDPS_S:
12998 gen_movcf_s(rs, rt, cc, 1);
12999 break;
13000 case FMT_SDPS_D:
13001 gen_movcf_d(ctx, rs, rt, cc, 1);
13002 break;
13003 case FMT_SDPS_PS:
13004 gen_movcf_ps(ctx, rs, rt, cc, 1);
13005 break;
13006 default:
13007 goto pool32f_invalid;
13009 break;
13010 case PREFX:
13011 break;
13012 default:
13013 goto pool32f_invalid;
13015 break;
13016 #define FINSN_3ARG_SDPS(prfx) \
13017 switch ((ctx->opcode >> 8) & 0x3) { \
13018 case FMT_SDPS_S: \
13019 mips32_op = OPC_##prfx##_S; \
13020 goto do_fpop; \
13021 case FMT_SDPS_D: \
13022 mips32_op = OPC_##prfx##_D; \
13023 goto do_fpop; \
13024 case FMT_SDPS_PS: \
13025 mips32_op = OPC_##prfx##_PS; \
13026 goto do_fpop; \
13027 default: \
13028 goto pool32f_invalid; \
13030 case 0x30:
13031 /* regular FP ops */
13032 switch ((ctx->opcode >> 6) & 0x3) {
13033 case ADD_FMT:
13034 FINSN_3ARG_SDPS(ADD);
13035 break;
13036 case SUB_FMT:
13037 FINSN_3ARG_SDPS(SUB);
13038 break;
13039 case MUL_FMT:
13040 FINSN_3ARG_SDPS(MUL);
13041 break;
13042 case DIV_FMT:
13043 fmt = (ctx->opcode >> 8) & 0x3;
13044 if (fmt == 1) {
13045 mips32_op = OPC_DIV_D;
13046 } else if (fmt == 0) {
13047 mips32_op = OPC_DIV_S;
13048 } else {
13049 goto pool32f_invalid;
13051 goto do_fpop;
13052 default:
13053 goto pool32f_invalid;
13055 break;
13056 case 0x38:
13057 /* cmovs */
13058 switch ((ctx->opcode >> 6) & 0x3) {
13059 case MOVN_FMT:
13060 FINSN_3ARG_SDPS(MOVN);
13061 break;
13062 case MOVZ_FMT:
13063 FINSN_3ARG_SDPS(MOVZ);
13064 break;
13065 default:
13066 goto pool32f_invalid;
13068 break;
13069 do_fpop:
13070 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13071 break;
13072 default:
13073 pool32f_invalid:
13074 MIPS_INVAL("pool32f");
13075 generate_exception(ctx, EXCP_RI);
13076 break;
13078 } else {
13079 generate_exception_err(ctx, EXCP_CpU, 1);
13081 break;
13082 case POOL32I:
13083 minor = (ctx->opcode >> 21) & 0x1f;
13084 switch (minor) {
13085 case BLTZ:
13086 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
13087 break;
13088 case BLTZAL:
13089 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
13090 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13091 break;
13092 case BLTZALS:
13093 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
13094 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13095 break;
13096 case BGEZ:
13097 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
13098 break;
13099 case BGEZAL:
13100 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
13101 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13102 break;
13103 case BGEZALS:
13104 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
13105 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13106 break;
13107 case BLEZ:
13108 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
13109 break;
13110 case BGTZ:
13111 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
13112 break;
13114 /* Traps */
13115 case TLTI:
13116 mips32_op = OPC_TLTI;
13117 goto do_trapi;
13118 case TGEI:
13119 mips32_op = OPC_TGEI;
13120 goto do_trapi;
13121 case TLTIU:
13122 mips32_op = OPC_TLTIU;
13123 goto do_trapi;
13124 case TGEIU:
13125 mips32_op = OPC_TGEIU;
13126 goto do_trapi;
13127 case TNEI:
13128 mips32_op = OPC_TNEI;
13129 goto do_trapi;
13130 case TEQI:
13131 mips32_op = OPC_TEQI;
13132 do_trapi:
13133 gen_trap(ctx, mips32_op, rs, -1, imm);
13134 break;
13136 case BNEZC:
13137 case BEQZC:
13138 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
13139 4, rs, 0, imm << 1, 0);
13140 /* Compact branches don't have a delay slot, so just let
13141 the normal delay slot handling take us to the branch
13142 target. */
13143 break;
13144 case LUI:
13145 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
13146 break;
13147 case SYNCI:
13148 /* Break the TB to be able to sync copied instructions
13149 immediately */
13150 ctx->bstate = BS_STOP;
13151 break;
13152 case BC2F:
13153 case BC2T:
13154 /* COP2: Not implemented. */
13155 generate_exception_err(ctx, EXCP_CpU, 2);
13156 break;
13157 case BC1F:
13158 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
13159 goto do_cp1branch;
13160 case BC1T:
13161 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
13162 goto do_cp1branch;
13163 case BC1ANY4F:
13164 mips32_op = OPC_BC1FANY4;
13165 goto do_cp1mips3d;
13166 case BC1ANY4T:
13167 mips32_op = OPC_BC1TANY4;
13168 do_cp1mips3d:
13169 check_cop1x(ctx);
13170 check_insn(ctx, ASE_MIPS3D);
13171 /* Fall through */
13172 do_cp1branch:
13173 gen_compute_branch1(ctx, mips32_op,
13174 (ctx->opcode >> 18) & 0x7, imm << 1);
13175 break;
13176 case BPOSGE64:
13177 case BPOSGE32:
13178 /* MIPS DSP: not implemented */
13179 /* Fall through */
13180 default:
13181 MIPS_INVAL("pool32i");
13182 generate_exception(ctx, EXCP_RI);
13183 break;
13185 break;
13186 case POOL32C:
13187 minor = (ctx->opcode >> 12) & 0xf;
13188 switch (minor) {
13189 case LWL:
13190 mips32_op = OPC_LWL;
13191 goto do_ld_lr;
13192 case SWL:
13193 mips32_op = OPC_SWL;
13194 goto do_st_lr;
13195 case LWR:
13196 mips32_op = OPC_LWR;
13197 goto do_ld_lr;
13198 case SWR:
13199 mips32_op = OPC_SWR;
13200 goto do_st_lr;
13201 #if defined(TARGET_MIPS64)
13202 case LDL:
13203 mips32_op = OPC_LDL;
13204 goto do_ld_lr;
13205 case SDL:
13206 mips32_op = OPC_SDL;
13207 goto do_st_lr;
13208 case LDR:
13209 mips32_op = OPC_LDR;
13210 goto do_ld_lr;
13211 case SDR:
13212 mips32_op = OPC_SDR;
13213 goto do_st_lr;
13214 case LWU:
13215 mips32_op = OPC_LWU;
13216 goto do_ld_lr;
13217 case LLD:
13218 mips32_op = OPC_LLD;
13219 goto do_ld_lr;
13220 #endif
13221 case LL:
13222 mips32_op = OPC_LL;
13223 goto do_ld_lr;
13224 do_ld_lr:
13225 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13226 break;
13227 do_st_lr:
13228 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13229 break;
13230 case SC:
13231 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
13232 break;
13233 #if defined(TARGET_MIPS64)
13234 case SCD:
13235 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
13236 break;
13237 #endif
13238 case PREF:
13239 /* Treat as no-op */
13240 break;
13241 default:
13242 MIPS_INVAL("pool32c");
13243 generate_exception(ctx, EXCP_RI);
13244 break;
13246 break;
13247 case ADDI32:
13248 mips32_op = OPC_ADDI;
13249 goto do_addi;
13250 case ADDIU32:
13251 mips32_op = OPC_ADDIU;
13252 do_addi:
13253 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
13254 break;
13256 /* Logical operations */
13257 case ORI32:
13258 mips32_op = OPC_ORI;
13259 goto do_logici;
13260 case XORI32:
13261 mips32_op = OPC_XORI;
13262 goto do_logici;
13263 case ANDI32:
13264 mips32_op = OPC_ANDI;
13265 do_logici:
13266 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
13267 break;
13269 /* Set less than immediate */
13270 case SLTI32:
13271 mips32_op = OPC_SLTI;
13272 goto do_slti;
13273 case SLTIU32:
13274 mips32_op = OPC_SLTIU;
13275 do_slti:
13276 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
13277 break;
13278 case JALX32:
13279 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
13280 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
13281 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13282 break;
13283 case JALS32:
13284 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
13285 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
13286 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13287 break;
13288 case BEQ32:
13289 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
13290 break;
13291 case BNE32:
13292 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
13293 break;
13294 case J32:
13295 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
13296 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13297 break;
13298 case JAL32:
13299 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
13300 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13301 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13302 break;
13303 /* Floating point (COP1) */
13304 case LWC132:
13305 mips32_op = OPC_LWC1;
13306 goto do_cop1;
13307 case LDC132:
13308 mips32_op = OPC_LDC1;
13309 goto do_cop1;
13310 case SWC132:
13311 mips32_op = OPC_SWC1;
13312 goto do_cop1;
13313 case SDC132:
13314 mips32_op = OPC_SDC1;
13315 do_cop1:
13316 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
13317 break;
13318 case ADDIUPC:
13320 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
13321 int offset = SIMM(ctx->opcode, 0, 23) << 2;
13323 gen_addiupc(ctx, reg, offset, 0, 0);
13325 break;
13326 /* Loads and stores */
13327 case LB32:
13328 mips32_op = OPC_LB;
13329 goto do_ld;
13330 case LBU32:
13331 mips32_op = OPC_LBU;
13332 goto do_ld;
13333 case LH32:
13334 mips32_op = OPC_LH;
13335 goto do_ld;
13336 case LHU32:
13337 mips32_op = OPC_LHU;
13338 goto do_ld;
13339 case LW32:
13340 mips32_op = OPC_LW;
13341 goto do_ld;
13342 #ifdef TARGET_MIPS64
13343 case LD32:
13344 mips32_op = OPC_LD;
13345 goto do_ld;
13346 case SD32:
13347 mips32_op = OPC_SD;
13348 goto do_st;
13349 #endif
13350 case SB32:
13351 mips32_op = OPC_SB;
13352 goto do_st;
13353 case SH32:
13354 mips32_op = OPC_SH;
13355 goto do_st;
13356 case SW32:
13357 mips32_op = OPC_SW;
13358 goto do_st;
13359 do_ld:
13360 gen_ld(ctx, mips32_op, rt, rs, imm);
13361 break;
13362 do_st:
13363 gen_st(ctx, mips32_op, rt, rs, imm);
13364 break;
13365 default:
13366 generate_exception(ctx, EXCP_RI);
13367 break;
13371 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
13373 uint32_t op;
13375 /* make sure instructions are on a halfword boundary */
13376 if (ctx->pc & 0x1) {
13377 env->CP0_BadVAddr = ctx->pc;
13378 generate_exception(ctx, EXCP_AdEL);
13379 ctx->bstate = BS_STOP;
13380 return 2;
13383 op = (ctx->opcode >> 10) & 0x3f;
13384 /* Enforce properly-sized instructions in a delay slot */
13385 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
13386 switch (op & 0x7) { /* MSB-3..MSB-5 */
13387 case 0:
13388 /* POOL32A, POOL32B, POOL32I, POOL32C */
13389 case 4:
13390 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
13391 case 5:
13392 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
13393 case 6:
13394 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
13395 case 7:
13396 /* LB32, LH32, LWC132, LDC132, LW32 */
13397 if (ctx->hflags & MIPS_HFLAG_BDS16) {
13398 generate_exception(ctx, EXCP_RI);
13399 /* Just stop translation; the user is confused. */
13400 ctx->bstate = BS_STOP;
13401 return 2;
13403 break;
13404 case 1:
13405 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
13406 case 2:
13407 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
13408 case 3:
13409 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
13410 if (ctx->hflags & MIPS_HFLAG_BDS32) {
13411 generate_exception(ctx, EXCP_RI);
13412 /* Just stop translation; the user is confused. */
13413 ctx->bstate = BS_STOP;
13414 return 2;
13416 break;
13420 switch (op) {
13421 case POOL16A:
13423 int rd = mmreg(uMIPS_RD(ctx->opcode));
13424 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
13425 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
13426 uint32_t opc = 0;
13428 switch (ctx->opcode & 0x1) {
13429 case ADDU16:
13430 opc = OPC_ADDU;
13431 break;
13432 case SUBU16:
13433 opc = OPC_SUBU;
13434 break;
13437 gen_arith(ctx, opc, rd, rs1, rs2);
13439 break;
13440 case POOL16B:
13442 int rd = mmreg(uMIPS_RD(ctx->opcode));
13443 int rs = mmreg(uMIPS_RS(ctx->opcode));
13444 int amount = (ctx->opcode >> 1) & 0x7;
13445 uint32_t opc = 0;
13446 amount = amount == 0 ? 8 : amount;
13448 switch (ctx->opcode & 0x1) {
13449 case SLL16:
13450 opc = OPC_SLL;
13451 break;
13452 case SRL16:
13453 opc = OPC_SRL;
13454 break;
13457 gen_shift_imm(ctx, opc, rd, rs, amount);
13459 break;
13460 case POOL16C:
13461 gen_pool16c_insn(ctx);
13462 break;
13463 case LWGP16:
13465 int rd = mmreg(uMIPS_RD(ctx->opcode));
13466 int rb = 28; /* GP */
13467 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
13469 gen_ld(ctx, OPC_LW, rd, rb, offset);
13471 break;
13472 case POOL16F:
13473 if (ctx->opcode & 1) {
13474 generate_exception(ctx, EXCP_RI);
13475 } else {
13476 /* MOVEP */
13477 int enc_dest = uMIPS_RD(ctx->opcode);
13478 int enc_rt = uMIPS_RS2(ctx->opcode);
13479 int enc_rs = uMIPS_RS1(ctx->opcode);
13480 int rd, rs, re, rt;
13481 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13482 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13483 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13485 rd = rd_enc[enc_dest];
13486 re = re_enc[enc_dest];
13487 rs = rs_rt_enc[enc_rs];
13488 rt = rs_rt_enc[enc_rt];
13490 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
13491 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
13493 break;
13494 case LBU16:
13496 int rd = mmreg(uMIPS_RD(ctx->opcode));
13497 int rb = mmreg(uMIPS_RS(ctx->opcode));
13498 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13499 offset = (offset == 0xf ? -1 : offset);
13501 gen_ld(ctx, OPC_LBU, rd, rb, offset);
13503 break;
13504 case LHU16:
13506 int rd = mmreg(uMIPS_RD(ctx->opcode));
13507 int rb = mmreg(uMIPS_RS(ctx->opcode));
13508 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13510 gen_ld(ctx, OPC_LHU, rd, rb, offset);
13512 break;
13513 case LWSP16:
13515 int rd = (ctx->opcode >> 5) & 0x1f;
13516 int rb = 29; /* SP */
13517 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
13519 gen_ld(ctx, OPC_LW, rd, rb, offset);
13521 break;
13522 case LW16:
13524 int rd = mmreg(uMIPS_RD(ctx->opcode));
13525 int rb = mmreg(uMIPS_RS(ctx->opcode));
13526 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
13528 gen_ld(ctx, OPC_LW, rd, rb, offset);
13530 break;
13531 case SB16:
13533 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13534 int rb = mmreg(uMIPS_RS(ctx->opcode));
13535 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13537 gen_st(ctx, OPC_SB, rd, rb, offset);
13539 break;
13540 case SH16:
13542 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13543 int rb = mmreg(uMIPS_RS(ctx->opcode));
13544 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13546 gen_st(ctx, OPC_SH, rd, rb, offset);
13548 break;
13549 case SWSP16:
13551 int rd = (ctx->opcode >> 5) & 0x1f;
13552 int rb = 29; /* SP */
13553 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
13555 gen_st(ctx, OPC_SW, rd, rb, offset);
13557 break;
13558 case SW16:
13560 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13561 int rb = mmreg(uMIPS_RS(ctx->opcode));
13562 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
13564 gen_st(ctx, OPC_SW, rd, rb, offset);
13566 break;
13567 case MOVE16:
13569 int rd = uMIPS_RD5(ctx->opcode);
13570 int rs = uMIPS_RS5(ctx->opcode);
13572 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
13574 break;
13575 case ANDI16:
13576 gen_andi16(ctx);
13577 break;
13578 case POOL16D:
13579 switch (ctx->opcode & 0x1) {
13580 case ADDIUS5:
13581 gen_addius5(ctx);
13582 break;
13583 case ADDIUSP:
13584 gen_addiusp(ctx);
13585 break;
13587 break;
13588 case POOL16E:
13589 switch (ctx->opcode & 0x1) {
13590 case ADDIUR2:
13591 gen_addiur2(ctx);
13592 break;
13593 case ADDIUR1SP:
13594 gen_addiur1sp(ctx);
13595 break;
13597 break;
13598 case B16:
13599 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
13600 SIMM(ctx->opcode, 0, 10) << 1, 4);
13601 break;
13602 case BNEZ16:
13603 case BEQZ16:
13604 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
13605 mmreg(uMIPS_RD(ctx->opcode)),
13606 0, SIMM(ctx->opcode, 0, 7) << 1, 4);
13607 break;
13608 case LI16:
13610 int reg = mmreg(uMIPS_RD(ctx->opcode));
13611 int imm = ZIMM(ctx->opcode, 0, 7);
13613 imm = (imm == 0x7f ? -1 : imm);
13614 tcg_gen_movi_tl(cpu_gpr[reg], imm);
13616 break;
13617 case RES_20:
13618 case RES_28:
13619 case RES_29:
13620 case RES_30:
13621 case RES_31:
13622 case RES_38:
13623 case RES_39:
13624 generate_exception(ctx, EXCP_RI);
13625 break;
13626 default:
13627 decode_micromips32_opc (env, ctx, op);
13628 return 4;
13631 return 2;
13634 /* SmartMIPS extension to MIPS32 */
13636 #if defined(TARGET_MIPS64)
13638 /* MDMX extension to MIPS64 */
13640 #endif
13642 /* MIPSDSP functions. */
13643 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
13644 int rd, int base, int offset)
13646 const char *opn = "ldx";
13647 TCGv t0;
13649 check_dsp(ctx);
13650 t0 = tcg_temp_new();
13652 if (base == 0) {
13653 gen_load_gpr(t0, offset);
13654 } else if (offset == 0) {
13655 gen_load_gpr(t0, base);
13656 } else {
13657 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
13660 switch (opc) {
13661 case OPC_LBUX:
13662 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
13663 gen_store_gpr(t0, rd);
13664 opn = "lbux";
13665 break;
13666 case OPC_LHX:
13667 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
13668 gen_store_gpr(t0, rd);
13669 opn = "lhx";
13670 break;
13671 case OPC_LWX:
13672 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
13673 gen_store_gpr(t0, rd);
13674 opn = "lwx";
13675 break;
13676 #if defined(TARGET_MIPS64)
13677 case OPC_LDX:
13678 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
13679 gen_store_gpr(t0, rd);
13680 opn = "ldx";
13681 break;
13682 #endif
13684 (void)opn; /* avoid a compiler warning */
13685 MIPS_DEBUG("%s %s, %s(%s)", opn,
13686 regnames[rd], regnames[offset], regnames[base]);
13687 tcg_temp_free(t0);
13690 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
13691 int ret, int v1, int v2)
13693 const char *opn = "mipsdsp arith";
13694 TCGv v1_t;
13695 TCGv v2_t;
13697 if (ret == 0) {
13698 /* Treat as NOP. */
13699 MIPS_DEBUG("NOP");
13700 return;
13703 v1_t = tcg_temp_new();
13704 v2_t = tcg_temp_new();
13706 gen_load_gpr(v1_t, v1);
13707 gen_load_gpr(v2_t, v2);
13709 switch (op1) {
13710 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
13711 case OPC_MULT_G_2E:
13712 check_dspr2(ctx);
13713 switch (op2) {
13714 case OPC_ADDUH_QB:
13715 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
13716 break;
13717 case OPC_ADDUH_R_QB:
13718 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
13719 break;
13720 case OPC_ADDQH_PH:
13721 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
13722 break;
13723 case OPC_ADDQH_R_PH:
13724 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
13725 break;
13726 case OPC_ADDQH_W:
13727 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
13728 break;
13729 case OPC_ADDQH_R_W:
13730 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
13731 break;
13732 case OPC_SUBUH_QB:
13733 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
13734 break;
13735 case OPC_SUBUH_R_QB:
13736 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
13737 break;
13738 case OPC_SUBQH_PH:
13739 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
13740 break;
13741 case OPC_SUBQH_R_PH:
13742 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
13743 break;
13744 case OPC_SUBQH_W:
13745 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
13746 break;
13747 case OPC_SUBQH_R_W:
13748 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
13749 break;
13751 break;
13752 case OPC_ABSQ_S_PH_DSP:
13753 switch (op2) {
13754 case OPC_ABSQ_S_QB:
13755 check_dspr2(ctx);
13756 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
13757 break;
13758 case OPC_ABSQ_S_PH:
13759 check_dsp(ctx);
13760 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
13761 break;
13762 case OPC_ABSQ_S_W:
13763 check_dsp(ctx);
13764 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
13765 break;
13766 case OPC_PRECEQ_W_PHL:
13767 check_dsp(ctx);
13768 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
13769 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13770 break;
13771 case OPC_PRECEQ_W_PHR:
13772 check_dsp(ctx);
13773 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
13774 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
13775 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13776 break;
13777 case OPC_PRECEQU_PH_QBL:
13778 check_dsp(ctx);
13779 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
13780 break;
13781 case OPC_PRECEQU_PH_QBR:
13782 check_dsp(ctx);
13783 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
13784 break;
13785 case OPC_PRECEQU_PH_QBLA:
13786 check_dsp(ctx);
13787 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
13788 break;
13789 case OPC_PRECEQU_PH_QBRA:
13790 check_dsp(ctx);
13791 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
13792 break;
13793 case OPC_PRECEU_PH_QBL:
13794 check_dsp(ctx);
13795 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
13796 break;
13797 case OPC_PRECEU_PH_QBR:
13798 check_dsp(ctx);
13799 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
13800 break;
13801 case OPC_PRECEU_PH_QBLA:
13802 check_dsp(ctx);
13803 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
13804 break;
13805 case OPC_PRECEU_PH_QBRA:
13806 check_dsp(ctx);
13807 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
13808 break;
13810 break;
13811 case OPC_ADDU_QB_DSP:
13812 switch (op2) {
13813 case OPC_ADDQ_PH:
13814 check_dsp(ctx);
13815 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13816 break;
13817 case OPC_ADDQ_S_PH:
13818 check_dsp(ctx);
13819 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13820 break;
13821 case OPC_ADDQ_S_W:
13822 check_dsp(ctx);
13823 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13824 break;
13825 case OPC_ADDU_QB:
13826 check_dsp(ctx);
13827 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13828 break;
13829 case OPC_ADDU_S_QB:
13830 check_dsp(ctx);
13831 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13832 break;
13833 case OPC_ADDU_PH:
13834 check_dspr2(ctx);
13835 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13836 break;
13837 case OPC_ADDU_S_PH:
13838 check_dspr2(ctx);
13839 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13840 break;
13841 case OPC_SUBQ_PH:
13842 check_dsp(ctx);
13843 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13844 break;
13845 case OPC_SUBQ_S_PH:
13846 check_dsp(ctx);
13847 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13848 break;
13849 case OPC_SUBQ_S_W:
13850 check_dsp(ctx);
13851 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13852 break;
13853 case OPC_SUBU_QB:
13854 check_dsp(ctx);
13855 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13856 break;
13857 case OPC_SUBU_S_QB:
13858 check_dsp(ctx);
13859 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13860 break;
13861 case OPC_SUBU_PH:
13862 check_dspr2(ctx);
13863 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13864 break;
13865 case OPC_SUBU_S_PH:
13866 check_dspr2(ctx);
13867 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13868 break;
13869 case OPC_ADDSC:
13870 check_dsp(ctx);
13871 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13872 break;
13873 case OPC_ADDWC:
13874 check_dsp(ctx);
13875 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13876 break;
13877 case OPC_MODSUB:
13878 check_dsp(ctx);
13879 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
13880 break;
13881 case OPC_RADDU_W_QB:
13882 check_dsp(ctx);
13883 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
13884 break;
13886 break;
13887 case OPC_CMPU_EQ_QB_DSP:
13888 switch (op2) {
13889 case OPC_PRECR_QB_PH:
13890 check_dspr2(ctx);
13891 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
13892 break;
13893 case OPC_PRECRQ_QB_PH:
13894 check_dsp(ctx);
13895 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
13896 break;
13897 case OPC_PRECR_SRA_PH_W:
13898 check_dspr2(ctx);
13900 TCGv_i32 sa_t = tcg_const_i32(v2);
13901 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
13902 cpu_gpr[ret]);
13903 tcg_temp_free_i32(sa_t);
13904 break;
13906 case OPC_PRECR_SRA_R_PH_W:
13907 check_dspr2(ctx);
13909 TCGv_i32 sa_t = tcg_const_i32(v2);
13910 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
13911 cpu_gpr[ret]);
13912 tcg_temp_free_i32(sa_t);
13913 break;
13915 case OPC_PRECRQ_PH_W:
13916 check_dsp(ctx);
13917 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
13918 break;
13919 case OPC_PRECRQ_RS_PH_W:
13920 check_dsp(ctx);
13921 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13922 break;
13923 case OPC_PRECRQU_S_QB_PH:
13924 check_dsp(ctx);
13925 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13926 break;
13928 break;
13929 #ifdef TARGET_MIPS64
13930 case OPC_ABSQ_S_QH_DSP:
13931 switch (op2) {
13932 case OPC_PRECEQ_L_PWL:
13933 check_dsp(ctx);
13934 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
13935 break;
13936 case OPC_PRECEQ_L_PWR:
13937 check_dsp(ctx);
13938 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
13939 break;
13940 case OPC_PRECEQ_PW_QHL:
13941 check_dsp(ctx);
13942 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
13943 break;
13944 case OPC_PRECEQ_PW_QHR:
13945 check_dsp(ctx);
13946 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
13947 break;
13948 case OPC_PRECEQ_PW_QHLA:
13949 check_dsp(ctx);
13950 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
13951 break;
13952 case OPC_PRECEQ_PW_QHRA:
13953 check_dsp(ctx);
13954 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
13955 break;
13956 case OPC_PRECEQU_QH_OBL:
13957 check_dsp(ctx);
13958 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
13959 break;
13960 case OPC_PRECEQU_QH_OBR:
13961 check_dsp(ctx);
13962 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
13963 break;
13964 case OPC_PRECEQU_QH_OBLA:
13965 check_dsp(ctx);
13966 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
13967 break;
13968 case OPC_PRECEQU_QH_OBRA:
13969 check_dsp(ctx);
13970 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
13971 break;
13972 case OPC_PRECEU_QH_OBL:
13973 check_dsp(ctx);
13974 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
13975 break;
13976 case OPC_PRECEU_QH_OBR:
13977 check_dsp(ctx);
13978 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
13979 break;
13980 case OPC_PRECEU_QH_OBLA:
13981 check_dsp(ctx);
13982 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
13983 break;
13984 case OPC_PRECEU_QH_OBRA:
13985 check_dsp(ctx);
13986 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
13987 break;
13988 case OPC_ABSQ_S_OB:
13989 check_dspr2(ctx);
13990 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
13991 break;
13992 case OPC_ABSQ_S_PW:
13993 check_dsp(ctx);
13994 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
13995 break;
13996 case OPC_ABSQ_S_QH:
13997 check_dsp(ctx);
13998 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
13999 break;
14001 break;
14002 case OPC_ADDU_OB_DSP:
14003 switch (op2) {
14004 case OPC_RADDU_L_OB:
14005 check_dsp(ctx);
14006 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
14007 break;
14008 case OPC_SUBQ_PW:
14009 check_dsp(ctx);
14010 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14011 break;
14012 case OPC_SUBQ_S_PW:
14013 check_dsp(ctx);
14014 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14015 break;
14016 case OPC_SUBQ_QH:
14017 check_dsp(ctx);
14018 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14019 break;
14020 case OPC_SUBQ_S_QH:
14021 check_dsp(ctx);
14022 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14023 break;
14024 case OPC_SUBU_OB:
14025 check_dsp(ctx);
14026 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14027 break;
14028 case OPC_SUBU_S_OB:
14029 check_dsp(ctx);
14030 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14031 break;
14032 case OPC_SUBU_QH:
14033 check_dspr2(ctx);
14034 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14035 break;
14036 case OPC_SUBU_S_QH:
14037 check_dspr2(ctx);
14038 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14039 break;
14040 case OPC_SUBUH_OB:
14041 check_dspr2(ctx);
14042 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
14043 break;
14044 case OPC_SUBUH_R_OB:
14045 check_dspr2(ctx);
14046 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14047 break;
14048 case OPC_ADDQ_PW:
14049 check_dsp(ctx);
14050 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14051 break;
14052 case OPC_ADDQ_S_PW:
14053 check_dsp(ctx);
14054 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14055 break;
14056 case OPC_ADDQ_QH:
14057 check_dsp(ctx);
14058 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14059 break;
14060 case OPC_ADDQ_S_QH:
14061 check_dsp(ctx);
14062 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14063 break;
14064 case OPC_ADDU_OB:
14065 check_dsp(ctx);
14066 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14067 break;
14068 case OPC_ADDU_S_OB:
14069 check_dsp(ctx);
14070 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14071 break;
14072 case OPC_ADDU_QH:
14073 check_dspr2(ctx);
14074 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14075 break;
14076 case OPC_ADDU_S_QH:
14077 check_dspr2(ctx);
14078 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14079 break;
14080 case OPC_ADDUH_OB:
14081 check_dspr2(ctx);
14082 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
14083 break;
14084 case OPC_ADDUH_R_OB:
14085 check_dspr2(ctx);
14086 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14087 break;
14089 break;
14090 case OPC_CMPU_EQ_OB_DSP:
14091 switch (op2) {
14092 case OPC_PRECR_OB_QH:
14093 check_dspr2(ctx);
14094 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14095 break;
14096 case OPC_PRECR_SRA_QH_PW:
14097 check_dspr2(ctx);
14099 TCGv_i32 ret_t = tcg_const_i32(ret);
14100 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
14101 tcg_temp_free_i32(ret_t);
14102 break;
14104 case OPC_PRECR_SRA_R_QH_PW:
14105 check_dspr2(ctx);
14107 TCGv_i32 sa_v = tcg_const_i32(ret);
14108 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
14109 tcg_temp_free_i32(sa_v);
14110 break;
14112 case OPC_PRECRQ_OB_QH:
14113 check_dsp(ctx);
14114 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14115 break;
14116 case OPC_PRECRQ_PW_L:
14117 check_dsp(ctx);
14118 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
14119 break;
14120 case OPC_PRECRQ_QH_PW:
14121 check_dsp(ctx);
14122 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
14123 break;
14124 case OPC_PRECRQ_RS_QH_PW:
14125 check_dsp(ctx);
14126 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14127 break;
14128 case OPC_PRECRQU_S_OB_QH:
14129 check_dsp(ctx);
14130 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14131 break;
14133 break;
14134 #endif
14137 tcg_temp_free(v1_t);
14138 tcg_temp_free(v2_t);
14140 (void)opn; /* avoid a compiler warning */
14141 MIPS_DEBUG("%s", opn);
14144 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
14145 int ret, int v1, int v2)
14147 uint32_t op2;
14148 const char *opn = "mipsdsp shift";
14149 TCGv t0;
14150 TCGv v1_t;
14151 TCGv v2_t;
14153 if (ret == 0) {
14154 /* Treat as NOP. */
14155 MIPS_DEBUG("NOP");
14156 return;
14159 t0 = tcg_temp_new();
14160 v1_t = tcg_temp_new();
14161 v2_t = tcg_temp_new();
14163 tcg_gen_movi_tl(t0, v1);
14164 gen_load_gpr(v1_t, v1);
14165 gen_load_gpr(v2_t, v2);
14167 switch (opc) {
14168 case OPC_SHLL_QB_DSP:
14170 op2 = MASK_SHLL_QB(ctx->opcode);
14171 switch (op2) {
14172 case OPC_SHLL_QB:
14173 check_dsp(ctx);
14174 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
14175 break;
14176 case OPC_SHLLV_QB:
14177 check_dsp(ctx);
14178 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14179 break;
14180 case OPC_SHLL_PH:
14181 check_dsp(ctx);
14182 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14183 break;
14184 case OPC_SHLLV_PH:
14185 check_dsp(ctx);
14186 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14187 break;
14188 case OPC_SHLL_S_PH:
14189 check_dsp(ctx);
14190 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14191 break;
14192 case OPC_SHLLV_S_PH:
14193 check_dsp(ctx);
14194 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14195 break;
14196 case OPC_SHLL_S_W:
14197 check_dsp(ctx);
14198 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
14199 break;
14200 case OPC_SHLLV_S_W:
14201 check_dsp(ctx);
14202 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14203 break;
14204 case OPC_SHRL_QB:
14205 check_dsp(ctx);
14206 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
14207 break;
14208 case OPC_SHRLV_QB:
14209 check_dsp(ctx);
14210 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
14211 break;
14212 case OPC_SHRL_PH:
14213 check_dspr2(ctx);
14214 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
14215 break;
14216 case OPC_SHRLV_PH:
14217 check_dspr2(ctx);
14218 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
14219 break;
14220 case OPC_SHRA_QB:
14221 check_dspr2(ctx);
14222 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
14223 break;
14224 case OPC_SHRA_R_QB:
14225 check_dspr2(ctx);
14226 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
14227 break;
14228 case OPC_SHRAV_QB:
14229 check_dspr2(ctx);
14230 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
14231 break;
14232 case OPC_SHRAV_R_QB:
14233 check_dspr2(ctx);
14234 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
14235 break;
14236 case OPC_SHRA_PH:
14237 check_dsp(ctx);
14238 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
14239 break;
14240 case OPC_SHRA_R_PH:
14241 check_dsp(ctx);
14242 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
14243 break;
14244 case OPC_SHRAV_PH:
14245 check_dsp(ctx);
14246 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
14247 break;
14248 case OPC_SHRAV_R_PH:
14249 check_dsp(ctx);
14250 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
14251 break;
14252 case OPC_SHRA_R_W:
14253 check_dsp(ctx);
14254 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
14255 break;
14256 case OPC_SHRAV_R_W:
14257 check_dsp(ctx);
14258 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
14259 break;
14260 default: /* Invalid */
14261 MIPS_INVAL("MASK SHLL.QB");
14262 generate_exception(ctx, EXCP_RI);
14263 break;
14265 break;
14267 #ifdef TARGET_MIPS64
14268 case OPC_SHLL_OB_DSP:
14269 op2 = MASK_SHLL_OB(ctx->opcode);
14270 switch (op2) {
14271 case OPC_SHLL_PW:
14272 check_dsp(ctx);
14273 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14274 break;
14275 case OPC_SHLLV_PW:
14276 check_dsp(ctx);
14277 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14278 break;
14279 case OPC_SHLL_S_PW:
14280 check_dsp(ctx);
14281 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14282 break;
14283 case OPC_SHLLV_S_PW:
14284 check_dsp(ctx);
14285 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14286 break;
14287 case OPC_SHLL_OB:
14288 check_dsp(ctx);
14289 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
14290 break;
14291 case OPC_SHLLV_OB:
14292 check_dsp(ctx);
14293 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14294 break;
14295 case OPC_SHLL_QH:
14296 check_dsp(ctx);
14297 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14298 break;
14299 case OPC_SHLLV_QH:
14300 check_dsp(ctx);
14301 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14302 break;
14303 case OPC_SHLL_S_QH:
14304 check_dsp(ctx);
14305 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14306 break;
14307 case OPC_SHLLV_S_QH:
14308 check_dsp(ctx);
14309 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14310 break;
14311 case OPC_SHRA_OB:
14312 check_dspr2(ctx);
14313 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
14314 break;
14315 case OPC_SHRAV_OB:
14316 check_dspr2(ctx);
14317 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
14318 break;
14319 case OPC_SHRA_R_OB:
14320 check_dspr2(ctx);
14321 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
14322 break;
14323 case OPC_SHRAV_R_OB:
14324 check_dspr2(ctx);
14325 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
14326 break;
14327 case OPC_SHRA_PW:
14328 check_dsp(ctx);
14329 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
14330 break;
14331 case OPC_SHRAV_PW:
14332 check_dsp(ctx);
14333 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
14334 break;
14335 case OPC_SHRA_R_PW:
14336 check_dsp(ctx);
14337 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
14338 break;
14339 case OPC_SHRAV_R_PW:
14340 check_dsp(ctx);
14341 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
14342 break;
14343 case OPC_SHRA_QH:
14344 check_dsp(ctx);
14345 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
14346 break;
14347 case OPC_SHRAV_QH:
14348 check_dsp(ctx);
14349 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
14350 break;
14351 case OPC_SHRA_R_QH:
14352 check_dsp(ctx);
14353 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
14354 break;
14355 case OPC_SHRAV_R_QH:
14356 check_dsp(ctx);
14357 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
14358 break;
14359 case OPC_SHRL_OB:
14360 check_dsp(ctx);
14361 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
14362 break;
14363 case OPC_SHRLV_OB:
14364 check_dsp(ctx);
14365 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
14366 break;
14367 case OPC_SHRL_QH:
14368 check_dspr2(ctx);
14369 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
14370 break;
14371 case OPC_SHRLV_QH:
14372 check_dspr2(ctx);
14373 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
14374 break;
14375 default: /* Invalid */
14376 MIPS_INVAL("MASK SHLL.OB");
14377 generate_exception(ctx, EXCP_RI);
14378 break;
14380 break;
14381 #endif
14384 tcg_temp_free(t0);
14385 tcg_temp_free(v1_t);
14386 tcg_temp_free(v2_t);
14387 (void)opn; /* avoid a compiler warning */
14388 MIPS_DEBUG("%s", opn);
14391 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
14392 int ret, int v1, int v2, int check_ret)
14394 const char *opn = "mipsdsp multiply";
14395 TCGv_i32 t0;
14396 TCGv v1_t;
14397 TCGv v2_t;
14399 if ((ret == 0) && (check_ret == 1)) {
14400 /* Treat as NOP. */
14401 MIPS_DEBUG("NOP");
14402 return;
14405 t0 = tcg_temp_new_i32();
14406 v1_t = tcg_temp_new();
14407 v2_t = tcg_temp_new();
14409 tcg_gen_movi_i32(t0, ret);
14410 gen_load_gpr(v1_t, v1);
14411 gen_load_gpr(v2_t, v2);
14413 switch (op1) {
14414 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14415 * the same mask and op1. */
14416 case OPC_MULT_G_2E:
14417 check_dspr2(ctx);
14418 switch (op2) {
14419 case OPC_MUL_PH:
14420 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14421 break;
14422 case OPC_MUL_S_PH:
14423 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14424 break;
14425 case OPC_MULQ_S_W:
14426 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14427 break;
14428 case OPC_MULQ_RS_W:
14429 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14430 break;
14432 break;
14433 case OPC_DPA_W_PH_DSP:
14434 switch (op2) {
14435 case OPC_DPAU_H_QBL:
14436 check_dsp(ctx);
14437 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
14438 break;
14439 case OPC_DPAU_H_QBR:
14440 check_dsp(ctx);
14441 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
14442 break;
14443 case OPC_DPSU_H_QBL:
14444 check_dsp(ctx);
14445 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
14446 break;
14447 case OPC_DPSU_H_QBR:
14448 check_dsp(ctx);
14449 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
14450 break;
14451 case OPC_DPA_W_PH:
14452 check_dspr2(ctx);
14453 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
14454 break;
14455 case OPC_DPAX_W_PH:
14456 check_dspr2(ctx);
14457 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
14458 break;
14459 case OPC_DPAQ_S_W_PH:
14460 check_dsp(ctx);
14461 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14462 break;
14463 case OPC_DPAQX_S_W_PH:
14464 check_dspr2(ctx);
14465 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14466 break;
14467 case OPC_DPAQX_SA_W_PH:
14468 check_dspr2(ctx);
14469 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14470 break;
14471 case OPC_DPS_W_PH:
14472 check_dspr2(ctx);
14473 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
14474 break;
14475 case OPC_DPSX_W_PH:
14476 check_dspr2(ctx);
14477 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
14478 break;
14479 case OPC_DPSQ_S_W_PH:
14480 check_dsp(ctx);
14481 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14482 break;
14483 case OPC_DPSQX_S_W_PH:
14484 check_dspr2(ctx);
14485 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14486 break;
14487 case OPC_DPSQX_SA_W_PH:
14488 check_dspr2(ctx);
14489 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14490 break;
14491 case OPC_MULSAQ_S_W_PH:
14492 check_dsp(ctx);
14493 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14494 break;
14495 case OPC_DPAQ_SA_L_W:
14496 check_dsp(ctx);
14497 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14498 break;
14499 case OPC_DPSQ_SA_L_W:
14500 check_dsp(ctx);
14501 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14502 break;
14503 case OPC_MAQ_S_W_PHL:
14504 check_dsp(ctx);
14505 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
14506 break;
14507 case OPC_MAQ_S_W_PHR:
14508 check_dsp(ctx);
14509 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
14510 break;
14511 case OPC_MAQ_SA_W_PHL:
14512 check_dsp(ctx);
14513 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
14514 break;
14515 case OPC_MAQ_SA_W_PHR:
14516 check_dsp(ctx);
14517 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
14518 break;
14519 case OPC_MULSA_W_PH:
14520 check_dspr2(ctx);
14521 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
14522 break;
14524 break;
14525 #ifdef TARGET_MIPS64
14526 case OPC_DPAQ_W_QH_DSP:
14528 int ac = ret & 0x03;
14529 tcg_gen_movi_i32(t0, ac);
14531 switch (op2) {
14532 case OPC_DMADD:
14533 check_dsp(ctx);
14534 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
14535 break;
14536 case OPC_DMADDU:
14537 check_dsp(ctx);
14538 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
14539 break;
14540 case OPC_DMSUB:
14541 check_dsp(ctx);
14542 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
14543 break;
14544 case OPC_DMSUBU:
14545 check_dsp(ctx);
14546 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
14547 break;
14548 case OPC_DPA_W_QH:
14549 check_dspr2(ctx);
14550 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
14551 break;
14552 case OPC_DPAQ_S_W_QH:
14553 check_dsp(ctx);
14554 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14555 break;
14556 case OPC_DPAQ_SA_L_PW:
14557 check_dsp(ctx);
14558 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
14559 break;
14560 case OPC_DPAU_H_OBL:
14561 check_dsp(ctx);
14562 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
14563 break;
14564 case OPC_DPAU_H_OBR:
14565 check_dsp(ctx);
14566 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
14567 break;
14568 case OPC_DPS_W_QH:
14569 check_dspr2(ctx);
14570 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
14571 break;
14572 case OPC_DPSQ_S_W_QH:
14573 check_dsp(ctx);
14574 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14575 break;
14576 case OPC_DPSQ_SA_L_PW:
14577 check_dsp(ctx);
14578 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
14579 break;
14580 case OPC_DPSU_H_OBL:
14581 check_dsp(ctx);
14582 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
14583 break;
14584 case OPC_DPSU_H_OBR:
14585 check_dsp(ctx);
14586 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
14587 break;
14588 case OPC_MAQ_S_L_PWL:
14589 check_dsp(ctx);
14590 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
14591 break;
14592 case OPC_MAQ_S_L_PWR:
14593 check_dsp(ctx);
14594 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
14595 break;
14596 case OPC_MAQ_S_W_QHLL:
14597 check_dsp(ctx);
14598 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
14599 break;
14600 case OPC_MAQ_SA_W_QHLL:
14601 check_dsp(ctx);
14602 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
14603 break;
14604 case OPC_MAQ_S_W_QHLR:
14605 check_dsp(ctx);
14606 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
14607 break;
14608 case OPC_MAQ_SA_W_QHLR:
14609 check_dsp(ctx);
14610 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
14611 break;
14612 case OPC_MAQ_S_W_QHRL:
14613 check_dsp(ctx);
14614 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
14615 break;
14616 case OPC_MAQ_SA_W_QHRL:
14617 check_dsp(ctx);
14618 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
14619 break;
14620 case OPC_MAQ_S_W_QHRR:
14621 check_dsp(ctx);
14622 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
14623 break;
14624 case OPC_MAQ_SA_W_QHRR:
14625 check_dsp(ctx);
14626 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
14627 break;
14628 case OPC_MULSAQ_S_L_PW:
14629 check_dsp(ctx);
14630 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
14631 break;
14632 case OPC_MULSAQ_S_W_QH:
14633 check_dsp(ctx);
14634 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14635 break;
14638 break;
14639 #endif
14640 case OPC_ADDU_QB_DSP:
14641 switch (op2) {
14642 case OPC_MULEU_S_PH_QBL:
14643 check_dsp(ctx);
14644 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14645 break;
14646 case OPC_MULEU_S_PH_QBR:
14647 check_dsp(ctx);
14648 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14649 break;
14650 case OPC_MULQ_RS_PH:
14651 check_dsp(ctx);
14652 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14653 break;
14654 case OPC_MULEQ_S_W_PHL:
14655 check_dsp(ctx);
14656 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14657 break;
14658 case OPC_MULEQ_S_W_PHR:
14659 check_dsp(ctx);
14660 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14661 break;
14662 case OPC_MULQ_S_PH:
14663 check_dspr2(ctx);
14664 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14665 break;
14667 break;
14668 #ifdef TARGET_MIPS64
14669 case OPC_ADDU_OB_DSP:
14670 switch (op2) {
14671 case OPC_MULEQ_S_PW_QHL:
14672 check_dsp(ctx);
14673 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14674 break;
14675 case OPC_MULEQ_S_PW_QHR:
14676 check_dsp(ctx);
14677 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14678 break;
14679 case OPC_MULEU_S_QH_OBL:
14680 check_dsp(ctx);
14681 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14682 break;
14683 case OPC_MULEU_S_QH_OBR:
14684 check_dsp(ctx);
14685 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14686 break;
14687 case OPC_MULQ_RS_QH:
14688 check_dsp(ctx);
14689 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14690 break;
14692 break;
14693 #endif
14696 tcg_temp_free_i32(t0);
14697 tcg_temp_free(v1_t);
14698 tcg_temp_free(v2_t);
14700 (void)opn; /* avoid a compiler warning */
14701 MIPS_DEBUG("%s", opn);
14705 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
14706 int ret, int val)
14708 const char *opn = "mipsdsp Bit/ Manipulation";
14709 int16_t imm;
14710 TCGv t0;
14711 TCGv val_t;
14713 if (ret == 0) {
14714 /* Treat as NOP. */
14715 MIPS_DEBUG("NOP");
14716 return;
14719 t0 = tcg_temp_new();
14720 val_t = tcg_temp_new();
14721 gen_load_gpr(val_t, val);
14723 switch (op1) {
14724 case OPC_ABSQ_S_PH_DSP:
14725 switch (op2) {
14726 case OPC_BITREV:
14727 check_dsp(ctx);
14728 gen_helper_bitrev(cpu_gpr[ret], val_t);
14729 break;
14730 case OPC_REPL_QB:
14731 check_dsp(ctx);
14733 target_long result;
14734 imm = (ctx->opcode >> 16) & 0xFF;
14735 result = (uint32_t)imm << 24 |
14736 (uint32_t)imm << 16 |
14737 (uint32_t)imm << 8 |
14738 (uint32_t)imm;
14739 result = (int32_t)result;
14740 tcg_gen_movi_tl(cpu_gpr[ret], result);
14742 break;
14743 case OPC_REPLV_QB:
14744 check_dsp(ctx);
14745 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
14746 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
14747 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14748 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14749 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14750 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14751 break;
14752 case OPC_REPL_PH:
14753 check_dsp(ctx);
14755 imm = (ctx->opcode >> 16) & 0x03FF;
14756 imm = (int16_t)(imm << 6) >> 6;
14757 tcg_gen_movi_tl(cpu_gpr[ret], \
14758 (target_long)((int32_t)imm << 16 | \
14759 (uint16_t)imm));
14761 break;
14762 case OPC_REPLV_PH:
14763 check_dsp(ctx);
14764 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
14765 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14766 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14767 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14768 break;
14770 break;
14771 #ifdef TARGET_MIPS64
14772 case OPC_ABSQ_S_QH_DSP:
14773 switch (op2) {
14774 case OPC_REPL_OB:
14775 check_dsp(ctx);
14777 target_long temp;
14779 imm = (ctx->opcode >> 16) & 0xFF;
14780 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
14781 temp = (temp << 16) | temp;
14782 temp = (temp << 32) | temp;
14783 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14784 break;
14786 case OPC_REPL_PW:
14787 check_dsp(ctx);
14789 target_long temp;
14791 imm = (ctx->opcode >> 16) & 0x03FF;
14792 imm = (int16_t)(imm << 6) >> 6;
14793 temp = ((target_long)imm << 32) \
14794 | ((target_long)imm & 0xFFFFFFFF);
14795 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14796 break;
14798 case OPC_REPL_QH:
14799 check_dsp(ctx);
14801 target_long temp;
14803 imm = (ctx->opcode >> 16) & 0x03FF;
14804 imm = (int16_t)(imm << 6) >> 6;
14806 temp = ((uint64_t)(uint16_t)imm << 48) |
14807 ((uint64_t)(uint16_t)imm << 32) |
14808 ((uint64_t)(uint16_t)imm << 16) |
14809 (uint64_t)(uint16_t)imm;
14810 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14811 break;
14813 case OPC_REPLV_OB:
14814 check_dsp(ctx);
14815 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
14816 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
14817 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14818 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14819 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14820 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14821 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14822 break;
14823 case OPC_REPLV_PW:
14824 check_dsp(ctx);
14825 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
14826 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14827 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14828 break;
14829 case OPC_REPLV_QH:
14830 check_dsp(ctx);
14831 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
14832 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14833 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14834 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14835 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14836 break;
14838 break;
14839 #endif
14841 tcg_temp_free(t0);
14842 tcg_temp_free(val_t);
14844 (void)opn; /* avoid a compiler warning */
14845 MIPS_DEBUG("%s", opn);
14848 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
14849 uint32_t op1, uint32_t op2,
14850 int ret, int v1, int v2, int check_ret)
14852 const char *opn = "mipsdsp add compare pick";
14853 TCGv t1;
14854 TCGv v1_t;
14855 TCGv v2_t;
14857 if ((ret == 0) && (check_ret == 1)) {
14858 /* Treat as NOP. */
14859 MIPS_DEBUG("NOP");
14860 return;
14863 t1 = tcg_temp_new();
14864 v1_t = tcg_temp_new();
14865 v2_t = tcg_temp_new();
14867 gen_load_gpr(v1_t, v1);
14868 gen_load_gpr(v2_t, v2);
14870 switch (op1) {
14871 case OPC_CMPU_EQ_QB_DSP:
14872 switch (op2) {
14873 case OPC_CMPU_EQ_QB:
14874 check_dsp(ctx);
14875 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
14876 break;
14877 case OPC_CMPU_LT_QB:
14878 check_dsp(ctx);
14879 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
14880 break;
14881 case OPC_CMPU_LE_QB:
14882 check_dsp(ctx);
14883 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
14884 break;
14885 case OPC_CMPGU_EQ_QB:
14886 check_dsp(ctx);
14887 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
14888 break;
14889 case OPC_CMPGU_LT_QB:
14890 check_dsp(ctx);
14891 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
14892 break;
14893 case OPC_CMPGU_LE_QB:
14894 check_dsp(ctx);
14895 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
14896 break;
14897 case OPC_CMPGDU_EQ_QB:
14898 check_dspr2(ctx);
14899 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
14900 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14901 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14902 tcg_gen_shli_tl(t1, t1, 24);
14903 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14904 break;
14905 case OPC_CMPGDU_LT_QB:
14906 check_dspr2(ctx);
14907 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
14908 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14909 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14910 tcg_gen_shli_tl(t1, t1, 24);
14911 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14912 break;
14913 case OPC_CMPGDU_LE_QB:
14914 check_dspr2(ctx);
14915 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
14916 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14917 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14918 tcg_gen_shli_tl(t1, t1, 24);
14919 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14920 break;
14921 case OPC_CMP_EQ_PH:
14922 check_dsp(ctx);
14923 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
14924 break;
14925 case OPC_CMP_LT_PH:
14926 check_dsp(ctx);
14927 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
14928 break;
14929 case OPC_CMP_LE_PH:
14930 check_dsp(ctx);
14931 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
14932 break;
14933 case OPC_PICK_QB:
14934 check_dsp(ctx);
14935 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14936 break;
14937 case OPC_PICK_PH:
14938 check_dsp(ctx);
14939 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14940 break;
14941 case OPC_PACKRL_PH:
14942 check_dsp(ctx);
14943 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
14944 break;
14946 break;
14947 #ifdef TARGET_MIPS64
14948 case OPC_CMPU_EQ_OB_DSP:
14949 switch (op2) {
14950 case OPC_CMP_EQ_PW:
14951 check_dsp(ctx);
14952 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
14953 break;
14954 case OPC_CMP_LT_PW:
14955 check_dsp(ctx);
14956 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
14957 break;
14958 case OPC_CMP_LE_PW:
14959 check_dsp(ctx);
14960 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
14961 break;
14962 case OPC_CMP_EQ_QH:
14963 check_dsp(ctx);
14964 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
14965 break;
14966 case OPC_CMP_LT_QH:
14967 check_dsp(ctx);
14968 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
14969 break;
14970 case OPC_CMP_LE_QH:
14971 check_dsp(ctx);
14972 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
14973 break;
14974 case OPC_CMPGDU_EQ_OB:
14975 check_dspr2(ctx);
14976 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14977 break;
14978 case OPC_CMPGDU_LT_OB:
14979 check_dspr2(ctx);
14980 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14981 break;
14982 case OPC_CMPGDU_LE_OB:
14983 check_dspr2(ctx);
14984 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14985 break;
14986 case OPC_CMPGU_EQ_OB:
14987 check_dsp(ctx);
14988 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
14989 break;
14990 case OPC_CMPGU_LT_OB:
14991 check_dsp(ctx);
14992 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
14993 break;
14994 case OPC_CMPGU_LE_OB:
14995 check_dsp(ctx);
14996 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
14997 break;
14998 case OPC_CMPU_EQ_OB:
14999 check_dsp(ctx);
15000 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
15001 break;
15002 case OPC_CMPU_LT_OB:
15003 check_dsp(ctx);
15004 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
15005 break;
15006 case OPC_CMPU_LE_OB:
15007 check_dsp(ctx);
15008 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
15009 break;
15010 case OPC_PACKRL_PW:
15011 check_dsp(ctx);
15012 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
15013 break;
15014 case OPC_PICK_OB:
15015 check_dsp(ctx);
15016 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15017 break;
15018 case OPC_PICK_PW:
15019 check_dsp(ctx);
15020 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15021 break;
15022 case OPC_PICK_QH:
15023 check_dsp(ctx);
15024 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15025 break;
15027 break;
15028 #endif
15031 tcg_temp_free(t1);
15032 tcg_temp_free(v1_t);
15033 tcg_temp_free(v2_t);
15035 (void)opn; /* avoid a compiler warning */
15036 MIPS_DEBUG("%s", opn);
15039 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
15040 uint32_t op1, int rt, int rs, int sa)
15042 const char *opn = "mipsdsp append/dappend";
15043 TCGv t0;
15045 check_dspr2(ctx);
15047 if (rt == 0) {
15048 /* Treat as NOP. */
15049 MIPS_DEBUG("NOP");
15050 return;
15053 t0 = tcg_temp_new();
15054 gen_load_gpr(t0, rs);
15056 switch (op1) {
15057 case OPC_APPEND_DSP:
15058 switch (MASK_APPEND(ctx->opcode)) {
15059 case OPC_APPEND:
15060 if (sa != 0) {
15061 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
15063 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15064 break;
15065 case OPC_PREPEND:
15066 if (sa != 0) {
15067 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
15068 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15069 tcg_gen_shli_tl(t0, t0, 32 - sa);
15070 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15072 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15073 break;
15074 case OPC_BALIGN:
15075 sa &= 3;
15076 if (sa != 0 && sa != 2) {
15077 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15078 tcg_gen_ext32u_tl(t0, t0);
15079 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
15080 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15082 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15083 break;
15084 default: /* Invalid */
15085 MIPS_INVAL("MASK APPEND");
15086 generate_exception(ctx, EXCP_RI);
15087 break;
15089 break;
15090 #ifdef TARGET_MIPS64
15091 case OPC_DAPPEND_DSP:
15092 switch (MASK_DAPPEND(ctx->opcode)) {
15093 case OPC_DAPPEND:
15094 if (sa != 0) {
15095 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
15097 break;
15098 case OPC_PREPENDD:
15099 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
15100 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
15101 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
15102 break;
15103 case OPC_PREPENDW:
15104 if (sa != 0) {
15105 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15106 tcg_gen_shli_tl(t0, t0, 64 - sa);
15107 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15109 break;
15110 case OPC_DBALIGN:
15111 sa &= 7;
15112 if (sa != 0 && sa != 2 && sa != 4) {
15113 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15114 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
15115 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15117 break;
15118 default: /* Invalid */
15119 MIPS_INVAL("MASK DAPPEND");
15120 generate_exception(ctx, EXCP_RI);
15121 break;
15123 break;
15124 #endif
15126 tcg_temp_free(t0);
15127 (void)opn; /* avoid a compiler warning */
15128 MIPS_DEBUG("%s", opn);
15131 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15132 int ret, int v1, int v2, int check_ret)
15135 const char *opn = "mipsdsp accumulator";
15136 TCGv t0;
15137 TCGv t1;
15138 TCGv v1_t;
15139 TCGv v2_t;
15140 int16_t imm;
15142 if ((ret == 0) && (check_ret == 1)) {
15143 /* Treat as NOP. */
15144 MIPS_DEBUG("NOP");
15145 return;
15148 t0 = tcg_temp_new();
15149 t1 = tcg_temp_new();
15150 v1_t = tcg_temp_new();
15151 v2_t = tcg_temp_new();
15153 gen_load_gpr(v1_t, v1);
15154 gen_load_gpr(v2_t, v2);
15156 switch (op1) {
15157 case OPC_EXTR_W_DSP:
15158 check_dsp(ctx);
15159 switch (op2) {
15160 case OPC_EXTR_W:
15161 tcg_gen_movi_tl(t0, v2);
15162 tcg_gen_movi_tl(t1, v1);
15163 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
15164 break;
15165 case OPC_EXTR_R_W:
15166 tcg_gen_movi_tl(t0, v2);
15167 tcg_gen_movi_tl(t1, v1);
15168 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15169 break;
15170 case OPC_EXTR_RS_W:
15171 tcg_gen_movi_tl(t0, v2);
15172 tcg_gen_movi_tl(t1, v1);
15173 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15174 break;
15175 case OPC_EXTR_S_H:
15176 tcg_gen_movi_tl(t0, v2);
15177 tcg_gen_movi_tl(t1, v1);
15178 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15179 break;
15180 case OPC_EXTRV_S_H:
15181 tcg_gen_movi_tl(t0, v2);
15182 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
15183 break;
15184 case OPC_EXTRV_W:
15185 tcg_gen_movi_tl(t0, v2);
15186 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15187 break;
15188 case OPC_EXTRV_R_W:
15189 tcg_gen_movi_tl(t0, v2);
15190 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15191 break;
15192 case OPC_EXTRV_RS_W:
15193 tcg_gen_movi_tl(t0, v2);
15194 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15195 break;
15196 case OPC_EXTP:
15197 tcg_gen_movi_tl(t0, v2);
15198 tcg_gen_movi_tl(t1, v1);
15199 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
15200 break;
15201 case OPC_EXTPV:
15202 tcg_gen_movi_tl(t0, v2);
15203 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
15204 break;
15205 case OPC_EXTPDP:
15206 tcg_gen_movi_tl(t0, v2);
15207 tcg_gen_movi_tl(t1, v1);
15208 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
15209 break;
15210 case OPC_EXTPDPV:
15211 tcg_gen_movi_tl(t0, v2);
15212 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15213 break;
15214 case OPC_SHILO:
15215 imm = (ctx->opcode >> 20) & 0x3F;
15216 tcg_gen_movi_tl(t0, ret);
15217 tcg_gen_movi_tl(t1, imm);
15218 gen_helper_shilo(t0, t1, cpu_env);
15219 break;
15220 case OPC_SHILOV:
15221 tcg_gen_movi_tl(t0, ret);
15222 gen_helper_shilo(t0, v1_t, cpu_env);
15223 break;
15224 case OPC_MTHLIP:
15225 tcg_gen_movi_tl(t0, ret);
15226 gen_helper_mthlip(t0, v1_t, cpu_env);
15227 break;
15228 case OPC_WRDSP:
15229 imm = (ctx->opcode >> 11) & 0x3FF;
15230 tcg_gen_movi_tl(t0, imm);
15231 gen_helper_wrdsp(v1_t, t0, cpu_env);
15232 break;
15233 case OPC_RDDSP:
15234 imm = (ctx->opcode >> 16) & 0x03FF;
15235 tcg_gen_movi_tl(t0, imm);
15236 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
15237 break;
15239 break;
15240 #ifdef TARGET_MIPS64
15241 case OPC_DEXTR_W_DSP:
15242 check_dsp(ctx);
15243 switch (op2) {
15244 case OPC_DMTHLIP:
15245 tcg_gen_movi_tl(t0, ret);
15246 gen_helper_dmthlip(v1_t, t0, cpu_env);
15247 break;
15248 case OPC_DSHILO:
15250 int shift = (ctx->opcode >> 19) & 0x7F;
15251 int ac = (ctx->opcode >> 11) & 0x03;
15252 tcg_gen_movi_tl(t0, shift);
15253 tcg_gen_movi_tl(t1, ac);
15254 gen_helper_dshilo(t0, t1, cpu_env);
15255 break;
15257 case OPC_DSHILOV:
15259 int ac = (ctx->opcode >> 11) & 0x03;
15260 tcg_gen_movi_tl(t0, ac);
15261 gen_helper_dshilo(v1_t, t0, cpu_env);
15262 break;
15264 case OPC_DEXTP:
15265 tcg_gen_movi_tl(t0, v2);
15266 tcg_gen_movi_tl(t1, v1);
15268 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
15269 break;
15270 case OPC_DEXTPV:
15271 tcg_gen_movi_tl(t0, v2);
15272 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
15273 break;
15274 case OPC_DEXTPDP:
15275 tcg_gen_movi_tl(t0, v2);
15276 tcg_gen_movi_tl(t1, v1);
15277 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
15278 break;
15279 case OPC_DEXTPDPV:
15280 tcg_gen_movi_tl(t0, v2);
15281 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15282 break;
15283 case OPC_DEXTR_L:
15284 tcg_gen_movi_tl(t0, v2);
15285 tcg_gen_movi_tl(t1, v1);
15286 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
15287 break;
15288 case OPC_DEXTR_R_L:
15289 tcg_gen_movi_tl(t0, v2);
15290 tcg_gen_movi_tl(t1, v1);
15291 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
15292 break;
15293 case OPC_DEXTR_RS_L:
15294 tcg_gen_movi_tl(t0, v2);
15295 tcg_gen_movi_tl(t1, v1);
15296 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
15297 break;
15298 case OPC_DEXTR_W:
15299 tcg_gen_movi_tl(t0, v2);
15300 tcg_gen_movi_tl(t1, v1);
15301 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
15302 break;
15303 case OPC_DEXTR_R_W:
15304 tcg_gen_movi_tl(t0, v2);
15305 tcg_gen_movi_tl(t1, v1);
15306 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15307 break;
15308 case OPC_DEXTR_RS_W:
15309 tcg_gen_movi_tl(t0, v2);
15310 tcg_gen_movi_tl(t1, v1);
15311 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15312 break;
15313 case OPC_DEXTR_S_H:
15314 tcg_gen_movi_tl(t0, v2);
15315 tcg_gen_movi_tl(t1, v1);
15316 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15317 break;
15318 case OPC_DEXTRV_S_H:
15319 tcg_gen_movi_tl(t0, v2);
15320 tcg_gen_movi_tl(t1, v1);
15321 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15322 break;
15323 case OPC_DEXTRV_L:
15324 tcg_gen_movi_tl(t0, v2);
15325 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15326 break;
15327 case OPC_DEXTRV_R_L:
15328 tcg_gen_movi_tl(t0, v2);
15329 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15330 break;
15331 case OPC_DEXTRV_RS_L:
15332 tcg_gen_movi_tl(t0, v2);
15333 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15334 break;
15335 case OPC_DEXTRV_W:
15336 tcg_gen_movi_tl(t0, v2);
15337 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15338 break;
15339 case OPC_DEXTRV_R_W:
15340 tcg_gen_movi_tl(t0, v2);
15341 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15342 break;
15343 case OPC_DEXTRV_RS_W:
15344 tcg_gen_movi_tl(t0, v2);
15345 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15346 break;
15348 break;
15349 #endif
15352 tcg_temp_free(t0);
15353 tcg_temp_free(t1);
15354 tcg_temp_free(v1_t);
15355 tcg_temp_free(v2_t);
15357 (void)opn; /* avoid a compiler warning */
15358 MIPS_DEBUG("%s", opn);
15361 /* End MIPSDSP functions. */
15363 /* Compact Branches */
15364 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15365 int rs, int rt, int32_t offset)
15367 int bcond_compute = 0;
15368 TCGv t0 = tcg_temp_new();
15369 TCGv t1 = tcg_temp_new();
15371 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15372 #ifdef MIPS_DEBUG_DISAS
15373 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
15374 #endif
15375 generate_exception(ctx, EXCP_RI);
15376 goto out;
15379 /* Load needed operands and calculate btarget */
15380 switch (opc) {
15381 /* compact branch */
15382 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15383 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15384 gen_load_gpr(t0, rs);
15385 gen_load_gpr(t1, rt);
15386 bcond_compute = 1;
15387 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15388 if (rs <= rt && rs == 0) {
15389 /* OPC_BEQZALC, OPC_BNEZALC */
15390 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15392 break;
15393 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15394 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15395 gen_load_gpr(t0, rs);
15396 gen_load_gpr(t1, rt);
15397 bcond_compute = 1;
15398 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15399 break;
15400 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15401 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15402 if (rs == 0 || rs == rt) {
15403 /* OPC_BLEZALC, OPC_BGEZALC */
15404 /* OPC_BGTZALC, OPC_BLTZALC */
15405 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15407 gen_load_gpr(t0, rs);
15408 gen_load_gpr(t1, rt);
15409 bcond_compute = 1;
15410 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15411 break;
15412 case OPC_BC:
15413 case OPC_BALC:
15414 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15415 break;
15416 case OPC_BEQZC:
15417 case OPC_BNEZC:
15418 if (rs != 0) {
15419 /* OPC_BEQZC, OPC_BNEZC */
15420 gen_load_gpr(t0, rs);
15421 bcond_compute = 1;
15422 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15423 } else {
15424 /* OPC_JIC, OPC_JIALC */
15425 TCGv tbase = tcg_temp_new();
15426 TCGv toffset = tcg_temp_new();
15428 gen_load_gpr(tbase, rt);
15429 tcg_gen_movi_tl(toffset, offset);
15430 gen_op_addr_add(ctx, btarget, tbase, toffset);
15431 tcg_temp_free(tbase);
15432 tcg_temp_free(toffset);
15434 break;
15435 default:
15436 MIPS_INVAL("Compact branch/jump");
15437 generate_exception(ctx, EXCP_RI);
15438 goto out;
15441 if (bcond_compute == 0) {
15442 /* Uncoditional compact branch */
15443 switch (opc) {
15444 case OPC_JIALC:
15445 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15446 /* Fallthrough */
15447 case OPC_JIC:
15448 ctx->hflags |= MIPS_HFLAG_BR;
15449 break;
15450 case OPC_BALC:
15451 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15452 /* Fallthrough */
15453 case OPC_BC:
15454 ctx->hflags |= MIPS_HFLAG_B;
15455 break;
15456 default:
15457 MIPS_INVAL("Compact branch/jump");
15458 generate_exception(ctx, EXCP_RI);
15459 goto out;
15462 /* Generating branch here as compact branches don't have delay slot */
15463 gen_branch(ctx, 4);
15464 } else {
15465 /* Conditional compact branch */
15466 int l1 = gen_new_label();
15467 save_cpu_state(ctx, 0);
15469 switch (opc) {
15470 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15471 if (rs == 0 && rt != 0) {
15472 /* OPC_BLEZALC */
15473 tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15474 } else if (rs != 0 && rt != 0 && rs == rt) {
15475 /* OPC_BGEZALC */
15476 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15477 } else {
15478 /* OPC_BGEUC */
15479 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
15481 break;
15482 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15483 if (rs == 0 && rt != 0) {
15484 /* OPC_BGTZALC */
15485 tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15486 } else if (rs != 0 && rt != 0 && rs == rt) {
15487 /* OPC_BLTZALC */
15488 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15489 } else {
15490 /* OPC_BLTUC */
15491 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
15493 break;
15494 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15495 if (rs == 0 && rt != 0) {
15496 /* OPC_BLEZC */
15497 tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15498 } else if (rs != 0 && rt != 0 && rs == rt) {
15499 /* OPC_BGEZC */
15500 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15501 } else {
15502 /* OPC_BGEC */
15503 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
15505 break;
15506 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15507 if (rs == 0 && rt != 0) {
15508 /* OPC_BGTZC */
15509 tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15510 } else if (rs != 0 && rt != 0 && rs == rt) {
15511 /* OPC_BLTZC */
15512 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15513 } else {
15514 /* OPC_BLTC */
15515 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
15517 break;
15518 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15519 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15520 if (rs >= rt) {
15521 /* OPC_BOVC, OPC_BNVC */
15522 TCGv t2 = tcg_temp_new();
15523 TCGv t3 = tcg_temp_new();
15524 TCGv t4 = tcg_temp_new();
15525 TCGv input_overflow = tcg_temp_new();
15527 gen_load_gpr(t0, rs);
15528 gen_load_gpr(t1, rt);
15529 tcg_gen_ext32s_tl(t2, t0);
15530 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
15531 tcg_gen_ext32s_tl(t3, t1);
15532 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
15533 tcg_gen_or_tl(input_overflow, input_overflow, t4);
15535 tcg_gen_add_tl(t4, t2, t3);
15536 tcg_gen_ext32s_tl(t4, t4);
15537 tcg_gen_xor_tl(t2, t2, t3);
15538 tcg_gen_xor_tl(t3, t4, t3);
15539 tcg_gen_andc_tl(t2, t3, t2);
15540 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
15541 tcg_gen_or_tl(t4, t4, input_overflow);
15542 if (opc == OPC_BOVC) {
15543 /* OPC_BOVC */
15544 tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1);
15545 } else {
15546 /* OPC_BNVC */
15547 tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1);
15549 tcg_temp_free(input_overflow);
15550 tcg_temp_free(t4);
15551 tcg_temp_free(t3);
15552 tcg_temp_free(t2);
15553 } else if (rs < rt && rs == 0) {
15554 /* OPC_BEQZALC, OPC_BNEZALC */
15555 if (opc == OPC_BEQZALC) {
15556 /* OPC_BEQZALC */
15557 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
15558 } else {
15559 /* OPC_BNEZALC */
15560 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
15562 } else {
15563 /* OPC_BEQC, OPC_BNEC */
15564 if (opc == OPC_BEQC) {
15565 /* OPC_BEQC */
15566 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
15567 } else {
15568 /* OPC_BNEC */
15569 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
15572 break;
15573 case OPC_BEQZC:
15574 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
15575 break;
15576 case OPC_BNEZC:
15577 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
15578 break;
15579 default:
15580 MIPS_INVAL("Compact conditional branch/jump");
15581 generate_exception(ctx, EXCP_RI);
15582 goto out;
15585 /* Generating branch here as compact branches don't have delay slot */
15586 /* TODO: implement forbidden slot */
15587 gen_goto_tb(ctx, 1, ctx->pc + 4);
15588 gen_set_label(l1);
15589 gen_goto_tb(ctx, 0, ctx->btarget);
15590 MIPS_DEBUG("Compact conditional branch");
15591 ctx->bstate = BS_BRANCH;
15594 out:
15595 tcg_temp_free(t0);
15596 tcg_temp_free(t1);
15599 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
15601 int rs, rt, rd, sa;
15602 uint32_t op1, op2;
15604 rs = (ctx->opcode >> 21) & 0x1f;
15605 rt = (ctx->opcode >> 16) & 0x1f;
15606 rd = (ctx->opcode >> 11) & 0x1f;
15607 sa = (ctx->opcode >> 6) & 0x1f;
15609 op1 = MASK_SPECIAL(ctx->opcode);
15610 switch (op1) {
15611 case OPC_LSA:
15612 if (rd != 0) {
15613 int imm2 = extract32(ctx->opcode, 6, 3);
15614 TCGv t0 = tcg_temp_new();
15615 TCGv t1 = tcg_temp_new();
15616 gen_load_gpr(t0, rs);
15617 gen_load_gpr(t1, rt);
15618 tcg_gen_shli_tl(t0, t0, imm2 + 1);
15619 tcg_gen_add_tl(t0, t0, t1);
15620 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
15621 tcg_temp_free(t1);
15622 tcg_temp_free(t0);
15624 break;
15625 case OPC_MULT ... OPC_DIVU:
15626 op2 = MASK_R6_MULDIV(ctx->opcode);
15627 switch (op2) {
15628 case R6_OPC_MUL:
15629 case R6_OPC_MUH:
15630 case R6_OPC_MULU:
15631 case R6_OPC_MUHU:
15632 case R6_OPC_DIV:
15633 case R6_OPC_MOD:
15634 case R6_OPC_DIVU:
15635 case R6_OPC_MODU:
15636 gen_r6_muldiv(ctx, op2, rd, rs, rt);
15637 break;
15638 default:
15639 MIPS_INVAL("special_r6 muldiv");
15640 generate_exception(ctx, EXCP_RI);
15641 break;
15643 break;
15644 case OPC_SELEQZ:
15645 case OPC_SELNEZ:
15646 gen_cond_move(ctx, op1, rd, rs, rt);
15647 break;
15648 case R6_OPC_CLO:
15649 case R6_OPC_CLZ:
15650 if (rt == 0 && sa == 1) {
15651 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
15652 We need additionally to check other fields */
15653 gen_cl(ctx, op1, rd, rs);
15654 } else {
15655 generate_exception(ctx, EXCP_RI);
15657 break;
15658 case R6_OPC_SDBBP:
15659 generate_exception(ctx, EXCP_DBp);
15660 break;
15661 #if defined(TARGET_MIPS64)
15662 case OPC_DLSA:
15663 check_mips_64(ctx);
15664 if (rd != 0) {
15665 int imm2 = extract32(ctx->opcode, 6, 3);
15666 TCGv t0 = tcg_temp_new();
15667 TCGv t1 = tcg_temp_new();
15668 gen_load_gpr(t0, rs);
15669 gen_load_gpr(t1, rt);
15670 tcg_gen_shli_tl(t0, t0, imm2 + 1);
15671 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
15672 tcg_temp_free(t1);
15673 tcg_temp_free(t0);
15675 break;
15676 case R6_OPC_DCLO:
15677 case R6_OPC_DCLZ:
15678 if (rt == 0 && sa == 1) {
15679 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
15680 We need additionally to check other fields */
15681 check_mips_64(ctx);
15682 gen_cl(ctx, op1, rd, rs);
15683 } else {
15684 generate_exception(ctx, EXCP_RI);
15686 break;
15687 case OPC_DMULT ... OPC_DDIVU:
15688 op2 = MASK_R6_MULDIV(ctx->opcode);
15689 switch (op2) {
15690 case R6_OPC_DMUL:
15691 case R6_OPC_DMUH:
15692 case R6_OPC_DMULU:
15693 case R6_OPC_DMUHU:
15694 case R6_OPC_DDIV:
15695 case R6_OPC_DMOD:
15696 case R6_OPC_DDIVU:
15697 case R6_OPC_DMODU:
15698 check_mips_64(ctx);
15699 gen_r6_muldiv(ctx, op2, rd, rs, rt);
15700 break;
15701 default:
15702 MIPS_INVAL("special_r6 muldiv");
15703 generate_exception(ctx, EXCP_RI);
15704 break;
15706 break;
15707 #endif
15708 default: /* Invalid */
15709 MIPS_INVAL("special_r6");
15710 generate_exception(ctx, EXCP_RI);
15711 break;
15715 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
15717 int rs, rt, rd, sa;
15718 uint32_t op1;
15720 rs = (ctx->opcode >> 21) & 0x1f;
15721 rt = (ctx->opcode >> 16) & 0x1f;
15722 rd = (ctx->opcode >> 11) & 0x1f;
15723 sa = (ctx->opcode >> 6) & 0x1f;
15725 op1 = MASK_SPECIAL(ctx->opcode);
15726 switch (op1) {
15727 case OPC_MOVN: /* Conditional move */
15728 case OPC_MOVZ:
15729 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
15730 INSN_LOONGSON2E | INSN_LOONGSON2F);
15731 gen_cond_move(ctx, op1, rd, rs, rt);
15732 break;
15733 case OPC_MFHI: /* Move from HI/LO */
15734 case OPC_MFLO:
15735 gen_HILO(ctx, op1, rs & 3, rd);
15736 break;
15737 case OPC_MTHI:
15738 case OPC_MTLO: /* Move to HI/LO */
15739 gen_HILO(ctx, op1, rd & 3, rs);
15740 break;
15741 case OPC_MOVCI:
15742 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
15743 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15744 check_cp1_enabled(ctx);
15745 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
15746 (ctx->opcode >> 16) & 1);
15747 } else {
15748 generate_exception_err(ctx, EXCP_CpU, 1);
15750 break;
15751 case OPC_MULT:
15752 case OPC_MULTU:
15753 if (sa) {
15754 check_insn(ctx, INSN_VR54XX);
15755 op1 = MASK_MUL_VR54XX(ctx->opcode);
15756 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
15757 } else {
15758 gen_muldiv(ctx, op1, rd & 3, rs, rt);
15760 break;
15761 case OPC_DIV:
15762 case OPC_DIVU:
15763 gen_muldiv(ctx, op1, 0, rs, rt);
15764 break;
15765 #if defined(TARGET_MIPS64)
15766 case OPC_DMULT ... OPC_DDIVU:
15767 check_insn(ctx, ISA_MIPS3);
15768 check_mips_64(ctx);
15769 gen_muldiv(ctx, op1, 0, rs, rt);
15770 break;
15771 #endif
15772 case OPC_JR:
15773 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
15774 break;
15775 case OPC_SPIM:
15776 #ifdef MIPS_STRICT_STANDARD
15777 MIPS_INVAL("SPIM");
15778 generate_exception(ctx, EXCP_RI);
15779 #else
15780 /* Implemented as RI exception for now. */
15781 MIPS_INVAL("spim (unofficial)");
15782 generate_exception(ctx, EXCP_RI);
15783 #endif
15784 break;
15785 default: /* Invalid */
15786 MIPS_INVAL("special_legacy");
15787 generate_exception(ctx, EXCP_RI);
15788 break;
15792 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
15794 int rs, rt, rd, sa;
15795 uint32_t op1;
15797 rs = (ctx->opcode >> 21) & 0x1f;
15798 rt = (ctx->opcode >> 16) & 0x1f;
15799 rd = (ctx->opcode >> 11) & 0x1f;
15800 sa = (ctx->opcode >> 6) & 0x1f;
15802 op1 = MASK_SPECIAL(ctx->opcode);
15803 switch (op1) {
15804 case OPC_SLL: /* Shift with immediate */
15805 case OPC_SRA:
15806 gen_shift_imm(ctx, op1, rd, rt, sa);
15807 break;
15808 case OPC_SRL:
15809 switch ((ctx->opcode >> 21) & 0x1f) {
15810 case 1:
15811 /* rotr is decoded as srl on non-R2 CPUs */
15812 if (ctx->insn_flags & ISA_MIPS32R2) {
15813 op1 = OPC_ROTR;
15815 /* Fallthrough */
15816 case 0:
15817 gen_shift_imm(ctx, op1, rd, rt, sa);
15818 break;
15819 default:
15820 generate_exception(ctx, EXCP_RI);
15821 break;
15823 break;
15824 case OPC_ADD ... OPC_SUBU:
15825 gen_arith(ctx, op1, rd, rs, rt);
15826 break;
15827 case OPC_SLLV: /* Shifts */
15828 case OPC_SRAV:
15829 gen_shift(ctx, op1, rd, rs, rt);
15830 break;
15831 case OPC_SRLV:
15832 switch ((ctx->opcode >> 6) & 0x1f) {
15833 case 1:
15834 /* rotrv is decoded as srlv on non-R2 CPUs */
15835 if (ctx->insn_flags & ISA_MIPS32R2) {
15836 op1 = OPC_ROTRV;
15838 /* Fallthrough */
15839 case 0:
15840 gen_shift(ctx, op1, rd, rs, rt);
15841 break;
15842 default:
15843 generate_exception(ctx, EXCP_RI);
15844 break;
15846 break;
15847 case OPC_SLT: /* Set on less than */
15848 case OPC_SLTU:
15849 gen_slt(ctx, op1, rd, rs, rt);
15850 break;
15851 case OPC_AND: /* Logic*/
15852 case OPC_OR:
15853 case OPC_NOR:
15854 case OPC_XOR:
15855 gen_logic(ctx, op1, rd, rs, rt);
15856 break;
15857 case OPC_JALR:
15858 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
15859 break;
15860 case OPC_TGE ... OPC_TEQ: /* Traps */
15861 case OPC_TNE:
15862 gen_trap(ctx, op1, rs, rt, -1);
15863 break;
15864 case OPC_LSA: /* OPC_PMON */
15865 if (ctx->insn_flags & ISA_MIPS32R6) {
15866 decode_opc_special_r6(env, ctx);
15867 } else {
15868 /* Pmon entry point, also R4010 selsl */
15869 #ifdef MIPS_STRICT_STANDARD
15870 MIPS_INVAL("PMON / selsl");
15871 generate_exception(ctx, EXCP_RI);
15872 #else
15873 gen_helper_0e0i(pmon, sa);
15874 #endif
15876 break;
15877 case OPC_SYSCALL:
15878 generate_exception(ctx, EXCP_SYSCALL);
15879 ctx->bstate = BS_STOP;
15880 break;
15881 case OPC_BREAK:
15882 generate_exception(ctx, EXCP_BREAK);
15883 break;
15884 case OPC_SYNC:
15885 /* Treat as NOP. */
15886 break;
15888 #if defined(TARGET_MIPS64)
15889 /* MIPS64 specific opcodes */
15890 case OPC_DSLL:
15891 case OPC_DSRA:
15892 case OPC_DSLL32:
15893 case OPC_DSRA32:
15894 check_insn(ctx, ISA_MIPS3);
15895 check_mips_64(ctx);
15896 gen_shift_imm(ctx, op1, rd, rt, sa);
15897 break;
15898 case OPC_DSRL:
15899 switch ((ctx->opcode >> 21) & 0x1f) {
15900 case 1:
15901 /* drotr is decoded as dsrl on non-R2 CPUs */
15902 if (ctx->insn_flags & ISA_MIPS32R2) {
15903 op1 = OPC_DROTR;
15905 /* Fallthrough */
15906 case 0:
15907 check_insn(ctx, ISA_MIPS3);
15908 check_mips_64(ctx);
15909 gen_shift_imm(ctx, op1, rd, rt, sa);
15910 break;
15911 default:
15912 generate_exception(ctx, EXCP_RI);
15913 break;
15915 break;
15916 case OPC_DSRL32:
15917 switch ((ctx->opcode >> 21) & 0x1f) {
15918 case 1:
15919 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
15920 if (ctx->insn_flags & ISA_MIPS32R2) {
15921 op1 = OPC_DROTR32;
15923 /* Fallthrough */
15924 case 0:
15925 check_insn(ctx, ISA_MIPS3);
15926 check_mips_64(ctx);
15927 gen_shift_imm(ctx, op1, rd, rt, sa);
15928 break;
15929 default:
15930 generate_exception(ctx, EXCP_RI);
15931 break;
15933 break;
15934 case OPC_DADD ... OPC_DSUBU:
15935 check_insn(ctx, ISA_MIPS3);
15936 check_mips_64(ctx);
15937 gen_arith(ctx, op1, rd, rs, rt);
15938 break;
15939 case OPC_DSLLV:
15940 case OPC_DSRAV:
15941 check_insn(ctx, ISA_MIPS3);
15942 check_mips_64(ctx);
15943 gen_shift(ctx, op1, rd, rs, rt);
15944 break;
15945 case OPC_DSRLV:
15946 switch ((ctx->opcode >> 6) & 0x1f) {
15947 case 1:
15948 /* drotrv is decoded as dsrlv on non-R2 CPUs */
15949 if (ctx->insn_flags & ISA_MIPS32R2) {
15950 op1 = OPC_DROTRV;
15952 /* Fallthrough */
15953 case 0:
15954 check_insn(ctx, ISA_MIPS3);
15955 check_mips_64(ctx);
15956 gen_shift(ctx, op1, rd, rs, rt);
15957 break;
15958 default:
15959 generate_exception(ctx, EXCP_RI);
15960 break;
15962 break;
15963 #endif
15964 default:
15965 if (ctx->insn_flags & ISA_MIPS32R6) {
15966 decode_opc_special_r6(env, ctx);
15967 } else {
15968 decode_opc_special_legacy(env, ctx);
15973 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
15975 int rs, rt, rd;
15976 uint32_t op1;
15978 check_insn_opc_removed(ctx, ISA_MIPS32R6);
15980 rs = (ctx->opcode >> 21) & 0x1f;
15981 rt = (ctx->opcode >> 16) & 0x1f;
15982 rd = (ctx->opcode >> 11) & 0x1f;
15984 op1 = MASK_SPECIAL2(ctx->opcode);
15985 switch (op1) {
15986 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
15987 case OPC_MSUB ... OPC_MSUBU:
15988 check_insn(ctx, ISA_MIPS32);
15989 gen_muldiv(ctx, op1, rd & 3, rs, rt);
15990 break;
15991 case OPC_MUL:
15992 gen_arith(ctx, op1, rd, rs, rt);
15993 break;
15994 case OPC_DIV_G_2F:
15995 case OPC_DIVU_G_2F:
15996 case OPC_MULT_G_2F:
15997 case OPC_MULTU_G_2F:
15998 case OPC_MOD_G_2F:
15999 case OPC_MODU_G_2F:
16000 check_insn(ctx, INSN_LOONGSON2F);
16001 gen_loongson_integer(ctx, op1, rd, rs, rt);
16002 break;
16003 case OPC_CLO:
16004 case OPC_CLZ:
16005 check_insn(ctx, ISA_MIPS32);
16006 gen_cl(ctx, op1, rd, rs);
16007 break;
16008 case OPC_SDBBP:
16009 /* XXX: not clear which exception should be raised
16010 * when in debug mode...
16012 check_insn(ctx, ISA_MIPS32);
16013 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
16014 generate_exception(ctx, EXCP_DBp);
16015 } else {
16016 generate_exception(ctx, EXCP_DBp);
16018 /* Treat as NOP. */
16019 break;
16020 #if defined(TARGET_MIPS64)
16021 case OPC_DCLO:
16022 case OPC_DCLZ:
16023 check_insn(ctx, ISA_MIPS64);
16024 check_mips_64(ctx);
16025 gen_cl(ctx, op1, rd, rs);
16026 break;
16027 case OPC_DMULT_G_2F:
16028 case OPC_DMULTU_G_2F:
16029 case OPC_DDIV_G_2F:
16030 case OPC_DDIVU_G_2F:
16031 case OPC_DMOD_G_2F:
16032 case OPC_DMODU_G_2F:
16033 check_insn(ctx, INSN_LOONGSON2F);
16034 gen_loongson_integer(ctx, op1, rd, rs, rt);
16035 break;
16036 #endif
16037 default: /* Invalid */
16038 MIPS_INVAL("special2_legacy");
16039 generate_exception(ctx, EXCP_RI);
16040 break;
16044 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
16046 int rs, rt, rd, sa;
16047 uint32_t op1, op2;
16048 int16_t imm;
16050 rs = (ctx->opcode >> 21) & 0x1f;
16051 rt = (ctx->opcode >> 16) & 0x1f;
16052 rd = (ctx->opcode >> 11) & 0x1f;
16053 sa = (ctx->opcode >> 6) & 0x1f;
16054 imm = (int16_t)ctx->opcode >> 7;
16056 op1 = MASK_SPECIAL3(ctx->opcode);
16057 switch (op1) {
16058 case R6_OPC_PREF:
16059 if (rt >= 24) {
16060 /* hint codes 24-31 are reserved and signal RI */
16061 generate_exception(ctx, EXCP_RI);
16063 /* Treat as NOP. */
16064 break;
16065 case R6_OPC_CACHE:
16066 /* Treat as NOP. */
16067 break;
16068 case R6_OPC_SC:
16069 gen_st_cond(ctx, op1, rt, rs, imm);
16070 break;
16071 case R6_OPC_LL:
16072 gen_ld(ctx, op1, rt, rs, imm);
16073 break;
16074 case OPC_BSHFL:
16076 if (rd == 0) {
16077 /* Treat as NOP. */
16078 break;
16080 TCGv t0 = tcg_temp_new();
16081 gen_load_gpr(t0, rt);
16083 op2 = MASK_BSHFL(ctx->opcode);
16084 switch (op2) {
16085 case OPC_ALIGN ... OPC_ALIGN_END:
16086 sa &= 3;
16087 if (sa == 0) {
16088 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16089 } else {
16090 TCGv t1 = tcg_temp_new();
16091 TCGv_i64 t2 = tcg_temp_new_i64();
16092 gen_load_gpr(t1, rs);
16093 tcg_gen_concat_tl_i64(t2, t1, t0);
16094 tcg_gen_shri_i64(t2, t2, 8 * (4 - sa));
16095 #if defined(TARGET_MIPS64)
16096 tcg_gen_ext32s_i64(cpu_gpr[rd], t2);
16097 #else
16098 tcg_gen_trunc_i64_i32(cpu_gpr[rd], t2);
16099 #endif
16100 tcg_temp_free_i64(t2);
16101 tcg_temp_free(t1);
16103 break;
16104 case OPC_BITSWAP:
16105 gen_helper_bitswap(cpu_gpr[rd], t0);
16106 break;
16108 tcg_temp_free(t0);
16110 break;
16111 #if defined(TARGET_MIPS64)
16112 case R6_OPC_SCD:
16113 gen_st_cond(ctx, op1, rt, rs, imm);
16114 break;
16115 case R6_OPC_LLD:
16116 gen_ld(ctx, op1, rt, rs, imm);
16117 break;
16118 case OPC_DBSHFL:
16119 check_mips_64(ctx);
16121 if (rd == 0) {
16122 /* Treat as NOP. */
16123 break;
16125 TCGv t0 = tcg_temp_new();
16126 gen_load_gpr(t0, rt);
16128 op2 = MASK_DBSHFL(ctx->opcode);
16129 switch (op2) {
16130 case OPC_DALIGN ... OPC_DALIGN_END:
16131 sa &= 7;
16132 if (sa == 0) {
16133 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16134 } else {
16135 TCGv t1 = tcg_temp_new();
16136 gen_load_gpr(t1, rs);
16137 tcg_gen_shli_tl(t0, t0, 8 * sa);
16138 tcg_gen_shri_tl(t1, t1, 8 * (8 - sa));
16139 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
16140 tcg_temp_free(t1);
16142 break;
16143 case OPC_DBITSWAP:
16144 gen_helper_dbitswap(cpu_gpr[rd], t0);
16145 break;
16147 tcg_temp_free(t0);
16149 break;
16150 #endif
16151 default: /* Invalid */
16152 MIPS_INVAL("special3_r6");
16153 generate_exception(ctx, EXCP_RI);
16154 break;
16158 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
16160 int rs, rt, rd;
16161 uint32_t op1, op2;
16163 rs = (ctx->opcode >> 21) & 0x1f;
16164 rt = (ctx->opcode >> 16) & 0x1f;
16165 rd = (ctx->opcode >> 11) & 0x1f;
16167 op1 = MASK_SPECIAL3(ctx->opcode);
16168 switch (op1) {
16169 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
16170 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
16171 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
16172 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16173 * the same mask and op1. */
16174 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
16175 op2 = MASK_ADDUH_QB(ctx->opcode);
16176 switch (op2) {
16177 case OPC_ADDUH_QB:
16178 case OPC_ADDUH_R_QB:
16179 case OPC_ADDQH_PH:
16180 case OPC_ADDQH_R_PH:
16181 case OPC_ADDQH_W:
16182 case OPC_ADDQH_R_W:
16183 case OPC_SUBUH_QB:
16184 case OPC_SUBUH_R_QB:
16185 case OPC_SUBQH_PH:
16186 case OPC_SUBQH_R_PH:
16187 case OPC_SUBQH_W:
16188 case OPC_SUBQH_R_W:
16189 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16190 break;
16191 case OPC_MUL_PH:
16192 case OPC_MUL_S_PH:
16193 case OPC_MULQ_S_W:
16194 case OPC_MULQ_RS_W:
16195 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16196 break;
16197 default:
16198 MIPS_INVAL("MASK ADDUH.QB");
16199 generate_exception(ctx, EXCP_RI);
16200 break;
16202 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
16203 gen_loongson_integer(ctx, op1, rd, rs, rt);
16204 } else {
16205 generate_exception(ctx, EXCP_RI);
16207 break;
16208 case OPC_LX_DSP:
16209 op2 = MASK_LX(ctx->opcode);
16210 switch (op2) {
16211 #if defined(TARGET_MIPS64)
16212 case OPC_LDX:
16213 #endif
16214 case OPC_LBUX:
16215 case OPC_LHX:
16216 case OPC_LWX:
16217 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
16218 break;
16219 default: /* Invalid */
16220 MIPS_INVAL("MASK LX");
16221 generate_exception(ctx, EXCP_RI);
16222 break;
16224 break;
16225 case OPC_ABSQ_S_PH_DSP:
16226 op2 = MASK_ABSQ_S_PH(ctx->opcode);
16227 switch (op2) {
16228 case OPC_ABSQ_S_QB:
16229 case OPC_ABSQ_S_PH:
16230 case OPC_ABSQ_S_W:
16231 case OPC_PRECEQ_W_PHL:
16232 case OPC_PRECEQ_W_PHR:
16233 case OPC_PRECEQU_PH_QBL:
16234 case OPC_PRECEQU_PH_QBR:
16235 case OPC_PRECEQU_PH_QBLA:
16236 case OPC_PRECEQU_PH_QBRA:
16237 case OPC_PRECEU_PH_QBL:
16238 case OPC_PRECEU_PH_QBR:
16239 case OPC_PRECEU_PH_QBLA:
16240 case OPC_PRECEU_PH_QBRA:
16241 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16242 break;
16243 case OPC_BITREV:
16244 case OPC_REPL_QB:
16245 case OPC_REPLV_QB:
16246 case OPC_REPL_PH:
16247 case OPC_REPLV_PH:
16248 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16249 break;
16250 default:
16251 MIPS_INVAL("MASK ABSQ_S.PH");
16252 generate_exception(ctx, EXCP_RI);
16253 break;
16255 break;
16256 case OPC_ADDU_QB_DSP:
16257 op2 = MASK_ADDU_QB(ctx->opcode);
16258 switch (op2) {
16259 case OPC_ADDQ_PH:
16260 case OPC_ADDQ_S_PH:
16261 case OPC_ADDQ_S_W:
16262 case OPC_ADDU_QB:
16263 case OPC_ADDU_S_QB:
16264 case OPC_ADDU_PH:
16265 case OPC_ADDU_S_PH:
16266 case OPC_SUBQ_PH:
16267 case OPC_SUBQ_S_PH:
16268 case OPC_SUBQ_S_W:
16269 case OPC_SUBU_QB:
16270 case OPC_SUBU_S_QB:
16271 case OPC_SUBU_PH:
16272 case OPC_SUBU_S_PH:
16273 case OPC_ADDSC:
16274 case OPC_ADDWC:
16275 case OPC_MODSUB:
16276 case OPC_RADDU_W_QB:
16277 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16278 break;
16279 case OPC_MULEU_S_PH_QBL:
16280 case OPC_MULEU_S_PH_QBR:
16281 case OPC_MULQ_RS_PH:
16282 case OPC_MULEQ_S_W_PHL:
16283 case OPC_MULEQ_S_W_PHR:
16284 case OPC_MULQ_S_PH:
16285 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16286 break;
16287 default: /* Invalid */
16288 MIPS_INVAL("MASK ADDU.QB");
16289 generate_exception(ctx, EXCP_RI);
16290 break;
16293 break;
16294 case OPC_CMPU_EQ_QB_DSP:
16295 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
16296 switch (op2) {
16297 case OPC_PRECR_SRA_PH_W:
16298 case OPC_PRECR_SRA_R_PH_W:
16299 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
16300 break;
16301 case OPC_PRECR_QB_PH:
16302 case OPC_PRECRQ_QB_PH:
16303 case OPC_PRECRQ_PH_W:
16304 case OPC_PRECRQ_RS_PH_W:
16305 case OPC_PRECRQU_S_QB_PH:
16306 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16307 break;
16308 case OPC_CMPU_EQ_QB:
16309 case OPC_CMPU_LT_QB:
16310 case OPC_CMPU_LE_QB:
16311 case OPC_CMP_EQ_PH:
16312 case OPC_CMP_LT_PH:
16313 case OPC_CMP_LE_PH:
16314 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
16315 break;
16316 case OPC_CMPGU_EQ_QB:
16317 case OPC_CMPGU_LT_QB:
16318 case OPC_CMPGU_LE_QB:
16319 case OPC_CMPGDU_EQ_QB:
16320 case OPC_CMPGDU_LT_QB:
16321 case OPC_CMPGDU_LE_QB:
16322 case OPC_PICK_QB:
16323 case OPC_PICK_PH:
16324 case OPC_PACKRL_PH:
16325 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
16326 break;
16327 default: /* Invalid */
16328 MIPS_INVAL("MASK CMPU.EQ.QB");
16329 generate_exception(ctx, EXCP_RI);
16330 break;
16332 break;
16333 case OPC_SHLL_QB_DSP:
16334 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16335 break;
16336 case OPC_DPA_W_PH_DSP:
16337 op2 = MASK_DPA_W_PH(ctx->opcode);
16338 switch (op2) {
16339 case OPC_DPAU_H_QBL:
16340 case OPC_DPAU_H_QBR:
16341 case OPC_DPSU_H_QBL:
16342 case OPC_DPSU_H_QBR:
16343 case OPC_DPA_W_PH:
16344 case OPC_DPAX_W_PH:
16345 case OPC_DPAQ_S_W_PH:
16346 case OPC_DPAQX_S_W_PH:
16347 case OPC_DPAQX_SA_W_PH:
16348 case OPC_DPS_W_PH:
16349 case OPC_DPSX_W_PH:
16350 case OPC_DPSQ_S_W_PH:
16351 case OPC_DPSQX_S_W_PH:
16352 case OPC_DPSQX_SA_W_PH:
16353 case OPC_MULSAQ_S_W_PH:
16354 case OPC_DPAQ_SA_L_W:
16355 case OPC_DPSQ_SA_L_W:
16356 case OPC_MAQ_S_W_PHL:
16357 case OPC_MAQ_S_W_PHR:
16358 case OPC_MAQ_SA_W_PHL:
16359 case OPC_MAQ_SA_W_PHR:
16360 case OPC_MULSA_W_PH:
16361 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16362 break;
16363 default: /* Invalid */
16364 MIPS_INVAL("MASK DPAW.PH");
16365 generate_exception(ctx, EXCP_RI);
16366 break;
16368 break;
16369 case OPC_INSV_DSP:
16370 op2 = MASK_INSV(ctx->opcode);
16371 switch (op2) {
16372 case OPC_INSV:
16373 check_dsp(ctx);
16375 TCGv t0, t1;
16377 if (rt == 0) {
16378 MIPS_DEBUG("NOP");
16379 break;
16382 t0 = tcg_temp_new();
16383 t1 = tcg_temp_new();
16385 gen_load_gpr(t0, rt);
16386 gen_load_gpr(t1, rs);
16388 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
16390 tcg_temp_free(t0);
16391 tcg_temp_free(t1);
16392 break;
16394 default: /* Invalid */
16395 MIPS_INVAL("MASK INSV");
16396 generate_exception(ctx, EXCP_RI);
16397 break;
16399 break;
16400 case OPC_APPEND_DSP:
16401 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16402 break;
16403 case OPC_EXTR_W_DSP:
16404 op2 = MASK_EXTR_W(ctx->opcode);
16405 switch (op2) {
16406 case OPC_EXTR_W:
16407 case OPC_EXTR_R_W:
16408 case OPC_EXTR_RS_W:
16409 case OPC_EXTR_S_H:
16410 case OPC_EXTRV_S_H:
16411 case OPC_EXTRV_W:
16412 case OPC_EXTRV_R_W:
16413 case OPC_EXTRV_RS_W:
16414 case OPC_EXTP:
16415 case OPC_EXTPV:
16416 case OPC_EXTPDP:
16417 case OPC_EXTPDPV:
16418 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
16419 break;
16420 case OPC_RDDSP:
16421 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
16422 break;
16423 case OPC_SHILO:
16424 case OPC_SHILOV:
16425 case OPC_MTHLIP:
16426 case OPC_WRDSP:
16427 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
16428 break;
16429 default: /* Invalid */
16430 MIPS_INVAL("MASK EXTR.W");
16431 generate_exception(ctx, EXCP_RI);
16432 break;
16434 break;
16435 #if defined(TARGET_MIPS64)
16436 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
16437 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
16438 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
16439 check_insn(ctx, INSN_LOONGSON2E);
16440 gen_loongson_integer(ctx, op1, rd, rs, rt);
16441 break;
16442 case OPC_ABSQ_S_QH_DSP:
16443 op2 = MASK_ABSQ_S_QH(ctx->opcode);
16444 switch (op2) {
16445 case OPC_PRECEQ_L_PWL:
16446 case OPC_PRECEQ_L_PWR:
16447 case OPC_PRECEQ_PW_QHL:
16448 case OPC_PRECEQ_PW_QHR:
16449 case OPC_PRECEQ_PW_QHLA:
16450 case OPC_PRECEQ_PW_QHRA:
16451 case OPC_PRECEQU_QH_OBL:
16452 case OPC_PRECEQU_QH_OBR:
16453 case OPC_PRECEQU_QH_OBLA:
16454 case OPC_PRECEQU_QH_OBRA:
16455 case OPC_PRECEU_QH_OBL:
16456 case OPC_PRECEU_QH_OBR:
16457 case OPC_PRECEU_QH_OBLA:
16458 case OPC_PRECEU_QH_OBRA:
16459 case OPC_ABSQ_S_OB:
16460 case OPC_ABSQ_S_PW:
16461 case OPC_ABSQ_S_QH:
16462 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16463 break;
16464 case OPC_REPL_OB:
16465 case OPC_REPL_PW:
16466 case OPC_REPL_QH:
16467 case OPC_REPLV_OB:
16468 case OPC_REPLV_PW:
16469 case OPC_REPLV_QH:
16470 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16471 break;
16472 default: /* Invalid */
16473 MIPS_INVAL("MASK ABSQ_S.QH");
16474 generate_exception(ctx, EXCP_RI);
16475 break;
16477 break;
16478 case OPC_ADDU_OB_DSP:
16479 op2 = MASK_ADDU_OB(ctx->opcode);
16480 switch (op2) {
16481 case OPC_RADDU_L_OB:
16482 case OPC_SUBQ_PW:
16483 case OPC_SUBQ_S_PW:
16484 case OPC_SUBQ_QH:
16485 case OPC_SUBQ_S_QH:
16486 case OPC_SUBU_OB:
16487 case OPC_SUBU_S_OB:
16488 case OPC_SUBU_QH:
16489 case OPC_SUBU_S_QH:
16490 case OPC_SUBUH_OB:
16491 case OPC_SUBUH_R_OB:
16492 case OPC_ADDQ_PW:
16493 case OPC_ADDQ_S_PW:
16494 case OPC_ADDQ_QH:
16495 case OPC_ADDQ_S_QH:
16496 case OPC_ADDU_OB:
16497 case OPC_ADDU_S_OB:
16498 case OPC_ADDU_QH:
16499 case OPC_ADDU_S_QH:
16500 case OPC_ADDUH_OB:
16501 case OPC_ADDUH_R_OB:
16502 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16503 break;
16504 case OPC_MULEQ_S_PW_QHL:
16505 case OPC_MULEQ_S_PW_QHR:
16506 case OPC_MULEU_S_QH_OBL:
16507 case OPC_MULEU_S_QH_OBR:
16508 case OPC_MULQ_RS_QH:
16509 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16510 break;
16511 default: /* Invalid */
16512 MIPS_INVAL("MASK ADDU.OB");
16513 generate_exception(ctx, EXCP_RI);
16514 break;
16516 break;
16517 case OPC_CMPU_EQ_OB_DSP:
16518 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
16519 switch (op2) {
16520 case OPC_PRECR_SRA_QH_PW:
16521 case OPC_PRECR_SRA_R_QH_PW:
16522 /* Return value is rt. */
16523 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
16524 break;
16525 case OPC_PRECR_OB_QH:
16526 case OPC_PRECRQ_OB_QH:
16527 case OPC_PRECRQ_PW_L:
16528 case OPC_PRECRQ_QH_PW:
16529 case OPC_PRECRQ_RS_QH_PW:
16530 case OPC_PRECRQU_S_OB_QH:
16531 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16532 break;
16533 case OPC_CMPU_EQ_OB:
16534 case OPC_CMPU_LT_OB:
16535 case OPC_CMPU_LE_OB:
16536 case OPC_CMP_EQ_QH:
16537 case OPC_CMP_LT_QH:
16538 case OPC_CMP_LE_QH:
16539 case OPC_CMP_EQ_PW:
16540 case OPC_CMP_LT_PW:
16541 case OPC_CMP_LE_PW:
16542 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
16543 break;
16544 case OPC_CMPGDU_EQ_OB:
16545 case OPC_CMPGDU_LT_OB:
16546 case OPC_CMPGDU_LE_OB:
16547 case OPC_CMPGU_EQ_OB:
16548 case OPC_CMPGU_LT_OB:
16549 case OPC_CMPGU_LE_OB:
16550 case OPC_PACKRL_PW:
16551 case OPC_PICK_OB:
16552 case OPC_PICK_PW:
16553 case OPC_PICK_QH:
16554 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
16555 break;
16556 default: /* Invalid */
16557 MIPS_INVAL("MASK CMPU_EQ.OB");
16558 generate_exception(ctx, EXCP_RI);
16559 break;
16561 break;
16562 case OPC_DAPPEND_DSP:
16563 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16564 break;
16565 case OPC_DEXTR_W_DSP:
16566 op2 = MASK_DEXTR_W(ctx->opcode);
16567 switch (op2) {
16568 case OPC_DEXTP:
16569 case OPC_DEXTPDP:
16570 case OPC_DEXTPDPV:
16571 case OPC_DEXTPV:
16572 case OPC_DEXTR_L:
16573 case OPC_DEXTR_R_L:
16574 case OPC_DEXTR_RS_L:
16575 case OPC_DEXTR_W:
16576 case OPC_DEXTR_R_W:
16577 case OPC_DEXTR_RS_W:
16578 case OPC_DEXTR_S_H:
16579 case OPC_DEXTRV_L:
16580 case OPC_DEXTRV_R_L:
16581 case OPC_DEXTRV_RS_L:
16582 case OPC_DEXTRV_S_H:
16583 case OPC_DEXTRV_W:
16584 case OPC_DEXTRV_R_W:
16585 case OPC_DEXTRV_RS_W:
16586 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
16587 break;
16588 case OPC_DMTHLIP:
16589 case OPC_DSHILO:
16590 case OPC_DSHILOV:
16591 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
16592 break;
16593 default: /* Invalid */
16594 MIPS_INVAL("MASK EXTR.W");
16595 generate_exception(ctx, EXCP_RI);
16596 break;
16598 break;
16599 case OPC_DPAQ_W_QH_DSP:
16600 op2 = MASK_DPAQ_W_QH(ctx->opcode);
16601 switch (op2) {
16602 case OPC_DPAU_H_OBL:
16603 case OPC_DPAU_H_OBR:
16604 case OPC_DPSU_H_OBL:
16605 case OPC_DPSU_H_OBR:
16606 case OPC_DPA_W_QH:
16607 case OPC_DPAQ_S_W_QH:
16608 case OPC_DPS_W_QH:
16609 case OPC_DPSQ_S_W_QH:
16610 case OPC_MULSAQ_S_W_QH:
16611 case OPC_DPAQ_SA_L_PW:
16612 case OPC_DPSQ_SA_L_PW:
16613 case OPC_MULSAQ_S_L_PW:
16614 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16615 break;
16616 case OPC_MAQ_S_W_QHLL:
16617 case OPC_MAQ_S_W_QHLR:
16618 case OPC_MAQ_S_W_QHRL:
16619 case OPC_MAQ_S_W_QHRR:
16620 case OPC_MAQ_SA_W_QHLL:
16621 case OPC_MAQ_SA_W_QHLR:
16622 case OPC_MAQ_SA_W_QHRL:
16623 case OPC_MAQ_SA_W_QHRR:
16624 case OPC_MAQ_S_L_PWL:
16625 case OPC_MAQ_S_L_PWR:
16626 case OPC_DMADD:
16627 case OPC_DMADDU:
16628 case OPC_DMSUB:
16629 case OPC_DMSUBU:
16630 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16631 break;
16632 default: /* Invalid */
16633 MIPS_INVAL("MASK DPAQ.W.QH");
16634 generate_exception(ctx, EXCP_RI);
16635 break;
16637 break;
16638 case OPC_DINSV_DSP:
16639 op2 = MASK_INSV(ctx->opcode);
16640 switch (op2) {
16641 case OPC_DINSV:
16643 TCGv t0, t1;
16645 if (rt == 0) {
16646 MIPS_DEBUG("NOP");
16647 break;
16649 check_dsp(ctx);
16651 t0 = tcg_temp_new();
16652 t1 = tcg_temp_new();
16654 gen_load_gpr(t0, rt);
16655 gen_load_gpr(t1, rs);
16657 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
16659 tcg_temp_free(t0);
16660 tcg_temp_free(t1);
16661 break;
16663 default: /* Invalid */
16664 MIPS_INVAL("MASK DINSV");
16665 generate_exception(ctx, EXCP_RI);
16666 break;
16668 break;
16669 case OPC_SHLL_OB_DSP:
16670 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16671 break;
16672 #endif
16673 default: /* Invalid */
16674 MIPS_INVAL("special3_legacy");
16675 generate_exception(ctx, EXCP_RI);
16676 break;
16680 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
16682 int rs, rt, rd, sa;
16683 uint32_t op1, op2;
16685 rs = (ctx->opcode >> 21) & 0x1f;
16686 rt = (ctx->opcode >> 16) & 0x1f;
16687 rd = (ctx->opcode >> 11) & 0x1f;
16688 sa = (ctx->opcode >> 6) & 0x1f;
16690 op1 = MASK_SPECIAL3(ctx->opcode);
16691 switch (op1) {
16692 case OPC_EXT:
16693 case OPC_INS:
16694 check_insn(ctx, ISA_MIPS32R2);
16695 gen_bitops(ctx, op1, rt, rs, sa, rd);
16696 break;
16697 case OPC_BSHFL:
16698 op2 = MASK_BSHFL(ctx->opcode);
16699 switch (op2) {
16700 case OPC_ALIGN ... OPC_ALIGN_END:
16701 case OPC_BITSWAP:
16702 check_insn(ctx, ISA_MIPS32R6);
16703 decode_opc_special3_r6(env, ctx);
16704 break;
16705 default:
16706 check_insn(ctx, ISA_MIPS32R2);
16707 gen_bshfl(ctx, op2, rt, rd);
16708 break;
16710 break;
16711 #if defined(TARGET_MIPS64)
16712 case OPC_DEXTM ... OPC_DEXT:
16713 case OPC_DINSM ... OPC_DINS:
16714 check_insn(ctx, ISA_MIPS64R2);
16715 check_mips_64(ctx);
16716 gen_bitops(ctx, op1, rt, rs, sa, rd);
16717 break;
16718 case OPC_DBSHFL:
16719 op2 = MASK_DBSHFL(ctx->opcode);
16720 switch (op2) {
16721 case OPC_DALIGN ... OPC_DALIGN_END:
16722 case OPC_DBITSWAP:
16723 check_insn(ctx, ISA_MIPS32R6);
16724 decode_opc_special3_r6(env, ctx);
16725 break;
16726 default:
16727 check_insn(ctx, ISA_MIPS64R2);
16728 check_mips_64(ctx);
16729 op2 = MASK_DBSHFL(ctx->opcode);
16730 gen_bshfl(ctx, op2, rt, rd);
16731 break;
16733 break;
16734 #endif
16735 case OPC_RDHWR:
16736 gen_rdhwr(ctx, rt, rd);
16737 break;
16738 case OPC_FORK:
16739 check_insn(ctx, ASE_MT);
16741 TCGv t0 = tcg_temp_new();
16742 TCGv t1 = tcg_temp_new();
16744 gen_load_gpr(t0, rt);
16745 gen_load_gpr(t1, rs);
16746 gen_helper_fork(t0, t1);
16747 tcg_temp_free(t0);
16748 tcg_temp_free(t1);
16750 break;
16751 case OPC_YIELD:
16752 check_insn(ctx, ASE_MT);
16754 TCGv t0 = tcg_temp_new();
16756 save_cpu_state(ctx, 1);
16757 gen_load_gpr(t0, rs);
16758 gen_helper_yield(t0, cpu_env, t0);
16759 gen_store_gpr(t0, rd);
16760 tcg_temp_free(t0);
16762 break;
16763 default:
16764 if (ctx->insn_flags & ISA_MIPS32R6) {
16765 decode_opc_special3_r6(env, ctx);
16766 } else {
16767 decode_opc_special3_legacy(env, ctx);
16772 static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
16774 int32_t offset;
16775 int rs, rt, rd, sa;
16776 uint32_t op, op1;
16777 int16_t imm;
16779 /* make sure instructions are on a word boundary */
16780 if (ctx->pc & 0x3) {
16781 env->CP0_BadVAddr = ctx->pc;
16782 generate_exception(ctx, EXCP_AdEL);
16783 return;
16786 /* Handle blikely not taken case */
16787 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
16788 int l1 = gen_new_label();
16790 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
16791 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
16792 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
16793 gen_goto_tb(ctx, 1, ctx->pc + 4);
16794 gen_set_label(l1);
16797 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
16798 tcg_gen_debug_insn_start(ctx->pc);
16801 op = MASK_OP_MAJOR(ctx->opcode);
16802 rs = (ctx->opcode >> 21) & 0x1f;
16803 rt = (ctx->opcode >> 16) & 0x1f;
16804 rd = (ctx->opcode >> 11) & 0x1f;
16805 sa = (ctx->opcode >> 6) & 0x1f;
16806 imm = (int16_t)ctx->opcode;
16807 switch (op) {
16808 case OPC_SPECIAL:
16809 decode_opc_special(env, ctx);
16810 break;
16811 case OPC_SPECIAL2:
16812 decode_opc_special2_legacy(env, ctx);
16813 break;
16814 case OPC_SPECIAL3:
16815 decode_opc_special3(env, ctx);
16816 break;
16817 case OPC_REGIMM:
16818 op1 = MASK_REGIMM(ctx->opcode);
16819 switch (op1) {
16820 case OPC_BLTZL: /* REGIMM branches */
16821 case OPC_BGEZL:
16822 case OPC_BLTZALL:
16823 case OPC_BGEZALL:
16824 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16825 case OPC_BLTZ:
16826 case OPC_BGEZ:
16827 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
16828 break;
16829 case OPC_BLTZAL:
16830 case OPC_BGEZAL:
16831 if (ctx->insn_flags & ISA_MIPS32R6) {
16832 if (rs == 0) {
16833 /* OPC_NAL, OPC_BAL */
16834 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
16835 } else {
16836 generate_exception(ctx, EXCP_RI);
16838 } else {
16839 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
16841 break;
16842 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
16843 case OPC_TNEI:
16844 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16845 gen_trap(ctx, op1, rs, -1, imm);
16846 break;
16847 case OPC_SYNCI:
16848 check_insn(ctx, ISA_MIPS32R2);
16849 /* Break the TB to be able to sync copied instructions
16850 immediately */
16851 ctx->bstate = BS_STOP;
16852 break;
16853 case OPC_BPOSGE32: /* MIPS DSP branch */
16854 #if defined(TARGET_MIPS64)
16855 case OPC_BPOSGE64:
16856 #endif
16857 check_dsp(ctx);
16858 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
16859 break;
16860 #if defined(TARGET_MIPS64)
16861 case OPC_DAHI:
16862 check_insn(ctx, ISA_MIPS32R6);
16863 check_mips_64(ctx);
16864 if (rs != 0) {
16865 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
16867 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
16868 break;
16869 case OPC_DATI:
16870 check_insn(ctx, ISA_MIPS32R6);
16871 check_mips_64(ctx);
16872 if (rs != 0) {
16873 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
16875 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
16876 break;
16877 #endif
16878 default: /* Invalid */
16879 MIPS_INVAL("regimm");
16880 generate_exception(ctx, EXCP_RI);
16881 break;
16883 break;
16884 case OPC_CP0:
16885 check_cp0_enabled(ctx);
16886 op1 = MASK_CP0(ctx->opcode);
16887 switch (op1) {
16888 case OPC_MFC0:
16889 case OPC_MTC0:
16890 case OPC_MFTR:
16891 case OPC_MTTR:
16892 #if defined(TARGET_MIPS64)
16893 case OPC_DMFC0:
16894 case OPC_DMTC0:
16895 #endif
16896 #ifndef CONFIG_USER_ONLY
16897 gen_cp0(env, ctx, op1, rt, rd);
16898 #endif /* !CONFIG_USER_ONLY */
16899 break;
16900 case OPC_C0_FIRST ... OPC_C0_LAST:
16901 #ifndef CONFIG_USER_ONLY
16902 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
16903 #endif /* !CONFIG_USER_ONLY */
16904 break;
16905 case OPC_MFMC0:
16906 #ifndef CONFIG_USER_ONLY
16908 uint32_t op2;
16909 TCGv t0 = tcg_temp_new();
16911 op2 = MASK_MFMC0(ctx->opcode);
16912 switch (op2) {
16913 case OPC_DMT:
16914 check_insn(ctx, ASE_MT);
16915 gen_helper_dmt(t0);
16916 gen_store_gpr(t0, rt);
16917 break;
16918 case OPC_EMT:
16919 check_insn(ctx, ASE_MT);
16920 gen_helper_emt(t0);
16921 gen_store_gpr(t0, rt);
16922 break;
16923 case OPC_DVPE:
16924 check_insn(ctx, ASE_MT);
16925 gen_helper_dvpe(t0, cpu_env);
16926 gen_store_gpr(t0, rt);
16927 break;
16928 case OPC_EVPE:
16929 check_insn(ctx, ASE_MT);
16930 gen_helper_evpe(t0, cpu_env);
16931 gen_store_gpr(t0, rt);
16932 break;
16933 case OPC_DI:
16934 check_insn(ctx, ISA_MIPS32R2);
16935 save_cpu_state(ctx, 1);
16936 gen_helper_di(t0, cpu_env);
16937 gen_store_gpr(t0, rt);
16938 /* Stop translation as we may have switched the execution mode */
16939 ctx->bstate = BS_STOP;
16940 break;
16941 case OPC_EI:
16942 check_insn(ctx, ISA_MIPS32R2);
16943 save_cpu_state(ctx, 1);
16944 gen_helper_ei(t0, cpu_env);
16945 gen_store_gpr(t0, rt);
16946 /* Stop translation as we may have switched the execution mode */
16947 ctx->bstate = BS_STOP;
16948 break;
16949 default: /* Invalid */
16950 MIPS_INVAL("mfmc0");
16951 generate_exception(ctx, EXCP_RI);
16952 break;
16954 tcg_temp_free(t0);
16956 #endif /* !CONFIG_USER_ONLY */
16957 break;
16958 case OPC_RDPGPR:
16959 check_insn(ctx, ISA_MIPS32R2);
16960 gen_load_srsgpr(rt, rd);
16961 break;
16962 case OPC_WRPGPR:
16963 check_insn(ctx, ISA_MIPS32R2);
16964 gen_store_srsgpr(rt, rd);
16965 break;
16966 default:
16967 MIPS_INVAL("cp0");
16968 generate_exception(ctx, EXCP_RI);
16969 break;
16971 break;
16972 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
16973 if (ctx->insn_flags & ISA_MIPS32R6) {
16974 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
16975 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
16976 } else {
16977 /* OPC_ADDI */
16978 /* Arithmetic with immediate opcode */
16979 gen_arith_imm(ctx, op, rt, rs, imm);
16981 break;
16982 case OPC_ADDIU:
16983 gen_arith_imm(ctx, op, rt, rs, imm);
16984 break;
16985 case OPC_SLTI: /* Set on less than with immediate opcode */
16986 case OPC_SLTIU:
16987 gen_slt_imm(ctx, op, rt, rs, imm);
16988 break;
16989 case OPC_ANDI: /* Arithmetic with immediate opcode */
16990 case OPC_LUI: /* OPC_AUI */
16991 case OPC_ORI:
16992 case OPC_XORI:
16993 gen_logic_imm(ctx, op, rt, rs, imm);
16994 break;
16995 case OPC_J ... OPC_JAL: /* Jump */
16996 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
16997 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
16998 break;
16999 /* Branch */
17000 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
17001 if (ctx->insn_flags & ISA_MIPS32R6) {
17002 if (rt == 0) {
17003 generate_exception(ctx, EXCP_RI);
17004 break;
17006 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
17007 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17008 } else {
17009 /* OPC_BLEZL */
17010 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17012 break;
17013 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
17014 if (ctx->insn_flags & ISA_MIPS32R6) {
17015 if (rt == 0) {
17016 generate_exception(ctx, EXCP_RI);
17017 break;
17019 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
17020 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17021 } else {
17022 /* OPC_BGTZL */
17023 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17025 break;
17026 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
17027 if (rt == 0) {
17028 /* OPC_BLEZ */
17029 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17030 } else {
17031 check_insn(ctx, ISA_MIPS32R6);
17032 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
17033 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17035 break;
17036 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
17037 if (rt == 0) {
17038 /* OPC_BGTZ */
17039 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17040 } else {
17041 check_insn(ctx, ISA_MIPS32R6);
17042 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
17043 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17045 break;
17046 case OPC_BEQL:
17047 case OPC_BNEL:
17048 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17049 case OPC_BEQ:
17050 case OPC_BNE:
17051 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17052 break;
17053 case OPC_LWL: /* Load and stores */
17054 case OPC_LWR:
17055 case OPC_LL:
17056 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17057 case OPC_LB ... OPC_LH:
17058 case OPC_LW ... OPC_LHU:
17059 gen_ld(ctx, op, rt, rs, imm);
17060 break;
17061 case OPC_SWL:
17062 case OPC_SWR:
17063 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17064 case OPC_SB ... OPC_SH:
17065 case OPC_SW:
17066 gen_st(ctx, op, rt, rs, imm);
17067 break;
17068 case OPC_SC:
17069 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17070 gen_st_cond(ctx, op, rt, rs, imm);
17071 break;
17072 case OPC_CACHE:
17073 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17074 check_cp0_enabled(ctx);
17075 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
17076 /* Treat as NOP. */
17077 break;
17078 case OPC_PREF:
17079 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17080 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17081 /* Treat as NOP. */
17082 break;
17084 /* Floating point (COP1). */
17085 case OPC_LWC1:
17086 case OPC_LDC1:
17087 case OPC_SWC1:
17088 case OPC_SDC1:
17089 gen_cop1_ldst(ctx, op, rt, rs, imm);
17090 break;
17092 case OPC_CP1:
17093 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
17094 check_cp1_enabled(ctx);
17095 op1 = MASK_CP1(ctx->opcode);
17096 switch (op1) {
17097 case OPC_MFHC1:
17098 case OPC_MTHC1:
17099 check_insn(ctx, ISA_MIPS32R2);
17100 case OPC_MFC1:
17101 case OPC_CFC1:
17102 case OPC_MTC1:
17103 case OPC_CTC1:
17104 gen_cp1(ctx, op1, rt, rd);
17105 break;
17106 #if defined(TARGET_MIPS64)
17107 case OPC_DMFC1:
17108 case OPC_DMTC1:
17109 check_insn(ctx, ISA_MIPS3);
17110 gen_cp1(ctx, op1, rt, rd);
17111 break;
17112 #endif
17113 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
17114 if (ctx->insn_flags & ISA_MIPS32R6) {
17115 /* OPC_BC1EQZ */
17116 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
17117 rt, imm << 2);
17118 } else {
17119 /* OPC_BC1ANY2 */
17120 check_cop1x(ctx);
17121 check_insn(ctx, ASE_MIPS3D);
17122 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
17123 (rt >> 2) & 0x7, imm << 2);
17125 break;
17126 case OPC_BC1NEZ:
17127 check_insn(ctx, ISA_MIPS32R6);
17128 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
17129 rt, imm << 2);
17130 break;
17131 case OPC_BC1ANY4:
17132 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17133 check_cop1x(ctx);
17134 check_insn(ctx, ASE_MIPS3D);
17135 /* fall through */
17136 case OPC_BC1:
17137 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17138 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
17139 (rt >> 2) & 0x7, imm << 2);
17140 break;
17141 case OPC_PS_FMT:
17142 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17143 case OPC_S_FMT:
17144 case OPC_D_FMT:
17145 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17146 (imm >> 8) & 0x7);
17147 break;
17148 case OPC_W_FMT:
17149 case OPC_L_FMT:
17151 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
17152 if (ctx->insn_flags & ISA_MIPS32R6) {
17153 switch (r6_op) {
17154 case R6_OPC_CMP_AF_S:
17155 case R6_OPC_CMP_UN_S:
17156 case R6_OPC_CMP_EQ_S:
17157 case R6_OPC_CMP_UEQ_S:
17158 case R6_OPC_CMP_LT_S:
17159 case R6_OPC_CMP_ULT_S:
17160 case R6_OPC_CMP_LE_S:
17161 case R6_OPC_CMP_ULE_S:
17162 case R6_OPC_CMP_SAF_S:
17163 case R6_OPC_CMP_SUN_S:
17164 case R6_OPC_CMP_SEQ_S:
17165 case R6_OPC_CMP_SEUQ_S:
17166 case R6_OPC_CMP_SLT_S:
17167 case R6_OPC_CMP_SULT_S:
17168 case R6_OPC_CMP_SLE_S:
17169 case R6_OPC_CMP_SULE_S:
17170 case R6_OPC_CMP_OR_S:
17171 case R6_OPC_CMP_UNE_S:
17172 case R6_OPC_CMP_NE_S:
17173 case R6_OPC_CMP_SOR_S:
17174 case R6_OPC_CMP_SUNE_S:
17175 case R6_OPC_CMP_SNE_S:
17176 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
17177 break;
17178 case R6_OPC_CMP_AF_D:
17179 case R6_OPC_CMP_UN_D:
17180 case R6_OPC_CMP_EQ_D:
17181 case R6_OPC_CMP_UEQ_D:
17182 case R6_OPC_CMP_LT_D:
17183 case R6_OPC_CMP_ULT_D:
17184 case R6_OPC_CMP_LE_D:
17185 case R6_OPC_CMP_ULE_D:
17186 case R6_OPC_CMP_SAF_D:
17187 case R6_OPC_CMP_SUN_D:
17188 case R6_OPC_CMP_SEQ_D:
17189 case R6_OPC_CMP_SEUQ_D:
17190 case R6_OPC_CMP_SLT_D:
17191 case R6_OPC_CMP_SULT_D:
17192 case R6_OPC_CMP_SLE_D:
17193 case R6_OPC_CMP_SULE_D:
17194 case R6_OPC_CMP_OR_D:
17195 case R6_OPC_CMP_UNE_D:
17196 case R6_OPC_CMP_NE_D:
17197 case R6_OPC_CMP_SOR_D:
17198 case R6_OPC_CMP_SUNE_D:
17199 case R6_OPC_CMP_SNE_D:
17200 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
17201 break;
17202 default:
17203 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17204 (imm >> 8) & 0x7);
17205 break;
17207 } else {
17208 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17209 (imm >> 8) & 0x7);
17211 break;
17213 default:
17214 MIPS_INVAL("cp1");
17215 generate_exception (ctx, EXCP_RI);
17216 break;
17218 } else {
17219 generate_exception_err(ctx, EXCP_CpU, 1);
17221 break;
17223 /* Compact branches [R6] and COP2 [non-R6] */
17224 case OPC_BC: /* OPC_LWC2 */
17225 case OPC_BALC: /* OPC_SWC2 */
17226 if (ctx->insn_flags & ISA_MIPS32R6) {
17227 /* OPC_BC, OPC_BALC */
17228 gen_compute_compact_branch(ctx, op, 0, 0,
17229 sextract32(ctx->opcode << 2, 0, 28));
17230 } else {
17231 /* OPC_LWC2, OPC_SWC2 */
17232 /* COP2: Not implemented. */
17233 generate_exception_err(ctx, EXCP_CpU, 2);
17235 break;
17236 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
17237 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
17238 if (ctx->insn_flags & ISA_MIPS32R6) {
17239 if (rs != 0) {
17240 /* OPC_BEQZC, OPC_BNEZC */
17241 gen_compute_compact_branch(ctx, op, rs, 0,
17242 sextract32(ctx->opcode << 2, 0, 23));
17243 } else {
17244 /* OPC_JIC, OPC_JIALC */
17245 gen_compute_compact_branch(ctx, op, 0, rt, imm);
17247 } else {
17248 /* OPC_LWC2, OPC_SWC2 */
17249 /* COP2: Not implemented. */
17250 generate_exception_err(ctx, EXCP_CpU, 2);
17252 break;
17253 case OPC_CP2:
17254 check_insn(ctx, INSN_LOONGSON2F);
17255 /* Note that these instructions use different fields. */
17256 gen_loongson_multimedia(ctx, sa, rd, rt);
17257 break;
17259 case OPC_CP3:
17260 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17261 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
17262 check_cp1_enabled(ctx);
17263 op1 = MASK_CP3(ctx->opcode);
17264 switch (op1) {
17265 case OPC_LWXC1:
17266 case OPC_LDXC1:
17267 case OPC_LUXC1:
17268 case OPC_SWXC1:
17269 case OPC_SDXC1:
17270 case OPC_SUXC1:
17271 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
17272 break;
17273 case OPC_PREFX:
17274 /* Treat as NOP. */
17275 break;
17276 case OPC_ALNV_PS:
17277 case OPC_MADD_S:
17278 case OPC_MADD_D:
17279 case OPC_MADD_PS:
17280 case OPC_MSUB_S:
17281 case OPC_MSUB_D:
17282 case OPC_MSUB_PS:
17283 case OPC_NMADD_S:
17284 case OPC_NMADD_D:
17285 case OPC_NMADD_PS:
17286 case OPC_NMSUB_S:
17287 case OPC_NMSUB_D:
17288 case OPC_NMSUB_PS:
17289 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
17290 break;
17291 default:
17292 MIPS_INVAL("cp3");
17293 generate_exception (ctx, EXCP_RI);
17294 break;
17296 } else {
17297 generate_exception_err(ctx, EXCP_CpU, 1);
17299 break;
17301 #if defined(TARGET_MIPS64)
17302 /* MIPS64 opcodes */
17303 case OPC_LDL ... OPC_LDR:
17304 case OPC_LLD:
17305 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17306 case OPC_LWU:
17307 case OPC_LD:
17308 check_insn(ctx, ISA_MIPS3);
17309 check_mips_64(ctx);
17310 gen_ld(ctx, op, rt, rs, imm);
17311 break;
17312 case OPC_SDL ... OPC_SDR:
17313 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17314 case OPC_SD:
17315 check_insn(ctx, ISA_MIPS3);
17316 check_mips_64(ctx);
17317 gen_st(ctx, op, rt, rs, imm);
17318 break;
17319 case OPC_SCD:
17320 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17321 check_insn(ctx, ISA_MIPS3);
17322 check_mips_64(ctx);
17323 gen_st_cond(ctx, op, rt, rs, imm);
17324 break;
17325 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
17326 if (ctx->insn_flags & ISA_MIPS32R6) {
17327 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
17328 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17329 } else {
17330 /* OPC_DADDI */
17331 check_insn(ctx, ISA_MIPS3);
17332 check_mips_64(ctx);
17333 gen_arith_imm(ctx, op, rt, rs, imm);
17335 break;
17336 case OPC_DADDIU:
17337 check_insn(ctx, ISA_MIPS3);
17338 check_mips_64(ctx);
17339 gen_arith_imm(ctx, op, rt, rs, imm);
17340 break;
17341 #else
17342 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
17343 if (ctx->insn_flags & ISA_MIPS32R6) {
17344 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17345 } else {
17346 MIPS_INVAL("major opcode");
17347 generate_exception(ctx, EXCP_RI);
17349 break;
17350 #endif
17351 case OPC_DAUI: /* OPC_JALX */
17352 if (ctx->insn_flags & ISA_MIPS32R6) {
17353 #if defined(TARGET_MIPS64)
17354 /* OPC_DAUI */
17355 check_mips_64(ctx);
17356 if (rt != 0) {
17357 TCGv t0 = tcg_temp_new();
17358 gen_load_gpr(t0, rs);
17359 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
17360 tcg_temp_free(t0);
17362 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
17363 #else
17364 generate_exception(ctx, EXCP_RI);
17365 MIPS_INVAL("major opcode");
17366 #endif
17367 } else {
17368 /* OPC_JALX */
17369 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
17370 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17371 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
17373 break;
17374 case OPC_MDMX:
17375 check_insn(ctx, ASE_MDMX);
17376 /* MDMX: Not implemented. */
17377 break;
17378 case OPC_PCREL:
17379 check_insn(ctx, ISA_MIPS32R6);
17380 gen_pcrel(ctx, rs, imm);
17381 break;
17382 default: /* Invalid */
17383 MIPS_INVAL("major opcode");
17384 generate_exception(ctx, EXCP_RI);
17385 break;
17389 static inline void
17390 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
17391 bool search_pc)
17393 CPUState *cs = CPU(cpu);
17394 CPUMIPSState *env = &cpu->env;
17395 DisasContext ctx;
17396 target_ulong pc_start;
17397 uint16_t *gen_opc_end;
17398 CPUBreakpoint *bp;
17399 int j, lj = -1;
17400 int num_insns;
17401 int max_insns;
17402 int insn_bytes;
17403 int is_delay;
17405 if (search_pc)
17406 qemu_log("search pc %d\n", search_pc);
17408 pc_start = tb->pc;
17409 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
17410 ctx.pc = pc_start;
17411 ctx.saved_pc = -1;
17412 ctx.singlestep_enabled = cs->singlestep_enabled;
17413 ctx.insn_flags = env->insn_flags;
17414 ctx.CP0_Config1 = env->CP0_Config1;
17415 ctx.tb = tb;
17416 ctx.bstate = BS_NONE;
17417 /* Restore delay slot state from the tb context. */
17418 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
17419 ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
17420 restore_cpu_state(env, &ctx);
17421 #ifdef CONFIG_USER_ONLY
17422 ctx.mem_idx = MIPS_HFLAG_UM;
17423 #else
17424 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
17425 #endif
17426 num_insns = 0;
17427 max_insns = tb->cflags & CF_COUNT_MASK;
17428 if (max_insns == 0)
17429 max_insns = CF_COUNT_MASK;
17430 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
17431 gen_tb_start();
17432 while (ctx.bstate == BS_NONE) {
17433 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
17434 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
17435 if (bp->pc == ctx.pc) {
17436 save_cpu_state(&ctx, 1);
17437 ctx.bstate = BS_BRANCH;
17438 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
17439 /* Include the breakpoint location or the tb won't
17440 * be flushed when it must be. */
17441 ctx.pc += 4;
17442 goto done_generating;
17447 if (search_pc) {
17448 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
17449 if (lj < j) {
17450 lj++;
17451 while (lj < j)
17452 tcg_ctx.gen_opc_instr_start[lj++] = 0;
17454 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
17455 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
17456 gen_opc_btarget[lj] = ctx.btarget;
17457 tcg_ctx.gen_opc_instr_start[lj] = 1;
17458 tcg_ctx.gen_opc_icount[lj] = num_insns;
17460 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
17461 gen_io_start();
17463 is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
17464 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
17465 ctx.opcode = cpu_ldl_code(env, ctx.pc);
17466 insn_bytes = 4;
17467 decode_opc(env, &ctx);
17468 } else if (ctx.insn_flags & ASE_MICROMIPS) {
17469 ctx.opcode = cpu_lduw_code(env, ctx.pc);
17470 insn_bytes = decode_micromips_opc(env, &ctx);
17471 } else if (ctx.insn_flags & ASE_MIPS16) {
17472 ctx.opcode = cpu_lduw_code(env, ctx.pc);
17473 insn_bytes = decode_mips16_opc(env, &ctx);
17474 } else {
17475 generate_exception(&ctx, EXCP_RI);
17476 ctx.bstate = BS_STOP;
17477 break;
17480 if (ctx.hflags & MIPS_HFLAG_BMASK) {
17481 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32))) {
17482 is_delay = 1;
17483 /* force to generate branch as no delay slot is required */
17486 if (is_delay) {
17487 gen_branch(&ctx, insn_bytes);
17489 ctx.pc += insn_bytes;
17491 num_insns++;
17493 /* Execute a branch and its delay slot as a single instruction.
17494 This is what GDB expects and is consistent with what the
17495 hardware does (e.g. if a delay slot instruction faults, the
17496 reported PC is the PC of the branch). */
17497 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
17498 break;
17501 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
17502 break;
17504 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
17505 break;
17508 if (num_insns >= max_insns)
17509 break;
17511 if (singlestep)
17512 break;
17514 if (tb->cflags & CF_LAST_IO) {
17515 gen_io_end();
17517 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
17518 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
17519 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
17520 } else {
17521 switch (ctx.bstate) {
17522 case BS_STOP:
17523 gen_goto_tb(&ctx, 0, ctx.pc);
17524 break;
17525 case BS_NONE:
17526 save_cpu_state(&ctx, 0);
17527 gen_goto_tb(&ctx, 0, ctx.pc);
17528 break;
17529 case BS_EXCP:
17530 tcg_gen_exit_tb(0);
17531 break;
17532 case BS_BRANCH:
17533 default:
17534 break;
17537 done_generating:
17538 gen_tb_end(tb, num_insns);
17539 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
17540 if (search_pc) {
17541 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
17542 lj++;
17543 while (lj <= j)
17544 tcg_ctx.gen_opc_instr_start[lj++] = 0;
17545 } else {
17546 tb->size = ctx.pc - pc_start;
17547 tb->icount = num_insns;
17549 #ifdef DEBUG_DISAS
17550 LOG_DISAS("\n");
17551 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
17552 qemu_log("IN: %s\n", lookup_symbol(pc_start));
17553 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
17554 qemu_log("\n");
17556 #endif
17559 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
17561 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
17564 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
17566 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
17569 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
17570 int flags)
17572 int i;
17573 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
17575 #define printfpr(fp) \
17576 do { \
17577 if (is_fpu64) \
17578 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
17579 " fd:%13g fs:%13g psu: %13g\n", \
17580 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
17581 (double)(fp)->fd, \
17582 (double)(fp)->fs[FP_ENDIAN_IDX], \
17583 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
17584 else { \
17585 fpr_t tmp; \
17586 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
17587 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
17588 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
17589 " fd:%13g fs:%13g psu:%13g\n", \
17590 tmp.w[FP_ENDIAN_IDX], tmp.d, \
17591 (double)tmp.fd, \
17592 (double)tmp.fs[FP_ENDIAN_IDX], \
17593 (double)tmp.fs[!FP_ENDIAN_IDX]); \
17595 } while(0)
17598 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
17599 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
17600 get_float_exception_flags(&env->active_fpu.fp_status));
17601 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
17602 fpu_fprintf(f, "%3s: ", fregnames[i]);
17603 printfpr(&env->active_fpu.fpr[i]);
17606 #undef printfpr
17609 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
17610 /* Debug help: The architecture requires 32bit code to maintain proper
17611 sign-extended values on 64bit machines. */
17613 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
17615 static void
17616 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
17617 fprintf_function cpu_fprintf,
17618 int flags)
17620 int i;
17622 if (!SIGN_EXT_P(env->active_tc.PC))
17623 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
17624 if (!SIGN_EXT_P(env->active_tc.HI[0]))
17625 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
17626 if (!SIGN_EXT_P(env->active_tc.LO[0]))
17627 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
17628 if (!SIGN_EXT_P(env->btarget))
17629 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
17631 for (i = 0; i < 32; i++) {
17632 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
17633 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
17636 if (!SIGN_EXT_P(env->CP0_EPC))
17637 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
17638 if (!SIGN_EXT_P(env->lladdr))
17639 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
17641 #endif
17643 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
17644 int flags)
17646 MIPSCPU *cpu = MIPS_CPU(cs);
17647 CPUMIPSState *env = &cpu->env;
17648 int i;
17650 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
17651 " LO=0x" TARGET_FMT_lx " ds %04x "
17652 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
17653 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
17654 env->hflags, env->btarget, env->bcond);
17655 for (i = 0; i < 32; i++) {
17656 if ((i & 3) == 0)
17657 cpu_fprintf(f, "GPR%02d:", i);
17658 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
17659 if ((i & 3) == 3)
17660 cpu_fprintf(f, "\n");
17663 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
17664 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
17665 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
17666 env->CP0_Config0, env->CP0_Config1, env->lladdr);
17667 if (env->hflags & MIPS_HFLAG_FPU)
17668 fpu_dump_state(env, f, cpu_fprintf, flags);
17669 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
17670 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
17671 #endif
17674 void mips_tcg_init(void)
17676 int i;
17677 static int inited;
17679 /* Initialize various static tables. */
17680 if (inited)
17681 return;
17683 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
17684 TCGV_UNUSED(cpu_gpr[0]);
17685 for (i = 1; i < 32; i++)
17686 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
17687 offsetof(CPUMIPSState, active_tc.gpr[i]),
17688 regnames[i]);
17690 for (i = 0; i < 32; i++) {
17691 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
17692 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
17695 cpu_PC = tcg_global_mem_new(TCG_AREG0,
17696 offsetof(CPUMIPSState, active_tc.PC), "PC");
17697 for (i = 0; i < MIPS_DSP_ACC; i++) {
17698 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
17699 offsetof(CPUMIPSState, active_tc.HI[i]),
17700 regnames_HI[i]);
17701 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
17702 offsetof(CPUMIPSState, active_tc.LO[i]),
17703 regnames_LO[i]);
17705 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
17706 offsetof(CPUMIPSState, active_tc.DSPControl),
17707 "DSPControl");
17708 bcond = tcg_global_mem_new(TCG_AREG0,
17709 offsetof(CPUMIPSState, bcond), "bcond");
17710 btarget = tcg_global_mem_new(TCG_AREG0,
17711 offsetof(CPUMIPSState, btarget), "btarget");
17712 hflags = tcg_global_mem_new_i32(TCG_AREG0,
17713 offsetof(CPUMIPSState, hflags), "hflags");
17715 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
17716 offsetof(CPUMIPSState, active_fpu.fcr0),
17717 "fcr0");
17718 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
17719 offsetof(CPUMIPSState, active_fpu.fcr31),
17720 "fcr31");
17722 inited = 1;
17725 #include "translate_init.c"
17727 MIPSCPU *cpu_mips_init(const char *cpu_model)
17729 MIPSCPU *cpu;
17730 CPUMIPSState *env;
17731 const mips_def_t *def;
17733 def = cpu_mips_find_by_name(cpu_model);
17734 if (!def)
17735 return NULL;
17736 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
17737 env = &cpu->env;
17738 env->cpu_model = def;
17740 #ifndef CONFIG_USER_ONLY
17741 mmu_init(env, def);
17742 #endif
17743 fpu_init(env, def);
17744 mvp_init(env, def);
17746 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
17748 return cpu;
17751 void cpu_state_reset(CPUMIPSState *env)
17753 MIPSCPU *cpu = mips_env_get_cpu(env);
17754 CPUState *cs = CPU(cpu);
17756 /* Reset registers to their default values */
17757 env->CP0_PRid = env->cpu_model->CP0_PRid;
17758 env->CP0_Config0 = env->cpu_model->CP0_Config0;
17759 #ifdef TARGET_WORDS_BIGENDIAN
17760 env->CP0_Config0 |= (1 << CP0C0_BE);
17761 #endif
17762 env->CP0_Config1 = env->cpu_model->CP0_Config1;
17763 env->CP0_Config2 = env->cpu_model->CP0_Config2;
17764 env->CP0_Config3 = env->cpu_model->CP0_Config3;
17765 env->CP0_Config4 = env->cpu_model->CP0_Config4;
17766 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
17767 env->CP0_Config5 = env->cpu_model->CP0_Config5;
17768 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
17769 env->CP0_Config6 = env->cpu_model->CP0_Config6;
17770 env->CP0_Config7 = env->cpu_model->CP0_Config7;
17771 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
17772 << env->cpu_model->CP0_LLAddr_shift;
17773 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
17774 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
17775 env->CCRes = env->cpu_model->CCRes;
17776 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
17777 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
17778 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
17779 env->current_tc = 0;
17780 env->SEGBITS = env->cpu_model->SEGBITS;
17781 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
17782 #if defined(TARGET_MIPS64)
17783 if (env->cpu_model->insn_flags & ISA_MIPS3) {
17784 env->SEGMask |= 3ULL << 62;
17786 #endif
17787 env->PABITS = env->cpu_model->PABITS;
17788 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
17789 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
17790 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
17791 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
17792 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
17793 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
17794 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
17795 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
17796 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
17797 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
17798 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
17799 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
17800 env->insn_flags = env->cpu_model->insn_flags;
17802 #if defined(CONFIG_USER_ONLY)
17803 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
17804 # ifdef TARGET_MIPS64
17805 /* Enable 64-bit register mode. */
17806 env->CP0_Status |= (1 << CP0St_PX);
17807 # endif
17808 # ifdef TARGET_ABI_MIPSN64
17809 /* Enable 64-bit address mode. */
17810 env->CP0_Status |= (1 << CP0St_UX);
17811 # endif
17812 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
17813 hardware registers. */
17814 env->CP0_HWREna |= 0x0000000F;
17815 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17816 env->CP0_Status |= (1 << CP0St_CU1);
17818 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
17819 env->CP0_Status |= (1 << CP0St_MX);
17821 # if defined(TARGET_MIPS64)
17822 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
17823 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
17824 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
17825 env->CP0_Status |= (1 << CP0St_FR);
17827 # endif
17828 #else
17829 if (env->hflags & MIPS_HFLAG_BMASK) {
17830 /* If the exception was raised from a delay slot,
17831 come back to the jump. */
17832 env->CP0_ErrorEPC = env->active_tc.PC - 4;
17833 } else {
17834 env->CP0_ErrorEPC = env->active_tc.PC;
17836 env->active_tc.PC = (int32_t)0xBFC00000;
17837 env->CP0_Random = env->tlb->nb_tlb - 1;
17838 env->tlb->tlb_in_use = env->tlb->nb_tlb;
17839 env->CP0_Wired = 0;
17840 env->CP0_EBase = (cs->cpu_index & 0x3FF);
17841 if (kvm_enabled()) {
17842 env->CP0_EBase |= 0x40000000;
17843 } else {
17844 env->CP0_EBase |= 0x80000000;
17846 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
17847 /* vectored interrupts not implemented, timer on int 7,
17848 no performance counters. */
17849 env->CP0_IntCtl = 0xe0000000;
17851 int i;
17853 for (i = 0; i < 7; i++) {
17854 env->CP0_WatchLo[i] = 0;
17855 env->CP0_WatchHi[i] = 0x80000000;
17857 env->CP0_WatchLo[7] = 0;
17858 env->CP0_WatchHi[7] = 0;
17860 /* Count register increments in debug mode, EJTAG version 1 */
17861 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
17863 cpu_mips_store_count(env, 1);
17865 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
17866 int i;
17868 /* Only TC0 on VPE 0 starts as active. */
17869 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
17870 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
17871 env->tcs[i].CP0_TCHalt = 1;
17873 env->active_tc.CP0_TCHalt = 1;
17874 cs->halted = 1;
17876 if (cs->cpu_index == 0) {
17877 /* VPE0 starts up enabled. */
17878 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
17879 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
17881 /* TC0 starts up unhalted. */
17882 cs->halted = 0;
17883 env->active_tc.CP0_TCHalt = 0;
17884 env->tcs[0].CP0_TCHalt = 0;
17885 /* With thread 0 active. */
17886 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
17887 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
17890 #endif
17891 if ((env->insn_flags & ISA_MIPS32R6) &&
17892 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
17893 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
17894 env->CP0_Status |= (1 << CP0St_FR);
17897 compute_hflags(env);
17898 cs->exception_index = EXCP_NONE;
17901 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
17903 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
17904 env->hflags &= ~MIPS_HFLAG_BMASK;
17905 env->hflags |= gen_opc_hflags[pc_pos];
17906 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
17907 case MIPS_HFLAG_BR:
17908 break;
17909 case MIPS_HFLAG_BC:
17910 case MIPS_HFLAG_BL:
17911 case MIPS_HFLAG_B:
17912 env->btarget = gen_opc_btarget[pc_pos];
17913 break;