target-mips: add TLBINV support
[qemu/ar7.git] / target-mips / translate.c
blobfdb61be8d3aa4f7131a7a3ae2a8ae07462434d5c
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_TLBINV = 0x03 | OPC_C0,
900 OPC_TLBINVF = 0x04 | OPC_C0,
901 OPC_TLBWR = 0x06 | OPC_C0,
902 OPC_TLBP = 0x08 | OPC_C0,
903 OPC_RFE = 0x10 | OPC_C0,
904 OPC_ERET = 0x18 | OPC_C0,
905 OPC_DERET = 0x1F | OPC_C0,
906 OPC_WAIT = 0x20 | OPC_C0,
909 /* Coprocessor 1 (rs field) */
910 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
912 /* Values for the fmt field in FP instructions */
913 enum {
914 /* 0 - 15 are reserved */
915 FMT_S = 16, /* single fp */
916 FMT_D = 17, /* double fp */
917 FMT_E = 18, /* extended fp */
918 FMT_Q = 19, /* quad fp */
919 FMT_W = 20, /* 32-bit fixed */
920 FMT_L = 21, /* 64-bit fixed */
921 FMT_PS = 22, /* paired single fp */
922 /* 23 - 31 are reserved */
925 enum {
926 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
927 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
928 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
929 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
930 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
931 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
932 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
933 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
934 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
935 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
936 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
937 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
938 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
939 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
940 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
941 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
942 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
943 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
944 OPC_BC1EQZ = (0x09 << 21) | OPC_CP1,
945 OPC_BC1NEZ = (0x0D << 21) | OPC_CP1,
948 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
949 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
951 enum {
952 OPC_BC1F = (0x00 << 16) | OPC_BC1,
953 OPC_BC1T = (0x01 << 16) | OPC_BC1,
954 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
955 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
958 enum {
959 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
960 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
963 enum {
964 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
965 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
968 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
970 enum {
971 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
972 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
973 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
974 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
975 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
976 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
977 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
978 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
979 OPC_BC2 = (0x08 << 21) | OPC_CP2,
980 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
981 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
984 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
986 enum {
987 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
988 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
989 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
990 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
991 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
992 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
993 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
994 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
996 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
997 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
998 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
999 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
1000 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
1001 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
1002 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
1003 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
1005 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
1006 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
1007 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
1008 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
1009 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
1010 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
1011 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
1012 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1014 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1015 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1016 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1017 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1018 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1019 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1020 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1021 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1023 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1024 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1025 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1026 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1027 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1028 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1030 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1031 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1032 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1033 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1034 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1035 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1037 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1038 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1039 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1040 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1041 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1042 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1044 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1045 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1046 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1047 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1048 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1049 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1051 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1052 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1053 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1054 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1055 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1056 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1058 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1059 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1060 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1061 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1062 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1063 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1065 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1066 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1067 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1068 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1069 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1070 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1072 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1073 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1074 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1075 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1076 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1077 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1081 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
1083 enum {
1084 OPC_LWXC1 = 0x00 | OPC_CP3,
1085 OPC_LDXC1 = 0x01 | OPC_CP3,
1086 OPC_LUXC1 = 0x05 | OPC_CP3,
1087 OPC_SWXC1 = 0x08 | OPC_CP3,
1088 OPC_SDXC1 = 0x09 | OPC_CP3,
1089 OPC_SUXC1 = 0x0D | OPC_CP3,
1090 OPC_PREFX = 0x0F | OPC_CP3,
1091 OPC_ALNV_PS = 0x1E | OPC_CP3,
1092 OPC_MADD_S = 0x20 | OPC_CP3,
1093 OPC_MADD_D = 0x21 | OPC_CP3,
1094 OPC_MADD_PS = 0x26 | OPC_CP3,
1095 OPC_MSUB_S = 0x28 | OPC_CP3,
1096 OPC_MSUB_D = 0x29 | OPC_CP3,
1097 OPC_MSUB_PS = 0x2E | OPC_CP3,
1098 OPC_NMADD_S = 0x30 | OPC_CP3,
1099 OPC_NMADD_D = 0x31 | OPC_CP3,
1100 OPC_NMADD_PS= 0x36 | OPC_CP3,
1101 OPC_NMSUB_S = 0x38 | OPC_CP3,
1102 OPC_NMSUB_D = 0x39 | OPC_CP3,
1103 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1106 /* global register indices */
1107 static TCGv_ptr cpu_env;
1108 static TCGv cpu_gpr[32], cpu_PC;
1109 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1110 static TCGv cpu_dspctrl, btarget, bcond;
1111 static TCGv_i32 hflags;
1112 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1113 static TCGv_i64 fpu_f64[32];
1115 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1116 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1118 #include "exec/gen-icount.h"
1120 #define gen_helper_0e0i(name, arg) do { \
1121 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1122 gen_helper_##name(cpu_env, helper_tmp); \
1123 tcg_temp_free_i32(helper_tmp); \
1124 } while(0)
1126 #define gen_helper_0e1i(name, arg1, arg2) do { \
1127 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1128 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1129 tcg_temp_free_i32(helper_tmp); \
1130 } while(0)
1132 #define gen_helper_1e0i(name, ret, arg1) do { \
1133 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1134 gen_helper_##name(ret, cpu_env, helper_tmp); \
1135 tcg_temp_free_i32(helper_tmp); \
1136 } while(0)
1138 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1139 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1140 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1141 tcg_temp_free_i32(helper_tmp); \
1142 } while(0)
1144 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1145 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1146 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1147 tcg_temp_free_i32(helper_tmp); \
1148 } while(0)
1150 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1151 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1152 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1153 tcg_temp_free_i32(helper_tmp); \
1154 } while(0)
1156 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1157 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1158 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1159 tcg_temp_free_i32(helper_tmp); \
1160 } while(0)
1162 typedef struct DisasContext {
1163 struct TranslationBlock *tb;
1164 target_ulong pc, saved_pc;
1165 uint32_t opcode;
1166 int singlestep_enabled;
1167 int insn_flags;
1168 int32_t CP0_Config1;
1169 /* Routine used to access memory */
1170 int mem_idx;
1171 uint32_t hflags, saved_hflags;
1172 int bstate;
1173 target_ulong btarget;
1174 bool ulri;
1175 int kscrexist;
1176 bool rxi;
1177 int ie;
1178 } DisasContext;
1180 enum {
1181 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1182 * exception condition */
1183 BS_STOP = 1, /* We want to stop translation for any reason */
1184 BS_BRANCH = 2, /* We reached a branch condition */
1185 BS_EXCP = 3, /* We reached an exception condition */
1188 static const char * const regnames[] = {
1189 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1190 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1191 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1192 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1195 static const char * const regnames_HI[] = {
1196 "HI0", "HI1", "HI2", "HI3",
1199 static const char * const regnames_LO[] = {
1200 "LO0", "LO1", "LO2", "LO3",
1203 static const char * const fregnames[] = {
1204 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1205 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1206 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1207 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1210 #define MIPS_DEBUG(fmt, ...) \
1211 do { \
1212 if (MIPS_DEBUG_DISAS) { \
1213 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1214 TARGET_FMT_lx ": %08x " fmt "\n", \
1215 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1217 } while (0)
1219 #define LOG_DISAS(...) \
1220 do { \
1221 if (MIPS_DEBUG_DISAS) { \
1222 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1224 } while (0)
1226 #define MIPS_INVAL(op) \
1227 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1228 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1230 /* General purpose registers moves. */
1231 static inline void gen_load_gpr (TCGv t, int reg)
1233 if (reg == 0)
1234 tcg_gen_movi_tl(t, 0);
1235 else
1236 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1239 static inline void gen_store_gpr (TCGv t, int reg)
1241 if (reg != 0)
1242 tcg_gen_mov_tl(cpu_gpr[reg], t);
1245 /* Moves to/from shadow registers. */
1246 static inline void gen_load_srsgpr (int from, int to)
1248 TCGv t0 = tcg_temp_new();
1250 if (from == 0)
1251 tcg_gen_movi_tl(t0, 0);
1252 else {
1253 TCGv_i32 t2 = tcg_temp_new_i32();
1254 TCGv_ptr addr = tcg_temp_new_ptr();
1256 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1257 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1258 tcg_gen_andi_i32(t2, t2, 0xf);
1259 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1260 tcg_gen_ext_i32_ptr(addr, t2);
1261 tcg_gen_add_ptr(addr, cpu_env, addr);
1263 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1264 tcg_temp_free_ptr(addr);
1265 tcg_temp_free_i32(t2);
1267 gen_store_gpr(t0, to);
1268 tcg_temp_free(t0);
1271 static inline void gen_store_srsgpr (int from, int to)
1273 if (to != 0) {
1274 TCGv t0 = tcg_temp_new();
1275 TCGv_i32 t2 = tcg_temp_new_i32();
1276 TCGv_ptr addr = tcg_temp_new_ptr();
1278 gen_load_gpr(t0, from);
1279 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1280 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1281 tcg_gen_andi_i32(t2, t2, 0xf);
1282 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1283 tcg_gen_ext_i32_ptr(addr, t2);
1284 tcg_gen_add_ptr(addr, cpu_env, addr);
1286 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1287 tcg_temp_free_ptr(addr);
1288 tcg_temp_free_i32(t2);
1289 tcg_temp_free(t0);
1293 /* Floating point register moves. */
1294 static void gen_load_fpr32(TCGv_i32 t, int reg)
1296 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1299 static void gen_store_fpr32(TCGv_i32 t, int reg)
1301 TCGv_i64 t64 = tcg_temp_new_i64();
1302 tcg_gen_extu_i32_i64(t64, t);
1303 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1304 tcg_temp_free_i64(t64);
1307 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1309 if (ctx->hflags & MIPS_HFLAG_F64) {
1310 TCGv_i64 t64 = tcg_temp_new_i64();
1311 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1312 tcg_gen_trunc_i64_i32(t, t64);
1313 tcg_temp_free_i64(t64);
1314 } else {
1315 gen_load_fpr32(t, reg | 1);
1319 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1321 if (ctx->hflags & MIPS_HFLAG_F64) {
1322 TCGv_i64 t64 = tcg_temp_new_i64();
1323 tcg_gen_extu_i32_i64(t64, t);
1324 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1325 tcg_temp_free_i64(t64);
1326 } else {
1327 gen_store_fpr32(t, reg | 1);
1331 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1333 if (ctx->hflags & MIPS_HFLAG_F64) {
1334 tcg_gen_mov_i64(t, fpu_f64[reg]);
1335 } else {
1336 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1340 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1342 if (ctx->hflags & MIPS_HFLAG_F64) {
1343 tcg_gen_mov_i64(fpu_f64[reg], t);
1344 } else {
1345 TCGv_i64 t0;
1346 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1347 t0 = tcg_temp_new_i64();
1348 tcg_gen_shri_i64(t0, t, 32);
1349 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1350 tcg_temp_free_i64(t0);
1354 static inline int get_fp_bit (int cc)
1356 if (cc)
1357 return 24 + cc;
1358 else
1359 return 23;
1362 /* Tests */
1363 static inline void gen_save_pc(target_ulong pc)
1365 tcg_gen_movi_tl(cpu_PC, pc);
1368 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1370 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1371 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1372 gen_save_pc(ctx->pc);
1373 ctx->saved_pc = ctx->pc;
1375 if (ctx->hflags != ctx->saved_hflags) {
1376 tcg_gen_movi_i32(hflags, ctx->hflags);
1377 ctx->saved_hflags = ctx->hflags;
1378 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1379 case MIPS_HFLAG_BR:
1380 break;
1381 case MIPS_HFLAG_BC:
1382 case MIPS_HFLAG_BL:
1383 case MIPS_HFLAG_B:
1384 tcg_gen_movi_tl(btarget, ctx->btarget);
1385 break;
1390 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1392 ctx->saved_hflags = ctx->hflags;
1393 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1394 case MIPS_HFLAG_BR:
1395 break;
1396 case MIPS_HFLAG_BC:
1397 case MIPS_HFLAG_BL:
1398 case MIPS_HFLAG_B:
1399 ctx->btarget = env->btarget;
1400 break;
1404 static inline void
1405 generate_exception_err (DisasContext *ctx, int excp, int err)
1407 TCGv_i32 texcp = tcg_const_i32(excp);
1408 TCGv_i32 terr = tcg_const_i32(err);
1409 save_cpu_state(ctx, 1);
1410 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1411 tcg_temp_free_i32(terr);
1412 tcg_temp_free_i32(texcp);
1415 static inline void
1416 generate_exception (DisasContext *ctx, int excp)
1418 save_cpu_state(ctx, 1);
1419 gen_helper_0e0i(raise_exception, excp);
1422 /* Addresses computation */
1423 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1425 tcg_gen_add_tl(ret, arg0, arg1);
1427 #if defined(TARGET_MIPS64)
1428 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1429 tcg_gen_ext32s_i64(ret, ret);
1431 #endif
1434 /* Addresses computation (translation time) */
1435 static target_long addr_add(DisasContext *ctx, target_long base,
1436 target_long offset)
1438 target_long sum = base + offset;
1440 #if defined(TARGET_MIPS64)
1441 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1442 sum = (int32_t)sum;
1444 #endif
1445 return sum;
1448 static inline void check_cp0_enabled(DisasContext *ctx)
1450 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1451 generate_exception_err(ctx, EXCP_CpU, 0);
1454 static inline void check_cp1_enabled(DisasContext *ctx)
1456 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1457 generate_exception_err(ctx, EXCP_CpU, 1);
1460 /* Verify that the processor is running with COP1X instructions enabled.
1461 This is associated with the nabla symbol in the MIPS32 and MIPS64
1462 opcode tables. */
1464 static inline void check_cop1x(DisasContext *ctx)
1466 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1467 generate_exception(ctx, EXCP_RI);
1470 /* Verify that the processor is running with 64-bit floating-point
1471 operations enabled. */
1473 static inline void check_cp1_64bitmode(DisasContext *ctx)
1475 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1476 generate_exception(ctx, EXCP_RI);
1480 * Verify if floating point register is valid; an operation is not defined
1481 * if bit 0 of any register specification is set and the FR bit in the
1482 * Status register equals zero, since the register numbers specify an
1483 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1484 * in the Status register equals one, both even and odd register numbers
1485 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1487 * Multiple 64 bit wide registers can be checked by calling
1488 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1490 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1492 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1493 generate_exception(ctx, EXCP_RI);
1496 /* Verify that the processor is running with DSP instructions enabled.
1497 This is enabled by CP0 Status register MX(24) bit.
1500 static inline void check_dsp(DisasContext *ctx)
1502 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1503 if (ctx->insn_flags & ASE_DSP) {
1504 generate_exception(ctx, EXCP_DSPDIS);
1505 } else {
1506 generate_exception(ctx, EXCP_RI);
1511 static inline void check_dspr2(DisasContext *ctx)
1513 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1514 if (ctx->insn_flags & ASE_DSP) {
1515 generate_exception(ctx, EXCP_DSPDIS);
1516 } else {
1517 generate_exception(ctx, EXCP_RI);
1522 /* This code generates a "reserved instruction" exception if the
1523 CPU does not support the instruction set corresponding to flags. */
1524 static inline void check_insn(DisasContext *ctx, int flags)
1526 if (unlikely(!(ctx->insn_flags & flags))) {
1527 generate_exception(ctx, EXCP_RI);
1531 /* This code generates a "reserved instruction" exception if the
1532 CPU has corresponding flag set which indicates that the instruction
1533 has been removed. */
1534 static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
1536 if (unlikely(ctx->insn_flags & flags)) {
1537 generate_exception(ctx, EXCP_RI);
1541 #ifdef TARGET_MIPS64
1542 /* This code generates a "reserved instruction" exception if 64-bit
1543 instructions are not enabled. */
1544 static inline void check_mips_64(DisasContext *ctx)
1546 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1547 generate_exception(ctx, EXCP_RI);
1549 #endif
1551 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1552 calling interface for 32 and 64-bit FPRs. No sense in changing
1553 all callers for gen_load_fpr32 when we need the CTX parameter for
1554 this one use. */
1555 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1556 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1557 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1558 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1559 int ft, int fs, int cc) \
1561 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1562 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1563 switch (ifmt) { \
1564 case FMT_PS: \
1565 check_cp1_64bitmode(ctx); \
1566 break; \
1567 case FMT_D: \
1568 if (abs) { \
1569 check_cop1x(ctx); \
1571 check_cp1_registers(ctx, fs | ft); \
1572 break; \
1573 case FMT_S: \
1574 if (abs) { \
1575 check_cop1x(ctx); \
1577 break; \
1579 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1580 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1581 switch (n) { \
1582 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1583 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1584 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1585 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1586 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1587 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1588 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1589 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1590 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1591 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1592 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1593 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1594 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1595 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1596 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1597 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1598 default: abort(); \
1600 tcg_temp_free_i##bits (fp0); \
1601 tcg_temp_free_i##bits (fp1); \
1604 FOP_CONDS(, 0, d, FMT_D, 64)
1605 FOP_CONDS(abs, 1, d, FMT_D, 64)
1606 FOP_CONDS(, 0, s, FMT_S, 32)
1607 FOP_CONDS(abs, 1, s, FMT_S, 32)
1608 FOP_CONDS(, 0, ps, FMT_PS, 64)
1609 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1610 #undef FOP_CONDS
1612 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1613 static inline void gen_r6_cmp_ ## fmt(DisasContext * ctx, int n, \
1614 int ft, int fs, int fd) \
1616 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1617 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1618 switch (ifmt) { \
1619 case FMT_D: \
1620 check_cp1_registers(ctx, fs | ft | fd); \
1621 break; \
1623 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1624 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1625 switch (n) { \
1626 case 0: \
1627 gen_helper_r6_cmp_ ## fmt ## _af(fp0, cpu_env, fp0, fp1); \
1628 break; \
1629 case 1: \
1630 gen_helper_r6_cmp_ ## fmt ## _un(fp0, cpu_env, fp0, fp1); \
1631 break; \
1632 case 2: \
1633 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, cpu_env, fp0, fp1); \
1634 break; \
1635 case 3: \
1636 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, cpu_env, fp0, fp1); \
1637 break; \
1638 case 4: \
1639 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, cpu_env, fp0, fp1); \
1640 break; \
1641 case 5: \
1642 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, cpu_env, fp0, fp1); \
1643 break; \
1644 case 6: \
1645 gen_helper_r6_cmp_ ## fmt ## _le(fp0, cpu_env, fp0, fp1); \
1646 break; \
1647 case 7: \
1648 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, cpu_env, fp0, fp1); \
1649 break; \
1650 case 8: \
1651 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, cpu_env, fp0, fp1); \
1652 break; \
1653 case 9: \
1654 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, cpu_env, fp0, fp1); \
1655 break; \
1656 case 10: \
1657 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, cpu_env, fp0, fp1); \
1658 break; \
1659 case 11: \
1660 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, cpu_env, fp0, fp1); \
1661 break; \
1662 case 12: \
1663 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, cpu_env, fp0, fp1); \
1664 break; \
1665 case 13: \
1666 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, cpu_env, fp0, fp1); \
1667 break; \
1668 case 14: \
1669 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, cpu_env, fp0, fp1); \
1670 break; \
1671 case 15: \
1672 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, cpu_env, fp0, fp1); \
1673 break; \
1674 case 17: \
1675 gen_helper_r6_cmp_ ## fmt ## _or(fp0, cpu_env, fp0, fp1); \
1676 break; \
1677 case 18: \
1678 gen_helper_r6_cmp_ ## fmt ## _une(fp0, cpu_env, fp0, fp1); \
1679 break; \
1680 case 19: \
1681 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, cpu_env, fp0, fp1); \
1682 break; \
1683 case 25: \
1684 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, cpu_env, fp0, fp1); \
1685 break; \
1686 case 26: \
1687 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, cpu_env, fp0, fp1); \
1688 break; \
1689 case 27: \
1690 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, cpu_env, fp0, fp1); \
1691 break; \
1692 default: \
1693 abort(); \
1695 STORE; \
1696 tcg_temp_free_i ## bits (fp0); \
1697 tcg_temp_free_i ## bits (fp1); \
1700 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1701 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(fp0, fd))
1702 #undef FOP_CONDNS
1703 #undef gen_ldcmp_fpr32
1704 #undef gen_ldcmp_fpr64
1706 /* load/store instructions. */
1707 #ifdef CONFIG_USER_ONLY
1708 #define OP_LD_ATOMIC(insn,fname) \
1709 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1711 TCGv t0 = tcg_temp_new(); \
1712 tcg_gen_mov_tl(t0, arg1); \
1713 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1714 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1715 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1716 tcg_temp_free(t0); \
1718 #else
1719 #define OP_LD_ATOMIC(insn,fname) \
1720 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1722 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1724 #endif
1725 OP_LD_ATOMIC(ll,ld32s);
1726 #if defined(TARGET_MIPS64)
1727 OP_LD_ATOMIC(lld,ld64);
1728 #endif
1729 #undef OP_LD_ATOMIC
1731 #ifdef CONFIG_USER_ONLY
1732 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1733 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1735 TCGv t0 = tcg_temp_new(); \
1736 int l1 = gen_new_label(); \
1737 int l2 = gen_new_label(); \
1739 tcg_gen_andi_tl(t0, arg2, almask); \
1740 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
1741 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
1742 generate_exception(ctx, EXCP_AdES); \
1743 gen_set_label(l1); \
1744 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1745 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1746 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
1747 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1748 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
1749 gen_helper_0e0i(raise_exception, EXCP_SC); \
1750 gen_set_label(l2); \
1751 tcg_gen_movi_tl(t0, 0); \
1752 gen_store_gpr(t0, rt); \
1753 tcg_temp_free(t0); \
1755 #else
1756 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1757 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1759 TCGv t0 = tcg_temp_new(); \
1760 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
1761 gen_store_gpr(t0, rt); \
1762 tcg_temp_free(t0); \
1764 #endif
1765 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1766 #if defined(TARGET_MIPS64)
1767 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1768 #endif
1769 #undef OP_ST_ATOMIC
1771 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1772 int base, int16_t offset)
1774 if (base == 0) {
1775 tcg_gen_movi_tl(addr, offset);
1776 } else if (offset == 0) {
1777 gen_load_gpr(addr, base);
1778 } else {
1779 tcg_gen_movi_tl(addr, offset);
1780 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1784 static target_ulong pc_relative_pc (DisasContext *ctx)
1786 target_ulong pc = ctx->pc;
1788 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1789 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1791 pc -= branch_bytes;
1794 pc &= ~(target_ulong)3;
1795 return pc;
1798 /* Load */
1799 static void gen_ld(DisasContext *ctx, uint32_t opc,
1800 int rt, int base, int16_t offset)
1802 const char *opn = "ld";
1803 TCGv t0, t1, t2;
1805 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1806 /* Loongson CPU uses a load to zero register for prefetch.
1807 We emulate it as a NOP. On other CPU we must perform the
1808 actual memory access. */
1809 MIPS_DEBUG("NOP");
1810 return;
1813 t0 = tcg_temp_new();
1814 gen_base_offset_addr(ctx, t0, base, offset);
1816 switch (opc) {
1817 #if defined(TARGET_MIPS64)
1818 case OPC_LWU:
1819 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1820 gen_store_gpr(t0, rt);
1821 opn = "lwu";
1822 break;
1823 case OPC_LD:
1824 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1825 gen_store_gpr(t0, rt);
1826 opn = "ld";
1827 break;
1828 case OPC_LLD:
1829 case R6_OPC_LLD:
1830 save_cpu_state(ctx, 1);
1831 op_ld_lld(t0, t0, ctx);
1832 gen_store_gpr(t0, rt);
1833 opn = "lld";
1834 break;
1835 case OPC_LDL:
1836 t1 = tcg_temp_new();
1837 tcg_gen_andi_tl(t1, t0, 7);
1838 #ifndef TARGET_WORDS_BIGENDIAN
1839 tcg_gen_xori_tl(t1, t1, 7);
1840 #endif
1841 tcg_gen_shli_tl(t1, t1, 3);
1842 tcg_gen_andi_tl(t0, t0, ~7);
1843 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1844 tcg_gen_shl_tl(t0, t0, t1);
1845 tcg_gen_xori_tl(t1, t1, 63);
1846 t2 = tcg_const_tl(0x7fffffffffffffffull);
1847 tcg_gen_shr_tl(t2, t2, t1);
1848 gen_load_gpr(t1, rt);
1849 tcg_gen_and_tl(t1, t1, t2);
1850 tcg_temp_free(t2);
1851 tcg_gen_or_tl(t0, t0, t1);
1852 tcg_temp_free(t1);
1853 gen_store_gpr(t0, rt);
1854 opn = "ldl";
1855 break;
1856 case OPC_LDR:
1857 t1 = tcg_temp_new();
1858 tcg_gen_andi_tl(t1, t0, 7);
1859 #ifdef TARGET_WORDS_BIGENDIAN
1860 tcg_gen_xori_tl(t1, t1, 7);
1861 #endif
1862 tcg_gen_shli_tl(t1, t1, 3);
1863 tcg_gen_andi_tl(t0, t0, ~7);
1864 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1865 tcg_gen_shr_tl(t0, t0, t1);
1866 tcg_gen_xori_tl(t1, t1, 63);
1867 t2 = tcg_const_tl(0xfffffffffffffffeull);
1868 tcg_gen_shl_tl(t2, t2, t1);
1869 gen_load_gpr(t1, rt);
1870 tcg_gen_and_tl(t1, t1, t2);
1871 tcg_temp_free(t2);
1872 tcg_gen_or_tl(t0, t0, t1);
1873 tcg_temp_free(t1);
1874 gen_store_gpr(t0, rt);
1875 opn = "ldr";
1876 break;
1877 case OPC_LDPC:
1878 t1 = tcg_const_tl(pc_relative_pc(ctx));
1879 gen_op_addr_add(ctx, t0, t0, t1);
1880 tcg_temp_free(t1);
1881 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1882 gen_store_gpr(t0, rt);
1883 opn = "ldpc";
1884 break;
1885 #endif
1886 case OPC_LWPC:
1887 t1 = tcg_const_tl(pc_relative_pc(ctx));
1888 gen_op_addr_add(ctx, t0, t0, t1);
1889 tcg_temp_free(t1);
1890 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1891 gen_store_gpr(t0, rt);
1892 opn = "lwpc";
1893 break;
1894 case OPC_LW:
1895 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1896 gen_store_gpr(t0, rt);
1897 opn = "lw";
1898 break;
1899 case OPC_LH:
1900 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
1901 gen_store_gpr(t0, rt);
1902 opn = "lh";
1903 break;
1904 case OPC_LHU:
1905 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
1906 gen_store_gpr(t0, rt);
1907 opn = "lhu";
1908 break;
1909 case OPC_LB:
1910 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
1911 gen_store_gpr(t0, rt);
1912 opn = "lb";
1913 break;
1914 case OPC_LBU:
1915 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
1916 gen_store_gpr(t0, rt);
1917 opn = "lbu";
1918 break;
1919 case OPC_LWL:
1920 t1 = tcg_temp_new();
1921 tcg_gen_andi_tl(t1, t0, 3);
1922 #ifndef TARGET_WORDS_BIGENDIAN
1923 tcg_gen_xori_tl(t1, t1, 3);
1924 #endif
1925 tcg_gen_shli_tl(t1, t1, 3);
1926 tcg_gen_andi_tl(t0, t0, ~3);
1927 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1928 tcg_gen_shl_tl(t0, t0, t1);
1929 tcg_gen_xori_tl(t1, t1, 31);
1930 t2 = tcg_const_tl(0x7fffffffull);
1931 tcg_gen_shr_tl(t2, t2, t1);
1932 gen_load_gpr(t1, rt);
1933 tcg_gen_and_tl(t1, t1, t2);
1934 tcg_temp_free(t2);
1935 tcg_gen_or_tl(t0, t0, t1);
1936 tcg_temp_free(t1);
1937 tcg_gen_ext32s_tl(t0, t0);
1938 gen_store_gpr(t0, rt);
1939 opn = "lwl";
1940 break;
1941 case OPC_LWR:
1942 t1 = tcg_temp_new();
1943 tcg_gen_andi_tl(t1, t0, 3);
1944 #ifdef TARGET_WORDS_BIGENDIAN
1945 tcg_gen_xori_tl(t1, t1, 3);
1946 #endif
1947 tcg_gen_shli_tl(t1, t1, 3);
1948 tcg_gen_andi_tl(t0, t0, ~3);
1949 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1950 tcg_gen_shr_tl(t0, t0, t1);
1951 tcg_gen_xori_tl(t1, t1, 31);
1952 t2 = tcg_const_tl(0xfffffffeull);
1953 tcg_gen_shl_tl(t2, t2, t1);
1954 gen_load_gpr(t1, rt);
1955 tcg_gen_and_tl(t1, t1, t2);
1956 tcg_temp_free(t2);
1957 tcg_gen_or_tl(t0, t0, t1);
1958 tcg_temp_free(t1);
1959 tcg_gen_ext32s_tl(t0, t0);
1960 gen_store_gpr(t0, rt);
1961 opn = "lwr";
1962 break;
1963 case OPC_LL:
1964 case R6_OPC_LL:
1965 save_cpu_state(ctx, 1);
1966 op_ld_ll(t0, t0, ctx);
1967 gen_store_gpr(t0, rt);
1968 opn = "ll";
1969 break;
1971 (void)opn; /* avoid a compiler warning */
1972 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1973 tcg_temp_free(t0);
1976 /* Store */
1977 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1978 int base, int16_t offset)
1980 const char *opn = "st";
1981 TCGv t0 = tcg_temp_new();
1982 TCGv t1 = tcg_temp_new();
1984 gen_base_offset_addr(ctx, t0, base, offset);
1985 gen_load_gpr(t1, rt);
1986 switch (opc) {
1987 #if defined(TARGET_MIPS64)
1988 case OPC_SD:
1989 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
1990 opn = "sd";
1991 break;
1992 case OPC_SDL:
1993 save_cpu_state(ctx, 1);
1994 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
1995 opn = "sdl";
1996 break;
1997 case OPC_SDR:
1998 save_cpu_state(ctx, 1);
1999 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
2000 opn = "sdr";
2001 break;
2002 #endif
2003 case OPC_SW:
2004 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
2005 opn = "sw";
2006 break;
2007 case OPC_SH:
2008 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
2009 opn = "sh";
2010 break;
2011 case OPC_SB:
2012 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
2013 opn = "sb";
2014 break;
2015 case OPC_SWL:
2016 save_cpu_state(ctx, 1);
2017 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
2018 opn = "swl";
2019 break;
2020 case OPC_SWR:
2021 save_cpu_state(ctx, 1);
2022 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
2023 opn = "swr";
2024 break;
2026 (void)opn; /* avoid a compiler warning */
2027 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2028 tcg_temp_free(t0);
2029 tcg_temp_free(t1);
2033 /* Store conditional */
2034 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
2035 int base, int16_t offset)
2037 const char *opn = "st_cond";
2038 TCGv t0, t1;
2040 #ifdef CONFIG_USER_ONLY
2041 t0 = tcg_temp_local_new();
2042 t1 = tcg_temp_local_new();
2043 #else
2044 t0 = tcg_temp_new();
2045 t1 = tcg_temp_new();
2046 #endif
2047 gen_base_offset_addr(ctx, t0, base, offset);
2048 gen_load_gpr(t1, rt);
2049 switch (opc) {
2050 #if defined(TARGET_MIPS64)
2051 case OPC_SCD:
2052 case R6_OPC_SCD:
2053 save_cpu_state(ctx, 1);
2054 op_st_scd(t1, t0, rt, ctx);
2055 opn = "scd";
2056 break;
2057 #endif
2058 case OPC_SC:
2059 case R6_OPC_SC:
2060 save_cpu_state(ctx, 1);
2061 op_st_sc(t1, t0, rt, ctx);
2062 opn = "sc";
2063 break;
2065 (void)opn; /* avoid a compiler warning */
2066 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
2067 tcg_temp_free(t1);
2068 tcg_temp_free(t0);
2071 /* Load and store */
2072 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
2073 int base, int16_t offset)
2075 const char *opn = "flt_ldst";
2076 TCGv t0 = tcg_temp_new();
2078 gen_base_offset_addr(ctx, t0, base, offset);
2079 /* Don't do NOP if destination is zero: we must perform the actual
2080 memory access. */
2081 switch (opc) {
2082 case OPC_LWC1:
2084 TCGv_i32 fp0 = tcg_temp_new_i32();
2085 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
2086 gen_store_fpr32(fp0, ft);
2087 tcg_temp_free_i32(fp0);
2089 opn = "lwc1";
2090 break;
2091 case OPC_SWC1:
2093 TCGv_i32 fp0 = tcg_temp_new_i32();
2094 gen_load_fpr32(fp0, ft);
2095 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
2096 tcg_temp_free_i32(fp0);
2098 opn = "swc1";
2099 break;
2100 case OPC_LDC1:
2102 TCGv_i64 fp0 = tcg_temp_new_i64();
2103 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2104 gen_store_fpr64(ctx, fp0, ft);
2105 tcg_temp_free_i64(fp0);
2107 opn = "ldc1";
2108 break;
2109 case OPC_SDC1:
2111 TCGv_i64 fp0 = tcg_temp_new_i64();
2112 gen_load_fpr64(ctx, fp0, ft);
2113 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
2114 tcg_temp_free_i64(fp0);
2116 opn = "sdc1";
2117 break;
2118 default:
2119 MIPS_INVAL(opn);
2120 generate_exception(ctx, EXCP_RI);
2121 goto out;
2123 (void)opn; /* avoid a compiler warning */
2124 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
2125 out:
2126 tcg_temp_free(t0);
2129 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2130 int rs, int16_t imm)
2132 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2133 check_cp1_enabled(ctx);
2134 gen_flt_ldst(ctx, op, rt, rs, imm);
2135 } else {
2136 generate_exception_err(ctx, EXCP_CpU, 1);
2140 /* Arithmetic with immediate operand */
2141 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2142 int rt, int rs, int16_t imm)
2144 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2145 const char *opn = "imm arith";
2147 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2148 /* If no destination, treat it as a NOP.
2149 For addi, we must generate the overflow exception when needed. */
2150 MIPS_DEBUG("NOP");
2151 return;
2153 switch (opc) {
2154 case OPC_ADDI:
2156 TCGv t0 = tcg_temp_local_new();
2157 TCGv t1 = tcg_temp_new();
2158 TCGv t2 = tcg_temp_new();
2159 int l1 = gen_new_label();
2161 gen_load_gpr(t1, rs);
2162 tcg_gen_addi_tl(t0, t1, uimm);
2163 tcg_gen_ext32s_tl(t0, t0);
2165 tcg_gen_xori_tl(t1, t1, ~uimm);
2166 tcg_gen_xori_tl(t2, t0, uimm);
2167 tcg_gen_and_tl(t1, t1, t2);
2168 tcg_temp_free(t2);
2169 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2170 tcg_temp_free(t1);
2171 /* operands of same sign, result different sign */
2172 generate_exception(ctx, EXCP_OVERFLOW);
2173 gen_set_label(l1);
2174 tcg_gen_ext32s_tl(t0, t0);
2175 gen_store_gpr(t0, rt);
2176 tcg_temp_free(t0);
2178 opn = "addi";
2179 break;
2180 case OPC_ADDIU:
2181 if (rs != 0) {
2182 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2183 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2184 } else {
2185 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2187 opn = "addiu";
2188 break;
2189 #if defined(TARGET_MIPS64)
2190 case OPC_DADDI:
2192 TCGv t0 = tcg_temp_local_new();
2193 TCGv t1 = tcg_temp_new();
2194 TCGv t2 = tcg_temp_new();
2195 int l1 = gen_new_label();
2197 gen_load_gpr(t1, rs);
2198 tcg_gen_addi_tl(t0, t1, uimm);
2200 tcg_gen_xori_tl(t1, t1, ~uimm);
2201 tcg_gen_xori_tl(t2, t0, uimm);
2202 tcg_gen_and_tl(t1, t1, t2);
2203 tcg_temp_free(t2);
2204 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2205 tcg_temp_free(t1);
2206 /* operands of same sign, result different sign */
2207 generate_exception(ctx, EXCP_OVERFLOW);
2208 gen_set_label(l1);
2209 gen_store_gpr(t0, rt);
2210 tcg_temp_free(t0);
2212 opn = "daddi";
2213 break;
2214 case OPC_DADDIU:
2215 if (rs != 0) {
2216 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2217 } else {
2218 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2220 opn = "daddiu";
2221 break;
2222 #endif
2224 (void)opn; /* avoid a compiler warning */
2225 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2228 /* Logic with immediate operand */
2229 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2230 int rt, int rs, int16_t imm)
2232 target_ulong uimm;
2234 if (rt == 0) {
2235 /* If no destination, treat it as a NOP. */
2236 MIPS_DEBUG("NOP");
2237 return;
2239 uimm = (uint16_t)imm;
2240 switch (opc) {
2241 case OPC_ANDI:
2242 if (likely(rs != 0))
2243 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2244 else
2245 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2246 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2247 regnames[rs], uimm);
2248 break;
2249 case OPC_ORI:
2250 if (rs != 0)
2251 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2252 else
2253 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2254 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2255 regnames[rs], uimm);
2256 break;
2257 case OPC_XORI:
2258 if (likely(rs != 0))
2259 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2260 else
2261 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2262 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2263 regnames[rs], uimm);
2264 break;
2265 case OPC_LUI:
2266 if (rs != 0 && (ctx->insn_flags & ISA_MIPS32R6)) {
2267 /* OPC_AUI */
2268 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2269 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2270 MIPS_DEBUG("aui %s, %s, %04x", regnames[rt], regnames[rs], imm);
2271 } else {
2272 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2273 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2275 break;
2277 default:
2278 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2279 break;
2283 /* Set on less than with immediate operand */
2284 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2285 int rt, int rs, int16_t imm)
2287 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2288 const char *opn = "imm arith";
2289 TCGv t0;
2291 if (rt == 0) {
2292 /* If no destination, treat it as a NOP. */
2293 MIPS_DEBUG("NOP");
2294 return;
2296 t0 = tcg_temp_new();
2297 gen_load_gpr(t0, rs);
2298 switch (opc) {
2299 case OPC_SLTI:
2300 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2301 opn = "slti";
2302 break;
2303 case OPC_SLTIU:
2304 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2305 opn = "sltiu";
2306 break;
2308 (void)opn; /* avoid a compiler warning */
2309 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2310 tcg_temp_free(t0);
2313 /* Shifts with immediate operand */
2314 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2315 int rt, int rs, int16_t imm)
2317 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2318 const char *opn = "imm shift";
2319 TCGv t0;
2321 if (rt == 0) {
2322 /* If no destination, treat it as a NOP. */
2323 MIPS_DEBUG("NOP");
2324 return;
2327 t0 = tcg_temp_new();
2328 gen_load_gpr(t0, rs);
2329 switch (opc) {
2330 case OPC_SLL:
2331 tcg_gen_shli_tl(t0, t0, uimm);
2332 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2333 opn = "sll";
2334 break;
2335 case OPC_SRA:
2336 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2337 opn = "sra";
2338 break;
2339 case OPC_SRL:
2340 if (uimm != 0) {
2341 tcg_gen_ext32u_tl(t0, t0);
2342 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2343 } else {
2344 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2346 opn = "srl";
2347 break;
2348 case OPC_ROTR:
2349 if (uimm != 0) {
2350 TCGv_i32 t1 = tcg_temp_new_i32();
2352 tcg_gen_trunc_tl_i32(t1, t0);
2353 tcg_gen_rotri_i32(t1, t1, uimm);
2354 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2355 tcg_temp_free_i32(t1);
2356 } else {
2357 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2359 opn = "rotr";
2360 break;
2361 #if defined(TARGET_MIPS64)
2362 case OPC_DSLL:
2363 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2364 opn = "dsll";
2365 break;
2366 case OPC_DSRA:
2367 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2368 opn = "dsra";
2369 break;
2370 case OPC_DSRL:
2371 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2372 opn = "dsrl";
2373 break;
2374 case OPC_DROTR:
2375 if (uimm != 0) {
2376 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2377 } else {
2378 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2380 opn = "drotr";
2381 break;
2382 case OPC_DSLL32:
2383 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2384 opn = "dsll32";
2385 break;
2386 case OPC_DSRA32:
2387 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2388 opn = "dsra32";
2389 break;
2390 case OPC_DSRL32:
2391 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2392 opn = "dsrl32";
2393 break;
2394 case OPC_DROTR32:
2395 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2396 opn = "drotr32";
2397 break;
2398 #endif
2400 (void)opn; /* avoid a compiler warning */
2401 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2402 tcg_temp_free(t0);
2405 /* Arithmetic */
2406 static void gen_arith(DisasContext *ctx, uint32_t opc,
2407 int rd, int rs, int rt)
2409 const char *opn = "arith";
2411 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2412 && opc != OPC_DADD && opc != OPC_DSUB) {
2413 /* If no destination, treat it as a NOP.
2414 For add & sub, we must generate the overflow exception when needed. */
2415 MIPS_DEBUG("NOP");
2416 return;
2419 switch (opc) {
2420 case OPC_ADD:
2422 TCGv t0 = tcg_temp_local_new();
2423 TCGv t1 = tcg_temp_new();
2424 TCGv t2 = tcg_temp_new();
2425 int l1 = gen_new_label();
2427 gen_load_gpr(t1, rs);
2428 gen_load_gpr(t2, rt);
2429 tcg_gen_add_tl(t0, t1, t2);
2430 tcg_gen_ext32s_tl(t0, t0);
2431 tcg_gen_xor_tl(t1, t1, t2);
2432 tcg_gen_xor_tl(t2, t0, t2);
2433 tcg_gen_andc_tl(t1, t2, t1);
2434 tcg_temp_free(t2);
2435 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2436 tcg_temp_free(t1);
2437 /* operands of same sign, result different sign */
2438 generate_exception(ctx, EXCP_OVERFLOW);
2439 gen_set_label(l1);
2440 gen_store_gpr(t0, rd);
2441 tcg_temp_free(t0);
2443 opn = "add";
2444 break;
2445 case OPC_ADDU:
2446 if (rs != 0 && rt != 0) {
2447 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2448 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2449 } else if (rs == 0 && rt != 0) {
2450 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2451 } else if (rs != 0 && rt == 0) {
2452 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2453 } else {
2454 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2456 opn = "addu";
2457 break;
2458 case OPC_SUB:
2460 TCGv t0 = tcg_temp_local_new();
2461 TCGv t1 = tcg_temp_new();
2462 TCGv t2 = tcg_temp_new();
2463 int l1 = gen_new_label();
2465 gen_load_gpr(t1, rs);
2466 gen_load_gpr(t2, rt);
2467 tcg_gen_sub_tl(t0, t1, t2);
2468 tcg_gen_ext32s_tl(t0, t0);
2469 tcg_gen_xor_tl(t2, t1, t2);
2470 tcg_gen_xor_tl(t1, t0, t1);
2471 tcg_gen_and_tl(t1, t1, t2);
2472 tcg_temp_free(t2);
2473 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2474 tcg_temp_free(t1);
2475 /* operands of different sign, first operand and result different sign */
2476 generate_exception(ctx, EXCP_OVERFLOW);
2477 gen_set_label(l1);
2478 gen_store_gpr(t0, rd);
2479 tcg_temp_free(t0);
2481 opn = "sub";
2482 break;
2483 case OPC_SUBU:
2484 if (rs != 0 && rt != 0) {
2485 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2486 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2487 } else if (rs == 0 && rt != 0) {
2488 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2489 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2490 } else if (rs != 0 && rt == 0) {
2491 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2492 } else {
2493 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2495 opn = "subu";
2496 break;
2497 #if defined(TARGET_MIPS64)
2498 case OPC_DADD:
2500 TCGv t0 = tcg_temp_local_new();
2501 TCGv t1 = tcg_temp_new();
2502 TCGv t2 = tcg_temp_new();
2503 int l1 = gen_new_label();
2505 gen_load_gpr(t1, rs);
2506 gen_load_gpr(t2, rt);
2507 tcg_gen_add_tl(t0, t1, t2);
2508 tcg_gen_xor_tl(t1, t1, t2);
2509 tcg_gen_xor_tl(t2, t0, t2);
2510 tcg_gen_andc_tl(t1, t2, t1);
2511 tcg_temp_free(t2);
2512 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2513 tcg_temp_free(t1);
2514 /* operands of same sign, result different sign */
2515 generate_exception(ctx, EXCP_OVERFLOW);
2516 gen_set_label(l1);
2517 gen_store_gpr(t0, rd);
2518 tcg_temp_free(t0);
2520 opn = "dadd";
2521 break;
2522 case OPC_DADDU:
2523 if (rs != 0 && rt != 0) {
2524 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2525 } else if (rs == 0 && rt != 0) {
2526 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2527 } else if (rs != 0 && rt == 0) {
2528 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2529 } else {
2530 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2532 opn = "daddu";
2533 break;
2534 case OPC_DSUB:
2536 TCGv t0 = tcg_temp_local_new();
2537 TCGv t1 = tcg_temp_new();
2538 TCGv t2 = tcg_temp_new();
2539 int l1 = gen_new_label();
2541 gen_load_gpr(t1, rs);
2542 gen_load_gpr(t2, rt);
2543 tcg_gen_sub_tl(t0, t1, t2);
2544 tcg_gen_xor_tl(t2, t1, t2);
2545 tcg_gen_xor_tl(t1, t0, t1);
2546 tcg_gen_and_tl(t1, t1, t2);
2547 tcg_temp_free(t2);
2548 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2549 tcg_temp_free(t1);
2550 /* operands of different sign, first operand and result different sign */
2551 generate_exception(ctx, EXCP_OVERFLOW);
2552 gen_set_label(l1);
2553 gen_store_gpr(t0, rd);
2554 tcg_temp_free(t0);
2556 opn = "dsub";
2557 break;
2558 case OPC_DSUBU:
2559 if (rs != 0 && rt != 0) {
2560 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2561 } else if (rs == 0 && rt != 0) {
2562 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2563 } else if (rs != 0 && rt == 0) {
2564 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2565 } else {
2566 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2568 opn = "dsubu";
2569 break;
2570 #endif
2571 case OPC_MUL:
2572 if (likely(rs != 0 && rt != 0)) {
2573 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2574 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2575 } else {
2576 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2578 opn = "mul";
2579 break;
2581 (void)opn; /* avoid a compiler warning */
2582 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2585 /* Conditional move */
2586 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2587 int rd, int rs, int rt)
2589 const char *opn = "cond move";
2590 TCGv t0, t1, t2;
2592 if (rd == 0) {
2593 /* If no destination, treat it as a NOP. */
2594 MIPS_DEBUG("NOP");
2595 return;
2598 t0 = tcg_temp_new();
2599 gen_load_gpr(t0, rt);
2600 t1 = tcg_const_tl(0);
2601 t2 = tcg_temp_new();
2602 gen_load_gpr(t2, rs);
2603 switch (opc) {
2604 case OPC_MOVN:
2605 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2606 opn = "movn";
2607 break;
2608 case OPC_MOVZ:
2609 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2610 opn = "movz";
2611 break;
2612 case OPC_SELNEZ:
2613 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2614 opn = "selnez";
2615 break;
2616 case OPC_SELEQZ:
2617 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2618 opn = "seleqz";
2619 break;
2621 tcg_temp_free(t2);
2622 tcg_temp_free(t1);
2623 tcg_temp_free(t0);
2625 (void)opn; /* avoid a compiler warning */
2626 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2629 /* Logic */
2630 static void gen_logic(DisasContext *ctx, uint32_t opc,
2631 int rd, int rs, int rt)
2633 const char *opn = "logic";
2635 if (rd == 0) {
2636 /* If no destination, treat it as a NOP. */
2637 MIPS_DEBUG("NOP");
2638 return;
2641 switch (opc) {
2642 case OPC_AND:
2643 if (likely(rs != 0 && rt != 0)) {
2644 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2645 } else {
2646 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2648 opn = "and";
2649 break;
2650 case OPC_NOR:
2651 if (rs != 0 && rt != 0) {
2652 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2653 } else if (rs == 0 && rt != 0) {
2654 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2655 } else if (rs != 0 && rt == 0) {
2656 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2657 } else {
2658 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2660 opn = "nor";
2661 break;
2662 case OPC_OR:
2663 if (likely(rs != 0 && rt != 0)) {
2664 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2665 } else if (rs == 0 && rt != 0) {
2666 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2667 } else if (rs != 0 && rt == 0) {
2668 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2669 } else {
2670 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2672 opn = "or";
2673 break;
2674 case OPC_XOR:
2675 if (likely(rs != 0 && rt != 0)) {
2676 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2677 } else if (rs == 0 && rt != 0) {
2678 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2679 } else if (rs != 0 && rt == 0) {
2680 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2681 } else {
2682 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2684 opn = "xor";
2685 break;
2687 (void)opn; /* avoid a compiler warning */
2688 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2691 /* Set on lower than */
2692 static void gen_slt(DisasContext *ctx, uint32_t opc,
2693 int rd, int rs, int rt)
2695 const char *opn = "slt";
2696 TCGv t0, t1;
2698 if (rd == 0) {
2699 /* If no destination, treat it as a NOP. */
2700 MIPS_DEBUG("NOP");
2701 return;
2704 t0 = tcg_temp_new();
2705 t1 = tcg_temp_new();
2706 gen_load_gpr(t0, rs);
2707 gen_load_gpr(t1, rt);
2708 switch (opc) {
2709 case OPC_SLT:
2710 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2711 opn = "slt";
2712 break;
2713 case OPC_SLTU:
2714 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2715 opn = "sltu";
2716 break;
2718 (void)opn; /* avoid a compiler warning */
2719 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2720 tcg_temp_free(t0);
2721 tcg_temp_free(t1);
2724 /* Shifts */
2725 static void gen_shift(DisasContext *ctx, uint32_t opc,
2726 int rd, int rs, int rt)
2728 const char *opn = "shifts";
2729 TCGv t0, t1;
2731 if (rd == 0) {
2732 /* If no destination, treat it as a NOP.
2733 For add & sub, we must generate the overflow exception when needed. */
2734 MIPS_DEBUG("NOP");
2735 return;
2738 t0 = tcg_temp_new();
2739 t1 = tcg_temp_new();
2740 gen_load_gpr(t0, rs);
2741 gen_load_gpr(t1, rt);
2742 switch (opc) {
2743 case OPC_SLLV:
2744 tcg_gen_andi_tl(t0, t0, 0x1f);
2745 tcg_gen_shl_tl(t0, t1, t0);
2746 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2747 opn = "sllv";
2748 break;
2749 case OPC_SRAV:
2750 tcg_gen_andi_tl(t0, t0, 0x1f);
2751 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2752 opn = "srav";
2753 break;
2754 case OPC_SRLV:
2755 tcg_gen_ext32u_tl(t1, t1);
2756 tcg_gen_andi_tl(t0, t0, 0x1f);
2757 tcg_gen_shr_tl(t0, t1, t0);
2758 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2759 opn = "srlv";
2760 break;
2761 case OPC_ROTRV:
2763 TCGv_i32 t2 = tcg_temp_new_i32();
2764 TCGv_i32 t3 = tcg_temp_new_i32();
2766 tcg_gen_trunc_tl_i32(t2, t0);
2767 tcg_gen_trunc_tl_i32(t3, t1);
2768 tcg_gen_andi_i32(t2, t2, 0x1f);
2769 tcg_gen_rotr_i32(t2, t3, t2);
2770 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2771 tcg_temp_free_i32(t2);
2772 tcg_temp_free_i32(t3);
2773 opn = "rotrv";
2775 break;
2776 #if defined(TARGET_MIPS64)
2777 case OPC_DSLLV:
2778 tcg_gen_andi_tl(t0, t0, 0x3f);
2779 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2780 opn = "dsllv";
2781 break;
2782 case OPC_DSRAV:
2783 tcg_gen_andi_tl(t0, t0, 0x3f);
2784 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2785 opn = "dsrav";
2786 break;
2787 case OPC_DSRLV:
2788 tcg_gen_andi_tl(t0, t0, 0x3f);
2789 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2790 opn = "dsrlv";
2791 break;
2792 case OPC_DROTRV:
2793 tcg_gen_andi_tl(t0, t0, 0x3f);
2794 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2795 opn = "drotrv";
2796 break;
2797 #endif
2799 (void)opn; /* avoid a compiler warning */
2800 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2801 tcg_temp_free(t0);
2802 tcg_temp_free(t1);
2805 /* Arithmetic on HI/LO registers */
2806 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2808 const char *opn = "hilo";
2810 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2811 /* Treat as NOP. */
2812 MIPS_DEBUG("NOP");
2813 return;
2816 if (acc != 0) {
2817 check_dsp(ctx);
2820 switch (opc) {
2821 case OPC_MFHI:
2822 #if defined(TARGET_MIPS64)
2823 if (acc != 0) {
2824 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2825 } else
2826 #endif
2828 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2830 opn = "mfhi";
2831 break;
2832 case OPC_MFLO:
2833 #if defined(TARGET_MIPS64)
2834 if (acc != 0) {
2835 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2836 } else
2837 #endif
2839 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2841 opn = "mflo";
2842 break;
2843 case OPC_MTHI:
2844 if (reg != 0) {
2845 #if defined(TARGET_MIPS64)
2846 if (acc != 0) {
2847 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2848 } else
2849 #endif
2851 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2853 } else {
2854 tcg_gen_movi_tl(cpu_HI[acc], 0);
2856 opn = "mthi";
2857 break;
2858 case OPC_MTLO:
2859 if (reg != 0) {
2860 #if defined(TARGET_MIPS64)
2861 if (acc != 0) {
2862 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2863 } else
2864 #endif
2866 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2868 } else {
2869 tcg_gen_movi_tl(cpu_LO[acc], 0);
2871 opn = "mtlo";
2872 break;
2874 (void)opn; /* avoid a compiler warning */
2875 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2878 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
2879 TCGMemOp memop)
2881 TCGv t0 = tcg_const_tl(addr);
2882 tcg_gen_qemu_ld_tl(t0, t0, memidx, memop);
2883 gen_store_gpr(t0, reg);
2884 tcg_temp_free(t0);
2887 static inline void gen_pcrel(DisasContext *ctx, int rs, int16_t imm)
2889 target_long offset;
2890 target_long addr;
2892 switch (MASK_OPC_PCREL_TOP2BITS(ctx->opcode)) {
2893 case OPC_ADDIUPC:
2894 if (rs != 0) {
2895 offset = sextract32(ctx->opcode << 2, 0, 21);
2896 addr = addr_add(ctx, ctx->pc, offset);
2897 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2899 break;
2900 case R6_OPC_LWPC:
2901 offset = sextract32(ctx->opcode << 2, 0, 21);
2902 addr = addr_add(ctx, ctx->pc, offset);
2903 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TESL);
2904 break;
2905 #if defined(TARGET_MIPS64)
2906 case OPC_LWUPC:
2907 check_mips_64(ctx);
2908 offset = sextract32(ctx->opcode << 2, 0, 21);
2909 addr = addr_add(ctx, ctx->pc, offset);
2910 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEUL);
2911 break;
2912 #endif
2913 default:
2914 switch (MASK_OPC_PCREL_TOP5BITS(ctx->opcode)) {
2915 case OPC_AUIPC:
2916 if (rs != 0) {
2917 offset = imm << 16;
2918 addr = addr_add(ctx, ctx->pc, offset);
2919 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2921 break;
2922 case OPC_ALUIPC:
2923 if (rs != 0) {
2924 offset = imm << 16;
2925 addr = ~0xFFFF & addr_add(ctx, ctx->pc, offset);
2926 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2928 break;
2929 #if defined(TARGET_MIPS64)
2930 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
2931 case R6_OPC_LDPC + (1 << 16):
2932 case R6_OPC_LDPC + (2 << 16):
2933 case R6_OPC_LDPC + (3 << 16):
2934 check_mips_64(ctx);
2935 offset = sextract32(ctx->opcode << 3, 0, 21);
2936 addr = addr_add(ctx, (ctx->pc & ~0x7), offset);
2937 gen_r6_ld(addr, rs, ctx->mem_idx, MO_TEQ);
2938 break;
2939 #endif
2940 default:
2941 MIPS_INVAL("OPC_PCREL");
2942 generate_exception(ctx, EXCP_RI);
2943 break;
2945 break;
2949 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
2951 const char *opn = "r6 mul/div";
2952 TCGv t0, t1;
2954 if (rd == 0) {
2955 /* Treat as NOP. */
2956 MIPS_DEBUG("NOP");
2957 return;
2960 t0 = tcg_temp_new();
2961 t1 = tcg_temp_new();
2963 gen_load_gpr(t0, rs);
2964 gen_load_gpr(t1, rt);
2966 switch (opc) {
2967 case R6_OPC_DIV:
2969 TCGv t2 = tcg_temp_new();
2970 TCGv t3 = tcg_temp_new();
2971 tcg_gen_ext32s_tl(t0, t0);
2972 tcg_gen_ext32s_tl(t1, t1);
2973 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2974 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2975 tcg_gen_and_tl(t2, t2, t3);
2976 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2977 tcg_gen_or_tl(t2, t2, t3);
2978 tcg_gen_movi_tl(t3, 0);
2979 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2980 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2981 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2982 tcg_temp_free(t3);
2983 tcg_temp_free(t2);
2985 opn = "div";
2986 break;
2987 case R6_OPC_MOD:
2989 TCGv t2 = tcg_temp_new();
2990 TCGv t3 = tcg_temp_new();
2991 tcg_gen_ext32s_tl(t0, t0);
2992 tcg_gen_ext32s_tl(t1, t1);
2993 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2994 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2995 tcg_gen_and_tl(t2, t2, t3);
2996 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2997 tcg_gen_or_tl(t2, t2, t3);
2998 tcg_gen_movi_tl(t3, 0);
2999 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3000 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3001 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3002 tcg_temp_free(t3);
3003 tcg_temp_free(t2);
3005 opn = "mod";
3006 break;
3007 case R6_OPC_DIVU:
3009 TCGv t2 = tcg_const_tl(0);
3010 TCGv t3 = tcg_const_tl(1);
3011 tcg_gen_ext32u_tl(t0, t0);
3012 tcg_gen_ext32u_tl(t1, t1);
3013 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3014 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3015 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3016 tcg_temp_free(t3);
3017 tcg_temp_free(t2);
3019 opn = "divu";
3020 break;
3021 case R6_OPC_MODU:
3023 TCGv t2 = tcg_const_tl(0);
3024 TCGv t3 = tcg_const_tl(1);
3025 tcg_gen_ext32u_tl(t0, t0);
3026 tcg_gen_ext32u_tl(t1, t1);
3027 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3028 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3029 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3030 tcg_temp_free(t3);
3031 tcg_temp_free(t2);
3033 opn = "modu";
3034 break;
3035 case R6_OPC_MUL:
3037 TCGv_i32 t2 = tcg_temp_new_i32();
3038 TCGv_i32 t3 = tcg_temp_new_i32();
3039 tcg_gen_trunc_tl_i32(t2, t0);
3040 tcg_gen_trunc_tl_i32(t3, t1);
3041 tcg_gen_mul_i32(t2, t2, t3);
3042 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3043 tcg_temp_free_i32(t2);
3044 tcg_temp_free_i32(t3);
3046 opn = "mul";
3047 break;
3048 case R6_OPC_MUH:
3050 TCGv_i32 t2 = tcg_temp_new_i32();
3051 TCGv_i32 t3 = tcg_temp_new_i32();
3052 tcg_gen_trunc_tl_i32(t2, t0);
3053 tcg_gen_trunc_tl_i32(t3, t1);
3054 tcg_gen_muls2_i32(t2, t3, t2, t3);
3055 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3056 tcg_temp_free_i32(t2);
3057 tcg_temp_free_i32(t3);
3059 opn = "muh";
3060 break;
3061 case R6_OPC_MULU:
3063 TCGv_i32 t2 = tcg_temp_new_i32();
3064 TCGv_i32 t3 = tcg_temp_new_i32();
3065 tcg_gen_trunc_tl_i32(t2, t0);
3066 tcg_gen_trunc_tl_i32(t3, t1);
3067 tcg_gen_mul_i32(t2, t2, t3);
3068 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3069 tcg_temp_free_i32(t2);
3070 tcg_temp_free_i32(t3);
3072 opn = "mulu";
3073 break;
3074 case R6_OPC_MUHU:
3076 TCGv_i32 t2 = tcg_temp_new_i32();
3077 TCGv_i32 t3 = tcg_temp_new_i32();
3078 tcg_gen_trunc_tl_i32(t2, t0);
3079 tcg_gen_trunc_tl_i32(t3, t1);
3080 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3081 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3082 tcg_temp_free_i32(t2);
3083 tcg_temp_free_i32(t3);
3085 opn = "muhu";
3086 break;
3087 #if defined(TARGET_MIPS64)
3088 case R6_OPC_DDIV:
3090 TCGv t2 = tcg_temp_new();
3091 TCGv t3 = tcg_temp_new();
3092 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3093 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3094 tcg_gen_and_tl(t2, t2, t3);
3095 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3096 tcg_gen_or_tl(t2, t2, t3);
3097 tcg_gen_movi_tl(t3, 0);
3098 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3099 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3100 tcg_temp_free(t3);
3101 tcg_temp_free(t2);
3103 opn = "ddiv";
3104 break;
3105 case R6_OPC_DMOD:
3107 TCGv t2 = tcg_temp_new();
3108 TCGv t3 = tcg_temp_new();
3109 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3110 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3111 tcg_gen_and_tl(t2, t2, t3);
3112 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3113 tcg_gen_or_tl(t2, t2, t3);
3114 tcg_gen_movi_tl(t3, 0);
3115 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3116 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3117 tcg_temp_free(t3);
3118 tcg_temp_free(t2);
3120 opn = "dmod";
3121 break;
3122 case R6_OPC_DDIVU:
3124 TCGv t2 = tcg_const_tl(0);
3125 TCGv t3 = tcg_const_tl(1);
3126 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3127 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3128 tcg_temp_free(t3);
3129 tcg_temp_free(t2);
3131 opn = "ddivu";
3132 break;
3133 case R6_OPC_DMODU:
3135 TCGv t2 = tcg_const_tl(0);
3136 TCGv t3 = tcg_const_tl(1);
3137 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3138 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3139 tcg_temp_free(t3);
3140 tcg_temp_free(t2);
3142 opn = "dmodu";
3143 break;
3144 case R6_OPC_DMUL:
3145 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3146 opn = "dmul";
3147 break;
3148 case R6_OPC_DMUH:
3150 TCGv t2 = tcg_temp_new();
3151 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3152 tcg_temp_free(t2);
3154 opn = "dmuh";
3155 break;
3156 case R6_OPC_DMULU:
3157 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3158 opn = "dmulu";
3159 break;
3160 case R6_OPC_DMUHU:
3162 TCGv t2 = tcg_temp_new();
3163 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3164 tcg_temp_free(t2);
3166 opn = "dmuhu";
3167 break;
3168 #endif
3169 default:
3170 MIPS_INVAL(opn);
3171 generate_exception(ctx, EXCP_RI);
3172 goto out;
3174 (void)opn; /* avoid a compiler warning */
3175 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3176 out:
3177 tcg_temp_free(t0);
3178 tcg_temp_free(t1);
3181 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3182 int acc, int rs, int rt)
3184 const char *opn = "mul/div";
3185 TCGv t0, t1;
3187 t0 = tcg_temp_new();
3188 t1 = tcg_temp_new();
3190 gen_load_gpr(t0, rs);
3191 gen_load_gpr(t1, rt);
3193 if (acc != 0) {
3194 check_dsp(ctx);
3197 switch (opc) {
3198 case OPC_DIV:
3200 TCGv t2 = tcg_temp_new();
3201 TCGv t3 = tcg_temp_new();
3202 tcg_gen_ext32s_tl(t0, t0);
3203 tcg_gen_ext32s_tl(t1, t1);
3204 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3205 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3206 tcg_gen_and_tl(t2, t2, t3);
3207 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3208 tcg_gen_or_tl(t2, t2, t3);
3209 tcg_gen_movi_tl(t3, 0);
3210 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3211 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3212 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3213 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3214 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3215 tcg_temp_free(t3);
3216 tcg_temp_free(t2);
3218 opn = "div";
3219 break;
3220 case OPC_DIVU:
3222 TCGv t2 = tcg_const_tl(0);
3223 TCGv t3 = tcg_const_tl(1);
3224 tcg_gen_ext32u_tl(t0, t0);
3225 tcg_gen_ext32u_tl(t1, t1);
3226 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3227 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3228 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3229 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3230 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3231 tcg_temp_free(t3);
3232 tcg_temp_free(t2);
3234 opn = "divu";
3235 break;
3236 case OPC_MULT:
3238 TCGv_i32 t2 = tcg_temp_new_i32();
3239 TCGv_i32 t3 = tcg_temp_new_i32();
3240 tcg_gen_trunc_tl_i32(t2, t0);
3241 tcg_gen_trunc_tl_i32(t3, t1);
3242 tcg_gen_muls2_i32(t2, t3, t2, t3);
3243 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3244 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3245 tcg_temp_free_i32(t2);
3246 tcg_temp_free_i32(t3);
3248 opn = "mult";
3249 break;
3250 case OPC_MULTU:
3252 TCGv_i32 t2 = tcg_temp_new_i32();
3253 TCGv_i32 t3 = tcg_temp_new_i32();
3254 tcg_gen_trunc_tl_i32(t2, t0);
3255 tcg_gen_trunc_tl_i32(t3, t1);
3256 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3257 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3258 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3259 tcg_temp_free_i32(t2);
3260 tcg_temp_free_i32(t3);
3262 opn = "multu";
3263 break;
3264 #if defined(TARGET_MIPS64)
3265 case OPC_DDIV:
3267 TCGv t2 = tcg_temp_new();
3268 TCGv t3 = tcg_temp_new();
3269 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3270 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3271 tcg_gen_and_tl(t2, t2, t3);
3272 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3273 tcg_gen_or_tl(t2, t2, t3);
3274 tcg_gen_movi_tl(t3, 0);
3275 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
3276 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3277 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3278 tcg_temp_free(t3);
3279 tcg_temp_free(t2);
3281 opn = "ddiv";
3282 break;
3283 case OPC_DDIVU:
3285 TCGv t2 = tcg_const_tl(0);
3286 TCGv t3 = tcg_const_tl(1);
3287 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3288 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3289 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3290 tcg_temp_free(t3);
3291 tcg_temp_free(t2);
3293 opn = "ddivu";
3294 break;
3295 case OPC_DMULT:
3296 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3297 opn = "dmult";
3298 break;
3299 case OPC_DMULTU:
3300 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3301 opn = "dmultu";
3302 break;
3303 #endif
3304 case OPC_MADD:
3306 TCGv_i64 t2 = tcg_temp_new_i64();
3307 TCGv_i64 t3 = tcg_temp_new_i64();
3309 tcg_gen_ext_tl_i64(t2, t0);
3310 tcg_gen_ext_tl_i64(t3, t1);
3311 tcg_gen_mul_i64(t2, t2, t3);
3312 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3313 tcg_gen_add_i64(t2, t2, t3);
3314 tcg_temp_free_i64(t3);
3315 tcg_gen_trunc_i64_tl(t0, t2);
3316 tcg_gen_shri_i64(t2, t2, 32);
3317 tcg_gen_trunc_i64_tl(t1, t2);
3318 tcg_temp_free_i64(t2);
3319 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3320 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3322 opn = "madd";
3323 break;
3324 case OPC_MADDU:
3326 TCGv_i64 t2 = tcg_temp_new_i64();
3327 TCGv_i64 t3 = tcg_temp_new_i64();
3329 tcg_gen_ext32u_tl(t0, t0);
3330 tcg_gen_ext32u_tl(t1, t1);
3331 tcg_gen_extu_tl_i64(t2, t0);
3332 tcg_gen_extu_tl_i64(t3, t1);
3333 tcg_gen_mul_i64(t2, t2, t3);
3334 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3335 tcg_gen_add_i64(t2, t2, t3);
3336 tcg_temp_free_i64(t3);
3337 tcg_gen_trunc_i64_tl(t0, t2);
3338 tcg_gen_shri_i64(t2, t2, 32);
3339 tcg_gen_trunc_i64_tl(t1, t2);
3340 tcg_temp_free_i64(t2);
3341 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3342 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3344 opn = "maddu";
3345 break;
3346 case OPC_MSUB:
3348 TCGv_i64 t2 = tcg_temp_new_i64();
3349 TCGv_i64 t3 = tcg_temp_new_i64();
3351 tcg_gen_ext_tl_i64(t2, t0);
3352 tcg_gen_ext_tl_i64(t3, t1);
3353 tcg_gen_mul_i64(t2, t2, t3);
3354 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3355 tcg_gen_sub_i64(t2, t3, t2);
3356 tcg_temp_free_i64(t3);
3357 tcg_gen_trunc_i64_tl(t0, t2);
3358 tcg_gen_shri_i64(t2, t2, 32);
3359 tcg_gen_trunc_i64_tl(t1, t2);
3360 tcg_temp_free_i64(t2);
3361 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3362 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3364 opn = "msub";
3365 break;
3366 case OPC_MSUBU:
3368 TCGv_i64 t2 = tcg_temp_new_i64();
3369 TCGv_i64 t3 = tcg_temp_new_i64();
3371 tcg_gen_ext32u_tl(t0, t0);
3372 tcg_gen_ext32u_tl(t1, t1);
3373 tcg_gen_extu_tl_i64(t2, t0);
3374 tcg_gen_extu_tl_i64(t3, t1);
3375 tcg_gen_mul_i64(t2, t2, t3);
3376 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3377 tcg_gen_sub_i64(t2, t3, t2);
3378 tcg_temp_free_i64(t3);
3379 tcg_gen_trunc_i64_tl(t0, t2);
3380 tcg_gen_shri_i64(t2, t2, 32);
3381 tcg_gen_trunc_i64_tl(t1, t2);
3382 tcg_temp_free_i64(t2);
3383 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
3384 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
3386 opn = "msubu";
3387 break;
3388 default:
3389 MIPS_INVAL(opn);
3390 generate_exception(ctx, EXCP_RI);
3391 goto out;
3393 (void)opn; /* avoid a compiler warning */
3394 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
3395 out:
3396 tcg_temp_free(t0);
3397 tcg_temp_free(t1);
3400 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
3401 int rd, int rs, int rt)
3403 const char *opn = "mul vr54xx";
3404 TCGv t0 = tcg_temp_new();
3405 TCGv t1 = tcg_temp_new();
3407 gen_load_gpr(t0, rs);
3408 gen_load_gpr(t1, rt);
3410 switch (opc) {
3411 case OPC_VR54XX_MULS:
3412 gen_helper_muls(t0, cpu_env, t0, t1);
3413 opn = "muls";
3414 break;
3415 case OPC_VR54XX_MULSU:
3416 gen_helper_mulsu(t0, cpu_env, t0, t1);
3417 opn = "mulsu";
3418 break;
3419 case OPC_VR54XX_MACC:
3420 gen_helper_macc(t0, cpu_env, t0, t1);
3421 opn = "macc";
3422 break;
3423 case OPC_VR54XX_MACCU:
3424 gen_helper_maccu(t0, cpu_env, t0, t1);
3425 opn = "maccu";
3426 break;
3427 case OPC_VR54XX_MSAC:
3428 gen_helper_msac(t0, cpu_env, t0, t1);
3429 opn = "msac";
3430 break;
3431 case OPC_VR54XX_MSACU:
3432 gen_helper_msacu(t0, cpu_env, t0, t1);
3433 opn = "msacu";
3434 break;
3435 case OPC_VR54XX_MULHI:
3436 gen_helper_mulhi(t0, cpu_env, t0, t1);
3437 opn = "mulhi";
3438 break;
3439 case OPC_VR54XX_MULHIU:
3440 gen_helper_mulhiu(t0, cpu_env, t0, t1);
3441 opn = "mulhiu";
3442 break;
3443 case OPC_VR54XX_MULSHI:
3444 gen_helper_mulshi(t0, cpu_env, t0, t1);
3445 opn = "mulshi";
3446 break;
3447 case OPC_VR54XX_MULSHIU:
3448 gen_helper_mulshiu(t0, cpu_env, t0, t1);
3449 opn = "mulshiu";
3450 break;
3451 case OPC_VR54XX_MACCHI:
3452 gen_helper_macchi(t0, cpu_env, t0, t1);
3453 opn = "macchi";
3454 break;
3455 case OPC_VR54XX_MACCHIU:
3456 gen_helper_macchiu(t0, cpu_env, t0, t1);
3457 opn = "macchiu";
3458 break;
3459 case OPC_VR54XX_MSACHI:
3460 gen_helper_msachi(t0, cpu_env, t0, t1);
3461 opn = "msachi";
3462 break;
3463 case OPC_VR54XX_MSACHIU:
3464 gen_helper_msachiu(t0, cpu_env, t0, t1);
3465 opn = "msachiu";
3466 break;
3467 default:
3468 MIPS_INVAL("mul vr54xx");
3469 generate_exception(ctx, EXCP_RI);
3470 goto out;
3472 gen_store_gpr(t0, rd);
3473 (void)opn; /* avoid a compiler warning */
3474 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
3476 out:
3477 tcg_temp_free(t0);
3478 tcg_temp_free(t1);
3481 static void gen_cl (DisasContext *ctx, uint32_t opc,
3482 int rd, int rs)
3484 const char *opn = "CLx";
3485 TCGv t0;
3487 if (rd == 0) {
3488 /* Treat as NOP. */
3489 MIPS_DEBUG("NOP");
3490 return;
3492 t0 = tcg_temp_new();
3493 gen_load_gpr(t0, rs);
3494 switch (opc) {
3495 case OPC_CLO:
3496 case R6_OPC_CLO:
3497 gen_helper_clo(cpu_gpr[rd], t0);
3498 opn = "clo";
3499 break;
3500 case OPC_CLZ:
3501 case R6_OPC_CLZ:
3502 gen_helper_clz(cpu_gpr[rd], t0);
3503 opn = "clz";
3504 break;
3505 #if defined(TARGET_MIPS64)
3506 case OPC_DCLO:
3507 case R6_OPC_DCLO:
3508 gen_helper_dclo(cpu_gpr[rd], t0);
3509 opn = "dclo";
3510 break;
3511 case OPC_DCLZ:
3512 case R6_OPC_DCLZ:
3513 gen_helper_dclz(cpu_gpr[rd], t0);
3514 opn = "dclz";
3515 break;
3516 #endif
3518 (void)opn; /* avoid a compiler warning */
3519 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3520 tcg_temp_free(t0);
3523 /* Godson integer instructions */
3524 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3525 int rd, int rs, int rt)
3527 const char *opn = "loongson";
3528 TCGv t0, t1;
3530 if (rd == 0) {
3531 /* Treat as NOP. */
3532 MIPS_DEBUG("NOP");
3533 return;
3536 switch (opc) {
3537 case OPC_MULT_G_2E:
3538 case OPC_MULT_G_2F:
3539 case OPC_MULTU_G_2E:
3540 case OPC_MULTU_G_2F:
3541 #if defined(TARGET_MIPS64)
3542 case OPC_DMULT_G_2E:
3543 case OPC_DMULT_G_2F:
3544 case OPC_DMULTU_G_2E:
3545 case OPC_DMULTU_G_2F:
3546 #endif
3547 t0 = tcg_temp_new();
3548 t1 = tcg_temp_new();
3549 break;
3550 default:
3551 t0 = tcg_temp_local_new();
3552 t1 = tcg_temp_local_new();
3553 break;
3556 gen_load_gpr(t0, rs);
3557 gen_load_gpr(t1, rt);
3559 switch (opc) {
3560 case OPC_MULT_G_2E:
3561 case OPC_MULT_G_2F:
3562 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3563 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3564 opn = "mult.g";
3565 break;
3566 case OPC_MULTU_G_2E:
3567 case OPC_MULTU_G_2F:
3568 tcg_gen_ext32u_tl(t0, t0);
3569 tcg_gen_ext32u_tl(t1, t1);
3570 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3571 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3572 opn = "multu.g";
3573 break;
3574 case OPC_DIV_G_2E:
3575 case OPC_DIV_G_2F:
3577 int l1 = gen_new_label();
3578 int l2 = gen_new_label();
3579 int l3 = gen_new_label();
3580 tcg_gen_ext32s_tl(t0, t0);
3581 tcg_gen_ext32s_tl(t1, t1);
3582 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3583 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3584 tcg_gen_br(l3);
3585 gen_set_label(l1);
3586 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3587 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3588 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3589 tcg_gen_br(l3);
3590 gen_set_label(l2);
3591 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3592 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3593 gen_set_label(l3);
3595 opn = "div.g";
3596 break;
3597 case OPC_DIVU_G_2E:
3598 case OPC_DIVU_G_2F:
3600 int l1 = gen_new_label();
3601 int l2 = gen_new_label();
3602 tcg_gen_ext32u_tl(t0, t0);
3603 tcg_gen_ext32u_tl(t1, t1);
3604 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3605 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3606 tcg_gen_br(l2);
3607 gen_set_label(l1);
3608 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3609 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3610 gen_set_label(l2);
3612 opn = "divu.g";
3613 break;
3614 case OPC_MOD_G_2E:
3615 case OPC_MOD_G_2F:
3617 int l1 = gen_new_label();
3618 int l2 = gen_new_label();
3619 int l3 = gen_new_label();
3620 tcg_gen_ext32u_tl(t0, t0);
3621 tcg_gen_ext32u_tl(t1, t1);
3622 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3623 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3624 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3625 gen_set_label(l1);
3626 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3627 tcg_gen_br(l3);
3628 gen_set_label(l2);
3629 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3630 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3631 gen_set_label(l3);
3633 opn = "mod.g";
3634 break;
3635 case OPC_MODU_G_2E:
3636 case OPC_MODU_G_2F:
3638 int l1 = gen_new_label();
3639 int l2 = gen_new_label();
3640 tcg_gen_ext32u_tl(t0, t0);
3641 tcg_gen_ext32u_tl(t1, t1);
3642 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3643 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3644 tcg_gen_br(l2);
3645 gen_set_label(l1);
3646 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3647 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3648 gen_set_label(l2);
3650 opn = "modu.g";
3651 break;
3652 #if defined(TARGET_MIPS64)
3653 case OPC_DMULT_G_2E:
3654 case OPC_DMULT_G_2F:
3655 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3656 opn = "dmult.g";
3657 break;
3658 case OPC_DMULTU_G_2E:
3659 case OPC_DMULTU_G_2F:
3660 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3661 opn = "dmultu.g";
3662 break;
3663 case OPC_DDIV_G_2E:
3664 case OPC_DDIV_G_2F:
3666 int l1 = gen_new_label();
3667 int l2 = gen_new_label();
3668 int l3 = gen_new_label();
3669 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3670 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3671 tcg_gen_br(l3);
3672 gen_set_label(l1);
3673 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3674 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3675 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3676 tcg_gen_br(l3);
3677 gen_set_label(l2);
3678 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3679 gen_set_label(l3);
3681 opn = "ddiv.g";
3682 break;
3683 case OPC_DDIVU_G_2E:
3684 case OPC_DDIVU_G_2F:
3686 int l1 = gen_new_label();
3687 int l2 = gen_new_label();
3688 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3689 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3690 tcg_gen_br(l2);
3691 gen_set_label(l1);
3692 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3693 gen_set_label(l2);
3695 opn = "ddivu.g";
3696 break;
3697 case OPC_DMOD_G_2E:
3698 case OPC_DMOD_G_2F:
3700 int l1 = gen_new_label();
3701 int l2 = gen_new_label();
3702 int l3 = gen_new_label();
3703 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3704 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3705 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3706 gen_set_label(l1);
3707 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3708 tcg_gen_br(l3);
3709 gen_set_label(l2);
3710 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3711 gen_set_label(l3);
3713 opn = "dmod.g";
3714 break;
3715 case OPC_DMODU_G_2E:
3716 case OPC_DMODU_G_2F:
3718 int l1 = gen_new_label();
3719 int l2 = gen_new_label();
3720 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3721 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3722 tcg_gen_br(l2);
3723 gen_set_label(l1);
3724 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3725 gen_set_label(l2);
3727 opn = "dmodu.g";
3728 break;
3729 #endif
3732 (void)opn; /* avoid a compiler warning */
3733 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3734 tcg_temp_free(t0);
3735 tcg_temp_free(t1);
3738 /* Loongson multimedia instructions */
3739 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3741 const char *opn = "loongson_cp2";
3742 uint32_t opc, shift_max;
3743 TCGv_i64 t0, t1;
3745 opc = MASK_LMI(ctx->opcode);
3746 switch (opc) {
3747 case OPC_ADD_CP2:
3748 case OPC_SUB_CP2:
3749 case OPC_DADD_CP2:
3750 case OPC_DSUB_CP2:
3751 t0 = tcg_temp_local_new_i64();
3752 t1 = tcg_temp_local_new_i64();
3753 break;
3754 default:
3755 t0 = tcg_temp_new_i64();
3756 t1 = tcg_temp_new_i64();
3757 break;
3760 gen_load_fpr64(ctx, t0, rs);
3761 gen_load_fpr64(ctx, t1, rt);
3763 #define LMI_HELPER(UP, LO) \
3764 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3765 #define LMI_HELPER_1(UP, LO) \
3766 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3767 #define LMI_DIRECT(UP, LO, OP) \
3768 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3770 switch (opc) {
3771 LMI_HELPER(PADDSH, paddsh);
3772 LMI_HELPER(PADDUSH, paddush);
3773 LMI_HELPER(PADDH, paddh);
3774 LMI_HELPER(PADDW, paddw);
3775 LMI_HELPER(PADDSB, paddsb);
3776 LMI_HELPER(PADDUSB, paddusb);
3777 LMI_HELPER(PADDB, paddb);
3779 LMI_HELPER(PSUBSH, psubsh);
3780 LMI_HELPER(PSUBUSH, psubush);
3781 LMI_HELPER(PSUBH, psubh);
3782 LMI_HELPER(PSUBW, psubw);
3783 LMI_HELPER(PSUBSB, psubsb);
3784 LMI_HELPER(PSUBUSB, psubusb);
3785 LMI_HELPER(PSUBB, psubb);
3787 LMI_HELPER(PSHUFH, pshufh);
3788 LMI_HELPER(PACKSSWH, packsswh);
3789 LMI_HELPER(PACKSSHB, packsshb);
3790 LMI_HELPER(PACKUSHB, packushb);
3792 LMI_HELPER(PUNPCKLHW, punpcklhw);
3793 LMI_HELPER(PUNPCKHHW, punpckhhw);
3794 LMI_HELPER(PUNPCKLBH, punpcklbh);
3795 LMI_HELPER(PUNPCKHBH, punpckhbh);
3796 LMI_HELPER(PUNPCKLWD, punpcklwd);
3797 LMI_HELPER(PUNPCKHWD, punpckhwd);
3799 LMI_HELPER(PAVGH, pavgh);
3800 LMI_HELPER(PAVGB, pavgb);
3801 LMI_HELPER(PMAXSH, pmaxsh);
3802 LMI_HELPER(PMINSH, pminsh);
3803 LMI_HELPER(PMAXUB, pmaxub);
3804 LMI_HELPER(PMINUB, pminub);
3806 LMI_HELPER(PCMPEQW, pcmpeqw);
3807 LMI_HELPER(PCMPGTW, pcmpgtw);
3808 LMI_HELPER(PCMPEQH, pcmpeqh);
3809 LMI_HELPER(PCMPGTH, pcmpgth);
3810 LMI_HELPER(PCMPEQB, pcmpeqb);
3811 LMI_HELPER(PCMPGTB, pcmpgtb);
3813 LMI_HELPER(PSLLW, psllw);
3814 LMI_HELPER(PSLLH, psllh);
3815 LMI_HELPER(PSRLW, psrlw);
3816 LMI_HELPER(PSRLH, psrlh);
3817 LMI_HELPER(PSRAW, psraw);
3818 LMI_HELPER(PSRAH, psrah);
3820 LMI_HELPER(PMULLH, pmullh);
3821 LMI_HELPER(PMULHH, pmulhh);
3822 LMI_HELPER(PMULHUH, pmulhuh);
3823 LMI_HELPER(PMADDHW, pmaddhw);
3825 LMI_HELPER(PASUBUB, pasubub);
3826 LMI_HELPER_1(BIADD, biadd);
3827 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3829 LMI_DIRECT(PADDD, paddd, add);
3830 LMI_DIRECT(PSUBD, psubd, sub);
3831 LMI_DIRECT(XOR_CP2, xor, xor);
3832 LMI_DIRECT(NOR_CP2, nor, nor);
3833 LMI_DIRECT(AND_CP2, and, and);
3834 LMI_DIRECT(PANDN, pandn, andc);
3835 LMI_DIRECT(OR, or, or);
3837 case OPC_PINSRH_0:
3838 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3839 opn = "pinsrh_0";
3840 break;
3841 case OPC_PINSRH_1:
3842 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3843 opn = "pinsrh_1";
3844 break;
3845 case OPC_PINSRH_2:
3846 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3847 opn = "pinsrh_2";
3848 break;
3849 case OPC_PINSRH_3:
3850 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3851 opn = "pinsrh_3";
3852 break;
3854 case OPC_PEXTRH:
3855 tcg_gen_andi_i64(t1, t1, 3);
3856 tcg_gen_shli_i64(t1, t1, 4);
3857 tcg_gen_shr_i64(t0, t0, t1);
3858 tcg_gen_ext16u_i64(t0, t0);
3859 opn = "pextrh";
3860 break;
3862 case OPC_ADDU_CP2:
3863 tcg_gen_add_i64(t0, t0, t1);
3864 tcg_gen_ext32s_i64(t0, t0);
3865 opn = "addu";
3866 break;
3867 case OPC_SUBU_CP2:
3868 tcg_gen_sub_i64(t0, t0, t1);
3869 tcg_gen_ext32s_i64(t0, t0);
3870 opn = "addu";
3871 break;
3873 case OPC_SLL_CP2:
3874 opn = "sll";
3875 shift_max = 32;
3876 goto do_shift;
3877 case OPC_SRL_CP2:
3878 opn = "srl";
3879 shift_max = 32;
3880 goto do_shift;
3881 case OPC_SRA_CP2:
3882 opn = "sra";
3883 shift_max = 32;
3884 goto do_shift;
3885 case OPC_DSLL_CP2:
3886 opn = "dsll";
3887 shift_max = 64;
3888 goto do_shift;
3889 case OPC_DSRL_CP2:
3890 opn = "dsrl";
3891 shift_max = 64;
3892 goto do_shift;
3893 case OPC_DSRA_CP2:
3894 opn = "dsra";
3895 shift_max = 64;
3896 goto do_shift;
3897 do_shift:
3898 /* Make sure shift count isn't TCG undefined behaviour. */
3899 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3901 switch (opc) {
3902 case OPC_SLL_CP2:
3903 case OPC_DSLL_CP2:
3904 tcg_gen_shl_i64(t0, t0, t1);
3905 break;
3906 case OPC_SRA_CP2:
3907 case OPC_DSRA_CP2:
3908 /* Since SRA is UndefinedResult without sign-extended inputs,
3909 we can treat SRA and DSRA the same. */
3910 tcg_gen_sar_i64(t0, t0, t1);
3911 break;
3912 case OPC_SRL_CP2:
3913 /* We want to shift in zeros for SRL; zero-extend first. */
3914 tcg_gen_ext32u_i64(t0, t0);
3915 /* FALLTHRU */
3916 case OPC_DSRL_CP2:
3917 tcg_gen_shr_i64(t0, t0, t1);
3918 break;
3921 if (shift_max == 32) {
3922 tcg_gen_ext32s_i64(t0, t0);
3925 /* Shifts larger than MAX produce zero. */
3926 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3927 tcg_gen_neg_i64(t1, t1);
3928 tcg_gen_and_i64(t0, t0, t1);
3929 break;
3931 case OPC_ADD_CP2:
3932 case OPC_DADD_CP2:
3934 TCGv_i64 t2 = tcg_temp_new_i64();
3935 int lab = gen_new_label();
3937 tcg_gen_mov_i64(t2, t0);
3938 tcg_gen_add_i64(t0, t1, t2);
3939 if (opc == OPC_ADD_CP2) {
3940 tcg_gen_ext32s_i64(t0, t0);
3942 tcg_gen_xor_i64(t1, t1, t2);
3943 tcg_gen_xor_i64(t2, t2, t0);
3944 tcg_gen_andc_i64(t1, t2, t1);
3945 tcg_temp_free_i64(t2);
3946 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3947 generate_exception(ctx, EXCP_OVERFLOW);
3948 gen_set_label(lab);
3950 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3951 break;
3954 case OPC_SUB_CP2:
3955 case OPC_DSUB_CP2:
3957 TCGv_i64 t2 = tcg_temp_new_i64();
3958 int lab = gen_new_label();
3960 tcg_gen_mov_i64(t2, t0);
3961 tcg_gen_sub_i64(t0, t1, t2);
3962 if (opc == OPC_SUB_CP2) {
3963 tcg_gen_ext32s_i64(t0, t0);
3965 tcg_gen_xor_i64(t1, t1, t2);
3966 tcg_gen_xor_i64(t2, t2, t0);
3967 tcg_gen_and_i64(t1, t1, t2);
3968 tcg_temp_free_i64(t2);
3969 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3970 generate_exception(ctx, EXCP_OVERFLOW);
3971 gen_set_label(lab);
3973 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3974 break;
3977 case OPC_PMULUW:
3978 tcg_gen_ext32u_i64(t0, t0);
3979 tcg_gen_ext32u_i64(t1, t1);
3980 tcg_gen_mul_i64(t0, t0, t1);
3981 opn = "pmuluw";
3982 break;
3984 case OPC_SEQU_CP2:
3985 case OPC_SEQ_CP2:
3986 case OPC_SLTU_CP2:
3987 case OPC_SLT_CP2:
3988 case OPC_SLEU_CP2:
3989 case OPC_SLE_CP2:
3990 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3991 FD field is the CC field? */
3992 default:
3993 MIPS_INVAL(opn);
3994 generate_exception(ctx, EXCP_RI);
3995 return;
3998 #undef LMI_HELPER
3999 #undef LMI_DIRECT
4001 gen_store_fpr64(ctx, t0, rd);
4003 (void)opn; /* avoid a compiler warning */
4004 MIPS_DEBUG("%s %s, %s, %s", opn,
4005 fregnames[rd], fregnames[rs], fregnames[rt]);
4006 tcg_temp_free_i64(t0);
4007 tcg_temp_free_i64(t1);
4010 /* Traps */
4011 static void gen_trap (DisasContext *ctx, uint32_t opc,
4012 int rs, int rt, int16_t imm)
4014 int cond;
4015 TCGv t0 = tcg_temp_new();
4016 TCGv t1 = tcg_temp_new();
4018 cond = 0;
4019 /* Load needed operands */
4020 switch (opc) {
4021 case OPC_TEQ:
4022 case OPC_TGE:
4023 case OPC_TGEU:
4024 case OPC_TLT:
4025 case OPC_TLTU:
4026 case OPC_TNE:
4027 /* Compare two registers */
4028 if (rs != rt) {
4029 gen_load_gpr(t0, rs);
4030 gen_load_gpr(t1, rt);
4031 cond = 1;
4033 break;
4034 case OPC_TEQI:
4035 case OPC_TGEI:
4036 case OPC_TGEIU:
4037 case OPC_TLTI:
4038 case OPC_TLTIU:
4039 case OPC_TNEI:
4040 /* Compare register to immediate */
4041 if (rs != 0 || imm != 0) {
4042 gen_load_gpr(t0, rs);
4043 tcg_gen_movi_tl(t1, (int32_t)imm);
4044 cond = 1;
4046 break;
4048 if (cond == 0) {
4049 switch (opc) {
4050 case OPC_TEQ: /* rs == rs */
4051 case OPC_TEQI: /* r0 == 0 */
4052 case OPC_TGE: /* rs >= rs */
4053 case OPC_TGEI: /* r0 >= 0 */
4054 case OPC_TGEU: /* rs >= rs unsigned */
4055 case OPC_TGEIU: /* r0 >= 0 unsigned */
4056 /* Always trap */
4057 generate_exception(ctx, EXCP_TRAP);
4058 break;
4059 case OPC_TLT: /* rs < rs */
4060 case OPC_TLTI: /* r0 < 0 */
4061 case OPC_TLTU: /* rs < rs unsigned */
4062 case OPC_TLTIU: /* r0 < 0 unsigned */
4063 case OPC_TNE: /* rs != rs */
4064 case OPC_TNEI: /* r0 != 0 */
4065 /* Never trap: treat as NOP. */
4066 break;
4068 } else {
4069 int l1 = gen_new_label();
4071 switch (opc) {
4072 case OPC_TEQ:
4073 case OPC_TEQI:
4074 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4075 break;
4076 case OPC_TGE:
4077 case OPC_TGEI:
4078 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4079 break;
4080 case OPC_TGEU:
4081 case OPC_TGEIU:
4082 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4083 break;
4084 case OPC_TLT:
4085 case OPC_TLTI:
4086 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4087 break;
4088 case OPC_TLTU:
4089 case OPC_TLTIU:
4090 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4091 break;
4092 case OPC_TNE:
4093 case OPC_TNEI:
4094 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4095 break;
4097 generate_exception(ctx, EXCP_TRAP);
4098 gen_set_label(l1);
4100 tcg_temp_free(t0);
4101 tcg_temp_free(t1);
4104 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4106 TranslationBlock *tb;
4107 tb = ctx->tb;
4108 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
4109 likely(!ctx->singlestep_enabled)) {
4110 tcg_gen_goto_tb(n);
4111 gen_save_pc(dest);
4112 tcg_gen_exit_tb((uintptr_t)tb + n);
4113 } else {
4114 gen_save_pc(dest);
4115 if (ctx->singlestep_enabled) {
4116 save_cpu_state(ctx, 0);
4117 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
4119 tcg_gen_exit_tb(0);
4123 /* Branches (before delay slot) */
4124 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
4125 int insn_bytes,
4126 int rs, int rt, int32_t offset,
4127 int delayslot_size)
4129 target_ulong btgt = -1;
4130 int blink = 0;
4131 int bcond_compute = 0;
4132 TCGv t0 = tcg_temp_new();
4133 TCGv t1 = tcg_temp_new();
4135 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4136 #ifdef MIPS_DEBUG_DISAS
4137 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
4138 #endif
4139 generate_exception(ctx, EXCP_RI);
4140 goto out;
4143 /* Load needed operands */
4144 switch (opc) {
4145 case OPC_BEQ:
4146 case OPC_BEQL:
4147 case OPC_BNE:
4148 case OPC_BNEL:
4149 /* Compare two registers */
4150 if (rs != rt) {
4151 gen_load_gpr(t0, rs);
4152 gen_load_gpr(t1, rt);
4153 bcond_compute = 1;
4155 btgt = ctx->pc + insn_bytes + offset;
4156 break;
4157 case OPC_BGEZ:
4158 case OPC_BGEZAL:
4159 case OPC_BGEZALL:
4160 case OPC_BGEZL:
4161 case OPC_BGTZ:
4162 case OPC_BGTZL:
4163 case OPC_BLEZ:
4164 case OPC_BLEZL:
4165 case OPC_BLTZ:
4166 case OPC_BLTZAL:
4167 case OPC_BLTZALL:
4168 case OPC_BLTZL:
4169 /* Compare to zero */
4170 if (rs != 0) {
4171 gen_load_gpr(t0, rs);
4172 bcond_compute = 1;
4174 btgt = ctx->pc + insn_bytes + offset;
4175 break;
4176 case OPC_BPOSGE32:
4177 #if defined(TARGET_MIPS64)
4178 case OPC_BPOSGE64:
4179 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4180 #else
4181 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4182 #endif
4183 bcond_compute = 1;
4184 btgt = ctx->pc + insn_bytes + offset;
4185 break;
4186 case OPC_J:
4187 case OPC_JAL:
4188 case OPC_JALX:
4189 /* Jump to immediate */
4190 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
4191 break;
4192 case OPC_JR:
4193 case OPC_JALR:
4194 /* Jump to register */
4195 if (offset != 0 && offset != 16) {
4196 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4197 others are reserved. */
4198 MIPS_INVAL("jump hint");
4199 generate_exception(ctx, EXCP_RI);
4200 goto out;
4202 gen_load_gpr(btarget, rs);
4203 break;
4204 default:
4205 MIPS_INVAL("branch/jump");
4206 generate_exception(ctx, EXCP_RI);
4207 goto out;
4209 if (bcond_compute == 0) {
4210 /* No condition to be computed */
4211 switch (opc) {
4212 case OPC_BEQ: /* rx == rx */
4213 case OPC_BEQL: /* rx == rx likely */
4214 case OPC_BGEZ: /* 0 >= 0 */
4215 case OPC_BGEZL: /* 0 >= 0 likely */
4216 case OPC_BLEZ: /* 0 <= 0 */
4217 case OPC_BLEZL: /* 0 <= 0 likely */
4218 /* Always take */
4219 ctx->hflags |= MIPS_HFLAG_B;
4220 MIPS_DEBUG("balways");
4221 break;
4222 case OPC_BGEZAL: /* 0 >= 0 */
4223 case OPC_BGEZALL: /* 0 >= 0 likely */
4224 /* Always take and link */
4225 blink = 31;
4226 ctx->hflags |= MIPS_HFLAG_B;
4227 MIPS_DEBUG("balways and link");
4228 break;
4229 case OPC_BNE: /* rx != rx */
4230 case OPC_BGTZ: /* 0 > 0 */
4231 case OPC_BLTZ: /* 0 < 0 */
4232 /* Treat as NOP. */
4233 MIPS_DEBUG("bnever (NOP)");
4234 goto out;
4235 case OPC_BLTZAL: /* 0 < 0 */
4236 /* Handle as an unconditional branch to get correct delay
4237 slot checking. */
4238 blink = 31;
4239 btgt = ctx->pc + insn_bytes + delayslot_size;
4240 ctx->hflags |= MIPS_HFLAG_B;
4241 MIPS_DEBUG("bnever and link");
4242 break;
4243 case OPC_BLTZALL: /* 0 < 0 likely */
4244 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
4245 /* Skip the instruction in the delay slot */
4246 MIPS_DEBUG("bnever, link and skip");
4247 ctx->pc += 4;
4248 goto out;
4249 case OPC_BNEL: /* rx != rx likely */
4250 case OPC_BGTZL: /* 0 > 0 likely */
4251 case OPC_BLTZL: /* 0 < 0 likely */
4252 /* Skip the instruction in the delay slot */
4253 MIPS_DEBUG("bnever and skip");
4254 ctx->pc += 4;
4255 goto out;
4256 case OPC_J:
4257 ctx->hflags |= MIPS_HFLAG_B;
4258 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
4259 break;
4260 case OPC_JALX:
4261 ctx->hflags |= MIPS_HFLAG_BX;
4262 /* Fallthrough */
4263 case OPC_JAL:
4264 blink = 31;
4265 ctx->hflags |= MIPS_HFLAG_B;
4266 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
4267 break;
4268 case OPC_JR:
4269 ctx->hflags |= MIPS_HFLAG_BR;
4270 MIPS_DEBUG("jr %s", regnames[rs]);
4271 break;
4272 case OPC_JALR:
4273 blink = rt;
4274 ctx->hflags |= MIPS_HFLAG_BR;
4275 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
4276 break;
4277 default:
4278 MIPS_INVAL("branch/jump");
4279 generate_exception(ctx, EXCP_RI);
4280 goto out;
4282 } else {
4283 switch (opc) {
4284 case OPC_BEQ:
4285 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4286 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
4287 regnames[rs], regnames[rt], btgt);
4288 goto not_likely;
4289 case OPC_BEQL:
4290 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4291 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
4292 regnames[rs], regnames[rt], btgt);
4293 goto likely;
4294 case OPC_BNE:
4295 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4296 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
4297 regnames[rs], regnames[rt], btgt);
4298 goto not_likely;
4299 case OPC_BNEL:
4300 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4301 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
4302 regnames[rs], regnames[rt], btgt);
4303 goto likely;
4304 case OPC_BGEZ:
4305 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4306 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4307 goto not_likely;
4308 case OPC_BGEZL:
4309 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4310 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4311 goto likely;
4312 case OPC_BGEZAL:
4313 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4314 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4315 blink = 31;
4316 goto not_likely;
4317 case OPC_BGEZALL:
4318 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4319 blink = 31;
4320 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4321 goto likely;
4322 case OPC_BGTZ:
4323 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4324 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4325 goto not_likely;
4326 case OPC_BGTZL:
4327 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4328 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4329 goto likely;
4330 case OPC_BLEZ:
4331 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4332 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
4333 goto not_likely;
4334 case OPC_BLEZL:
4335 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4336 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4337 goto likely;
4338 case OPC_BLTZ:
4339 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4340 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
4341 goto not_likely;
4342 case OPC_BLTZL:
4343 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4344 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
4345 goto likely;
4346 case OPC_BPOSGE32:
4347 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4348 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
4349 goto not_likely;
4350 #if defined(TARGET_MIPS64)
4351 case OPC_BPOSGE64:
4352 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4353 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
4354 goto not_likely;
4355 #endif
4356 case OPC_BLTZAL:
4357 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4358 blink = 31;
4359 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
4360 not_likely:
4361 ctx->hflags |= MIPS_HFLAG_BC;
4362 break;
4363 case OPC_BLTZALL:
4364 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4365 blink = 31;
4366 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
4367 likely:
4368 ctx->hflags |= MIPS_HFLAG_BL;
4369 break;
4370 default:
4371 MIPS_INVAL("conditional branch/jump");
4372 generate_exception(ctx, EXCP_RI);
4373 goto out;
4376 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
4377 blink, ctx->hflags, btgt);
4379 ctx->btarget = btgt;
4381 switch (delayslot_size) {
4382 case 2:
4383 ctx->hflags |= MIPS_HFLAG_BDS16;
4384 break;
4385 case 4:
4386 ctx->hflags |= MIPS_HFLAG_BDS32;
4387 break;
4390 if (blink > 0) {
4391 int post_delay = insn_bytes + delayslot_size;
4392 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4394 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
4397 out:
4398 if (insn_bytes == 2)
4399 ctx->hflags |= MIPS_HFLAG_B16;
4400 tcg_temp_free(t0);
4401 tcg_temp_free(t1);
4404 /* special3 bitfield operations */
4405 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
4406 int rs, int lsb, int msb)
4408 TCGv t0 = tcg_temp_new();
4409 TCGv t1 = tcg_temp_new();
4411 gen_load_gpr(t1, rs);
4412 switch (opc) {
4413 case OPC_EXT:
4414 if (lsb + msb > 31)
4415 goto fail;
4416 tcg_gen_shri_tl(t0, t1, lsb);
4417 if (msb != 31) {
4418 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
4419 } else {
4420 tcg_gen_ext32s_tl(t0, t0);
4422 break;
4423 #if defined(TARGET_MIPS64)
4424 case OPC_DEXTM:
4425 tcg_gen_shri_tl(t0, t1, lsb);
4426 if (msb != 31) {
4427 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
4429 break;
4430 case OPC_DEXTU:
4431 tcg_gen_shri_tl(t0, t1, lsb + 32);
4432 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4433 break;
4434 case OPC_DEXT:
4435 tcg_gen_shri_tl(t0, t1, lsb);
4436 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
4437 break;
4438 #endif
4439 case OPC_INS:
4440 if (lsb > msb)
4441 goto fail;
4442 gen_load_gpr(t0, rt);
4443 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4444 tcg_gen_ext32s_tl(t0, t0);
4445 break;
4446 #if defined(TARGET_MIPS64)
4447 case OPC_DINSM:
4448 gen_load_gpr(t0, rt);
4449 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
4450 break;
4451 case OPC_DINSU:
4452 gen_load_gpr(t0, rt);
4453 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
4454 break;
4455 case OPC_DINS:
4456 gen_load_gpr(t0, rt);
4457 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4458 break;
4459 #endif
4460 default:
4461 fail:
4462 MIPS_INVAL("bitops");
4463 generate_exception(ctx, EXCP_RI);
4464 tcg_temp_free(t0);
4465 tcg_temp_free(t1);
4466 return;
4468 gen_store_gpr(t0, rt);
4469 tcg_temp_free(t0);
4470 tcg_temp_free(t1);
4473 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
4475 TCGv t0;
4477 if (rd == 0) {
4478 /* If no destination, treat it as a NOP. */
4479 MIPS_DEBUG("NOP");
4480 return;
4483 t0 = tcg_temp_new();
4484 gen_load_gpr(t0, rt);
4485 switch (op2) {
4486 case OPC_WSBH:
4488 TCGv t1 = tcg_temp_new();
4490 tcg_gen_shri_tl(t1, t0, 8);
4491 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
4492 tcg_gen_shli_tl(t0, t0, 8);
4493 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
4494 tcg_gen_or_tl(t0, t0, t1);
4495 tcg_temp_free(t1);
4496 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4498 break;
4499 case OPC_SEB:
4500 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4501 break;
4502 case OPC_SEH:
4503 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4504 break;
4505 #if defined(TARGET_MIPS64)
4506 case OPC_DSBH:
4508 TCGv t1 = tcg_temp_new();
4510 tcg_gen_shri_tl(t1, t0, 8);
4511 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4512 tcg_gen_shli_tl(t0, t0, 8);
4513 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4514 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4515 tcg_temp_free(t1);
4517 break;
4518 case OPC_DSHD:
4520 TCGv t1 = tcg_temp_new();
4522 tcg_gen_shri_tl(t1, t0, 16);
4523 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4524 tcg_gen_shli_tl(t0, t0, 16);
4525 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4526 tcg_gen_or_tl(t0, t0, t1);
4527 tcg_gen_shri_tl(t1, t0, 32);
4528 tcg_gen_shli_tl(t0, t0, 32);
4529 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4530 tcg_temp_free(t1);
4532 break;
4533 #endif
4534 default:
4535 MIPS_INVAL("bsfhl");
4536 generate_exception(ctx, EXCP_RI);
4537 tcg_temp_free(t0);
4538 return;
4540 tcg_temp_free(t0);
4543 #ifndef CONFIG_USER_ONLY
4544 /* CP0 (MMU and control) */
4545 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4547 TCGv_i32 t0 = tcg_temp_new_i32();
4549 tcg_gen_ld_i32(t0, cpu_env, off);
4550 tcg_gen_ext_i32_tl(arg, t0);
4551 tcg_temp_free_i32(t0);
4554 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4556 tcg_gen_ld_tl(arg, cpu_env, off);
4557 tcg_gen_ext32s_tl(arg, arg);
4560 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4562 TCGv_i32 t0 = tcg_temp_new_i32();
4564 tcg_gen_trunc_tl_i32(t0, arg);
4565 tcg_gen_st_i32(t0, cpu_env, off);
4566 tcg_temp_free_i32(t0);
4569 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
4571 tcg_gen_ext32s_tl(arg, arg);
4572 tcg_gen_st_tl(arg, cpu_env, off);
4575 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
4577 if (ctx->insn_flags & ISA_MIPS32R6) {
4578 tcg_gen_movi_tl(arg, 0);
4579 } else {
4580 tcg_gen_movi_tl(arg, ~0);
4584 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4586 const char *rn = "invalid";
4588 if (sel != 0)
4589 check_insn(ctx, ISA_MIPS32);
4591 switch (reg) {
4592 case 0:
4593 switch (sel) {
4594 case 0:
4595 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4596 rn = "Index";
4597 break;
4598 case 1:
4599 check_insn(ctx, ASE_MT);
4600 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4601 rn = "MVPControl";
4602 break;
4603 case 2:
4604 check_insn(ctx, ASE_MT);
4605 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4606 rn = "MVPConf0";
4607 break;
4608 case 3:
4609 check_insn(ctx, ASE_MT);
4610 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4611 rn = "MVPConf1";
4612 break;
4613 default:
4614 goto die;
4616 break;
4617 case 1:
4618 switch (sel) {
4619 case 0:
4620 gen_helper_mfc0_random(arg, cpu_env);
4621 rn = "Random";
4622 break;
4623 case 1:
4624 check_insn(ctx, ASE_MT);
4625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4626 rn = "VPEControl";
4627 break;
4628 case 2:
4629 check_insn(ctx, ASE_MT);
4630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4631 rn = "VPEConf0";
4632 break;
4633 case 3:
4634 check_insn(ctx, ASE_MT);
4635 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4636 rn = "VPEConf1";
4637 break;
4638 case 4:
4639 check_insn(ctx, ASE_MT);
4640 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4641 rn = "YQMask";
4642 break;
4643 case 5:
4644 check_insn(ctx, ASE_MT);
4645 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4646 rn = "VPESchedule";
4647 break;
4648 case 6:
4649 check_insn(ctx, ASE_MT);
4650 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4651 rn = "VPEScheFBack";
4652 break;
4653 case 7:
4654 check_insn(ctx, ASE_MT);
4655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4656 rn = "VPEOpt";
4657 break;
4658 default:
4659 goto die;
4661 break;
4662 case 2:
4663 switch (sel) {
4664 case 0:
4665 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4666 #if defined(TARGET_MIPS64)
4667 if (ctx->rxi) {
4668 TCGv tmp = tcg_temp_new();
4669 tcg_gen_andi_tl(tmp, arg, (3ull << 62));
4670 tcg_gen_shri_tl(tmp, tmp, 32);
4671 tcg_gen_or_tl(arg, arg, tmp);
4672 tcg_temp_free(tmp);
4674 #endif
4675 tcg_gen_ext32s_tl(arg, arg);
4676 rn = "EntryLo0";
4677 break;
4678 case 1:
4679 check_insn(ctx, ASE_MT);
4680 gen_helper_mfc0_tcstatus(arg, cpu_env);
4681 rn = "TCStatus";
4682 break;
4683 case 2:
4684 check_insn(ctx, ASE_MT);
4685 gen_helper_mfc0_tcbind(arg, cpu_env);
4686 rn = "TCBind";
4687 break;
4688 case 3:
4689 check_insn(ctx, ASE_MT);
4690 gen_helper_mfc0_tcrestart(arg, cpu_env);
4691 rn = "TCRestart";
4692 break;
4693 case 4:
4694 check_insn(ctx, ASE_MT);
4695 gen_helper_mfc0_tchalt(arg, cpu_env);
4696 rn = "TCHalt";
4697 break;
4698 case 5:
4699 check_insn(ctx, ASE_MT);
4700 gen_helper_mfc0_tccontext(arg, cpu_env);
4701 rn = "TCContext";
4702 break;
4703 case 6:
4704 check_insn(ctx, ASE_MT);
4705 gen_helper_mfc0_tcschedule(arg, cpu_env);
4706 rn = "TCSchedule";
4707 break;
4708 case 7:
4709 check_insn(ctx, ASE_MT);
4710 gen_helper_mfc0_tcschefback(arg, cpu_env);
4711 rn = "TCScheFBack";
4712 break;
4713 default:
4714 goto die;
4716 break;
4717 case 3:
4718 switch (sel) {
4719 case 0:
4720 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4721 #if defined(TARGET_MIPS64)
4722 if (ctx->rxi) {
4723 TCGv tmp = tcg_temp_new();
4724 tcg_gen_andi_tl(tmp, arg, (3ull << 62));
4725 tcg_gen_shri_tl(tmp, tmp, 32);
4726 tcg_gen_or_tl(arg, arg, tmp);
4727 tcg_temp_free(tmp);
4729 #endif
4730 tcg_gen_ext32s_tl(arg, arg);
4731 rn = "EntryLo1";
4732 break;
4733 default:
4734 goto die;
4736 break;
4737 case 4:
4738 switch (sel) {
4739 case 0:
4740 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
4741 tcg_gen_ext32s_tl(arg, arg);
4742 rn = "Context";
4743 break;
4744 case 1:
4745 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
4746 rn = "ContextConfig";
4747 goto die;
4748 // break;
4749 case 2:
4750 if (ctx->ulri) {
4751 tcg_gen_ld32s_tl(arg, cpu_env,
4752 offsetof(CPUMIPSState,
4753 active_tc.CP0_UserLocal));
4754 rn = "UserLocal";
4755 } else {
4756 tcg_gen_movi_tl(arg, 0);
4758 break;
4759 default:
4760 goto die;
4762 break;
4763 case 5:
4764 switch (sel) {
4765 case 0:
4766 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
4767 rn = "PageMask";
4768 break;
4769 case 1:
4770 check_insn(ctx, ISA_MIPS32R2);
4771 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
4772 rn = "PageGrain";
4773 break;
4774 default:
4775 goto die;
4777 break;
4778 case 6:
4779 switch (sel) {
4780 case 0:
4781 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
4782 rn = "Wired";
4783 break;
4784 case 1:
4785 check_insn(ctx, ISA_MIPS32R2);
4786 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
4787 rn = "SRSConf0";
4788 break;
4789 case 2:
4790 check_insn(ctx, ISA_MIPS32R2);
4791 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
4792 rn = "SRSConf1";
4793 break;
4794 case 3:
4795 check_insn(ctx, ISA_MIPS32R2);
4796 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
4797 rn = "SRSConf2";
4798 break;
4799 case 4:
4800 check_insn(ctx, ISA_MIPS32R2);
4801 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
4802 rn = "SRSConf3";
4803 break;
4804 case 5:
4805 check_insn(ctx, ISA_MIPS32R2);
4806 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
4807 rn = "SRSConf4";
4808 break;
4809 default:
4810 goto die;
4812 break;
4813 case 7:
4814 switch (sel) {
4815 case 0:
4816 check_insn(ctx, ISA_MIPS32R2);
4817 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
4818 rn = "HWREna";
4819 break;
4820 default:
4821 goto die;
4823 break;
4824 case 8:
4825 switch (sel) {
4826 case 0:
4827 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
4828 tcg_gen_ext32s_tl(arg, arg);
4829 rn = "BadVAddr";
4830 break;
4831 default:
4832 goto die;
4834 break;
4835 case 9:
4836 switch (sel) {
4837 case 0:
4838 /* Mark as an IO operation because we read the time. */
4839 if (use_icount)
4840 gen_io_start();
4841 gen_helper_mfc0_count(arg, cpu_env);
4842 if (use_icount) {
4843 gen_io_end();
4845 /* Break the TB to be able to take timer interrupts immediately
4846 after reading count. */
4847 ctx->bstate = BS_STOP;
4848 rn = "Count";
4849 break;
4850 /* 6,7 are implementation dependent */
4851 default:
4852 goto die;
4854 break;
4855 case 10:
4856 switch (sel) {
4857 case 0:
4858 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
4859 tcg_gen_ext32s_tl(arg, arg);
4860 rn = "EntryHi";
4861 break;
4862 default:
4863 goto die;
4865 break;
4866 case 11:
4867 switch (sel) {
4868 case 0:
4869 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
4870 rn = "Compare";
4871 break;
4872 /* 6,7 are implementation dependent */
4873 default:
4874 goto die;
4876 break;
4877 case 12:
4878 switch (sel) {
4879 case 0:
4880 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
4881 rn = "Status";
4882 break;
4883 case 1:
4884 check_insn(ctx, ISA_MIPS32R2);
4885 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
4886 rn = "IntCtl";
4887 break;
4888 case 2:
4889 check_insn(ctx, ISA_MIPS32R2);
4890 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
4891 rn = "SRSCtl";
4892 break;
4893 case 3:
4894 check_insn(ctx, ISA_MIPS32R2);
4895 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4896 rn = "SRSMap";
4897 break;
4898 default:
4899 goto die;
4901 break;
4902 case 13:
4903 switch (sel) {
4904 case 0:
4905 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
4906 rn = "Cause";
4907 break;
4908 default:
4909 goto die;
4911 break;
4912 case 14:
4913 switch (sel) {
4914 case 0:
4915 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
4916 tcg_gen_ext32s_tl(arg, arg);
4917 rn = "EPC";
4918 break;
4919 default:
4920 goto die;
4922 break;
4923 case 15:
4924 switch (sel) {
4925 case 0:
4926 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
4927 rn = "PRid";
4928 break;
4929 case 1:
4930 check_insn(ctx, ISA_MIPS32R2);
4931 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
4932 rn = "EBase";
4933 break;
4934 default:
4935 goto die;
4937 break;
4938 case 16:
4939 switch (sel) {
4940 case 0:
4941 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
4942 rn = "Config";
4943 break;
4944 case 1:
4945 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
4946 rn = "Config1";
4947 break;
4948 case 2:
4949 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
4950 rn = "Config2";
4951 break;
4952 case 3:
4953 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
4954 rn = "Config3";
4955 break;
4956 case 4:
4957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
4958 rn = "Config4";
4959 break;
4960 case 5:
4961 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
4962 rn = "Config5";
4963 break;
4964 /* 6,7 are implementation dependent */
4965 case 6:
4966 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
4967 rn = "Config6";
4968 break;
4969 case 7:
4970 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
4971 rn = "Config7";
4972 break;
4973 default:
4974 goto die;
4976 break;
4977 case 17:
4978 switch (sel) {
4979 case 0:
4980 gen_helper_mfc0_lladdr(arg, cpu_env);
4981 rn = "LLAddr";
4982 break;
4983 default:
4984 goto die;
4986 break;
4987 case 18:
4988 switch (sel) {
4989 case 0 ... 7:
4990 gen_helper_1e0i(mfc0_watchlo, arg, sel);
4991 rn = "WatchLo";
4992 break;
4993 default:
4994 goto die;
4996 break;
4997 case 19:
4998 switch (sel) {
4999 case 0 ...7:
5000 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5001 rn = "WatchHi";
5002 break;
5003 default:
5004 goto die;
5006 break;
5007 case 20:
5008 switch (sel) {
5009 case 0:
5010 #if defined(TARGET_MIPS64)
5011 check_insn(ctx, ISA_MIPS3);
5012 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5013 tcg_gen_ext32s_tl(arg, arg);
5014 rn = "XContext";
5015 break;
5016 #endif
5017 default:
5018 goto die;
5020 break;
5021 case 21:
5022 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5023 switch (sel) {
5024 case 0:
5025 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5026 rn = "Framemask";
5027 break;
5028 default:
5029 goto die;
5031 break;
5032 case 22:
5033 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5034 rn = "'Diagnostic"; /* implementation dependent */
5035 break;
5036 case 23:
5037 switch (sel) {
5038 case 0:
5039 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5040 rn = "Debug";
5041 break;
5042 case 1:
5043 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
5044 rn = "TraceControl";
5045 // break;
5046 case 2:
5047 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
5048 rn = "TraceControl2";
5049 // break;
5050 case 3:
5051 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
5052 rn = "UserTraceData";
5053 // break;
5054 case 4:
5055 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
5056 rn = "TraceBPC";
5057 // break;
5058 default:
5059 goto die;
5061 break;
5062 case 24:
5063 switch (sel) {
5064 case 0:
5065 /* EJTAG support */
5066 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5067 tcg_gen_ext32s_tl(arg, arg);
5068 rn = "DEPC";
5069 break;
5070 default:
5071 goto die;
5073 break;
5074 case 25:
5075 switch (sel) {
5076 case 0:
5077 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5078 rn = "Performance0";
5079 break;
5080 case 1:
5081 // gen_helper_mfc0_performance1(arg);
5082 rn = "Performance1";
5083 // break;
5084 case 2:
5085 // gen_helper_mfc0_performance2(arg);
5086 rn = "Performance2";
5087 // break;
5088 case 3:
5089 // gen_helper_mfc0_performance3(arg);
5090 rn = "Performance3";
5091 // break;
5092 case 4:
5093 // gen_helper_mfc0_performance4(arg);
5094 rn = "Performance4";
5095 // break;
5096 case 5:
5097 // gen_helper_mfc0_performance5(arg);
5098 rn = "Performance5";
5099 // break;
5100 case 6:
5101 // gen_helper_mfc0_performance6(arg);
5102 rn = "Performance6";
5103 // break;
5104 case 7:
5105 // gen_helper_mfc0_performance7(arg);
5106 rn = "Performance7";
5107 // break;
5108 default:
5109 goto die;
5111 break;
5112 case 26:
5113 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5114 rn = "ECC";
5115 break;
5116 case 27:
5117 switch (sel) {
5118 case 0 ... 3:
5119 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5120 rn = "CacheErr";
5121 break;
5122 default:
5123 goto die;
5125 break;
5126 case 28:
5127 switch (sel) {
5128 case 0:
5129 case 2:
5130 case 4:
5131 case 6:
5132 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
5133 rn = "TagLo";
5134 break;
5135 case 1:
5136 case 3:
5137 case 5:
5138 case 7:
5139 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5140 rn = "DataLo";
5141 break;
5142 default:
5143 goto die;
5145 break;
5146 case 29:
5147 switch (sel) {
5148 case 0:
5149 case 2:
5150 case 4:
5151 case 6:
5152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5153 rn = "TagHi";
5154 break;
5155 case 1:
5156 case 3:
5157 case 5:
5158 case 7:
5159 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5160 rn = "DataHi";
5161 break;
5162 default:
5163 goto die;
5165 break;
5166 case 30:
5167 switch (sel) {
5168 case 0:
5169 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5170 tcg_gen_ext32s_tl(arg, arg);
5171 rn = "ErrorEPC";
5172 break;
5173 default:
5174 goto die;
5176 break;
5177 case 31:
5178 switch (sel) {
5179 case 0:
5180 /* EJTAG support */
5181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5182 rn = "DESAVE";
5183 break;
5184 case 2 ... 7:
5185 if (ctx->kscrexist & (1 << sel)) {
5186 tcg_gen_ld_tl(arg, cpu_env,
5187 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5188 tcg_gen_ext32s_tl(arg, arg);
5189 rn = "KScratch";
5190 } else {
5191 gen_mfc0_unimplemented(ctx, arg);
5193 break;
5194 default:
5195 goto die;
5197 break;
5198 default:
5199 goto die;
5201 (void)rn; /* avoid a compiler warning */
5202 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5203 return;
5205 die:
5206 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5207 generate_exception(ctx, EXCP_RI);
5210 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5212 const char *rn = "invalid";
5214 if (sel != 0)
5215 check_insn(ctx, ISA_MIPS32);
5217 if (use_icount)
5218 gen_io_start();
5220 switch (reg) {
5221 case 0:
5222 switch (sel) {
5223 case 0:
5224 gen_helper_mtc0_index(cpu_env, arg);
5225 rn = "Index";
5226 break;
5227 case 1:
5228 check_insn(ctx, ASE_MT);
5229 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5230 rn = "MVPControl";
5231 break;
5232 case 2:
5233 check_insn(ctx, ASE_MT);
5234 /* ignored */
5235 rn = "MVPConf0";
5236 break;
5237 case 3:
5238 check_insn(ctx, ASE_MT);
5239 /* ignored */
5240 rn = "MVPConf1";
5241 break;
5242 default:
5243 goto die;
5245 break;
5246 case 1:
5247 switch (sel) {
5248 case 0:
5249 /* ignored */
5250 rn = "Random";
5251 break;
5252 case 1:
5253 check_insn(ctx, ASE_MT);
5254 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5255 rn = "VPEControl";
5256 break;
5257 case 2:
5258 check_insn(ctx, ASE_MT);
5259 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5260 rn = "VPEConf0";
5261 break;
5262 case 3:
5263 check_insn(ctx, ASE_MT);
5264 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5265 rn = "VPEConf1";
5266 break;
5267 case 4:
5268 check_insn(ctx, ASE_MT);
5269 gen_helper_mtc0_yqmask(cpu_env, arg);
5270 rn = "YQMask";
5271 break;
5272 case 5:
5273 check_insn(ctx, ASE_MT);
5274 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5275 rn = "VPESchedule";
5276 break;
5277 case 6:
5278 check_insn(ctx, ASE_MT);
5279 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5280 rn = "VPEScheFBack";
5281 break;
5282 case 7:
5283 check_insn(ctx, ASE_MT);
5284 gen_helper_mtc0_vpeopt(cpu_env, arg);
5285 rn = "VPEOpt";
5286 break;
5287 default:
5288 goto die;
5290 break;
5291 case 2:
5292 switch (sel) {
5293 case 0:
5294 gen_helper_mtc0_entrylo0(cpu_env, arg);
5295 rn = "EntryLo0";
5296 break;
5297 case 1:
5298 check_insn(ctx, ASE_MT);
5299 gen_helper_mtc0_tcstatus(cpu_env, arg);
5300 rn = "TCStatus";
5301 break;
5302 case 2:
5303 check_insn(ctx, ASE_MT);
5304 gen_helper_mtc0_tcbind(cpu_env, arg);
5305 rn = "TCBind";
5306 break;
5307 case 3:
5308 check_insn(ctx, ASE_MT);
5309 gen_helper_mtc0_tcrestart(cpu_env, arg);
5310 rn = "TCRestart";
5311 break;
5312 case 4:
5313 check_insn(ctx, ASE_MT);
5314 gen_helper_mtc0_tchalt(cpu_env, arg);
5315 rn = "TCHalt";
5316 break;
5317 case 5:
5318 check_insn(ctx, ASE_MT);
5319 gen_helper_mtc0_tccontext(cpu_env, arg);
5320 rn = "TCContext";
5321 break;
5322 case 6:
5323 check_insn(ctx, ASE_MT);
5324 gen_helper_mtc0_tcschedule(cpu_env, arg);
5325 rn = "TCSchedule";
5326 break;
5327 case 7:
5328 check_insn(ctx, ASE_MT);
5329 gen_helper_mtc0_tcschefback(cpu_env, arg);
5330 rn = "TCScheFBack";
5331 break;
5332 default:
5333 goto die;
5335 break;
5336 case 3:
5337 switch (sel) {
5338 case 0:
5339 gen_helper_mtc0_entrylo1(cpu_env, arg);
5340 rn = "EntryLo1";
5341 break;
5342 default:
5343 goto die;
5345 break;
5346 case 4:
5347 switch (sel) {
5348 case 0:
5349 gen_helper_mtc0_context(cpu_env, arg);
5350 rn = "Context";
5351 break;
5352 case 1:
5353 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
5354 rn = "ContextConfig";
5355 goto die;
5356 // break;
5357 case 2:
5358 if (ctx->ulri) {
5359 tcg_gen_st_tl(arg, cpu_env,
5360 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5361 rn = "UserLocal";
5363 break;
5364 default:
5365 goto die;
5367 break;
5368 case 5:
5369 switch (sel) {
5370 case 0:
5371 gen_helper_mtc0_pagemask(cpu_env, arg);
5372 rn = "PageMask";
5373 break;
5374 case 1:
5375 check_insn(ctx, ISA_MIPS32R2);
5376 gen_helper_mtc0_pagegrain(cpu_env, arg);
5377 rn = "PageGrain";
5378 break;
5379 default:
5380 goto die;
5382 break;
5383 case 6:
5384 switch (sel) {
5385 case 0:
5386 gen_helper_mtc0_wired(cpu_env, arg);
5387 rn = "Wired";
5388 break;
5389 case 1:
5390 check_insn(ctx, ISA_MIPS32R2);
5391 gen_helper_mtc0_srsconf0(cpu_env, arg);
5392 rn = "SRSConf0";
5393 break;
5394 case 2:
5395 check_insn(ctx, ISA_MIPS32R2);
5396 gen_helper_mtc0_srsconf1(cpu_env, arg);
5397 rn = "SRSConf1";
5398 break;
5399 case 3:
5400 check_insn(ctx, ISA_MIPS32R2);
5401 gen_helper_mtc0_srsconf2(cpu_env, arg);
5402 rn = "SRSConf2";
5403 break;
5404 case 4:
5405 check_insn(ctx, ISA_MIPS32R2);
5406 gen_helper_mtc0_srsconf3(cpu_env, arg);
5407 rn = "SRSConf3";
5408 break;
5409 case 5:
5410 check_insn(ctx, ISA_MIPS32R2);
5411 gen_helper_mtc0_srsconf4(cpu_env, arg);
5412 rn = "SRSConf4";
5413 break;
5414 default:
5415 goto die;
5417 break;
5418 case 7:
5419 switch (sel) {
5420 case 0:
5421 check_insn(ctx, ISA_MIPS32R2);
5422 gen_helper_mtc0_hwrena(cpu_env, arg);
5423 ctx->bstate = BS_STOP;
5424 rn = "HWREna";
5425 break;
5426 default:
5427 goto die;
5429 break;
5430 case 8:
5431 /* ignored */
5432 rn = "BadVAddr";
5433 break;
5434 case 9:
5435 switch (sel) {
5436 case 0:
5437 gen_helper_mtc0_count(cpu_env, arg);
5438 rn = "Count";
5439 break;
5440 /* 6,7 are implementation dependent */
5441 default:
5442 goto die;
5444 break;
5445 case 10:
5446 switch (sel) {
5447 case 0:
5448 gen_helper_mtc0_entryhi(cpu_env, arg);
5449 rn = "EntryHi";
5450 break;
5451 default:
5452 goto die;
5454 break;
5455 case 11:
5456 switch (sel) {
5457 case 0:
5458 gen_helper_mtc0_compare(cpu_env, arg);
5459 rn = "Compare";
5460 break;
5461 /* 6,7 are implementation dependent */
5462 default:
5463 goto die;
5465 break;
5466 case 12:
5467 switch (sel) {
5468 case 0:
5469 save_cpu_state(ctx, 1);
5470 gen_helper_mtc0_status(cpu_env, arg);
5471 /* BS_STOP isn't good enough here, hflags may have changed. */
5472 gen_save_pc(ctx->pc + 4);
5473 ctx->bstate = BS_EXCP;
5474 rn = "Status";
5475 break;
5476 case 1:
5477 check_insn(ctx, ISA_MIPS32R2);
5478 gen_helper_mtc0_intctl(cpu_env, arg);
5479 /* Stop translation as we may have switched the execution mode */
5480 ctx->bstate = BS_STOP;
5481 rn = "IntCtl";
5482 break;
5483 case 2:
5484 check_insn(ctx, ISA_MIPS32R2);
5485 gen_helper_mtc0_srsctl(cpu_env, arg);
5486 /* Stop translation as we may have switched the execution mode */
5487 ctx->bstate = BS_STOP;
5488 rn = "SRSCtl";
5489 break;
5490 case 3:
5491 check_insn(ctx, ISA_MIPS32R2);
5492 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5493 /* Stop translation as we may have switched the execution mode */
5494 ctx->bstate = BS_STOP;
5495 rn = "SRSMap";
5496 break;
5497 default:
5498 goto die;
5500 break;
5501 case 13:
5502 switch (sel) {
5503 case 0:
5504 save_cpu_state(ctx, 1);
5505 gen_helper_mtc0_cause(cpu_env, arg);
5506 rn = "Cause";
5507 break;
5508 default:
5509 goto die;
5511 break;
5512 case 14:
5513 switch (sel) {
5514 case 0:
5515 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
5516 rn = "EPC";
5517 break;
5518 default:
5519 goto die;
5521 break;
5522 case 15:
5523 switch (sel) {
5524 case 0:
5525 /* ignored */
5526 rn = "PRid";
5527 break;
5528 case 1:
5529 check_insn(ctx, ISA_MIPS32R2);
5530 gen_helper_mtc0_ebase(cpu_env, arg);
5531 rn = "EBase";
5532 break;
5533 default:
5534 goto die;
5536 break;
5537 case 16:
5538 switch (sel) {
5539 case 0:
5540 gen_helper_mtc0_config0(cpu_env, arg);
5541 rn = "Config";
5542 /* Stop translation as we may have switched the execution mode */
5543 ctx->bstate = BS_STOP;
5544 break;
5545 case 1:
5546 /* ignored, read only */
5547 rn = "Config1";
5548 break;
5549 case 2:
5550 gen_helper_mtc0_config2(cpu_env, arg);
5551 rn = "Config2";
5552 /* Stop translation as we may have switched the execution mode */
5553 ctx->bstate = BS_STOP;
5554 break;
5555 case 3:
5556 /* ignored, read only */
5557 rn = "Config3";
5558 break;
5559 case 4:
5560 gen_helper_mtc0_config4(cpu_env, arg);
5561 rn = "Config4";
5562 ctx->bstate = BS_STOP;
5563 break;
5564 case 5:
5565 gen_helper_mtc0_config5(cpu_env, arg);
5566 rn = "Config5";
5567 /* Stop translation as we may have switched the execution mode */
5568 ctx->bstate = BS_STOP;
5569 break;
5570 /* 6,7 are implementation dependent */
5571 case 6:
5572 /* ignored */
5573 rn = "Config6";
5574 break;
5575 case 7:
5576 /* ignored */
5577 rn = "Config7";
5578 break;
5579 default:
5580 rn = "Invalid config selector";
5581 goto die;
5583 break;
5584 case 17:
5585 switch (sel) {
5586 case 0:
5587 gen_helper_mtc0_lladdr(cpu_env, arg);
5588 rn = "LLAddr";
5589 break;
5590 default:
5591 goto die;
5593 break;
5594 case 18:
5595 switch (sel) {
5596 case 0 ... 7:
5597 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5598 rn = "WatchLo";
5599 break;
5600 default:
5601 goto die;
5603 break;
5604 case 19:
5605 switch (sel) {
5606 case 0 ... 7:
5607 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5608 rn = "WatchHi";
5609 break;
5610 default:
5611 goto die;
5613 break;
5614 case 20:
5615 switch (sel) {
5616 case 0:
5617 #if defined(TARGET_MIPS64)
5618 check_insn(ctx, ISA_MIPS3);
5619 gen_helper_mtc0_xcontext(cpu_env, arg);
5620 rn = "XContext";
5621 break;
5622 #endif
5623 default:
5624 goto die;
5626 break;
5627 case 21:
5628 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5629 switch (sel) {
5630 case 0:
5631 gen_helper_mtc0_framemask(cpu_env, arg);
5632 rn = "Framemask";
5633 break;
5634 default:
5635 goto die;
5637 break;
5638 case 22:
5639 /* ignored */
5640 rn = "Diagnostic"; /* implementation dependent */
5641 break;
5642 case 23:
5643 switch (sel) {
5644 case 0:
5645 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5646 /* BS_STOP isn't good enough here, hflags may have changed. */
5647 gen_save_pc(ctx->pc + 4);
5648 ctx->bstate = BS_EXCP;
5649 rn = "Debug";
5650 break;
5651 case 1:
5652 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5653 rn = "TraceControl";
5654 /* Stop translation as we may have switched the execution mode */
5655 ctx->bstate = BS_STOP;
5656 // break;
5657 case 2:
5658 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5659 rn = "TraceControl2";
5660 /* Stop translation as we may have switched the execution mode */
5661 ctx->bstate = BS_STOP;
5662 // break;
5663 case 3:
5664 /* Stop translation as we may have switched the execution mode */
5665 ctx->bstate = BS_STOP;
5666 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5667 rn = "UserTraceData";
5668 /* Stop translation as we may have switched the execution mode */
5669 ctx->bstate = BS_STOP;
5670 // break;
5671 case 4:
5672 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5673 /* Stop translation as we may have switched the execution mode */
5674 ctx->bstate = BS_STOP;
5675 rn = "TraceBPC";
5676 // break;
5677 default:
5678 goto die;
5680 break;
5681 case 24:
5682 switch (sel) {
5683 case 0:
5684 /* EJTAG support */
5685 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
5686 rn = "DEPC";
5687 break;
5688 default:
5689 goto die;
5691 break;
5692 case 25:
5693 switch (sel) {
5694 case 0:
5695 gen_helper_mtc0_performance0(cpu_env, arg);
5696 rn = "Performance0";
5697 break;
5698 case 1:
5699 // gen_helper_mtc0_performance1(arg);
5700 rn = "Performance1";
5701 // break;
5702 case 2:
5703 // gen_helper_mtc0_performance2(arg);
5704 rn = "Performance2";
5705 // break;
5706 case 3:
5707 // gen_helper_mtc0_performance3(arg);
5708 rn = "Performance3";
5709 // break;
5710 case 4:
5711 // gen_helper_mtc0_performance4(arg);
5712 rn = "Performance4";
5713 // break;
5714 case 5:
5715 // gen_helper_mtc0_performance5(arg);
5716 rn = "Performance5";
5717 // break;
5718 case 6:
5719 // gen_helper_mtc0_performance6(arg);
5720 rn = "Performance6";
5721 // break;
5722 case 7:
5723 // gen_helper_mtc0_performance7(arg);
5724 rn = "Performance7";
5725 // break;
5726 default:
5727 goto die;
5729 break;
5730 case 26:
5731 /* ignored */
5732 rn = "ECC";
5733 break;
5734 case 27:
5735 switch (sel) {
5736 case 0 ... 3:
5737 /* ignored */
5738 rn = "CacheErr";
5739 break;
5740 default:
5741 goto die;
5743 break;
5744 case 28:
5745 switch (sel) {
5746 case 0:
5747 case 2:
5748 case 4:
5749 case 6:
5750 gen_helper_mtc0_taglo(cpu_env, arg);
5751 rn = "TagLo";
5752 break;
5753 case 1:
5754 case 3:
5755 case 5:
5756 case 7:
5757 gen_helper_mtc0_datalo(cpu_env, arg);
5758 rn = "DataLo";
5759 break;
5760 default:
5761 goto die;
5763 break;
5764 case 29:
5765 switch (sel) {
5766 case 0:
5767 case 2:
5768 case 4:
5769 case 6:
5770 gen_helper_mtc0_taghi(cpu_env, arg);
5771 rn = "TagHi";
5772 break;
5773 case 1:
5774 case 3:
5775 case 5:
5776 case 7:
5777 gen_helper_mtc0_datahi(cpu_env, arg);
5778 rn = "DataHi";
5779 break;
5780 default:
5781 rn = "invalid sel";
5782 goto die;
5784 break;
5785 case 30:
5786 switch (sel) {
5787 case 0:
5788 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
5789 rn = "ErrorEPC";
5790 break;
5791 default:
5792 goto die;
5794 break;
5795 case 31:
5796 switch (sel) {
5797 case 0:
5798 /* EJTAG support */
5799 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5800 rn = "DESAVE";
5801 break;
5802 case 2 ... 7:
5803 if (ctx->kscrexist & (1 << sel)) {
5804 tcg_gen_st_tl(arg, cpu_env,
5805 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
5806 rn = "KScratch";
5808 break;
5809 default:
5810 goto die;
5812 /* Stop translation as we may have switched the execution mode */
5813 ctx->bstate = BS_STOP;
5814 break;
5815 default:
5816 goto die;
5818 (void)rn; /* avoid a compiler warning */
5819 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5820 /* For simplicity assume that all writes can cause interrupts. */
5821 if (use_icount) {
5822 gen_io_end();
5823 ctx->bstate = BS_STOP;
5825 return;
5827 die:
5828 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5829 generate_exception(ctx, EXCP_RI);
5832 #if defined(TARGET_MIPS64)
5833 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5835 const char *rn = "invalid";
5837 if (sel != 0)
5838 check_insn(ctx, ISA_MIPS64);
5840 switch (reg) {
5841 case 0:
5842 switch (sel) {
5843 case 0:
5844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5845 rn = "Index";
5846 break;
5847 case 1:
5848 check_insn(ctx, ASE_MT);
5849 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5850 rn = "MVPControl";
5851 break;
5852 case 2:
5853 check_insn(ctx, ASE_MT);
5854 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5855 rn = "MVPConf0";
5856 break;
5857 case 3:
5858 check_insn(ctx, ASE_MT);
5859 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5860 rn = "MVPConf1";
5861 break;
5862 default:
5863 goto die;
5865 break;
5866 case 1:
5867 switch (sel) {
5868 case 0:
5869 gen_helper_mfc0_random(arg, cpu_env);
5870 rn = "Random";
5871 break;
5872 case 1:
5873 check_insn(ctx, ASE_MT);
5874 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5875 rn = "VPEControl";
5876 break;
5877 case 2:
5878 check_insn(ctx, ASE_MT);
5879 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5880 rn = "VPEConf0";
5881 break;
5882 case 3:
5883 check_insn(ctx, ASE_MT);
5884 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5885 rn = "VPEConf1";
5886 break;
5887 case 4:
5888 check_insn(ctx, ASE_MT);
5889 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
5890 rn = "YQMask";
5891 break;
5892 case 5:
5893 check_insn(ctx, ASE_MT);
5894 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5895 rn = "VPESchedule";
5896 break;
5897 case 6:
5898 check_insn(ctx, ASE_MT);
5899 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5900 rn = "VPEScheFBack";
5901 break;
5902 case 7:
5903 check_insn(ctx, ASE_MT);
5904 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5905 rn = "VPEOpt";
5906 break;
5907 default:
5908 goto die;
5910 break;
5911 case 2:
5912 switch (sel) {
5913 case 0:
5914 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
5915 rn = "EntryLo0";
5916 break;
5917 case 1:
5918 check_insn(ctx, ASE_MT);
5919 gen_helper_mfc0_tcstatus(arg, cpu_env);
5920 rn = "TCStatus";
5921 break;
5922 case 2:
5923 check_insn(ctx, ASE_MT);
5924 gen_helper_mfc0_tcbind(arg, cpu_env);
5925 rn = "TCBind";
5926 break;
5927 case 3:
5928 check_insn(ctx, ASE_MT);
5929 gen_helper_dmfc0_tcrestart(arg, cpu_env);
5930 rn = "TCRestart";
5931 break;
5932 case 4:
5933 check_insn(ctx, ASE_MT);
5934 gen_helper_dmfc0_tchalt(arg, cpu_env);
5935 rn = "TCHalt";
5936 break;
5937 case 5:
5938 check_insn(ctx, ASE_MT);
5939 gen_helper_dmfc0_tccontext(arg, cpu_env);
5940 rn = "TCContext";
5941 break;
5942 case 6:
5943 check_insn(ctx, ASE_MT);
5944 gen_helper_dmfc0_tcschedule(arg, cpu_env);
5945 rn = "TCSchedule";
5946 break;
5947 case 7:
5948 check_insn(ctx, ASE_MT);
5949 gen_helper_dmfc0_tcschefback(arg, cpu_env);
5950 rn = "TCScheFBack";
5951 break;
5952 default:
5953 goto die;
5955 break;
5956 case 3:
5957 switch (sel) {
5958 case 0:
5959 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
5960 rn = "EntryLo1";
5961 break;
5962 default:
5963 goto die;
5965 break;
5966 case 4:
5967 switch (sel) {
5968 case 0:
5969 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5970 rn = "Context";
5971 break;
5972 case 1:
5973 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
5974 rn = "ContextConfig";
5975 goto die;
5976 // break;
5977 case 2:
5978 if (ctx->ulri) {
5979 tcg_gen_ld_tl(arg, cpu_env,
5980 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5981 rn = "UserLocal";
5982 } else {
5983 tcg_gen_movi_tl(arg, 0);
5985 break;
5986 default:
5987 goto die;
5989 break;
5990 case 5:
5991 switch (sel) {
5992 case 0:
5993 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5994 rn = "PageMask";
5995 break;
5996 case 1:
5997 check_insn(ctx, ISA_MIPS32R2);
5998 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5999 rn = "PageGrain";
6000 break;
6001 default:
6002 goto die;
6004 break;
6005 case 6:
6006 switch (sel) {
6007 case 0:
6008 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6009 rn = "Wired";
6010 break;
6011 case 1:
6012 check_insn(ctx, ISA_MIPS32R2);
6013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6014 rn = "SRSConf0";
6015 break;
6016 case 2:
6017 check_insn(ctx, ISA_MIPS32R2);
6018 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6019 rn = "SRSConf1";
6020 break;
6021 case 3:
6022 check_insn(ctx, ISA_MIPS32R2);
6023 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6024 rn = "SRSConf2";
6025 break;
6026 case 4:
6027 check_insn(ctx, ISA_MIPS32R2);
6028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6029 rn = "SRSConf3";
6030 break;
6031 case 5:
6032 check_insn(ctx, ISA_MIPS32R2);
6033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6034 rn = "SRSConf4";
6035 break;
6036 default:
6037 goto die;
6039 break;
6040 case 7:
6041 switch (sel) {
6042 case 0:
6043 check_insn(ctx, ISA_MIPS32R2);
6044 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6045 rn = "HWREna";
6046 break;
6047 default:
6048 goto die;
6050 break;
6051 case 8:
6052 switch (sel) {
6053 case 0:
6054 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6055 rn = "BadVAddr";
6056 break;
6057 default:
6058 goto die;
6060 break;
6061 case 9:
6062 switch (sel) {
6063 case 0:
6064 /* Mark as an IO operation because we read the time. */
6065 if (use_icount)
6066 gen_io_start();
6067 gen_helper_mfc0_count(arg, cpu_env);
6068 if (use_icount) {
6069 gen_io_end();
6071 /* Break the TB to be able to take timer interrupts immediately
6072 after reading count. */
6073 ctx->bstate = BS_STOP;
6074 rn = "Count";
6075 break;
6076 /* 6,7 are implementation dependent */
6077 default:
6078 goto die;
6080 break;
6081 case 10:
6082 switch (sel) {
6083 case 0:
6084 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
6085 rn = "EntryHi";
6086 break;
6087 default:
6088 goto die;
6090 break;
6091 case 11:
6092 switch (sel) {
6093 case 0:
6094 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6095 rn = "Compare";
6096 break;
6097 /* 6,7 are implementation dependent */
6098 default:
6099 goto die;
6101 break;
6102 case 12:
6103 switch (sel) {
6104 case 0:
6105 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6106 rn = "Status";
6107 break;
6108 case 1:
6109 check_insn(ctx, ISA_MIPS32R2);
6110 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6111 rn = "IntCtl";
6112 break;
6113 case 2:
6114 check_insn(ctx, ISA_MIPS32R2);
6115 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6116 rn = "SRSCtl";
6117 break;
6118 case 3:
6119 check_insn(ctx, ISA_MIPS32R2);
6120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6121 rn = "SRSMap";
6122 break;
6123 default:
6124 goto die;
6126 break;
6127 case 13:
6128 switch (sel) {
6129 case 0:
6130 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6131 rn = "Cause";
6132 break;
6133 default:
6134 goto die;
6136 break;
6137 case 14:
6138 switch (sel) {
6139 case 0:
6140 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6141 rn = "EPC";
6142 break;
6143 default:
6144 goto die;
6146 break;
6147 case 15:
6148 switch (sel) {
6149 case 0:
6150 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6151 rn = "PRid";
6152 break;
6153 case 1:
6154 check_insn(ctx, ISA_MIPS32R2);
6155 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
6156 rn = "EBase";
6157 break;
6158 default:
6159 goto die;
6161 break;
6162 case 16:
6163 switch (sel) {
6164 case 0:
6165 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
6166 rn = "Config";
6167 break;
6168 case 1:
6169 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
6170 rn = "Config1";
6171 break;
6172 case 2:
6173 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
6174 rn = "Config2";
6175 break;
6176 case 3:
6177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
6178 rn = "Config3";
6179 break;
6180 /* 6,7 are implementation dependent */
6181 case 6:
6182 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
6183 rn = "Config6";
6184 break;
6185 case 7:
6186 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
6187 rn = "Config7";
6188 break;
6189 default:
6190 goto die;
6192 break;
6193 case 17:
6194 switch (sel) {
6195 case 0:
6196 gen_helper_dmfc0_lladdr(arg, cpu_env);
6197 rn = "LLAddr";
6198 break;
6199 default:
6200 goto die;
6202 break;
6203 case 18:
6204 switch (sel) {
6205 case 0 ... 7:
6206 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
6207 rn = "WatchLo";
6208 break;
6209 default:
6210 goto die;
6212 break;
6213 case 19:
6214 switch (sel) {
6215 case 0 ... 7:
6216 gen_helper_1e0i(mfc0_watchhi, arg, sel);
6217 rn = "WatchHi";
6218 break;
6219 default:
6220 goto die;
6222 break;
6223 case 20:
6224 switch (sel) {
6225 case 0:
6226 check_insn(ctx, ISA_MIPS3);
6227 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
6228 rn = "XContext";
6229 break;
6230 default:
6231 goto die;
6233 break;
6234 case 21:
6235 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6236 switch (sel) {
6237 case 0:
6238 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
6239 rn = "Framemask";
6240 break;
6241 default:
6242 goto die;
6244 break;
6245 case 22:
6246 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6247 rn = "'Diagnostic"; /* implementation dependent */
6248 break;
6249 case 23:
6250 switch (sel) {
6251 case 0:
6252 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
6253 rn = "Debug";
6254 break;
6255 case 1:
6256 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
6257 rn = "TraceControl";
6258 // break;
6259 case 2:
6260 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
6261 rn = "TraceControl2";
6262 // break;
6263 case 3:
6264 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
6265 rn = "UserTraceData";
6266 // break;
6267 case 4:
6268 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
6269 rn = "TraceBPC";
6270 // break;
6271 default:
6272 goto die;
6274 break;
6275 case 24:
6276 switch (sel) {
6277 case 0:
6278 /* EJTAG support */
6279 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6280 rn = "DEPC";
6281 break;
6282 default:
6283 goto die;
6285 break;
6286 case 25:
6287 switch (sel) {
6288 case 0:
6289 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
6290 rn = "Performance0";
6291 break;
6292 case 1:
6293 // gen_helper_dmfc0_performance1(arg);
6294 rn = "Performance1";
6295 // break;
6296 case 2:
6297 // gen_helper_dmfc0_performance2(arg);
6298 rn = "Performance2";
6299 // break;
6300 case 3:
6301 // gen_helper_dmfc0_performance3(arg);
6302 rn = "Performance3";
6303 // break;
6304 case 4:
6305 // gen_helper_dmfc0_performance4(arg);
6306 rn = "Performance4";
6307 // break;
6308 case 5:
6309 // gen_helper_dmfc0_performance5(arg);
6310 rn = "Performance5";
6311 // break;
6312 case 6:
6313 // gen_helper_dmfc0_performance6(arg);
6314 rn = "Performance6";
6315 // break;
6316 case 7:
6317 // gen_helper_dmfc0_performance7(arg);
6318 rn = "Performance7";
6319 // break;
6320 default:
6321 goto die;
6323 break;
6324 case 26:
6325 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6326 rn = "ECC";
6327 break;
6328 case 27:
6329 switch (sel) {
6330 /* ignored */
6331 case 0 ... 3:
6332 tcg_gen_movi_tl(arg, 0); /* unimplemented */
6333 rn = "CacheErr";
6334 break;
6335 default:
6336 goto die;
6338 break;
6339 case 28:
6340 switch (sel) {
6341 case 0:
6342 case 2:
6343 case 4:
6344 case 6:
6345 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
6346 rn = "TagLo";
6347 break;
6348 case 1:
6349 case 3:
6350 case 5:
6351 case 7:
6352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
6353 rn = "DataLo";
6354 break;
6355 default:
6356 goto die;
6358 break;
6359 case 29:
6360 switch (sel) {
6361 case 0:
6362 case 2:
6363 case 4:
6364 case 6:
6365 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
6366 rn = "TagHi";
6367 break;
6368 case 1:
6369 case 3:
6370 case 5:
6371 case 7:
6372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
6373 rn = "DataHi";
6374 break;
6375 default:
6376 goto die;
6378 break;
6379 case 30:
6380 switch (sel) {
6381 case 0:
6382 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6383 rn = "ErrorEPC";
6384 break;
6385 default:
6386 goto die;
6388 break;
6389 case 31:
6390 switch (sel) {
6391 case 0:
6392 /* EJTAG support */
6393 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6394 rn = "DESAVE";
6395 break;
6396 case 2 ... 7:
6397 if (ctx->kscrexist & (1 << sel)) {
6398 tcg_gen_ld_tl(arg, cpu_env,
6399 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
6400 rn = "KScratch";
6401 } else {
6402 gen_mfc0_unimplemented(ctx, arg);
6404 break;
6405 default:
6406 goto die;
6408 break;
6409 default:
6410 goto die;
6412 (void)rn; /* avoid a compiler warning */
6413 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6414 return;
6416 die:
6417 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
6418 generate_exception(ctx, EXCP_RI);
6421 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6423 const char *rn = "invalid";
6425 if (sel != 0)
6426 check_insn(ctx, ISA_MIPS64);
6428 if (use_icount)
6429 gen_io_start();
6431 switch (reg) {
6432 case 0:
6433 switch (sel) {
6434 case 0:
6435 gen_helper_mtc0_index(cpu_env, arg);
6436 rn = "Index";
6437 break;
6438 case 1:
6439 check_insn(ctx, ASE_MT);
6440 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
6441 rn = "MVPControl";
6442 break;
6443 case 2:
6444 check_insn(ctx, ASE_MT);
6445 /* ignored */
6446 rn = "MVPConf0";
6447 break;
6448 case 3:
6449 check_insn(ctx, ASE_MT);
6450 /* ignored */
6451 rn = "MVPConf1";
6452 break;
6453 default:
6454 goto die;
6456 break;
6457 case 1:
6458 switch (sel) {
6459 case 0:
6460 /* ignored */
6461 rn = "Random";
6462 break;
6463 case 1:
6464 check_insn(ctx, ASE_MT);
6465 gen_helper_mtc0_vpecontrol(cpu_env, arg);
6466 rn = "VPEControl";
6467 break;
6468 case 2:
6469 check_insn(ctx, ASE_MT);
6470 gen_helper_mtc0_vpeconf0(cpu_env, arg);
6471 rn = "VPEConf0";
6472 break;
6473 case 3:
6474 check_insn(ctx, ASE_MT);
6475 gen_helper_mtc0_vpeconf1(cpu_env, arg);
6476 rn = "VPEConf1";
6477 break;
6478 case 4:
6479 check_insn(ctx, ASE_MT);
6480 gen_helper_mtc0_yqmask(cpu_env, arg);
6481 rn = "YQMask";
6482 break;
6483 case 5:
6484 check_insn(ctx, ASE_MT);
6485 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
6486 rn = "VPESchedule";
6487 break;
6488 case 6:
6489 check_insn(ctx, ASE_MT);
6490 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
6491 rn = "VPEScheFBack";
6492 break;
6493 case 7:
6494 check_insn(ctx, ASE_MT);
6495 gen_helper_mtc0_vpeopt(cpu_env, arg);
6496 rn = "VPEOpt";
6497 break;
6498 default:
6499 goto die;
6501 break;
6502 case 2:
6503 switch (sel) {
6504 case 0:
6505 gen_helper_dmtc0_entrylo0(cpu_env, arg);
6506 rn = "EntryLo0";
6507 break;
6508 case 1:
6509 check_insn(ctx, ASE_MT);
6510 gen_helper_mtc0_tcstatus(cpu_env, arg);
6511 rn = "TCStatus";
6512 break;
6513 case 2:
6514 check_insn(ctx, ASE_MT);
6515 gen_helper_mtc0_tcbind(cpu_env, arg);
6516 rn = "TCBind";
6517 break;
6518 case 3:
6519 check_insn(ctx, ASE_MT);
6520 gen_helper_mtc0_tcrestart(cpu_env, arg);
6521 rn = "TCRestart";
6522 break;
6523 case 4:
6524 check_insn(ctx, ASE_MT);
6525 gen_helper_mtc0_tchalt(cpu_env, arg);
6526 rn = "TCHalt";
6527 break;
6528 case 5:
6529 check_insn(ctx, ASE_MT);
6530 gen_helper_mtc0_tccontext(cpu_env, arg);
6531 rn = "TCContext";
6532 break;
6533 case 6:
6534 check_insn(ctx, ASE_MT);
6535 gen_helper_mtc0_tcschedule(cpu_env, arg);
6536 rn = "TCSchedule";
6537 break;
6538 case 7:
6539 check_insn(ctx, ASE_MT);
6540 gen_helper_mtc0_tcschefback(cpu_env, arg);
6541 rn = "TCScheFBack";
6542 break;
6543 default:
6544 goto die;
6546 break;
6547 case 3:
6548 switch (sel) {
6549 case 0:
6550 gen_helper_dmtc0_entrylo1(cpu_env, arg);
6551 rn = "EntryLo1";
6552 break;
6553 default:
6554 goto die;
6556 break;
6557 case 4:
6558 switch (sel) {
6559 case 0:
6560 gen_helper_mtc0_context(cpu_env, arg);
6561 rn = "Context";
6562 break;
6563 case 1:
6564 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6565 rn = "ContextConfig";
6566 goto die;
6567 // break;
6568 case 2:
6569 if (ctx->ulri) {
6570 tcg_gen_st_tl(arg, cpu_env,
6571 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6572 rn = "UserLocal";
6574 break;
6575 default:
6576 goto die;
6578 break;
6579 case 5:
6580 switch (sel) {
6581 case 0:
6582 gen_helper_mtc0_pagemask(cpu_env, arg);
6583 rn = "PageMask";
6584 break;
6585 case 1:
6586 check_insn(ctx, ISA_MIPS32R2);
6587 gen_helper_mtc0_pagegrain(cpu_env, arg);
6588 rn = "PageGrain";
6589 break;
6590 default:
6591 goto die;
6593 break;
6594 case 6:
6595 switch (sel) {
6596 case 0:
6597 gen_helper_mtc0_wired(cpu_env, arg);
6598 rn = "Wired";
6599 break;
6600 case 1:
6601 check_insn(ctx, ISA_MIPS32R2);
6602 gen_helper_mtc0_srsconf0(cpu_env, arg);
6603 rn = "SRSConf0";
6604 break;
6605 case 2:
6606 check_insn(ctx, ISA_MIPS32R2);
6607 gen_helper_mtc0_srsconf1(cpu_env, arg);
6608 rn = "SRSConf1";
6609 break;
6610 case 3:
6611 check_insn(ctx, ISA_MIPS32R2);
6612 gen_helper_mtc0_srsconf2(cpu_env, arg);
6613 rn = "SRSConf2";
6614 break;
6615 case 4:
6616 check_insn(ctx, ISA_MIPS32R2);
6617 gen_helper_mtc0_srsconf3(cpu_env, arg);
6618 rn = "SRSConf3";
6619 break;
6620 case 5:
6621 check_insn(ctx, ISA_MIPS32R2);
6622 gen_helper_mtc0_srsconf4(cpu_env, arg);
6623 rn = "SRSConf4";
6624 break;
6625 default:
6626 goto die;
6628 break;
6629 case 7:
6630 switch (sel) {
6631 case 0:
6632 check_insn(ctx, ISA_MIPS32R2);
6633 gen_helper_mtc0_hwrena(cpu_env, arg);
6634 ctx->bstate = BS_STOP;
6635 rn = "HWREna";
6636 break;
6637 default:
6638 goto die;
6640 break;
6641 case 8:
6642 /* ignored */
6643 rn = "BadVAddr";
6644 break;
6645 case 9:
6646 switch (sel) {
6647 case 0:
6648 gen_helper_mtc0_count(cpu_env, arg);
6649 rn = "Count";
6650 break;
6651 /* 6,7 are implementation dependent */
6652 default:
6653 goto die;
6655 /* Stop translation as we may have switched the execution mode */
6656 ctx->bstate = BS_STOP;
6657 break;
6658 case 10:
6659 switch (sel) {
6660 case 0:
6661 gen_helper_mtc0_entryhi(cpu_env, arg);
6662 rn = "EntryHi";
6663 break;
6664 default:
6665 goto die;
6667 break;
6668 case 11:
6669 switch (sel) {
6670 case 0:
6671 gen_helper_mtc0_compare(cpu_env, arg);
6672 rn = "Compare";
6673 break;
6674 /* 6,7 are implementation dependent */
6675 default:
6676 goto die;
6678 /* Stop translation as we may have switched the execution mode */
6679 ctx->bstate = BS_STOP;
6680 break;
6681 case 12:
6682 switch (sel) {
6683 case 0:
6684 save_cpu_state(ctx, 1);
6685 gen_helper_mtc0_status(cpu_env, arg);
6686 /* BS_STOP isn't good enough here, hflags may have changed. */
6687 gen_save_pc(ctx->pc + 4);
6688 ctx->bstate = BS_EXCP;
6689 rn = "Status";
6690 break;
6691 case 1:
6692 check_insn(ctx, ISA_MIPS32R2);
6693 gen_helper_mtc0_intctl(cpu_env, arg);
6694 /* Stop translation as we may have switched the execution mode */
6695 ctx->bstate = BS_STOP;
6696 rn = "IntCtl";
6697 break;
6698 case 2:
6699 check_insn(ctx, ISA_MIPS32R2);
6700 gen_helper_mtc0_srsctl(cpu_env, arg);
6701 /* Stop translation as we may have switched the execution mode */
6702 ctx->bstate = BS_STOP;
6703 rn = "SRSCtl";
6704 break;
6705 case 3:
6706 check_insn(ctx, ISA_MIPS32R2);
6707 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6708 /* Stop translation as we may have switched the execution mode */
6709 ctx->bstate = BS_STOP;
6710 rn = "SRSMap";
6711 break;
6712 default:
6713 goto die;
6715 break;
6716 case 13:
6717 switch (sel) {
6718 case 0:
6719 save_cpu_state(ctx, 1);
6720 /* Mark as an IO operation because we may trigger a software
6721 interrupt. */
6722 if (use_icount) {
6723 gen_io_start();
6725 gen_helper_mtc0_cause(cpu_env, arg);
6726 if (use_icount) {
6727 gen_io_end();
6729 /* Stop translation as we may have triggered an intetrupt */
6730 ctx->bstate = BS_STOP;
6731 rn = "Cause";
6732 break;
6733 default:
6734 goto die;
6736 break;
6737 case 14:
6738 switch (sel) {
6739 case 0:
6740 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6741 rn = "EPC";
6742 break;
6743 default:
6744 goto die;
6746 break;
6747 case 15:
6748 switch (sel) {
6749 case 0:
6750 /* ignored */
6751 rn = "PRid";
6752 break;
6753 case 1:
6754 check_insn(ctx, ISA_MIPS32R2);
6755 gen_helper_mtc0_ebase(cpu_env, arg);
6756 rn = "EBase";
6757 break;
6758 default:
6759 goto die;
6761 break;
6762 case 16:
6763 switch (sel) {
6764 case 0:
6765 gen_helper_mtc0_config0(cpu_env, arg);
6766 rn = "Config";
6767 /* Stop translation as we may have switched the execution mode */
6768 ctx->bstate = BS_STOP;
6769 break;
6770 case 1:
6771 /* ignored, read only */
6772 rn = "Config1";
6773 break;
6774 case 2:
6775 gen_helper_mtc0_config2(cpu_env, arg);
6776 rn = "Config2";
6777 /* Stop translation as we may have switched the execution mode */
6778 ctx->bstate = BS_STOP;
6779 break;
6780 case 3:
6781 /* ignored */
6782 rn = "Config3";
6783 break;
6784 /* 6,7 are implementation dependent */
6785 default:
6786 rn = "Invalid config selector";
6787 goto die;
6789 break;
6790 case 17:
6791 switch (sel) {
6792 case 0:
6793 gen_helper_mtc0_lladdr(cpu_env, arg);
6794 rn = "LLAddr";
6795 break;
6796 default:
6797 goto die;
6799 break;
6800 case 18:
6801 switch (sel) {
6802 case 0 ... 7:
6803 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6804 rn = "WatchLo";
6805 break;
6806 default:
6807 goto die;
6809 break;
6810 case 19:
6811 switch (sel) {
6812 case 0 ... 7:
6813 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6814 rn = "WatchHi";
6815 break;
6816 default:
6817 goto die;
6819 break;
6820 case 20:
6821 switch (sel) {
6822 case 0:
6823 check_insn(ctx, ISA_MIPS3);
6824 gen_helper_mtc0_xcontext(cpu_env, arg);
6825 rn = "XContext";
6826 break;
6827 default:
6828 goto die;
6830 break;
6831 case 21:
6832 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6833 switch (sel) {
6834 case 0:
6835 gen_helper_mtc0_framemask(cpu_env, arg);
6836 rn = "Framemask";
6837 break;
6838 default:
6839 goto die;
6841 break;
6842 case 22:
6843 /* ignored */
6844 rn = "Diagnostic"; /* implementation dependent */
6845 break;
6846 case 23:
6847 switch (sel) {
6848 case 0:
6849 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6850 /* BS_STOP isn't good enough here, hflags may have changed. */
6851 gen_save_pc(ctx->pc + 4);
6852 ctx->bstate = BS_EXCP;
6853 rn = "Debug";
6854 break;
6855 case 1:
6856 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6857 /* Stop translation as we may have switched the execution mode */
6858 ctx->bstate = BS_STOP;
6859 rn = "TraceControl";
6860 // break;
6861 case 2:
6862 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6863 /* Stop translation as we may have switched the execution mode */
6864 ctx->bstate = BS_STOP;
6865 rn = "TraceControl2";
6866 // break;
6867 case 3:
6868 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6869 /* Stop translation as we may have switched the execution mode */
6870 ctx->bstate = BS_STOP;
6871 rn = "UserTraceData";
6872 // break;
6873 case 4:
6874 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6875 /* Stop translation as we may have switched the execution mode */
6876 ctx->bstate = BS_STOP;
6877 rn = "TraceBPC";
6878 // break;
6879 default:
6880 goto die;
6882 break;
6883 case 24:
6884 switch (sel) {
6885 case 0:
6886 /* EJTAG support */
6887 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6888 rn = "DEPC";
6889 break;
6890 default:
6891 goto die;
6893 break;
6894 case 25:
6895 switch (sel) {
6896 case 0:
6897 gen_helper_mtc0_performance0(cpu_env, arg);
6898 rn = "Performance0";
6899 break;
6900 case 1:
6901 // gen_helper_mtc0_performance1(cpu_env, arg);
6902 rn = "Performance1";
6903 // break;
6904 case 2:
6905 // gen_helper_mtc0_performance2(cpu_env, arg);
6906 rn = "Performance2";
6907 // break;
6908 case 3:
6909 // gen_helper_mtc0_performance3(cpu_env, arg);
6910 rn = "Performance3";
6911 // break;
6912 case 4:
6913 // gen_helper_mtc0_performance4(cpu_env, arg);
6914 rn = "Performance4";
6915 // break;
6916 case 5:
6917 // gen_helper_mtc0_performance5(cpu_env, arg);
6918 rn = "Performance5";
6919 // break;
6920 case 6:
6921 // gen_helper_mtc0_performance6(cpu_env, arg);
6922 rn = "Performance6";
6923 // break;
6924 case 7:
6925 // gen_helper_mtc0_performance7(cpu_env, arg);
6926 rn = "Performance7";
6927 // break;
6928 default:
6929 goto die;
6931 break;
6932 case 26:
6933 /* ignored */
6934 rn = "ECC";
6935 break;
6936 case 27:
6937 switch (sel) {
6938 case 0 ... 3:
6939 /* ignored */
6940 rn = "CacheErr";
6941 break;
6942 default:
6943 goto die;
6945 break;
6946 case 28:
6947 switch (sel) {
6948 case 0:
6949 case 2:
6950 case 4:
6951 case 6:
6952 gen_helper_mtc0_taglo(cpu_env, arg);
6953 rn = "TagLo";
6954 break;
6955 case 1:
6956 case 3:
6957 case 5:
6958 case 7:
6959 gen_helper_mtc0_datalo(cpu_env, arg);
6960 rn = "DataLo";
6961 break;
6962 default:
6963 goto die;
6965 break;
6966 case 29:
6967 switch (sel) {
6968 case 0:
6969 case 2:
6970 case 4:
6971 case 6:
6972 gen_helper_mtc0_taghi(cpu_env, arg);
6973 rn = "TagHi";
6974 break;
6975 case 1:
6976 case 3:
6977 case 5:
6978 case 7:
6979 gen_helper_mtc0_datahi(cpu_env, arg);
6980 rn = "DataHi";
6981 break;
6982 default:
6983 rn = "invalid sel";
6984 goto die;
6986 break;
6987 case 30:
6988 switch (sel) {
6989 case 0:
6990 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6991 rn = "ErrorEPC";
6992 break;
6993 default:
6994 goto die;
6996 break;
6997 case 31:
6998 switch (sel) {
6999 case 0:
7000 /* EJTAG support */
7001 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7002 rn = "DESAVE";
7003 break;
7004 case 2 ... 7:
7005 if (ctx->kscrexist & (1 << sel)) {
7006 tcg_gen_st_tl(arg, cpu_env,
7007 offsetof(CPUMIPSState, CP0_KScratch[sel-2]));
7008 rn = "KScratch";
7010 break;
7011 default:
7012 goto die;
7014 /* Stop translation as we may have switched the execution mode */
7015 ctx->bstate = BS_STOP;
7016 break;
7017 default:
7018 goto die;
7020 (void)rn; /* avoid a compiler warning */
7021 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7022 /* For simplicity assume that all writes can cause interrupts. */
7023 if (use_icount) {
7024 gen_io_end();
7025 ctx->bstate = BS_STOP;
7027 return;
7029 die:
7030 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
7031 generate_exception(ctx, EXCP_RI);
7033 #endif /* TARGET_MIPS64 */
7035 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
7036 int u, int sel, int h)
7038 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7039 TCGv t0 = tcg_temp_local_new();
7041 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7042 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7043 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7044 tcg_gen_movi_tl(t0, -1);
7045 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7046 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7047 tcg_gen_movi_tl(t0, -1);
7048 else if (u == 0) {
7049 switch (rt) {
7050 case 1:
7051 switch (sel) {
7052 case 1:
7053 gen_helper_mftc0_vpecontrol(t0, cpu_env);
7054 break;
7055 case 2:
7056 gen_helper_mftc0_vpeconf0(t0, cpu_env);
7057 break;
7058 default:
7059 goto die;
7060 break;
7062 break;
7063 case 2:
7064 switch (sel) {
7065 case 1:
7066 gen_helper_mftc0_tcstatus(t0, cpu_env);
7067 break;
7068 case 2:
7069 gen_helper_mftc0_tcbind(t0, cpu_env);
7070 break;
7071 case 3:
7072 gen_helper_mftc0_tcrestart(t0, cpu_env);
7073 break;
7074 case 4:
7075 gen_helper_mftc0_tchalt(t0, cpu_env);
7076 break;
7077 case 5:
7078 gen_helper_mftc0_tccontext(t0, cpu_env);
7079 break;
7080 case 6:
7081 gen_helper_mftc0_tcschedule(t0, cpu_env);
7082 break;
7083 case 7:
7084 gen_helper_mftc0_tcschefback(t0, cpu_env);
7085 break;
7086 default:
7087 gen_mfc0(ctx, t0, rt, sel);
7088 break;
7090 break;
7091 case 10:
7092 switch (sel) {
7093 case 0:
7094 gen_helper_mftc0_entryhi(t0, cpu_env);
7095 break;
7096 default:
7097 gen_mfc0(ctx, t0, rt, sel);
7098 break;
7100 case 12:
7101 switch (sel) {
7102 case 0:
7103 gen_helper_mftc0_status(t0, cpu_env);
7104 break;
7105 default:
7106 gen_mfc0(ctx, t0, rt, sel);
7107 break;
7109 case 13:
7110 switch (sel) {
7111 case 0:
7112 gen_helper_mftc0_cause(t0, cpu_env);
7113 break;
7114 default:
7115 goto die;
7116 break;
7118 break;
7119 case 14:
7120 switch (sel) {
7121 case 0:
7122 gen_helper_mftc0_epc(t0, cpu_env);
7123 break;
7124 default:
7125 goto die;
7126 break;
7128 break;
7129 case 15:
7130 switch (sel) {
7131 case 1:
7132 gen_helper_mftc0_ebase(t0, cpu_env);
7133 break;
7134 default:
7135 goto die;
7136 break;
7138 break;
7139 case 16:
7140 switch (sel) {
7141 case 0 ... 7:
7142 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
7143 break;
7144 default:
7145 goto die;
7146 break;
7148 break;
7149 case 23:
7150 switch (sel) {
7151 case 0:
7152 gen_helper_mftc0_debug(t0, cpu_env);
7153 break;
7154 default:
7155 gen_mfc0(ctx, t0, rt, sel);
7156 break;
7158 break;
7159 default:
7160 gen_mfc0(ctx, t0, rt, sel);
7162 } else switch (sel) {
7163 /* GPR registers. */
7164 case 0:
7165 gen_helper_1e0i(mftgpr, t0, rt);
7166 break;
7167 /* Auxiliary CPU registers */
7168 case 1:
7169 switch (rt) {
7170 case 0:
7171 gen_helper_1e0i(mftlo, t0, 0);
7172 break;
7173 case 1:
7174 gen_helper_1e0i(mfthi, t0, 0);
7175 break;
7176 case 2:
7177 gen_helper_1e0i(mftacx, t0, 0);
7178 break;
7179 case 4:
7180 gen_helper_1e0i(mftlo, t0, 1);
7181 break;
7182 case 5:
7183 gen_helper_1e0i(mfthi, t0, 1);
7184 break;
7185 case 6:
7186 gen_helper_1e0i(mftacx, t0, 1);
7187 break;
7188 case 8:
7189 gen_helper_1e0i(mftlo, t0, 2);
7190 break;
7191 case 9:
7192 gen_helper_1e0i(mfthi, t0, 2);
7193 break;
7194 case 10:
7195 gen_helper_1e0i(mftacx, t0, 2);
7196 break;
7197 case 12:
7198 gen_helper_1e0i(mftlo, t0, 3);
7199 break;
7200 case 13:
7201 gen_helper_1e0i(mfthi, t0, 3);
7202 break;
7203 case 14:
7204 gen_helper_1e0i(mftacx, t0, 3);
7205 break;
7206 case 16:
7207 gen_helper_mftdsp(t0, cpu_env);
7208 break;
7209 default:
7210 goto die;
7212 break;
7213 /* Floating point (COP1). */
7214 case 2:
7215 /* XXX: For now we support only a single FPU context. */
7216 if (h == 0) {
7217 TCGv_i32 fp0 = tcg_temp_new_i32();
7219 gen_load_fpr32(fp0, rt);
7220 tcg_gen_ext_i32_tl(t0, fp0);
7221 tcg_temp_free_i32(fp0);
7222 } else {
7223 TCGv_i32 fp0 = tcg_temp_new_i32();
7225 gen_load_fpr32h(ctx, fp0, rt);
7226 tcg_gen_ext_i32_tl(t0, fp0);
7227 tcg_temp_free_i32(fp0);
7229 break;
7230 case 3:
7231 /* XXX: For now we support only a single FPU context. */
7232 gen_helper_1e0i(cfc1, t0, rt);
7233 break;
7234 /* COP2: Not implemented. */
7235 case 4:
7236 case 5:
7237 /* fall through */
7238 default:
7239 goto die;
7241 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7242 gen_store_gpr(t0, rd);
7243 tcg_temp_free(t0);
7244 return;
7246 die:
7247 tcg_temp_free(t0);
7248 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
7249 generate_exception(ctx, EXCP_RI);
7252 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
7253 int u, int sel, int h)
7255 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
7256 TCGv t0 = tcg_temp_local_new();
7258 gen_load_gpr(t0, rt);
7259 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
7260 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
7261 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
7262 /* NOP */ ;
7263 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
7264 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
7265 /* NOP */ ;
7266 else if (u == 0) {
7267 switch (rd) {
7268 case 1:
7269 switch (sel) {
7270 case 1:
7271 gen_helper_mttc0_vpecontrol(cpu_env, t0);
7272 break;
7273 case 2:
7274 gen_helper_mttc0_vpeconf0(cpu_env, t0);
7275 break;
7276 default:
7277 goto die;
7278 break;
7280 break;
7281 case 2:
7282 switch (sel) {
7283 case 1:
7284 gen_helper_mttc0_tcstatus(cpu_env, t0);
7285 break;
7286 case 2:
7287 gen_helper_mttc0_tcbind(cpu_env, t0);
7288 break;
7289 case 3:
7290 gen_helper_mttc0_tcrestart(cpu_env, t0);
7291 break;
7292 case 4:
7293 gen_helper_mttc0_tchalt(cpu_env, t0);
7294 break;
7295 case 5:
7296 gen_helper_mttc0_tccontext(cpu_env, t0);
7297 break;
7298 case 6:
7299 gen_helper_mttc0_tcschedule(cpu_env, t0);
7300 break;
7301 case 7:
7302 gen_helper_mttc0_tcschefback(cpu_env, t0);
7303 break;
7304 default:
7305 gen_mtc0(ctx, t0, rd, sel);
7306 break;
7308 break;
7309 case 10:
7310 switch (sel) {
7311 case 0:
7312 gen_helper_mttc0_entryhi(cpu_env, t0);
7313 break;
7314 default:
7315 gen_mtc0(ctx, t0, rd, sel);
7316 break;
7318 case 12:
7319 switch (sel) {
7320 case 0:
7321 gen_helper_mttc0_status(cpu_env, t0);
7322 break;
7323 default:
7324 gen_mtc0(ctx, t0, rd, sel);
7325 break;
7327 case 13:
7328 switch (sel) {
7329 case 0:
7330 gen_helper_mttc0_cause(cpu_env, t0);
7331 break;
7332 default:
7333 goto die;
7334 break;
7336 break;
7337 case 15:
7338 switch (sel) {
7339 case 1:
7340 gen_helper_mttc0_ebase(cpu_env, t0);
7341 break;
7342 default:
7343 goto die;
7344 break;
7346 break;
7347 case 23:
7348 switch (sel) {
7349 case 0:
7350 gen_helper_mttc0_debug(cpu_env, t0);
7351 break;
7352 default:
7353 gen_mtc0(ctx, t0, rd, sel);
7354 break;
7356 break;
7357 default:
7358 gen_mtc0(ctx, t0, rd, sel);
7360 } else switch (sel) {
7361 /* GPR registers. */
7362 case 0:
7363 gen_helper_0e1i(mttgpr, t0, rd);
7364 break;
7365 /* Auxiliary CPU registers */
7366 case 1:
7367 switch (rd) {
7368 case 0:
7369 gen_helper_0e1i(mttlo, t0, 0);
7370 break;
7371 case 1:
7372 gen_helper_0e1i(mtthi, t0, 0);
7373 break;
7374 case 2:
7375 gen_helper_0e1i(mttacx, t0, 0);
7376 break;
7377 case 4:
7378 gen_helper_0e1i(mttlo, t0, 1);
7379 break;
7380 case 5:
7381 gen_helper_0e1i(mtthi, t0, 1);
7382 break;
7383 case 6:
7384 gen_helper_0e1i(mttacx, t0, 1);
7385 break;
7386 case 8:
7387 gen_helper_0e1i(mttlo, t0, 2);
7388 break;
7389 case 9:
7390 gen_helper_0e1i(mtthi, t0, 2);
7391 break;
7392 case 10:
7393 gen_helper_0e1i(mttacx, t0, 2);
7394 break;
7395 case 12:
7396 gen_helper_0e1i(mttlo, t0, 3);
7397 break;
7398 case 13:
7399 gen_helper_0e1i(mtthi, t0, 3);
7400 break;
7401 case 14:
7402 gen_helper_0e1i(mttacx, t0, 3);
7403 break;
7404 case 16:
7405 gen_helper_mttdsp(cpu_env, t0);
7406 break;
7407 default:
7408 goto die;
7410 break;
7411 /* Floating point (COP1). */
7412 case 2:
7413 /* XXX: For now we support only a single FPU context. */
7414 if (h == 0) {
7415 TCGv_i32 fp0 = tcg_temp_new_i32();
7417 tcg_gen_trunc_tl_i32(fp0, t0);
7418 gen_store_fpr32(fp0, rd);
7419 tcg_temp_free_i32(fp0);
7420 } else {
7421 TCGv_i32 fp0 = tcg_temp_new_i32();
7423 tcg_gen_trunc_tl_i32(fp0, t0);
7424 gen_store_fpr32h(ctx, fp0, rd);
7425 tcg_temp_free_i32(fp0);
7427 break;
7428 case 3:
7429 /* XXX: For now we support only a single FPU context. */
7431 TCGv_i32 fs_tmp = tcg_const_i32(rd);
7433 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7434 tcg_temp_free_i32(fs_tmp);
7436 break;
7437 /* COP2: Not implemented. */
7438 case 4:
7439 case 5:
7440 /* fall through */
7441 default:
7442 goto die;
7444 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7445 tcg_temp_free(t0);
7446 return;
7448 die:
7449 tcg_temp_free(t0);
7450 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
7451 generate_exception(ctx, EXCP_RI);
7454 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
7456 const char *opn = "ldst";
7458 check_cp0_enabled(ctx);
7459 switch (opc) {
7460 case OPC_MFC0:
7461 if (rt == 0) {
7462 /* Treat as NOP. */
7463 return;
7465 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7466 opn = "mfc0";
7467 break;
7468 case OPC_MTC0:
7470 TCGv t0 = tcg_temp_new();
7472 gen_load_gpr(t0, rt);
7473 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
7474 tcg_temp_free(t0);
7476 opn = "mtc0";
7477 break;
7478 #if defined(TARGET_MIPS64)
7479 case OPC_DMFC0:
7480 check_insn(ctx, ISA_MIPS3);
7481 if (rt == 0) {
7482 /* Treat as NOP. */
7483 return;
7485 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
7486 opn = "dmfc0";
7487 break;
7488 case OPC_DMTC0:
7489 check_insn(ctx, ISA_MIPS3);
7491 TCGv t0 = tcg_temp_new();
7493 gen_load_gpr(t0, rt);
7494 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
7495 tcg_temp_free(t0);
7497 opn = "dmtc0";
7498 break;
7499 #endif
7500 case OPC_MFTR:
7501 check_insn(ctx, ASE_MT);
7502 if (rd == 0) {
7503 /* Treat as NOP. */
7504 return;
7506 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
7507 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7508 opn = "mftr";
7509 break;
7510 case OPC_MTTR:
7511 check_insn(ctx, ASE_MT);
7512 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
7513 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
7514 opn = "mttr";
7515 break;
7516 case OPC_TLBWI:
7517 opn = "tlbwi";
7518 if (!env->tlb->helper_tlbwi)
7519 goto die;
7520 gen_helper_tlbwi(cpu_env);
7521 break;
7522 case OPC_TLBINV:
7523 opn = "tlbinv";
7524 if (ctx->ie >= 2) {
7525 if (!env->tlb->helper_tlbinv) {
7526 goto die;
7528 gen_helper_tlbinv(cpu_env);
7529 } /* treat as nop if TLBINV not supported */
7530 break;
7531 case OPC_TLBINVF:
7532 opn = "tlbinvf";
7533 if (ctx->ie >= 2) {
7534 if (!env->tlb->helper_tlbinvf) {
7535 goto die;
7537 gen_helper_tlbinvf(cpu_env);
7538 } /* treat as nop if TLBINV not supported */
7539 break;
7540 case OPC_TLBWR:
7541 opn = "tlbwr";
7542 if (!env->tlb->helper_tlbwr)
7543 goto die;
7544 gen_helper_tlbwr(cpu_env);
7545 break;
7546 case OPC_TLBP:
7547 opn = "tlbp";
7548 if (!env->tlb->helper_tlbp)
7549 goto die;
7550 gen_helper_tlbp(cpu_env);
7551 break;
7552 case OPC_TLBR:
7553 opn = "tlbr";
7554 if (!env->tlb->helper_tlbr)
7555 goto die;
7556 gen_helper_tlbr(cpu_env);
7557 break;
7558 case OPC_ERET:
7559 opn = "eret";
7560 check_insn(ctx, ISA_MIPS2);
7561 gen_helper_eret(cpu_env);
7562 ctx->bstate = BS_EXCP;
7563 break;
7564 case OPC_DERET:
7565 opn = "deret";
7566 check_insn(ctx, ISA_MIPS32);
7567 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
7568 MIPS_INVAL(opn);
7569 generate_exception(ctx, EXCP_RI);
7570 } else {
7571 gen_helper_deret(cpu_env);
7572 ctx->bstate = BS_EXCP;
7574 break;
7575 case OPC_WAIT:
7576 opn = "wait";
7577 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
7578 /* If we get an exception, we want to restart at next instruction */
7579 ctx->pc += 4;
7580 save_cpu_state(ctx, 1);
7581 ctx->pc -= 4;
7582 gen_helper_wait(cpu_env);
7583 ctx->bstate = BS_EXCP;
7584 break;
7585 default:
7586 die:
7587 MIPS_INVAL(opn);
7588 generate_exception(ctx, EXCP_RI);
7589 return;
7591 (void)opn; /* avoid a compiler warning */
7592 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
7594 #endif /* !CONFIG_USER_ONLY */
7596 /* CP1 Branches (before delay slot) */
7597 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7598 int32_t cc, int32_t offset)
7600 target_ulong btarget;
7601 const char *opn = "cp1 cond branch";
7602 TCGv_i32 t0 = tcg_temp_new_i32();
7604 if (cc != 0)
7605 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
7607 btarget = ctx->pc + 4 + offset;
7609 switch (op) {
7610 case OPC_BC1F:
7611 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7612 tcg_gen_not_i32(t0, t0);
7613 tcg_gen_andi_i32(t0, t0, 1);
7614 tcg_gen_extu_i32_tl(bcond, t0);
7615 opn = "bc1f";
7616 goto not_likely;
7617 case OPC_BC1FL:
7618 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7619 tcg_gen_not_i32(t0, t0);
7620 tcg_gen_andi_i32(t0, t0, 1);
7621 tcg_gen_extu_i32_tl(bcond, t0);
7622 opn = "bc1fl";
7623 goto likely;
7624 case OPC_BC1T:
7625 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7626 tcg_gen_andi_i32(t0, t0, 1);
7627 tcg_gen_extu_i32_tl(bcond, t0);
7628 opn = "bc1t";
7629 goto not_likely;
7630 case OPC_BC1TL:
7631 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7632 tcg_gen_andi_i32(t0, t0, 1);
7633 tcg_gen_extu_i32_tl(bcond, t0);
7634 opn = "bc1tl";
7635 likely:
7636 ctx->hflags |= MIPS_HFLAG_BL;
7637 break;
7638 case OPC_BC1FANY2:
7640 TCGv_i32 t1 = tcg_temp_new_i32();
7641 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7642 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7643 tcg_gen_nand_i32(t0, t0, t1);
7644 tcg_temp_free_i32(t1);
7645 tcg_gen_andi_i32(t0, t0, 1);
7646 tcg_gen_extu_i32_tl(bcond, t0);
7648 opn = "bc1any2f";
7649 goto not_likely;
7650 case OPC_BC1TANY2:
7652 TCGv_i32 t1 = tcg_temp_new_i32();
7653 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7654 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7655 tcg_gen_or_i32(t0, t0, t1);
7656 tcg_temp_free_i32(t1);
7657 tcg_gen_andi_i32(t0, t0, 1);
7658 tcg_gen_extu_i32_tl(bcond, t0);
7660 opn = "bc1any2t";
7661 goto not_likely;
7662 case OPC_BC1FANY4:
7664 TCGv_i32 t1 = tcg_temp_new_i32();
7665 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7666 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7667 tcg_gen_and_i32(t0, t0, t1);
7668 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7669 tcg_gen_and_i32(t0, t0, t1);
7670 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7671 tcg_gen_nand_i32(t0, t0, t1);
7672 tcg_temp_free_i32(t1);
7673 tcg_gen_andi_i32(t0, t0, 1);
7674 tcg_gen_extu_i32_tl(bcond, t0);
7676 opn = "bc1any4f";
7677 goto not_likely;
7678 case OPC_BC1TANY4:
7680 TCGv_i32 t1 = tcg_temp_new_i32();
7681 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7682 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7683 tcg_gen_or_i32(t0, t0, t1);
7684 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7685 tcg_gen_or_i32(t0, t0, t1);
7686 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7687 tcg_gen_or_i32(t0, t0, t1);
7688 tcg_temp_free_i32(t1);
7689 tcg_gen_andi_i32(t0, t0, 1);
7690 tcg_gen_extu_i32_tl(bcond, t0);
7692 opn = "bc1any4t";
7693 not_likely:
7694 ctx->hflags |= MIPS_HFLAG_BC;
7695 break;
7696 default:
7697 MIPS_INVAL(opn);
7698 generate_exception (ctx, EXCP_RI);
7699 goto out;
7701 (void)opn; /* avoid a compiler warning */
7702 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
7703 ctx->hflags, btarget);
7704 ctx->btarget = btarget;
7705 ctx->hflags |= MIPS_HFLAG_BDS32;
7706 out:
7707 tcg_temp_free_i32(t0);
7710 /* R6 CP1 Branches */
7711 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
7712 int32_t ft, int32_t offset)
7714 target_ulong btarget;
7715 const char *opn = "cp1 cond branch";
7716 TCGv_i64 t0 = tcg_temp_new_i64();
7718 if (ctx->hflags & MIPS_HFLAG_BMASK) {
7719 #ifdef MIPS_DEBUG_DISAS
7720 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
7721 #endif
7722 generate_exception(ctx, EXCP_RI);
7723 goto out;
7726 gen_load_fpr64(ctx, t0, ft);
7727 tcg_gen_andi_i64(t0, t0, 1);
7729 btarget = addr_add(ctx, ctx->pc + 4, offset);
7731 switch (op) {
7732 case OPC_BC1EQZ:
7733 tcg_gen_xori_i64(t0, t0, 1);
7734 opn = "bc1eqz";
7735 ctx->hflags |= MIPS_HFLAG_BC;
7736 break;
7737 case OPC_BC1NEZ:
7738 /* t0 already set */
7739 opn = "bc1nez";
7740 ctx->hflags |= MIPS_HFLAG_BC;
7741 break;
7742 default:
7743 MIPS_INVAL(opn);
7744 generate_exception(ctx, EXCP_RI);
7745 goto out;
7748 tcg_gen_trunc_i64_tl(bcond, t0);
7750 (void)opn; /* avoid a compiler warning */
7751 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
7752 ctx->hflags, btarget);
7753 ctx->btarget = btarget;
7755 out:
7756 tcg_temp_free_i64(t0);
7759 /* Coprocessor 1 (FPU) */
7761 #define FOP(func, fmt) (((fmt) << 21) | (func))
7763 enum fopcode {
7764 OPC_ADD_S = FOP(0, FMT_S),
7765 OPC_SUB_S = FOP(1, FMT_S),
7766 OPC_MUL_S = FOP(2, FMT_S),
7767 OPC_DIV_S = FOP(3, FMT_S),
7768 OPC_SQRT_S = FOP(4, FMT_S),
7769 OPC_ABS_S = FOP(5, FMT_S),
7770 OPC_MOV_S = FOP(6, FMT_S),
7771 OPC_NEG_S = FOP(7, FMT_S),
7772 OPC_ROUND_L_S = FOP(8, FMT_S),
7773 OPC_TRUNC_L_S = FOP(9, FMT_S),
7774 OPC_CEIL_L_S = FOP(10, FMT_S),
7775 OPC_FLOOR_L_S = FOP(11, FMT_S),
7776 OPC_ROUND_W_S = FOP(12, FMT_S),
7777 OPC_TRUNC_W_S = FOP(13, FMT_S),
7778 OPC_CEIL_W_S = FOP(14, FMT_S),
7779 OPC_FLOOR_W_S = FOP(15, FMT_S),
7780 OPC_SEL_S = FOP(16, FMT_S),
7781 OPC_MOVCF_S = FOP(17, FMT_S),
7782 OPC_MOVZ_S = FOP(18, FMT_S),
7783 OPC_MOVN_S = FOP(19, FMT_S),
7784 OPC_SELEQZ_S = FOP(20, FMT_S),
7785 OPC_RECIP_S = FOP(21, FMT_S),
7786 OPC_RSQRT_S = FOP(22, FMT_S),
7787 OPC_SELNEZ_S = FOP(23, FMT_S),
7788 OPC_MADDF_S = FOP(24, FMT_S),
7789 OPC_MSUBF_S = FOP(25, FMT_S),
7790 OPC_RINT_S = FOP(26, FMT_S),
7791 OPC_CLASS_S = FOP(27, FMT_S),
7792 OPC_MIN_S = FOP(28, FMT_S),
7793 OPC_RECIP2_S = FOP(28, FMT_S),
7794 OPC_MINA_S = FOP(29, FMT_S),
7795 OPC_RECIP1_S = FOP(29, FMT_S),
7796 OPC_MAX_S = FOP(30, FMT_S),
7797 OPC_RSQRT1_S = FOP(30, FMT_S),
7798 OPC_MAXA_S = FOP(31, FMT_S),
7799 OPC_RSQRT2_S = FOP(31, FMT_S),
7800 OPC_CVT_D_S = FOP(33, FMT_S),
7801 OPC_CVT_W_S = FOP(36, FMT_S),
7802 OPC_CVT_L_S = FOP(37, FMT_S),
7803 OPC_CVT_PS_S = FOP(38, FMT_S),
7804 OPC_CMP_F_S = FOP (48, FMT_S),
7805 OPC_CMP_UN_S = FOP (49, FMT_S),
7806 OPC_CMP_EQ_S = FOP (50, FMT_S),
7807 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7808 OPC_CMP_OLT_S = FOP (52, FMT_S),
7809 OPC_CMP_ULT_S = FOP (53, FMT_S),
7810 OPC_CMP_OLE_S = FOP (54, FMT_S),
7811 OPC_CMP_ULE_S = FOP (55, FMT_S),
7812 OPC_CMP_SF_S = FOP (56, FMT_S),
7813 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7814 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7815 OPC_CMP_NGL_S = FOP (59, FMT_S),
7816 OPC_CMP_LT_S = FOP (60, FMT_S),
7817 OPC_CMP_NGE_S = FOP (61, FMT_S),
7818 OPC_CMP_LE_S = FOP (62, FMT_S),
7819 OPC_CMP_NGT_S = FOP (63, FMT_S),
7821 OPC_ADD_D = FOP(0, FMT_D),
7822 OPC_SUB_D = FOP(1, FMT_D),
7823 OPC_MUL_D = FOP(2, FMT_D),
7824 OPC_DIV_D = FOP(3, FMT_D),
7825 OPC_SQRT_D = FOP(4, FMT_D),
7826 OPC_ABS_D = FOP(5, FMT_D),
7827 OPC_MOV_D = FOP(6, FMT_D),
7828 OPC_NEG_D = FOP(7, FMT_D),
7829 OPC_ROUND_L_D = FOP(8, FMT_D),
7830 OPC_TRUNC_L_D = FOP(9, FMT_D),
7831 OPC_CEIL_L_D = FOP(10, FMT_D),
7832 OPC_FLOOR_L_D = FOP(11, FMT_D),
7833 OPC_ROUND_W_D = FOP(12, FMT_D),
7834 OPC_TRUNC_W_D = FOP(13, FMT_D),
7835 OPC_CEIL_W_D = FOP(14, FMT_D),
7836 OPC_FLOOR_W_D = FOP(15, FMT_D),
7837 OPC_SEL_D = FOP(16, FMT_D),
7838 OPC_MOVCF_D = FOP(17, FMT_D),
7839 OPC_MOVZ_D = FOP(18, FMT_D),
7840 OPC_MOVN_D = FOP(19, FMT_D),
7841 OPC_SELEQZ_D = FOP(20, FMT_D),
7842 OPC_RECIP_D = FOP(21, FMT_D),
7843 OPC_RSQRT_D = FOP(22, FMT_D),
7844 OPC_SELNEZ_D = FOP(23, FMT_D),
7845 OPC_MADDF_D = FOP(24, FMT_D),
7846 OPC_MSUBF_D = FOP(25, FMT_D),
7847 OPC_RINT_D = FOP(26, FMT_D),
7848 OPC_CLASS_D = FOP(27, FMT_D),
7849 OPC_MIN_D = FOP(28, FMT_D),
7850 OPC_RECIP2_D = FOP(28, FMT_D),
7851 OPC_MINA_D = FOP(29, FMT_D),
7852 OPC_RECIP1_D = FOP(29, FMT_D),
7853 OPC_MAX_D = FOP(30, FMT_D),
7854 OPC_RSQRT1_D = FOP(30, FMT_D),
7855 OPC_MAXA_D = FOP(31, FMT_D),
7856 OPC_RSQRT2_D = FOP(31, FMT_D),
7857 OPC_CVT_S_D = FOP(32, FMT_D),
7858 OPC_CVT_W_D = FOP(36, FMT_D),
7859 OPC_CVT_L_D = FOP(37, FMT_D),
7860 OPC_CMP_F_D = FOP (48, FMT_D),
7861 OPC_CMP_UN_D = FOP (49, FMT_D),
7862 OPC_CMP_EQ_D = FOP (50, FMT_D),
7863 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7864 OPC_CMP_OLT_D = FOP (52, FMT_D),
7865 OPC_CMP_ULT_D = FOP (53, FMT_D),
7866 OPC_CMP_OLE_D = FOP (54, FMT_D),
7867 OPC_CMP_ULE_D = FOP (55, FMT_D),
7868 OPC_CMP_SF_D = FOP (56, FMT_D),
7869 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7870 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7871 OPC_CMP_NGL_D = FOP (59, FMT_D),
7872 OPC_CMP_LT_D = FOP (60, FMT_D),
7873 OPC_CMP_NGE_D = FOP (61, FMT_D),
7874 OPC_CMP_LE_D = FOP (62, FMT_D),
7875 OPC_CMP_NGT_D = FOP (63, FMT_D),
7877 OPC_CVT_S_W = FOP(32, FMT_W),
7878 OPC_CVT_D_W = FOP(33, FMT_W),
7879 OPC_CVT_S_L = FOP(32, FMT_L),
7880 OPC_CVT_D_L = FOP(33, FMT_L),
7881 OPC_CVT_PS_PW = FOP(38, FMT_W),
7883 OPC_ADD_PS = FOP(0, FMT_PS),
7884 OPC_SUB_PS = FOP(1, FMT_PS),
7885 OPC_MUL_PS = FOP(2, FMT_PS),
7886 OPC_DIV_PS = FOP(3, FMT_PS),
7887 OPC_ABS_PS = FOP(5, FMT_PS),
7888 OPC_MOV_PS = FOP(6, FMT_PS),
7889 OPC_NEG_PS = FOP(7, FMT_PS),
7890 OPC_MOVCF_PS = FOP(17, FMT_PS),
7891 OPC_MOVZ_PS = FOP(18, FMT_PS),
7892 OPC_MOVN_PS = FOP(19, FMT_PS),
7893 OPC_ADDR_PS = FOP(24, FMT_PS),
7894 OPC_MULR_PS = FOP(26, FMT_PS),
7895 OPC_RECIP2_PS = FOP(28, FMT_PS),
7896 OPC_RECIP1_PS = FOP(29, FMT_PS),
7897 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7898 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7900 OPC_CVT_S_PU = FOP(32, FMT_PS),
7901 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7902 OPC_CVT_S_PL = FOP(40, FMT_PS),
7903 OPC_PLL_PS = FOP(44, FMT_PS),
7904 OPC_PLU_PS = FOP(45, FMT_PS),
7905 OPC_PUL_PS = FOP(46, FMT_PS),
7906 OPC_PUU_PS = FOP(47, FMT_PS),
7907 OPC_CMP_F_PS = FOP (48, FMT_PS),
7908 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7909 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7910 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7911 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7912 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7913 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7914 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7915 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7916 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7917 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7918 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7919 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7920 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7921 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7922 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7925 enum r6_f_cmp_op {
7926 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
7927 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
7928 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
7929 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
7930 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
7931 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
7932 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
7933 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
7934 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
7935 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
7936 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
7937 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
7938 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
7939 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
7940 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
7941 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
7942 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
7943 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
7944 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
7945 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
7946 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
7947 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
7949 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
7950 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
7951 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
7952 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
7953 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
7954 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
7955 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
7956 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
7957 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
7958 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
7959 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
7960 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
7961 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
7962 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
7963 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
7964 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
7965 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
7966 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
7967 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
7968 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
7969 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
7970 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
7972 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
7974 const char *opn = "cp1 move";
7975 TCGv t0 = tcg_temp_new();
7977 switch (opc) {
7978 case OPC_MFC1:
7980 TCGv_i32 fp0 = tcg_temp_new_i32();
7982 gen_load_fpr32(fp0, fs);
7983 tcg_gen_ext_i32_tl(t0, fp0);
7984 tcg_temp_free_i32(fp0);
7986 gen_store_gpr(t0, rt);
7987 opn = "mfc1";
7988 break;
7989 case OPC_MTC1:
7990 gen_load_gpr(t0, rt);
7992 TCGv_i32 fp0 = tcg_temp_new_i32();
7994 tcg_gen_trunc_tl_i32(fp0, t0);
7995 gen_store_fpr32(fp0, fs);
7996 tcg_temp_free_i32(fp0);
7998 opn = "mtc1";
7999 break;
8000 case OPC_CFC1:
8001 gen_helper_1e0i(cfc1, t0, fs);
8002 gen_store_gpr(t0, rt);
8003 opn = "cfc1";
8004 break;
8005 case OPC_CTC1:
8006 gen_load_gpr(t0, rt);
8008 TCGv_i32 fs_tmp = tcg_const_i32(fs);
8010 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
8011 tcg_temp_free_i32(fs_tmp);
8013 opn = "ctc1";
8014 break;
8015 #if defined(TARGET_MIPS64)
8016 case OPC_DMFC1:
8017 gen_load_fpr64(ctx, t0, fs);
8018 gen_store_gpr(t0, rt);
8019 opn = "dmfc1";
8020 break;
8021 case OPC_DMTC1:
8022 gen_load_gpr(t0, rt);
8023 gen_store_fpr64(ctx, t0, fs);
8024 opn = "dmtc1";
8025 break;
8026 #endif
8027 case OPC_MFHC1:
8029 TCGv_i32 fp0 = tcg_temp_new_i32();
8031 gen_load_fpr32h(ctx, fp0, fs);
8032 tcg_gen_ext_i32_tl(t0, fp0);
8033 tcg_temp_free_i32(fp0);
8035 gen_store_gpr(t0, rt);
8036 opn = "mfhc1";
8037 break;
8038 case OPC_MTHC1:
8039 gen_load_gpr(t0, rt);
8041 TCGv_i32 fp0 = tcg_temp_new_i32();
8043 tcg_gen_trunc_tl_i32(fp0, t0);
8044 gen_store_fpr32h(ctx, fp0, fs);
8045 tcg_temp_free_i32(fp0);
8047 opn = "mthc1";
8048 break;
8049 default:
8050 MIPS_INVAL(opn);
8051 generate_exception (ctx, EXCP_RI);
8052 goto out;
8054 (void)opn; /* avoid a compiler warning */
8055 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
8057 out:
8058 tcg_temp_free(t0);
8061 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
8063 int l1;
8064 TCGCond cond;
8065 TCGv_i32 t0;
8067 if (rd == 0) {
8068 /* Treat as NOP. */
8069 return;
8072 if (tf)
8073 cond = TCG_COND_EQ;
8074 else
8075 cond = TCG_COND_NE;
8077 l1 = gen_new_label();
8078 t0 = tcg_temp_new_i32();
8079 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8080 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8081 tcg_temp_free_i32(t0);
8082 if (rs == 0) {
8083 tcg_gen_movi_tl(cpu_gpr[rd], 0);
8084 } else {
8085 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
8087 gen_set_label(l1);
8090 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
8092 int cond;
8093 TCGv_i32 t0 = tcg_temp_new_i32();
8094 int l1 = gen_new_label();
8096 if (tf)
8097 cond = TCG_COND_EQ;
8098 else
8099 cond = TCG_COND_NE;
8101 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8102 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8103 gen_load_fpr32(t0, fs);
8104 gen_store_fpr32(t0, fd);
8105 gen_set_label(l1);
8106 tcg_temp_free_i32(t0);
8109 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
8111 int cond;
8112 TCGv_i32 t0 = tcg_temp_new_i32();
8113 TCGv_i64 fp0;
8114 int l1 = gen_new_label();
8116 if (tf)
8117 cond = TCG_COND_EQ;
8118 else
8119 cond = TCG_COND_NE;
8121 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8122 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8123 tcg_temp_free_i32(t0);
8124 fp0 = tcg_temp_new_i64();
8125 gen_load_fpr64(ctx, fp0, fs);
8126 gen_store_fpr64(ctx, fp0, fd);
8127 tcg_temp_free_i64(fp0);
8128 gen_set_label(l1);
8131 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
8132 int cc, int tf)
8134 int cond;
8135 TCGv_i32 t0 = tcg_temp_new_i32();
8136 int l1 = gen_new_label();
8137 int l2 = gen_new_label();
8139 if (tf)
8140 cond = TCG_COND_EQ;
8141 else
8142 cond = TCG_COND_NE;
8144 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
8145 tcg_gen_brcondi_i32(cond, t0, 0, l1);
8146 gen_load_fpr32(t0, fs);
8147 gen_store_fpr32(t0, fd);
8148 gen_set_label(l1);
8150 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
8151 tcg_gen_brcondi_i32(cond, t0, 0, l2);
8152 gen_load_fpr32h(ctx, t0, fs);
8153 gen_store_fpr32h(ctx, t0, fd);
8154 tcg_temp_free_i32(t0);
8155 gen_set_label(l2);
8158 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8159 int fs)
8161 TCGv_i32 t1 = tcg_const_i32(0);
8162 TCGv_i32 fp0 = tcg_temp_new_i32();
8163 TCGv_i32 fp1 = tcg_temp_new_i32();
8164 TCGv_i32 fp2 = tcg_temp_new_i32();
8165 gen_load_fpr32(fp0, fd);
8166 gen_load_fpr32(fp1, ft);
8167 gen_load_fpr32(fp2, fs);
8169 switch (op1) {
8170 case OPC_SEL_S:
8171 tcg_gen_andi_i32(fp0, fp0, 1);
8172 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8173 break;
8174 case OPC_SELEQZ_S:
8175 tcg_gen_andi_i32(fp1, fp1, 1);
8176 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8177 break;
8178 case OPC_SELNEZ_S:
8179 tcg_gen_andi_i32(fp1, fp1, 1);
8180 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8181 break;
8182 default:
8183 MIPS_INVAL("gen_sel_s");
8184 generate_exception (ctx, EXCP_RI);
8185 break;
8188 gen_store_fpr32(fp0, fd);
8189 tcg_temp_free_i32(fp2);
8190 tcg_temp_free_i32(fp1);
8191 tcg_temp_free_i32(fp0);
8192 tcg_temp_free_i32(t1);
8195 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
8196 int fs)
8198 TCGv_i64 t1 = tcg_const_i64(0);
8199 TCGv_i64 fp0 = tcg_temp_new_i64();
8200 TCGv_i64 fp1 = tcg_temp_new_i64();
8201 TCGv_i64 fp2 = tcg_temp_new_i64();
8202 gen_load_fpr64(ctx, fp0, fd);
8203 gen_load_fpr64(ctx, fp1, ft);
8204 gen_load_fpr64(ctx, fp2, fs);
8206 switch (op1) {
8207 case OPC_SEL_D:
8208 tcg_gen_andi_i64(fp0, fp0, 1);
8209 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
8210 break;
8211 case OPC_SELEQZ_D:
8212 tcg_gen_andi_i64(fp1, fp1, 1);
8213 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
8214 break;
8215 case OPC_SELNEZ_D:
8216 tcg_gen_andi_i64(fp1, fp1, 1);
8217 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
8218 break;
8219 default:
8220 MIPS_INVAL("gen_sel_d");
8221 generate_exception (ctx, EXCP_RI);
8222 break;
8225 gen_store_fpr64(ctx, fp0, fd);
8226 tcg_temp_free_i64(fp2);
8227 tcg_temp_free_i64(fp1);
8228 tcg_temp_free_i64(fp0);
8229 tcg_temp_free_i64(t1);
8232 static void gen_farith (DisasContext *ctx, enum fopcode op1,
8233 int ft, int fs, int fd, int cc)
8235 const char *opn = "farith";
8236 const char *condnames[] = {
8237 "c.f",
8238 "c.un",
8239 "c.eq",
8240 "c.ueq",
8241 "c.olt",
8242 "c.ult",
8243 "c.ole",
8244 "c.ule",
8245 "c.sf",
8246 "c.ngle",
8247 "c.seq",
8248 "c.ngl",
8249 "c.lt",
8250 "c.nge",
8251 "c.le",
8252 "c.ngt",
8254 const char *condnames_abs[] = {
8255 "cabs.f",
8256 "cabs.un",
8257 "cabs.eq",
8258 "cabs.ueq",
8259 "cabs.olt",
8260 "cabs.ult",
8261 "cabs.ole",
8262 "cabs.ule",
8263 "cabs.sf",
8264 "cabs.ngle",
8265 "cabs.seq",
8266 "cabs.ngl",
8267 "cabs.lt",
8268 "cabs.nge",
8269 "cabs.le",
8270 "cabs.ngt",
8272 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
8273 uint32_t func = ctx->opcode & 0x3f;
8275 switch (op1) {
8276 case OPC_ADD_S:
8278 TCGv_i32 fp0 = tcg_temp_new_i32();
8279 TCGv_i32 fp1 = tcg_temp_new_i32();
8281 gen_load_fpr32(fp0, fs);
8282 gen_load_fpr32(fp1, ft);
8283 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
8284 tcg_temp_free_i32(fp1);
8285 gen_store_fpr32(fp0, fd);
8286 tcg_temp_free_i32(fp0);
8288 opn = "add.s";
8289 optype = BINOP;
8290 break;
8291 case OPC_SUB_S:
8293 TCGv_i32 fp0 = tcg_temp_new_i32();
8294 TCGv_i32 fp1 = tcg_temp_new_i32();
8296 gen_load_fpr32(fp0, fs);
8297 gen_load_fpr32(fp1, ft);
8298 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
8299 tcg_temp_free_i32(fp1);
8300 gen_store_fpr32(fp0, fd);
8301 tcg_temp_free_i32(fp0);
8303 opn = "sub.s";
8304 optype = BINOP;
8305 break;
8306 case OPC_MUL_S:
8308 TCGv_i32 fp0 = tcg_temp_new_i32();
8309 TCGv_i32 fp1 = tcg_temp_new_i32();
8311 gen_load_fpr32(fp0, fs);
8312 gen_load_fpr32(fp1, ft);
8313 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
8314 tcg_temp_free_i32(fp1);
8315 gen_store_fpr32(fp0, fd);
8316 tcg_temp_free_i32(fp0);
8318 opn = "mul.s";
8319 optype = BINOP;
8320 break;
8321 case OPC_DIV_S:
8323 TCGv_i32 fp0 = tcg_temp_new_i32();
8324 TCGv_i32 fp1 = tcg_temp_new_i32();
8326 gen_load_fpr32(fp0, fs);
8327 gen_load_fpr32(fp1, ft);
8328 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
8329 tcg_temp_free_i32(fp1);
8330 gen_store_fpr32(fp0, fd);
8331 tcg_temp_free_i32(fp0);
8333 opn = "div.s";
8334 optype = BINOP;
8335 break;
8336 case OPC_SQRT_S:
8338 TCGv_i32 fp0 = tcg_temp_new_i32();
8340 gen_load_fpr32(fp0, fs);
8341 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
8342 gen_store_fpr32(fp0, fd);
8343 tcg_temp_free_i32(fp0);
8345 opn = "sqrt.s";
8346 break;
8347 case OPC_ABS_S:
8349 TCGv_i32 fp0 = tcg_temp_new_i32();
8351 gen_load_fpr32(fp0, fs);
8352 gen_helper_float_abs_s(fp0, fp0);
8353 gen_store_fpr32(fp0, fd);
8354 tcg_temp_free_i32(fp0);
8356 opn = "abs.s";
8357 break;
8358 case OPC_MOV_S:
8360 TCGv_i32 fp0 = tcg_temp_new_i32();
8362 gen_load_fpr32(fp0, fs);
8363 gen_store_fpr32(fp0, fd);
8364 tcg_temp_free_i32(fp0);
8366 opn = "mov.s";
8367 break;
8368 case OPC_NEG_S:
8370 TCGv_i32 fp0 = tcg_temp_new_i32();
8372 gen_load_fpr32(fp0, fs);
8373 gen_helper_float_chs_s(fp0, fp0);
8374 gen_store_fpr32(fp0, fd);
8375 tcg_temp_free_i32(fp0);
8377 opn = "neg.s";
8378 break;
8379 case OPC_ROUND_L_S:
8380 check_cp1_64bitmode(ctx);
8382 TCGv_i32 fp32 = tcg_temp_new_i32();
8383 TCGv_i64 fp64 = tcg_temp_new_i64();
8385 gen_load_fpr32(fp32, fs);
8386 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
8387 tcg_temp_free_i32(fp32);
8388 gen_store_fpr64(ctx, fp64, fd);
8389 tcg_temp_free_i64(fp64);
8391 opn = "round.l.s";
8392 break;
8393 case OPC_TRUNC_L_S:
8394 check_cp1_64bitmode(ctx);
8396 TCGv_i32 fp32 = tcg_temp_new_i32();
8397 TCGv_i64 fp64 = tcg_temp_new_i64();
8399 gen_load_fpr32(fp32, fs);
8400 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
8401 tcg_temp_free_i32(fp32);
8402 gen_store_fpr64(ctx, fp64, fd);
8403 tcg_temp_free_i64(fp64);
8405 opn = "trunc.l.s";
8406 break;
8407 case OPC_CEIL_L_S:
8408 check_cp1_64bitmode(ctx);
8410 TCGv_i32 fp32 = tcg_temp_new_i32();
8411 TCGv_i64 fp64 = tcg_temp_new_i64();
8413 gen_load_fpr32(fp32, fs);
8414 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
8415 tcg_temp_free_i32(fp32);
8416 gen_store_fpr64(ctx, fp64, fd);
8417 tcg_temp_free_i64(fp64);
8419 opn = "ceil.l.s";
8420 break;
8421 case OPC_FLOOR_L_S:
8422 check_cp1_64bitmode(ctx);
8424 TCGv_i32 fp32 = tcg_temp_new_i32();
8425 TCGv_i64 fp64 = tcg_temp_new_i64();
8427 gen_load_fpr32(fp32, fs);
8428 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
8429 tcg_temp_free_i32(fp32);
8430 gen_store_fpr64(ctx, fp64, fd);
8431 tcg_temp_free_i64(fp64);
8433 opn = "floor.l.s";
8434 break;
8435 case OPC_ROUND_W_S:
8437 TCGv_i32 fp0 = tcg_temp_new_i32();
8439 gen_load_fpr32(fp0, fs);
8440 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
8441 gen_store_fpr32(fp0, fd);
8442 tcg_temp_free_i32(fp0);
8444 opn = "round.w.s";
8445 break;
8446 case OPC_TRUNC_W_S:
8448 TCGv_i32 fp0 = tcg_temp_new_i32();
8450 gen_load_fpr32(fp0, fs);
8451 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
8452 gen_store_fpr32(fp0, fd);
8453 tcg_temp_free_i32(fp0);
8455 opn = "trunc.w.s";
8456 break;
8457 case OPC_CEIL_W_S:
8459 TCGv_i32 fp0 = tcg_temp_new_i32();
8461 gen_load_fpr32(fp0, fs);
8462 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
8463 gen_store_fpr32(fp0, fd);
8464 tcg_temp_free_i32(fp0);
8466 opn = "ceil.w.s";
8467 break;
8468 case OPC_FLOOR_W_S:
8470 TCGv_i32 fp0 = tcg_temp_new_i32();
8472 gen_load_fpr32(fp0, fs);
8473 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
8474 gen_store_fpr32(fp0, fd);
8475 tcg_temp_free_i32(fp0);
8477 opn = "floor.w.s";
8478 break;
8479 case OPC_SEL_S:
8480 check_insn(ctx, ISA_MIPS32R6);
8481 gen_sel_s(ctx, op1, fd, ft, fs);
8482 opn = "sel.s";
8483 break;
8484 case OPC_SELEQZ_S:
8485 check_insn(ctx, ISA_MIPS32R6);
8486 gen_sel_s(ctx, op1, fd, ft, fs);
8487 opn = "seleqz.s";
8488 break;
8489 case OPC_SELNEZ_S:
8490 check_insn(ctx, ISA_MIPS32R6);
8491 gen_sel_s(ctx, op1, fd, ft, fs);
8492 opn = "selnez.s";
8493 break;
8494 case OPC_MOVCF_S:
8495 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8496 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8497 opn = "movcf.s";
8498 break;
8499 case OPC_MOVZ_S:
8500 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8502 int l1 = gen_new_label();
8503 TCGv_i32 fp0;
8505 if (ft != 0) {
8506 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8508 fp0 = tcg_temp_new_i32();
8509 gen_load_fpr32(fp0, fs);
8510 gen_store_fpr32(fp0, fd);
8511 tcg_temp_free_i32(fp0);
8512 gen_set_label(l1);
8514 opn = "movz.s";
8515 break;
8516 case OPC_MOVN_S:
8517 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8519 int l1 = gen_new_label();
8520 TCGv_i32 fp0;
8522 if (ft != 0) {
8523 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8524 fp0 = tcg_temp_new_i32();
8525 gen_load_fpr32(fp0, fs);
8526 gen_store_fpr32(fp0, fd);
8527 tcg_temp_free_i32(fp0);
8528 gen_set_label(l1);
8531 opn = "movn.s";
8532 break;
8533 case OPC_RECIP_S:
8534 check_cop1x(ctx);
8536 TCGv_i32 fp0 = tcg_temp_new_i32();
8538 gen_load_fpr32(fp0, fs);
8539 gen_helper_float_recip_s(fp0, cpu_env, fp0);
8540 gen_store_fpr32(fp0, fd);
8541 tcg_temp_free_i32(fp0);
8543 opn = "recip.s";
8544 break;
8545 case OPC_RSQRT_S:
8546 check_cop1x(ctx);
8548 TCGv_i32 fp0 = tcg_temp_new_i32();
8550 gen_load_fpr32(fp0, fs);
8551 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
8552 gen_store_fpr32(fp0, fd);
8553 tcg_temp_free_i32(fp0);
8555 opn = "rsqrt.s";
8556 break;
8557 case OPC_MADDF_S:
8558 check_insn(ctx, ISA_MIPS32R6);
8560 TCGv_i32 fp0 = tcg_temp_new_i32();
8561 TCGv_i32 fp1 = tcg_temp_new_i32();
8562 TCGv_i32 fp2 = tcg_temp_new_i32();
8563 gen_load_fpr32(fp0, fs);
8564 gen_load_fpr32(fp1, ft);
8565 gen_load_fpr32(fp2, fd);
8566 gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
8567 gen_store_fpr32(fp2, fd);
8568 tcg_temp_free_i32(fp2);
8569 tcg_temp_free_i32(fp1);
8570 tcg_temp_free_i32(fp0);
8571 opn = "maddf.s";
8573 break;
8574 case OPC_MSUBF_S:
8575 check_insn(ctx, ISA_MIPS32R6);
8577 TCGv_i32 fp0 = tcg_temp_new_i32();
8578 TCGv_i32 fp1 = tcg_temp_new_i32();
8579 TCGv_i32 fp2 = tcg_temp_new_i32();
8580 gen_load_fpr32(fp0, fs);
8581 gen_load_fpr32(fp1, ft);
8582 gen_load_fpr32(fp2, fd);
8583 gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
8584 gen_store_fpr32(fp2, fd);
8585 tcg_temp_free_i32(fp2);
8586 tcg_temp_free_i32(fp1);
8587 tcg_temp_free_i32(fp0);
8588 opn = "msubf.s";
8590 break;
8591 case OPC_RINT_S:
8592 check_insn(ctx, ISA_MIPS32R6);
8594 TCGv_i32 fp0 = tcg_temp_new_i32();
8595 gen_load_fpr32(fp0, fs);
8596 gen_helper_float_rint_s(fp0, cpu_env, fp0);
8597 gen_store_fpr32(fp0, fd);
8598 tcg_temp_free_i32(fp0);
8599 opn = "rint.s";
8601 break;
8602 case OPC_CLASS_S:
8603 check_insn(ctx, ISA_MIPS32R6);
8605 TCGv_i32 fp0 = tcg_temp_new_i32();
8606 gen_load_fpr32(fp0, fs);
8607 gen_helper_float_class_s(fp0, fp0);
8608 gen_store_fpr32(fp0, fd);
8609 tcg_temp_free_i32(fp0);
8610 opn = "class.s";
8612 break;
8613 case OPC_MIN_S: /* OPC_RECIP2_S */
8614 if (ctx->insn_flags & ISA_MIPS32R6) {
8615 /* OPC_MIN_S */
8616 TCGv_i32 fp0 = tcg_temp_new_i32();
8617 TCGv_i32 fp1 = tcg_temp_new_i32();
8618 TCGv_i32 fp2 = tcg_temp_new_i32();
8619 gen_load_fpr32(fp0, fs);
8620 gen_load_fpr32(fp1, ft);
8621 gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
8622 gen_store_fpr32(fp2, fd);
8623 tcg_temp_free_i32(fp2);
8624 tcg_temp_free_i32(fp1);
8625 tcg_temp_free_i32(fp0);
8626 opn = "min.s";
8627 } else {
8628 /* OPC_RECIP2_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_recip2_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 = "recip2.s";
8643 break;
8644 case OPC_MINA_S: /* OPC_RECIP1_S */
8645 if (ctx->insn_flags & ISA_MIPS32R6) {
8646 /* OPC_MINA_S */
8647 TCGv_i32 fp0 = tcg_temp_new_i32();
8648 TCGv_i32 fp1 = tcg_temp_new_i32();
8649 TCGv_i32 fp2 = tcg_temp_new_i32();
8650 gen_load_fpr32(fp0, fs);
8651 gen_load_fpr32(fp1, ft);
8652 gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
8653 gen_store_fpr32(fp2, fd);
8654 tcg_temp_free_i32(fp2);
8655 tcg_temp_free_i32(fp1);
8656 tcg_temp_free_i32(fp0);
8657 opn = "mina.s";
8658 } else {
8659 /* OPC_RECIP1_S */
8660 check_cp1_64bitmode(ctx);
8662 TCGv_i32 fp0 = tcg_temp_new_i32();
8664 gen_load_fpr32(fp0, fs);
8665 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
8666 gen_store_fpr32(fp0, fd);
8667 tcg_temp_free_i32(fp0);
8669 opn = "recip1.s";
8671 break;
8672 case OPC_MAX_S: /* OPC_RSQRT1_S */
8673 if (ctx->insn_flags & ISA_MIPS32R6) {
8674 /* OPC_MAX_S */
8675 TCGv_i32 fp0 = tcg_temp_new_i32();
8676 TCGv_i32 fp1 = tcg_temp_new_i32();
8677 gen_load_fpr32(fp0, fs);
8678 gen_load_fpr32(fp1, ft);
8679 gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
8680 gen_store_fpr32(fp1, fd);
8681 tcg_temp_free_i32(fp1);
8682 tcg_temp_free_i32(fp0);
8683 opn = "max.s";
8684 } else {
8685 /* OPC_RSQRT1_S */
8686 check_cp1_64bitmode(ctx);
8688 TCGv_i32 fp0 = tcg_temp_new_i32();
8690 gen_load_fpr32(fp0, fs);
8691 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
8692 gen_store_fpr32(fp0, fd);
8693 tcg_temp_free_i32(fp0);
8695 opn = "rsqrt1.s";
8697 break;
8698 case OPC_MAXA_S: /* OPC_RSQRT2_S */
8699 if (ctx->insn_flags & ISA_MIPS32R6) {
8700 /* OPC_MAXA_S */
8701 TCGv_i32 fp0 = tcg_temp_new_i32();
8702 TCGv_i32 fp1 = tcg_temp_new_i32();
8703 gen_load_fpr32(fp0, fs);
8704 gen_load_fpr32(fp1, ft);
8705 gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
8706 gen_store_fpr32(fp1, fd);
8707 tcg_temp_free_i32(fp1);
8708 tcg_temp_free_i32(fp0);
8709 opn = "maxa.s";
8710 } else {
8711 /* OPC_RSQRT2_S */
8712 check_cp1_64bitmode(ctx);
8714 TCGv_i32 fp0 = tcg_temp_new_i32();
8715 TCGv_i32 fp1 = tcg_temp_new_i32();
8717 gen_load_fpr32(fp0, fs);
8718 gen_load_fpr32(fp1, ft);
8719 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
8720 tcg_temp_free_i32(fp1);
8721 gen_store_fpr32(fp0, fd);
8722 tcg_temp_free_i32(fp0);
8724 opn = "rsqrt2.s";
8726 break;
8727 case OPC_CVT_D_S:
8728 check_cp1_registers(ctx, fd);
8730 TCGv_i32 fp32 = tcg_temp_new_i32();
8731 TCGv_i64 fp64 = tcg_temp_new_i64();
8733 gen_load_fpr32(fp32, fs);
8734 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
8735 tcg_temp_free_i32(fp32);
8736 gen_store_fpr64(ctx, fp64, fd);
8737 tcg_temp_free_i64(fp64);
8739 opn = "cvt.d.s";
8740 break;
8741 case OPC_CVT_W_S:
8743 TCGv_i32 fp0 = tcg_temp_new_i32();
8745 gen_load_fpr32(fp0, fs);
8746 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
8747 gen_store_fpr32(fp0, fd);
8748 tcg_temp_free_i32(fp0);
8750 opn = "cvt.w.s";
8751 break;
8752 case OPC_CVT_L_S:
8753 check_cp1_64bitmode(ctx);
8755 TCGv_i32 fp32 = tcg_temp_new_i32();
8756 TCGv_i64 fp64 = tcg_temp_new_i64();
8758 gen_load_fpr32(fp32, fs);
8759 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
8760 tcg_temp_free_i32(fp32);
8761 gen_store_fpr64(ctx, fp64, fd);
8762 tcg_temp_free_i64(fp64);
8764 opn = "cvt.l.s";
8765 break;
8766 case OPC_CVT_PS_S:
8767 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8768 check_cp1_64bitmode(ctx);
8770 TCGv_i64 fp64 = tcg_temp_new_i64();
8771 TCGv_i32 fp32_0 = tcg_temp_new_i32();
8772 TCGv_i32 fp32_1 = tcg_temp_new_i32();
8774 gen_load_fpr32(fp32_0, fs);
8775 gen_load_fpr32(fp32_1, ft);
8776 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
8777 tcg_temp_free_i32(fp32_1);
8778 tcg_temp_free_i32(fp32_0);
8779 gen_store_fpr64(ctx, fp64, fd);
8780 tcg_temp_free_i64(fp64);
8782 opn = "cvt.ps.s";
8783 break;
8784 case OPC_CMP_F_S:
8785 case OPC_CMP_UN_S:
8786 case OPC_CMP_EQ_S:
8787 case OPC_CMP_UEQ_S:
8788 case OPC_CMP_OLT_S:
8789 case OPC_CMP_ULT_S:
8790 case OPC_CMP_OLE_S:
8791 case OPC_CMP_ULE_S:
8792 case OPC_CMP_SF_S:
8793 case OPC_CMP_NGLE_S:
8794 case OPC_CMP_SEQ_S:
8795 case OPC_CMP_NGL_S:
8796 case OPC_CMP_LT_S:
8797 case OPC_CMP_NGE_S:
8798 case OPC_CMP_LE_S:
8799 case OPC_CMP_NGT_S:
8800 check_insn_opc_removed(ctx, ISA_MIPS32R6);
8801 if (ctx->opcode & (1 << 6)) {
8802 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
8803 opn = condnames_abs[func-48];
8804 } else {
8805 gen_cmp_s(ctx, func-48, ft, fs, cc);
8806 opn = condnames[func-48];
8808 break;
8809 case OPC_ADD_D:
8810 check_cp1_registers(ctx, fs | ft | fd);
8812 TCGv_i64 fp0 = tcg_temp_new_i64();
8813 TCGv_i64 fp1 = tcg_temp_new_i64();
8815 gen_load_fpr64(ctx, fp0, fs);
8816 gen_load_fpr64(ctx, fp1, ft);
8817 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
8818 tcg_temp_free_i64(fp1);
8819 gen_store_fpr64(ctx, fp0, fd);
8820 tcg_temp_free_i64(fp0);
8822 opn = "add.d";
8823 optype = BINOP;
8824 break;
8825 case OPC_SUB_D:
8826 check_cp1_registers(ctx, fs | ft | fd);
8828 TCGv_i64 fp0 = tcg_temp_new_i64();
8829 TCGv_i64 fp1 = tcg_temp_new_i64();
8831 gen_load_fpr64(ctx, fp0, fs);
8832 gen_load_fpr64(ctx, fp1, ft);
8833 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
8834 tcg_temp_free_i64(fp1);
8835 gen_store_fpr64(ctx, fp0, fd);
8836 tcg_temp_free_i64(fp0);
8838 opn = "sub.d";
8839 optype = BINOP;
8840 break;
8841 case OPC_MUL_D:
8842 check_cp1_registers(ctx, fs | ft | fd);
8844 TCGv_i64 fp0 = tcg_temp_new_i64();
8845 TCGv_i64 fp1 = tcg_temp_new_i64();
8847 gen_load_fpr64(ctx, fp0, fs);
8848 gen_load_fpr64(ctx, fp1, ft);
8849 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
8850 tcg_temp_free_i64(fp1);
8851 gen_store_fpr64(ctx, fp0, fd);
8852 tcg_temp_free_i64(fp0);
8854 opn = "mul.d";
8855 optype = BINOP;
8856 break;
8857 case OPC_DIV_D:
8858 check_cp1_registers(ctx, fs | ft | fd);
8860 TCGv_i64 fp0 = tcg_temp_new_i64();
8861 TCGv_i64 fp1 = tcg_temp_new_i64();
8863 gen_load_fpr64(ctx, fp0, fs);
8864 gen_load_fpr64(ctx, fp1, ft);
8865 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
8866 tcg_temp_free_i64(fp1);
8867 gen_store_fpr64(ctx, fp0, fd);
8868 tcg_temp_free_i64(fp0);
8870 opn = "div.d";
8871 optype = BINOP;
8872 break;
8873 case OPC_SQRT_D:
8874 check_cp1_registers(ctx, fs | fd);
8876 TCGv_i64 fp0 = tcg_temp_new_i64();
8878 gen_load_fpr64(ctx, fp0, fs);
8879 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
8880 gen_store_fpr64(ctx, fp0, fd);
8881 tcg_temp_free_i64(fp0);
8883 opn = "sqrt.d";
8884 break;
8885 case OPC_ABS_D:
8886 check_cp1_registers(ctx, fs | fd);
8888 TCGv_i64 fp0 = tcg_temp_new_i64();
8890 gen_load_fpr64(ctx, fp0, fs);
8891 gen_helper_float_abs_d(fp0, fp0);
8892 gen_store_fpr64(ctx, fp0, fd);
8893 tcg_temp_free_i64(fp0);
8895 opn = "abs.d";
8896 break;
8897 case OPC_MOV_D:
8898 check_cp1_registers(ctx, fs | fd);
8900 TCGv_i64 fp0 = tcg_temp_new_i64();
8902 gen_load_fpr64(ctx, fp0, fs);
8903 gen_store_fpr64(ctx, fp0, fd);
8904 tcg_temp_free_i64(fp0);
8906 opn = "mov.d";
8907 break;
8908 case OPC_NEG_D:
8909 check_cp1_registers(ctx, fs | fd);
8911 TCGv_i64 fp0 = tcg_temp_new_i64();
8913 gen_load_fpr64(ctx, fp0, fs);
8914 gen_helper_float_chs_d(fp0, fp0);
8915 gen_store_fpr64(ctx, fp0, fd);
8916 tcg_temp_free_i64(fp0);
8918 opn = "neg.d";
8919 break;
8920 case OPC_ROUND_L_D:
8921 check_cp1_64bitmode(ctx);
8923 TCGv_i64 fp0 = tcg_temp_new_i64();
8925 gen_load_fpr64(ctx, fp0, fs);
8926 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
8927 gen_store_fpr64(ctx, fp0, fd);
8928 tcg_temp_free_i64(fp0);
8930 opn = "round.l.d";
8931 break;
8932 case OPC_TRUNC_L_D:
8933 check_cp1_64bitmode(ctx);
8935 TCGv_i64 fp0 = tcg_temp_new_i64();
8937 gen_load_fpr64(ctx, fp0, fs);
8938 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
8939 gen_store_fpr64(ctx, fp0, fd);
8940 tcg_temp_free_i64(fp0);
8942 opn = "trunc.l.d";
8943 break;
8944 case OPC_CEIL_L_D:
8945 check_cp1_64bitmode(ctx);
8947 TCGv_i64 fp0 = tcg_temp_new_i64();
8949 gen_load_fpr64(ctx, fp0, fs);
8950 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
8951 gen_store_fpr64(ctx, fp0, fd);
8952 tcg_temp_free_i64(fp0);
8954 opn = "ceil.l.d";
8955 break;
8956 case OPC_FLOOR_L_D:
8957 check_cp1_64bitmode(ctx);
8959 TCGv_i64 fp0 = tcg_temp_new_i64();
8961 gen_load_fpr64(ctx, fp0, fs);
8962 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
8963 gen_store_fpr64(ctx, fp0, fd);
8964 tcg_temp_free_i64(fp0);
8966 opn = "floor.l.d";
8967 break;
8968 case OPC_ROUND_W_D:
8969 check_cp1_registers(ctx, fs);
8971 TCGv_i32 fp32 = tcg_temp_new_i32();
8972 TCGv_i64 fp64 = tcg_temp_new_i64();
8974 gen_load_fpr64(ctx, fp64, fs);
8975 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
8976 tcg_temp_free_i64(fp64);
8977 gen_store_fpr32(fp32, fd);
8978 tcg_temp_free_i32(fp32);
8980 opn = "round.w.d";
8981 break;
8982 case OPC_TRUNC_W_D:
8983 check_cp1_registers(ctx, fs);
8985 TCGv_i32 fp32 = tcg_temp_new_i32();
8986 TCGv_i64 fp64 = tcg_temp_new_i64();
8988 gen_load_fpr64(ctx, fp64, fs);
8989 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
8990 tcg_temp_free_i64(fp64);
8991 gen_store_fpr32(fp32, fd);
8992 tcg_temp_free_i32(fp32);
8994 opn = "trunc.w.d";
8995 break;
8996 case OPC_CEIL_W_D:
8997 check_cp1_registers(ctx, fs);
8999 TCGv_i32 fp32 = tcg_temp_new_i32();
9000 TCGv_i64 fp64 = tcg_temp_new_i64();
9002 gen_load_fpr64(ctx, fp64, fs);
9003 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
9004 tcg_temp_free_i64(fp64);
9005 gen_store_fpr32(fp32, fd);
9006 tcg_temp_free_i32(fp32);
9008 opn = "ceil.w.d";
9009 break;
9010 case OPC_FLOOR_W_D:
9011 check_cp1_registers(ctx, fs);
9013 TCGv_i32 fp32 = tcg_temp_new_i32();
9014 TCGv_i64 fp64 = tcg_temp_new_i64();
9016 gen_load_fpr64(ctx, fp64, fs);
9017 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
9018 tcg_temp_free_i64(fp64);
9019 gen_store_fpr32(fp32, fd);
9020 tcg_temp_free_i32(fp32);
9022 opn = "floor.w.d";
9023 break;
9024 case OPC_SEL_D:
9025 check_insn(ctx, ISA_MIPS32R6);
9026 gen_sel_d(ctx, op1, fd, ft, fs);
9027 opn = "sel.d";
9028 break;
9029 case OPC_SELEQZ_D:
9030 check_insn(ctx, ISA_MIPS32R6);
9031 gen_sel_d(ctx, op1, fd, ft, fs);
9032 opn = "seleqz.d";
9033 break;
9034 case OPC_SELNEZ_D:
9035 check_insn(ctx, ISA_MIPS32R6);
9036 gen_sel_d(ctx, op1, fd, ft, fs);
9037 opn = "selnez.d";
9038 break;
9039 case OPC_MOVCF_D:
9040 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9041 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9042 opn = "movcf.d";
9043 break;
9044 case OPC_MOVZ_D:
9045 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9047 int l1 = gen_new_label();
9048 TCGv_i64 fp0;
9050 if (ft != 0) {
9051 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9053 fp0 = tcg_temp_new_i64();
9054 gen_load_fpr64(ctx, fp0, fs);
9055 gen_store_fpr64(ctx, fp0, fd);
9056 tcg_temp_free_i64(fp0);
9057 gen_set_label(l1);
9059 opn = "movz.d";
9060 break;
9061 case OPC_MOVN_D:
9062 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9064 int l1 = gen_new_label();
9065 TCGv_i64 fp0;
9067 if (ft != 0) {
9068 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9069 fp0 = tcg_temp_new_i64();
9070 gen_load_fpr64(ctx, fp0, fs);
9071 gen_store_fpr64(ctx, fp0, fd);
9072 tcg_temp_free_i64(fp0);
9073 gen_set_label(l1);
9076 opn = "movn.d";
9077 break;
9078 case OPC_RECIP_D:
9079 check_cp1_64bitmode(ctx);
9081 TCGv_i64 fp0 = tcg_temp_new_i64();
9083 gen_load_fpr64(ctx, fp0, fs);
9084 gen_helper_float_recip_d(fp0, cpu_env, fp0);
9085 gen_store_fpr64(ctx, fp0, fd);
9086 tcg_temp_free_i64(fp0);
9088 opn = "recip.d";
9089 break;
9090 case OPC_RSQRT_D:
9091 check_cp1_64bitmode(ctx);
9093 TCGv_i64 fp0 = tcg_temp_new_i64();
9095 gen_load_fpr64(ctx, fp0, fs);
9096 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
9097 gen_store_fpr64(ctx, fp0, fd);
9098 tcg_temp_free_i64(fp0);
9100 opn = "rsqrt.d";
9101 break;
9102 case OPC_MADDF_D:
9103 check_insn(ctx, ISA_MIPS32R6);
9105 TCGv_i64 fp0 = tcg_temp_new_i64();
9106 TCGv_i64 fp1 = tcg_temp_new_i64();
9107 TCGv_i64 fp2 = tcg_temp_new_i64();
9108 gen_load_fpr64(ctx, fp0, fs);
9109 gen_load_fpr64(ctx, fp1, ft);
9110 gen_load_fpr64(ctx, fp2, fd);
9111 gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
9112 gen_store_fpr64(ctx, fp2, fd);
9113 tcg_temp_free_i64(fp2);
9114 tcg_temp_free_i64(fp1);
9115 tcg_temp_free_i64(fp0);
9116 opn = "maddf.d";
9118 break;
9119 case OPC_MSUBF_D:
9120 check_insn(ctx, ISA_MIPS32R6);
9122 TCGv_i64 fp0 = tcg_temp_new_i64();
9123 TCGv_i64 fp1 = tcg_temp_new_i64();
9124 TCGv_i64 fp2 = tcg_temp_new_i64();
9125 gen_load_fpr64(ctx, fp0, fs);
9126 gen_load_fpr64(ctx, fp1, ft);
9127 gen_load_fpr64(ctx, fp2, fd);
9128 gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
9129 gen_store_fpr64(ctx, fp2, fd);
9130 tcg_temp_free_i64(fp2);
9131 tcg_temp_free_i64(fp1);
9132 tcg_temp_free_i64(fp0);
9133 opn = "msubf.d";
9135 break;
9136 case OPC_RINT_D:
9137 check_insn(ctx, ISA_MIPS32R6);
9139 TCGv_i64 fp0 = tcg_temp_new_i64();
9140 gen_load_fpr64(ctx, fp0, fs);
9141 gen_helper_float_rint_d(fp0, cpu_env, fp0);
9142 gen_store_fpr64(ctx, fp0, fd);
9143 tcg_temp_free_i64(fp0);
9144 opn = "rint.d";
9146 break;
9147 case OPC_CLASS_D:
9148 check_insn(ctx, ISA_MIPS32R6);
9150 TCGv_i64 fp0 = tcg_temp_new_i64();
9151 gen_load_fpr64(ctx, fp0, fs);
9152 gen_helper_float_class_d(fp0, fp0);
9153 gen_store_fpr64(ctx, fp0, fd);
9154 tcg_temp_free_i64(fp0);
9155 opn = "class.d";
9157 break;
9158 case OPC_MIN_D: /* OPC_RECIP2_D */
9159 if (ctx->insn_flags & ISA_MIPS32R6) {
9160 /* OPC_MIN_D */
9161 TCGv_i64 fp0 = tcg_temp_new_i64();
9162 TCGv_i64 fp1 = tcg_temp_new_i64();
9163 gen_load_fpr64(ctx, fp0, fs);
9164 gen_load_fpr64(ctx, fp1, ft);
9165 gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
9166 gen_store_fpr64(ctx, fp1, fd);
9167 tcg_temp_free_i64(fp1);
9168 tcg_temp_free_i64(fp0);
9169 opn = "min.d";
9170 } else {
9171 /* OPC_RECIP2_D */
9172 check_cp1_64bitmode(ctx);
9174 TCGv_i64 fp0 = tcg_temp_new_i64();
9175 TCGv_i64 fp1 = tcg_temp_new_i64();
9177 gen_load_fpr64(ctx, fp0, fs);
9178 gen_load_fpr64(ctx, fp1, ft);
9179 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
9180 tcg_temp_free_i64(fp1);
9181 gen_store_fpr64(ctx, fp0, fd);
9182 tcg_temp_free_i64(fp0);
9184 opn = "recip2.d";
9186 break;
9187 case OPC_MINA_D: /* OPC_RECIP1_D */
9188 if (ctx->insn_flags & ISA_MIPS32R6) {
9189 /* OPC_MINA_D */
9190 TCGv_i64 fp0 = tcg_temp_new_i64();
9191 TCGv_i64 fp1 = tcg_temp_new_i64();
9192 gen_load_fpr64(ctx, fp0, fs);
9193 gen_load_fpr64(ctx, fp1, ft);
9194 gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
9195 gen_store_fpr64(ctx, fp1, fd);
9196 tcg_temp_free_i64(fp1);
9197 tcg_temp_free_i64(fp0);
9198 opn = "mina.d";
9199 } else {
9200 /* OPC_RECIP1_D */
9201 check_cp1_64bitmode(ctx);
9203 TCGv_i64 fp0 = tcg_temp_new_i64();
9205 gen_load_fpr64(ctx, fp0, fs);
9206 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
9207 gen_store_fpr64(ctx, fp0, fd);
9208 tcg_temp_free_i64(fp0);
9210 opn = "recip1.d";
9212 break;
9213 case OPC_MAX_D: /* OPC_RSQRT1_D */
9214 if (ctx->insn_flags & ISA_MIPS32R6) {
9215 /* OPC_MAX_D */
9216 TCGv_i64 fp0 = tcg_temp_new_i64();
9217 TCGv_i64 fp1 = tcg_temp_new_i64();
9218 gen_load_fpr64(ctx, fp0, fs);
9219 gen_load_fpr64(ctx, fp1, ft);
9220 gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
9221 gen_store_fpr64(ctx, fp1, fd);
9222 tcg_temp_free_i64(fp1);
9223 tcg_temp_free_i64(fp0);
9224 opn = "max.d";
9225 } else {
9226 /* OPC_RSQRT1_D */
9227 check_cp1_64bitmode(ctx);
9229 TCGv_i64 fp0 = tcg_temp_new_i64();
9231 gen_load_fpr64(ctx, fp0, fs);
9232 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
9233 gen_store_fpr64(ctx, fp0, fd);
9234 tcg_temp_free_i64(fp0);
9236 opn = "rsqrt1.d";
9238 break;
9239 case OPC_MAXA_D: /* OPC_RSQRT2_D */
9240 if (ctx->insn_flags & ISA_MIPS32R6) {
9241 /* OPC_MAXA_D */
9242 TCGv_i64 fp0 = tcg_temp_new_i64();
9243 TCGv_i64 fp1 = tcg_temp_new_i64();
9244 gen_load_fpr64(ctx, fp0, fs);
9245 gen_load_fpr64(ctx, fp1, ft);
9246 gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
9247 gen_store_fpr64(ctx, fp1, fd);
9248 tcg_temp_free_i64(fp1);
9249 tcg_temp_free_i64(fp0);
9250 opn = "maxa.d";
9251 } else {
9252 /* OPC_RSQRT2_D */
9253 check_cp1_64bitmode(ctx);
9255 TCGv_i64 fp0 = tcg_temp_new_i64();
9256 TCGv_i64 fp1 = tcg_temp_new_i64();
9258 gen_load_fpr64(ctx, fp0, fs);
9259 gen_load_fpr64(ctx, fp1, ft);
9260 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
9261 tcg_temp_free_i64(fp1);
9262 gen_store_fpr64(ctx, fp0, fd);
9263 tcg_temp_free_i64(fp0);
9265 opn = "rsqrt2.d";
9267 break;
9268 case OPC_CMP_F_D:
9269 case OPC_CMP_UN_D:
9270 case OPC_CMP_EQ_D:
9271 case OPC_CMP_UEQ_D:
9272 case OPC_CMP_OLT_D:
9273 case OPC_CMP_ULT_D:
9274 case OPC_CMP_OLE_D:
9275 case OPC_CMP_ULE_D:
9276 case OPC_CMP_SF_D:
9277 case OPC_CMP_NGLE_D:
9278 case OPC_CMP_SEQ_D:
9279 case OPC_CMP_NGL_D:
9280 case OPC_CMP_LT_D:
9281 case OPC_CMP_NGE_D:
9282 case OPC_CMP_LE_D:
9283 case OPC_CMP_NGT_D:
9284 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9285 if (ctx->opcode & (1 << 6)) {
9286 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
9287 opn = condnames_abs[func-48];
9288 } else {
9289 gen_cmp_d(ctx, func-48, ft, fs, cc);
9290 opn = condnames[func-48];
9292 break;
9293 case OPC_CVT_S_D:
9294 check_cp1_registers(ctx, fs);
9296 TCGv_i32 fp32 = tcg_temp_new_i32();
9297 TCGv_i64 fp64 = tcg_temp_new_i64();
9299 gen_load_fpr64(ctx, fp64, fs);
9300 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
9301 tcg_temp_free_i64(fp64);
9302 gen_store_fpr32(fp32, fd);
9303 tcg_temp_free_i32(fp32);
9305 opn = "cvt.s.d";
9306 break;
9307 case OPC_CVT_W_D:
9308 check_cp1_registers(ctx, fs);
9310 TCGv_i32 fp32 = tcg_temp_new_i32();
9311 TCGv_i64 fp64 = tcg_temp_new_i64();
9313 gen_load_fpr64(ctx, fp64, fs);
9314 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
9315 tcg_temp_free_i64(fp64);
9316 gen_store_fpr32(fp32, fd);
9317 tcg_temp_free_i32(fp32);
9319 opn = "cvt.w.d";
9320 break;
9321 case OPC_CVT_L_D:
9322 check_cp1_64bitmode(ctx);
9324 TCGv_i64 fp0 = tcg_temp_new_i64();
9326 gen_load_fpr64(ctx, fp0, fs);
9327 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
9328 gen_store_fpr64(ctx, fp0, fd);
9329 tcg_temp_free_i64(fp0);
9331 opn = "cvt.l.d";
9332 break;
9333 case OPC_CVT_S_W:
9335 TCGv_i32 fp0 = tcg_temp_new_i32();
9337 gen_load_fpr32(fp0, fs);
9338 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
9339 gen_store_fpr32(fp0, fd);
9340 tcg_temp_free_i32(fp0);
9342 opn = "cvt.s.w";
9343 break;
9344 case OPC_CVT_D_W:
9345 check_cp1_registers(ctx, fd);
9347 TCGv_i32 fp32 = tcg_temp_new_i32();
9348 TCGv_i64 fp64 = tcg_temp_new_i64();
9350 gen_load_fpr32(fp32, fs);
9351 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
9352 tcg_temp_free_i32(fp32);
9353 gen_store_fpr64(ctx, fp64, fd);
9354 tcg_temp_free_i64(fp64);
9356 opn = "cvt.d.w";
9357 break;
9358 case OPC_CVT_S_L:
9359 check_cp1_64bitmode(ctx);
9361 TCGv_i32 fp32 = tcg_temp_new_i32();
9362 TCGv_i64 fp64 = tcg_temp_new_i64();
9364 gen_load_fpr64(ctx, fp64, fs);
9365 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
9366 tcg_temp_free_i64(fp64);
9367 gen_store_fpr32(fp32, fd);
9368 tcg_temp_free_i32(fp32);
9370 opn = "cvt.s.l";
9371 break;
9372 case OPC_CVT_D_L:
9373 check_cp1_64bitmode(ctx);
9375 TCGv_i64 fp0 = tcg_temp_new_i64();
9377 gen_load_fpr64(ctx, fp0, fs);
9378 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
9379 gen_store_fpr64(ctx, fp0, fd);
9380 tcg_temp_free_i64(fp0);
9382 opn = "cvt.d.l";
9383 break;
9384 case OPC_CVT_PS_PW:
9385 check_insn_opc_removed(ctx, ISA_MIPS32R6);
9386 check_cp1_64bitmode(ctx);
9388 TCGv_i64 fp0 = tcg_temp_new_i64();
9390 gen_load_fpr64(ctx, fp0, fs);
9391 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
9392 gen_store_fpr64(ctx, fp0, fd);
9393 tcg_temp_free_i64(fp0);
9395 opn = "cvt.ps.pw";
9396 break;
9397 case OPC_ADD_PS:
9398 check_cp1_64bitmode(ctx);
9400 TCGv_i64 fp0 = tcg_temp_new_i64();
9401 TCGv_i64 fp1 = tcg_temp_new_i64();
9403 gen_load_fpr64(ctx, fp0, fs);
9404 gen_load_fpr64(ctx, fp1, ft);
9405 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
9406 tcg_temp_free_i64(fp1);
9407 gen_store_fpr64(ctx, fp0, fd);
9408 tcg_temp_free_i64(fp0);
9410 opn = "add.ps";
9411 break;
9412 case OPC_SUB_PS:
9413 check_cp1_64bitmode(ctx);
9415 TCGv_i64 fp0 = tcg_temp_new_i64();
9416 TCGv_i64 fp1 = tcg_temp_new_i64();
9418 gen_load_fpr64(ctx, fp0, fs);
9419 gen_load_fpr64(ctx, fp1, ft);
9420 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
9421 tcg_temp_free_i64(fp1);
9422 gen_store_fpr64(ctx, fp0, fd);
9423 tcg_temp_free_i64(fp0);
9425 opn = "sub.ps";
9426 break;
9427 case OPC_MUL_PS:
9428 check_cp1_64bitmode(ctx);
9430 TCGv_i64 fp0 = tcg_temp_new_i64();
9431 TCGv_i64 fp1 = tcg_temp_new_i64();
9433 gen_load_fpr64(ctx, fp0, fs);
9434 gen_load_fpr64(ctx, fp1, ft);
9435 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
9436 tcg_temp_free_i64(fp1);
9437 gen_store_fpr64(ctx, fp0, fd);
9438 tcg_temp_free_i64(fp0);
9440 opn = "mul.ps";
9441 break;
9442 case OPC_ABS_PS:
9443 check_cp1_64bitmode(ctx);
9445 TCGv_i64 fp0 = tcg_temp_new_i64();
9447 gen_load_fpr64(ctx, fp0, fs);
9448 gen_helper_float_abs_ps(fp0, fp0);
9449 gen_store_fpr64(ctx, fp0, fd);
9450 tcg_temp_free_i64(fp0);
9452 opn = "abs.ps";
9453 break;
9454 case OPC_MOV_PS:
9455 check_cp1_64bitmode(ctx);
9457 TCGv_i64 fp0 = tcg_temp_new_i64();
9459 gen_load_fpr64(ctx, fp0, fs);
9460 gen_store_fpr64(ctx, fp0, fd);
9461 tcg_temp_free_i64(fp0);
9463 opn = "mov.ps";
9464 break;
9465 case OPC_NEG_PS:
9466 check_cp1_64bitmode(ctx);
9468 TCGv_i64 fp0 = tcg_temp_new_i64();
9470 gen_load_fpr64(ctx, fp0, fs);
9471 gen_helper_float_chs_ps(fp0, fp0);
9472 gen_store_fpr64(ctx, fp0, fd);
9473 tcg_temp_free_i64(fp0);
9475 opn = "neg.ps";
9476 break;
9477 case OPC_MOVCF_PS:
9478 check_cp1_64bitmode(ctx);
9479 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9480 opn = "movcf.ps";
9481 break;
9482 case OPC_MOVZ_PS:
9483 check_cp1_64bitmode(ctx);
9485 int l1 = gen_new_label();
9486 TCGv_i64 fp0;
9488 if (ft != 0)
9489 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9490 fp0 = tcg_temp_new_i64();
9491 gen_load_fpr64(ctx, fp0, fs);
9492 gen_store_fpr64(ctx, fp0, fd);
9493 tcg_temp_free_i64(fp0);
9494 gen_set_label(l1);
9496 opn = "movz.ps";
9497 break;
9498 case OPC_MOVN_PS:
9499 check_cp1_64bitmode(ctx);
9501 int l1 = gen_new_label();
9502 TCGv_i64 fp0;
9504 if (ft != 0) {
9505 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9506 fp0 = tcg_temp_new_i64();
9507 gen_load_fpr64(ctx, fp0, fs);
9508 gen_store_fpr64(ctx, fp0, fd);
9509 tcg_temp_free_i64(fp0);
9510 gen_set_label(l1);
9513 opn = "movn.ps";
9514 break;
9515 case OPC_ADDR_PS:
9516 check_cp1_64bitmode(ctx);
9518 TCGv_i64 fp0 = tcg_temp_new_i64();
9519 TCGv_i64 fp1 = tcg_temp_new_i64();
9521 gen_load_fpr64(ctx, fp0, ft);
9522 gen_load_fpr64(ctx, fp1, fs);
9523 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
9524 tcg_temp_free_i64(fp1);
9525 gen_store_fpr64(ctx, fp0, fd);
9526 tcg_temp_free_i64(fp0);
9528 opn = "addr.ps";
9529 break;
9530 case OPC_MULR_PS:
9531 check_cp1_64bitmode(ctx);
9533 TCGv_i64 fp0 = tcg_temp_new_i64();
9534 TCGv_i64 fp1 = tcg_temp_new_i64();
9536 gen_load_fpr64(ctx, fp0, ft);
9537 gen_load_fpr64(ctx, fp1, fs);
9538 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
9539 tcg_temp_free_i64(fp1);
9540 gen_store_fpr64(ctx, fp0, fd);
9541 tcg_temp_free_i64(fp0);
9543 opn = "mulr.ps";
9544 break;
9545 case OPC_RECIP2_PS:
9546 check_cp1_64bitmode(ctx);
9548 TCGv_i64 fp0 = tcg_temp_new_i64();
9549 TCGv_i64 fp1 = tcg_temp_new_i64();
9551 gen_load_fpr64(ctx, fp0, fs);
9552 gen_load_fpr64(ctx, fp1, ft);
9553 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
9554 tcg_temp_free_i64(fp1);
9555 gen_store_fpr64(ctx, fp0, fd);
9556 tcg_temp_free_i64(fp0);
9558 opn = "recip2.ps";
9559 break;
9560 case OPC_RECIP1_PS:
9561 check_cp1_64bitmode(ctx);
9563 TCGv_i64 fp0 = tcg_temp_new_i64();
9565 gen_load_fpr64(ctx, fp0, fs);
9566 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
9567 gen_store_fpr64(ctx, fp0, fd);
9568 tcg_temp_free_i64(fp0);
9570 opn = "recip1.ps";
9571 break;
9572 case OPC_RSQRT1_PS:
9573 check_cp1_64bitmode(ctx);
9575 TCGv_i64 fp0 = tcg_temp_new_i64();
9577 gen_load_fpr64(ctx, fp0, fs);
9578 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
9579 gen_store_fpr64(ctx, fp0, fd);
9580 tcg_temp_free_i64(fp0);
9582 opn = "rsqrt1.ps";
9583 break;
9584 case OPC_RSQRT2_PS:
9585 check_cp1_64bitmode(ctx);
9587 TCGv_i64 fp0 = tcg_temp_new_i64();
9588 TCGv_i64 fp1 = tcg_temp_new_i64();
9590 gen_load_fpr64(ctx, fp0, fs);
9591 gen_load_fpr64(ctx, fp1, ft);
9592 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
9593 tcg_temp_free_i64(fp1);
9594 gen_store_fpr64(ctx, fp0, fd);
9595 tcg_temp_free_i64(fp0);
9597 opn = "rsqrt2.ps";
9598 break;
9599 case OPC_CVT_S_PU:
9600 check_cp1_64bitmode(ctx);
9602 TCGv_i32 fp0 = tcg_temp_new_i32();
9604 gen_load_fpr32h(ctx, fp0, fs);
9605 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
9606 gen_store_fpr32(fp0, fd);
9607 tcg_temp_free_i32(fp0);
9609 opn = "cvt.s.pu";
9610 break;
9611 case OPC_CVT_PW_PS:
9612 check_cp1_64bitmode(ctx);
9614 TCGv_i64 fp0 = tcg_temp_new_i64();
9616 gen_load_fpr64(ctx, fp0, fs);
9617 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
9618 gen_store_fpr64(ctx, fp0, fd);
9619 tcg_temp_free_i64(fp0);
9621 opn = "cvt.pw.ps";
9622 break;
9623 case OPC_CVT_S_PL:
9624 check_cp1_64bitmode(ctx);
9626 TCGv_i32 fp0 = tcg_temp_new_i32();
9628 gen_load_fpr32(fp0, fs);
9629 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
9630 gen_store_fpr32(fp0, fd);
9631 tcg_temp_free_i32(fp0);
9633 opn = "cvt.s.pl";
9634 break;
9635 case OPC_PLL_PS:
9636 check_cp1_64bitmode(ctx);
9638 TCGv_i32 fp0 = tcg_temp_new_i32();
9639 TCGv_i32 fp1 = tcg_temp_new_i32();
9641 gen_load_fpr32(fp0, fs);
9642 gen_load_fpr32(fp1, ft);
9643 gen_store_fpr32h(ctx, fp0, fd);
9644 gen_store_fpr32(fp1, fd);
9645 tcg_temp_free_i32(fp0);
9646 tcg_temp_free_i32(fp1);
9648 opn = "pll.ps";
9649 break;
9650 case OPC_PLU_PS:
9651 check_cp1_64bitmode(ctx);
9653 TCGv_i32 fp0 = tcg_temp_new_i32();
9654 TCGv_i32 fp1 = tcg_temp_new_i32();
9656 gen_load_fpr32(fp0, fs);
9657 gen_load_fpr32h(ctx, fp1, ft);
9658 gen_store_fpr32(fp1, fd);
9659 gen_store_fpr32h(ctx, fp0, fd);
9660 tcg_temp_free_i32(fp0);
9661 tcg_temp_free_i32(fp1);
9663 opn = "plu.ps";
9664 break;
9665 case OPC_PUL_PS:
9666 check_cp1_64bitmode(ctx);
9668 TCGv_i32 fp0 = tcg_temp_new_i32();
9669 TCGv_i32 fp1 = tcg_temp_new_i32();
9671 gen_load_fpr32h(ctx, fp0, fs);
9672 gen_load_fpr32(fp1, ft);
9673 gen_store_fpr32(fp1, fd);
9674 gen_store_fpr32h(ctx, fp0, fd);
9675 tcg_temp_free_i32(fp0);
9676 tcg_temp_free_i32(fp1);
9678 opn = "pul.ps";
9679 break;
9680 case OPC_PUU_PS:
9681 check_cp1_64bitmode(ctx);
9683 TCGv_i32 fp0 = tcg_temp_new_i32();
9684 TCGv_i32 fp1 = tcg_temp_new_i32();
9686 gen_load_fpr32h(ctx, fp0, fs);
9687 gen_load_fpr32h(ctx, fp1, ft);
9688 gen_store_fpr32(fp1, fd);
9689 gen_store_fpr32h(ctx, fp0, fd);
9690 tcg_temp_free_i32(fp0);
9691 tcg_temp_free_i32(fp1);
9693 opn = "puu.ps";
9694 break;
9695 case OPC_CMP_F_PS:
9696 case OPC_CMP_UN_PS:
9697 case OPC_CMP_EQ_PS:
9698 case OPC_CMP_UEQ_PS:
9699 case OPC_CMP_OLT_PS:
9700 case OPC_CMP_ULT_PS:
9701 case OPC_CMP_OLE_PS:
9702 case OPC_CMP_ULE_PS:
9703 case OPC_CMP_SF_PS:
9704 case OPC_CMP_NGLE_PS:
9705 case OPC_CMP_SEQ_PS:
9706 case OPC_CMP_NGL_PS:
9707 case OPC_CMP_LT_PS:
9708 case OPC_CMP_NGE_PS:
9709 case OPC_CMP_LE_PS:
9710 case OPC_CMP_NGT_PS:
9711 if (ctx->opcode & (1 << 6)) {
9712 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
9713 opn = condnames_abs[func-48];
9714 } else {
9715 gen_cmp_ps(ctx, func-48, ft, fs, cc);
9716 opn = condnames[func-48];
9718 break;
9719 default:
9720 MIPS_INVAL(opn);
9721 generate_exception (ctx, EXCP_RI);
9722 return;
9724 (void)opn; /* avoid a compiler warning */
9725 switch (optype) {
9726 case BINOP:
9727 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
9728 break;
9729 case CMPOP:
9730 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
9731 break;
9732 default:
9733 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
9734 break;
9738 /* Coprocessor 3 (FPU) */
9739 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
9740 int fd, int fs, int base, int index)
9742 const char *opn = "extended float load/store";
9743 int store = 0;
9744 TCGv t0 = tcg_temp_new();
9746 if (base == 0) {
9747 gen_load_gpr(t0, index);
9748 } else if (index == 0) {
9749 gen_load_gpr(t0, base);
9750 } else {
9751 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
9753 /* Don't do NOP if destination is zero: we must perform the actual
9754 memory access. */
9755 switch (opc) {
9756 case OPC_LWXC1:
9757 check_cop1x(ctx);
9759 TCGv_i32 fp0 = tcg_temp_new_i32();
9761 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
9762 tcg_gen_trunc_tl_i32(fp0, t0);
9763 gen_store_fpr32(fp0, fd);
9764 tcg_temp_free_i32(fp0);
9766 opn = "lwxc1";
9767 break;
9768 case OPC_LDXC1:
9769 check_cop1x(ctx);
9770 check_cp1_registers(ctx, fd);
9772 TCGv_i64 fp0 = tcg_temp_new_i64();
9773 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9774 gen_store_fpr64(ctx, fp0, fd);
9775 tcg_temp_free_i64(fp0);
9777 opn = "ldxc1";
9778 break;
9779 case OPC_LUXC1:
9780 check_cp1_64bitmode(ctx);
9781 tcg_gen_andi_tl(t0, t0, ~0x7);
9783 TCGv_i64 fp0 = tcg_temp_new_i64();
9785 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9786 gen_store_fpr64(ctx, fp0, fd);
9787 tcg_temp_free_i64(fp0);
9789 opn = "luxc1";
9790 break;
9791 case OPC_SWXC1:
9792 check_cop1x(ctx);
9794 TCGv_i32 fp0 = tcg_temp_new_i32();
9795 gen_load_fpr32(fp0, fs);
9796 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
9797 tcg_temp_free_i32(fp0);
9799 opn = "swxc1";
9800 store = 1;
9801 break;
9802 case OPC_SDXC1:
9803 check_cop1x(ctx);
9804 check_cp1_registers(ctx, fs);
9806 TCGv_i64 fp0 = tcg_temp_new_i64();
9807 gen_load_fpr64(ctx, fp0, fs);
9808 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9809 tcg_temp_free_i64(fp0);
9811 opn = "sdxc1";
9812 store = 1;
9813 break;
9814 case OPC_SUXC1:
9815 check_cp1_64bitmode(ctx);
9816 tcg_gen_andi_tl(t0, t0, ~0x7);
9818 TCGv_i64 fp0 = tcg_temp_new_i64();
9819 gen_load_fpr64(ctx, fp0, fs);
9820 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
9821 tcg_temp_free_i64(fp0);
9823 opn = "suxc1";
9824 store = 1;
9825 break;
9827 tcg_temp_free(t0);
9828 (void)opn; (void)store; /* avoid compiler warnings */
9829 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
9830 regnames[index], regnames[base]);
9833 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
9834 int fd, int fr, int fs, int ft)
9836 const char *opn = "flt3_arith";
9838 switch (opc) {
9839 case OPC_ALNV_PS:
9840 check_cp1_64bitmode(ctx);
9842 TCGv t0 = tcg_temp_local_new();
9843 TCGv_i32 fp = tcg_temp_new_i32();
9844 TCGv_i32 fph = tcg_temp_new_i32();
9845 int l1 = gen_new_label();
9846 int l2 = gen_new_label();
9848 gen_load_gpr(t0, fr);
9849 tcg_gen_andi_tl(t0, t0, 0x7);
9851 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
9852 gen_load_fpr32(fp, fs);
9853 gen_load_fpr32h(ctx, fph, fs);
9854 gen_store_fpr32(fp, fd);
9855 gen_store_fpr32h(ctx, fph, fd);
9856 tcg_gen_br(l2);
9857 gen_set_label(l1);
9858 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
9859 tcg_temp_free(t0);
9860 #ifdef TARGET_WORDS_BIGENDIAN
9861 gen_load_fpr32(fp, fs);
9862 gen_load_fpr32h(ctx, fph, ft);
9863 gen_store_fpr32h(ctx, fp, fd);
9864 gen_store_fpr32(fph, fd);
9865 #else
9866 gen_load_fpr32h(ctx, fph, fs);
9867 gen_load_fpr32(fp, ft);
9868 gen_store_fpr32(fph, fd);
9869 gen_store_fpr32h(ctx, fp, fd);
9870 #endif
9871 gen_set_label(l2);
9872 tcg_temp_free_i32(fp);
9873 tcg_temp_free_i32(fph);
9875 opn = "alnv.ps";
9876 break;
9877 case OPC_MADD_S:
9878 check_cop1x(ctx);
9880 TCGv_i32 fp0 = tcg_temp_new_i32();
9881 TCGv_i32 fp1 = tcg_temp_new_i32();
9882 TCGv_i32 fp2 = tcg_temp_new_i32();
9884 gen_load_fpr32(fp0, fs);
9885 gen_load_fpr32(fp1, ft);
9886 gen_load_fpr32(fp2, fr);
9887 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
9888 tcg_temp_free_i32(fp0);
9889 tcg_temp_free_i32(fp1);
9890 gen_store_fpr32(fp2, fd);
9891 tcg_temp_free_i32(fp2);
9893 opn = "madd.s";
9894 break;
9895 case OPC_MADD_D:
9896 check_cop1x(ctx);
9897 check_cp1_registers(ctx, fd | fs | ft | fr);
9899 TCGv_i64 fp0 = tcg_temp_new_i64();
9900 TCGv_i64 fp1 = tcg_temp_new_i64();
9901 TCGv_i64 fp2 = tcg_temp_new_i64();
9903 gen_load_fpr64(ctx, fp0, fs);
9904 gen_load_fpr64(ctx, fp1, ft);
9905 gen_load_fpr64(ctx, fp2, fr);
9906 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
9907 tcg_temp_free_i64(fp0);
9908 tcg_temp_free_i64(fp1);
9909 gen_store_fpr64(ctx, fp2, fd);
9910 tcg_temp_free_i64(fp2);
9912 opn = "madd.d";
9913 break;
9914 case OPC_MADD_PS:
9915 check_cp1_64bitmode(ctx);
9917 TCGv_i64 fp0 = tcg_temp_new_i64();
9918 TCGv_i64 fp1 = tcg_temp_new_i64();
9919 TCGv_i64 fp2 = tcg_temp_new_i64();
9921 gen_load_fpr64(ctx, fp0, fs);
9922 gen_load_fpr64(ctx, fp1, ft);
9923 gen_load_fpr64(ctx, fp2, fr);
9924 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
9925 tcg_temp_free_i64(fp0);
9926 tcg_temp_free_i64(fp1);
9927 gen_store_fpr64(ctx, fp2, fd);
9928 tcg_temp_free_i64(fp2);
9930 opn = "madd.ps";
9931 break;
9932 case OPC_MSUB_S:
9933 check_cop1x(ctx);
9935 TCGv_i32 fp0 = tcg_temp_new_i32();
9936 TCGv_i32 fp1 = tcg_temp_new_i32();
9937 TCGv_i32 fp2 = tcg_temp_new_i32();
9939 gen_load_fpr32(fp0, fs);
9940 gen_load_fpr32(fp1, ft);
9941 gen_load_fpr32(fp2, fr);
9942 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
9943 tcg_temp_free_i32(fp0);
9944 tcg_temp_free_i32(fp1);
9945 gen_store_fpr32(fp2, fd);
9946 tcg_temp_free_i32(fp2);
9948 opn = "msub.s";
9949 break;
9950 case OPC_MSUB_D:
9951 check_cop1x(ctx);
9952 check_cp1_registers(ctx, fd | fs | ft | fr);
9954 TCGv_i64 fp0 = tcg_temp_new_i64();
9955 TCGv_i64 fp1 = tcg_temp_new_i64();
9956 TCGv_i64 fp2 = tcg_temp_new_i64();
9958 gen_load_fpr64(ctx, fp0, fs);
9959 gen_load_fpr64(ctx, fp1, ft);
9960 gen_load_fpr64(ctx, fp2, fr);
9961 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
9962 tcg_temp_free_i64(fp0);
9963 tcg_temp_free_i64(fp1);
9964 gen_store_fpr64(ctx, fp2, fd);
9965 tcg_temp_free_i64(fp2);
9967 opn = "msub.d";
9968 break;
9969 case OPC_MSUB_PS:
9970 check_cp1_64bitmode(ctx);
9972 TCGv_i64 fp0 = tcg_temp_new_i64();
9973 TCGv_i64 fp1 = tcg_temp_new_i64();
9974 TCGv_i64 fp2 = tcg_temp_new_i64();
9976 gen_load_fpr64(ctx, fp0, fs);
9977 gen_load_fpr64(ctx, fp1, ft);
9978 gen_load_fpr64(ctx, fp2, fr);
9979 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
9980 tcg_temp_free_i64(fp0);
9981 tcg_temp_free_i64(fp1);
9982 gen_store_fpr64(ctx, fp2, fd);
9983 tcg_temp_free_i64(fp2);
9985 opn = "msub.ps";
9986 break;
9987 case OPC_NMADD_S:
9988 check_cop1x(ctx);
9990 TCGv_i32 fp0 = tcg_temp_new_i32();
9991 TCGv_i32 fp1 = tcg_temp_new_i32();
9992 TCGv_i32 fp2 = tcg_temp_new_i32();
9994 gen_load_fpr32(fp0, fs);
9995 gen_load_fpr32(fp1, ft);
9996 gen_load_fpr32(fp2, fr);
9997 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
9998 tcg_temp_free_i32(fp0);
9999 tcg_temp_free_i32(fp1);
10000 gen_store_fpr32(fp2, fd);
10001 tcg_temp_free_i32(fp2);
10003 opn = "nmadd.s";
10004 break;
10005 case OPC_NMADD_D:
10006 check_cop1x(ctx);
10007 check_cp1_registers(ctx, fd | fs | ft | fr);
10009 TCGv_i64 fp0 = tcg_temp_new_i64();
10010 TCGv_i64 fp1 = tcg_temp_new_i64();
10011 TCGv_i64 fp2 = tcg_temp_new_i64();
10013 gen_load_fpr64(ctx, fp0, fs);
10014 gen_load_fpr64(ctx, fp1, ft);
10015 gen_load_fpr64(ctx, fp2, fr);
10016 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
10017 tcg_temp_free_i64(fp0);
10018 tcg_temp_free_i64(fp1);
10019 gen_store_fpr64(ctx, fp2, fd);
10020 tcg_temp_free_i64(fp2);
10022 opn = "nmadd.d";
10023 break;
10024 case OPC_NMADD_PS:
10025 check_cp1_64bitmode(ctx);
10027 TCGv_i64 fp0 = tcg_temp_new_i64();
10028 TCGv_i64 fp1 = tcg_temp_new_i64();
10029 TCGv_i64 fp2 = tcg_temp_new_i64();
10031 gen_load_fpr64(ctx, fp0, fs);
10032 gen_load_fpr64(ctx, fp1, ft);
10033 gen_load_fpr64(ctx, fp2, fr);
10034 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
10035 tcg_temp_free_i64(fp0);
10036 tcg_temp_free_i64(fp1);
10037 gen_store_fpr64(ctx, fp2, fd);
10038 tcg_temp_free_i64(fp2);
10040 opn = "nmadd.ps";
10041 break;
10042 case OPC_NMSUB_S:
10043 check_cop1x(ctx);
10045 TCGv_i32 fp0 = tcg_temp_new_i32();
10046 TCGv_i32 fp1 = tcg_temp_new_i32();
10047 TCGv_i32 fp2 = tcg_temp_new_i32();
10049 gen_load_fpr32(fp0, fs);
10050 gen_load_fpr32(fp1, ft);
10051 gen_load_fpr32(fp2, fr);
10052 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
10053 tcg_temp_free_i32(fp0);
10054 tcg_temp_free_i32(fp1);
10055 gen_store_fpr32(fp2, fd);
10056 tcg_temp_free_i32(fp2);
10058 opn = "nmsub.s";
10059 break;
10060 case OPC_NMSUB_D:
10061 check_cop1x(ctx);
10062 check_cp1_registers(ctx, fd | fs | ft | fr);
10064 TCGv_i64 fp0 = tcg_temp_new_i64();
10065 TCGv_i64 fp1 = tcg_temp_new_i64();
10066 TCGv_i64 fp2 = tcg_temp_new_i64();
10068 gen_load_fpr64(ctx, fp0, fs);
10069 gen_load_fpr64(ctx, fp1, ft);
10070 gen_load_fpr64(ctx, fp2, fr);
10071 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
10072 tcg_temp_free_i64(fp0);
10073 tcg_temp_free_i64(fp1);
10074 gen_store_fpr64(ctx, fp2, fd);
10075 tcg_temp_free_i64(fp2);
10077 opn = "nmsub.d";
10078 break;
10079 case OPC_NMSUB_PS:
10080 check_cp1_64bitmode(ctx);
10082 TCGv_i64 fp0 = tcg_temp_new_i64();
10083 TCGv_i64 fp1 = tcg_temp_new_i64();
10084 TCGv_i64 fp2 = tcg_temp_new_i64();
10086 gen_load_fpr64(ctx, fp0, fs);
10087 gen_load_fpr64(ctx, fp1, ft);
10088 gen_load_fpr64(ctx, fp2, fr);
10089 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
10090 tcg_temp_free_i64(fp0);
10091 tcg_temp_free_i64(fp1);
10092 gen_store_fpr64(ctx, fp2, fd);
10093 tcg_temp_free_i64(fp2);
10095 opn = "nmsub.ps";
10096 break;
10097 default:
10098 MIPS_INVAL(opn);
10099 generate_exception (ctx, EXCP_RI);
10100 return;
10102 (void)opn; /* avoid a compiler warning */
10103 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
10104 fregnames[fs], fregnames[ft]);
10107 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
10109 TCGv t0;
10111 #if !defined(CONFIG_USER_ONLY)
10112 /* The Linux kernel will emulate rdhwr if it's not supported natively.
10113 Therefore only check the ISA in system mode. */
10114 check_insn(ctx, ISA_MIPS32R2);
10115 #endif
10116 t0 = tcg_temp_new();
10118 switch (rd) {
10119 case 0:
10120 save_cpu_state(ctx, 1);
10121 gen_helper_rdhwr_cpunum(t0, cpu_env);
10122 gen_store_gpr(t0, rt);
10123 break;
10124 case 1:
10125 save_cpu_state(ctx, 1);
10126 gen_helper_rdhwr_synci_step(t0, cpu_env);
10127 gen_store_gpr(t0, rt);
10128 break;
10129 case 2:
10130 save_cpu_state(ctx, 1);
10131 gen_helper_rdhwr_cc(t0, cpu_env);
10132 gen_store_gpr(t0, rt);
10133 break;
10134 case 3:
10135 save_cpu_state(ctx, 1);
10136 gen_helper_rdhwr_ccres(t0, cpu_env);
10137 gen_store_gpr(t0, rt);
10138 break;
10139 case 29:
10140 #if defined(CONFIG_USER_ONLY)
10141 tcg_gen_ld_tl(t0, cpu_env,
10142 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10143 gen_store_gpr(t0, rt);
10144 break;
10145 #else
10146 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10147 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10148 tcg_gen_ld_tl(t0, cpu_env,
10149 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10150 gen_store_gpr(t0, rt);
10151 } else {
10152 generate_exception(ctx, EXCP_RI);
10154 break;
10155 #endif
10156 default: /* Invalid */
10157 MIPS_INVAL("rdhwr");
10158 generate_exception(ctx, EXCP_RI);
10159 break;
10161 tcg_temp_free(t0);
10164 static void gen_branch(DisasContext *ctx, int insn_bytes)
10166 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10167 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10168 /* Branches completion */
10169 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10170 ctx->bstate = BS_BRANCH;
10171 save_cpu_state(ctx, 0);
10172 /* FIXME: Need to clear can_do_io. */
10173 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10174 case MIPS_HFLAG_B:
10175 /* unconditional branch */
10176 MIPS_DEBUG("unconditional branch");
10177 if (proc_hflags & MIPS_HFLAG_BX) {
10178 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10180 gen_goto_tb(ctx, 0, ctx->btarget);
10181 break;
10182 case MIPS_HFLAG_BL:
10183 /* blikely taken case */
10184 MIPS_DEBUG("blikely branch taken");
10185 gen_goto_tb(ctx, 0, ctx->btarget);
10186 break;
10187 case MIPS_HFLAG_BC:
10188 /* Conditional branch */
10189 MIPS_DEBUG("conditional branch");
10191 int l1 = gen_new_label();
10193 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10194 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
10195 gen_set_label(l1);
10196 gen_goto_tb(ctx, 0, ctx->btarget);
10198 break;
10199 case MIPS_HFLAG_BR:
10200 /* unconditional branch to register */
10201 MIPS_DEBUG("branch to register");
10202 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10203 TCGv t0 = tcg_temp_new();
10204 TCGv_i32 t1 = tcg_temp_new_i32();
10206 tcg_gen_andi_tl(t0, btarget, 0x1);
10207 tcg_gen_trunc_tl_i32(t1, t0);
10208 tcg_temp_free(t0);
10209 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10210 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10211 tcg_gen_or_i32(hflags, hflags, t1);
10212 tcg_temp_free_i32(t1);
10214 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10215 } else {
10216 tcg_gen_mov_tl(cpu_PC, btarget);
10218 if (ctx->singlestep_enabled) {
10219 save_cpu_state(ctx, 0);
10220 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
10222 tcg_gen_exit_tb(0);
10223 break;
10224 default:
10225 MIPS_DEBUG("unknown branch");
10226 break;
10231 /* ISA extensions (ASEs) */
10232 /* MIPS16 extension to MIPS32 */
10234 /* MIPS16 major opcodes */
10235 enum {
10236 M16_OPC_ADDIUSP = 0x00,
10237 M16_OPC_ADDIUPC = 0x01,
10238 M16_OPC_B = 0x02,
10239 M16_OPC_JAL = 0x03,
10240 M16_OPC_BEQZ = 0x04,
10241 M16_OPC_BNEQZ = 0x05,
10242 M16_OPC_SHIFT = 0x06,
10243 M16_OPC_LD = 0x07,
10244 M16_OPC_RRIA = 0x08,
10245 M16_OPC_ADDIU8 = 0x09,
10246 M16_OPC_SLTI = 0x0a,
10247 M16_OPC_SLTIU = 0x0b,
10248 M16_OPC_I8 = 0x0c,
10249 M16_OPC_LI = 0x0d,
10250 M16_OPC_CMPI = 0x0e,
10251 M16_OPC_SD = 0x0f,
10252 M16_OPC_LB = 0x10,
10253 M16_OPC_LH = 0x11,
10254 M16_OPC_LWSP = 0x12,
10255 M16_OPC_LW = 0x13,
10256 M16_OPC_LBU = 0x14,
10257 M16_OPC_LHU = 0x15,
10258 M16_OPC_LWPC = 0x16,
10259 M16_OPC_LWU = 0x17,
10260 M16_OPC_SB = 0x18,
10261 M16_OPC_SH = 0x19,
10262 M16_OPC_SWSP = 0x1a,
10263 M16_OPC_SW = 0x1b,
10264 M16_OPC_RRR = 0x1c,
10265 M16_OPC_RR = 0x1d,
10266 M16_OPC_EXTEND = 0x1e,
10267 M16_OPC_I64 = 0x1f
10270 /* I8 funct field */
10271 enum {
10272 I8_BTEQZ = 0x0,
10273 I8_BTNEZ = 0x1,
10274 I8_SWRASP = 0x2,
10275 I8_ADJSP = 0x3,
10276 I8_SVRS = 0x4,
10277 I8_MOV32R = 0x5,
10278 I8_MOVR32 = 0x7
10281 /* RRR f field */
10282 enum {
10283 RRR_DADDU = 0x0,
10284 RRR_ADDU = 0x1,
10285 RRR_DSUBU = 0x2,
10286 RRR_SUBU = 0x3
10289 /* RR funct field */
10290 enum {
10291 RR_JR = 0x00,
10292 RR_SDBBP = 0x01,
10293 RR_SLT = 0x02,
10294 RR_SLTU = 0x03,
10295 RR_SLLV = 0x04,
10296 RR_BREAK = 0x05,
10297 RR_SRLV = 0x06,
10298 RR_SRAV = 0x07,
10299 RR_DSRL = 0x08,
10300 RR_CMP = 0x0a,
10301 RR_NEG = 0x0b,
10302 RR_AND = 0x0c,
10303 RR_OR = 0x0d,
10304 RR_XOR = 0x0e,
10305 RR_NOT = 0x0f,
10306 RR_MFHI = 0x10,
10307 RR_CNVT = 0x11,
10308 RR_MFLO = 0x12,
10309 RR_DSRA = 0x13,
10310 RR_DSLLV = 0x14,
10311 RR_DSRLV = 0x16,
10312 RR_DSRAV = 0x17,
10313 RR_MULT = 0x18,
10314 RR_MULTU = 0x19,
10315 RR_DIV = 0x1a,
10316 RR_DIVU = 0x1b,
10317 RR_DMULT = 0x1c,
10318 RR_DMULTU = 0x1d,
10319 RR_DDIV = 0x1e,
10320 RR_DDIVU = 0x1f
10323 /* I64 funct field */
10324 enum {
10325 I64_LDSP = 0x0,
10326 I64_SDSP = 0x1,
10327 I64_SDRASP = 0x2,
10328 I64_DADJSP = 0x3,
10329 I64_LDPC = 0x4,
10330 I64_DADDIU5 = 0x5,
10331 I64_DADDIUPC = 0x6,
10332 I64_DADDIUSP = 0x7
10335 /* RR ry field for CNVT */
10336 enum {
10337 RR_RY_CNVT_ZEB = 0x0,
10338 RR_RY_CNVT_ZEH = 0x1,
10339 RR_RY_CNVT_ZEW = 0x2,
10340 RR_RY_CNVT_SEB = 0x4,
10341 RR_RY_CNVT_SEH = 0x5,
10342 RR_RY_CNVT_SEW = 0x6,
10345 static int xlat (int r)
10347 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10349 return map[r];
10352 static void gen_mips16_save (DisasContext *ctx,
10353 int xsregs, int aregs,
10354 int do_ra, int do_s0, int do_s1,
10355 int framesize)
10357 TCGv t0 = tcg_temp_new();
10358 TCGv t1 = tcg_temp_new();
10359 int args, astatic;
10361 switch (aregs) {
10362 case 0:
10363 case 1:
10364 case 2:
10365 case 3:
10366 case 11:
10367 args = 0;
10368 break;
10369 case 4:
10370 case 5:
10371 case 6:
10372 case 7:
10373 args = 1;
10374 break;
10375 case 8:
10376 case 9:
10377 case 10:
10378 args = 2;
10379 break;
10380 case 12:
10381 case 13:
10382 args = 3;
10383 break;
10384 case 14:
10385 args = 4;
10386 break;
10387 default:
10388 generate_exception(ctx, EXCP_RI);
10389 return;
10392 switch (args) {
10393 case 4:
10394 gen_base_offset_addr(ctx, t0, 29, 12);
10395 gen_load_gpr(t1, 7);
10396 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10397 /* Fall through */
10398 case 3:
10399 gen_base_offset_addr(ctx, t0, 29, 8);
10400 gen_load_gpr(t1, 6);
10401 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10402 /* Fall through */
10403 case 2:
10404 gen_base_offset_addr(ctx, t0, 29, 4);
10405 gen_load_gpr(t1, 5);
10406 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10407 /* Fall through */
10408 case 1:
10409 gen_base_offset_addr(ctx, t0, 29, 0);
10410 gen_load_gpr(t1, 4);
10411 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
10414 gen_load_gpr(t0, 29);
10416 #define DECR_AND_STORE(reg) do { \
10417 tcg_gen_subi_tl(t0, t0, 4); \
10418 gen_load_gpr(t1, reg); \
10419 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
10420 } while (0)
10422 if (do_ra) {
10423 DECR_AND_STORE(31);
10426 switch (xsregs) {
10427 case 7:
10428 DECR_AND_STORE(30);
10429 /* Fall through */
10430 case 6:
10431 DECR_AND_STORE(23);
10432 /* Fall through */
10433 case 5:
10434 DECR_AND_STORE(22);
10435 /* Fall through */
10436 case 4:
10437 DECR_AND_STORE(21);
10438 /* Fall through */
10439 case 3:
10440 DECR_AND_STORE(20);
10441 /* Fall through */
10442 case 2:
10443 DECR_AND_STORE(19);
10444 /* Fall through */
10445 case 1:
10446 DECR_AND_STORE(18);
10449 if (do_s1) {
10450 DECR_AND_STORE(17);
10452 if (do_s0) {
10453 DECR_AND_STORE(16);
10456 switch (aregs) {
10457 case 0:
10458 case 4:
10459 case 8:
10460 case 12:
10461 case 14:
10462 astatic = 0;
10463 break;
10464 case 1:
10465 case 5:
10466 case 9:
10467 case 13:
10468 astatic = 1;
10469 break;
10470 case 2:
10471 case 6:
10472 case 10:
10473 astatic = 2;
10474 break;
10475 case 3:
10476 case 7:
10477 astatic = 3;
10478 break;
10479 case 11:
10480 astatic = 4;
10481 break;
10482 default:
10483 generate_exception(ctx, EXCP_RI);
10484 return;
10487 if (astatic > 0) {
10488 DECR_AND_STORE(7);
10489 if (astatic > 1) {
10490 DECR_AND_STORE(6);
10491 if (astatic > 2) {
10492 DECR_AND_STORE(5);
10493 if (astatic > 3) {
10494 DECR_AND_STORE(4);
10499 #undef DECR_AND_STORE
10501 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10502 tcg_temp_free(t0);
10503 tcg_temp_free(t1);
10506 static void gen_mips16_restore (DisasContext *ctx,
10507 int xsregs, int aregs,
10508 int do_ra, int do_s0, int do_s1,
10509 int framesize)
10511 int astatic;
10512 TCGv t0 = tcg_temp_new();
10513 TCGv t1 = tcg_temp_new();
10515 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
10517 #define DECR_AND_LOAD(reg) do { \
10518 tcg_gen_subi_tl(t0, t0, 4); \
10519 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
10520 gen_store_gpr(t1, reg); \
10521 } while (0)
10523 if (do_ra) {
10524 DECR_AND_LOAD(31);
10527 switch (xsregs) {
10528 case 7:
10529 DECR_AND_LOAD(30);
10530 /* Fall through */
10531 case 6:
10532 DECR_AND_LOAD(23);
10533 /* Fall through */
10534 case 5:
10535 DECR_AND_LOAD(22);
10536 /* Fall through */
10537 case 4:
10538 DECR_AND_LOAD(21);
10539 /* Fall through */
10540 case 3:
10541 DECR_AND_LOAD(20);
10542 /* Fall through */
10543 case 2:
10544 DECR_AND_LOAD(19);
10545 /* Fall through */
10546 case 1:
10547 DECR_AND_LOAD(18);
10550 if (do_s1) {
10551 DECR_AND_LOAD(17);
10553 if (do_s0) {
10554 DECR_AND_LOAD(16);
10557 switch (aregs) {
10558 case 0:
10559 case 4:
10560 case 8:
10561 case 12:
10562 case 14:
10563 astatic = 0;
10564 break;
10565 case 1:
10566 case 5:
10567 case 9:
10568 case 13:
10569 astatic = 1;
10570 break;
10571 case 2:
10572 case 6:
10573 case 10:
10574 astatic = 2;
10575 break;
10576 case 3:
10577 case 7:
10578 astatic = 3;
10579 break;
10580 case 11:
10581 astatic = 4;
10582 break;
10583 default:
10584 generate_exception(ctx, EXCP_RI);
10585 return;
10588 if (astatic > 0) {
10589 DECR_AND_LOAD(7);
10590 if (astatic > 1) {
10591 DECR_AND_LOAD(6);
10592 if (astatic > 2) {
10593 DECR_AND_LOAD(5);
10594 if (astatic > 3) {
10595 DECR_AND_LOAD(4);
10600 #undef DECR_AND_LOAD
10602 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
10603 tcg_temp_free(t0);
10604 tcg_temp_free(t1);
10607 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
10608 int is_64_bit, int extended)
10610 TCGv t0;
10612 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10613 generate_exception(ctx, EXCP_RI);
10614 return;
10617 t0 = tcg_temp_new();
10619 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
10620 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
10621 if (!is_64_bit) {
10622 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10625 tcg_temp_free(t0);
10628 #if defined(TARGET_MIPS64)
10629 static void decode_i64_mips16 (DisasContext *ctx,
10630 int ry, int funct, int16_t offset,
10631 int extended)
10633 switch (funct) {
10634 case I64_LDSP:
10635 check_mips_64(ctx);
10636 offset = extended ? offset : offset << 3;
10637 gen_ld(ctx, OPC_LD, ry, 29, offset);
10638 break;
10639 case I64_SDSP:
10640 check_mips_64(ctx);
10641 offset = extended ? offset : offset << 3;
10642 gen_st(ctx, OPC_SD, ry, 29, offset);
10643 break;
10644 case I64_SDRASP:
10645 check_mips_64(ctx);
10646 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
10647 gen_st(ctx, OPC_SD, 31, 29, offset);
10648 break;
10649 case I64_DADJSP:
10650 check_mips_64(ctx);
10651 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
10652 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
10653 break;
10654 case I64_LDPC:
10655 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
10656 generate_exception(ctx, EXCP_RI);
10657 } else {
10658 offset = extended ? offset : offset << 3;
10659 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
10661 break;
10662 case I64_DADDIU5:
10663 check_mips_64(ctx);
10664 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
10665 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
10666 break;
10667 case I64_DADDIUPC:
10668 check_mips_64(ctx);
10669 offset = extended ? offset : offset << 2;
10670 gen_addiupc(ctx, ry, offset, 1, extended);
10671 break;
10672 case I64_DADDIUSP:
10673 check_mips_64(ctx);
10674 offset = extended ? offset : offset << 2;
10675 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
10676 break;
10679 #endif
10681 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
10683 int extend = cpu_lduw_code(env, ctx->pc + 2);
10684 int op, rx, ry, funct, sa;
10685 int16_t imm, offset;
10687 ctx->opcode = (ctx->opcode << 16) | extend;
10688 op = (ctx->opcode >> 11) & 0x1f;
10689 sa = (ctx->opcode >> 22) & 0x1f;
10690 funct = (ctx->opcode >> 8) & 0x7;
10691 rx = xlat((ctx->opcode >> 8) & 0x7);
10692 ry = xlat((ctx->opcode >> 5) & 0x7);
10693 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
10694 | ((ctx->opcode >> 21) & 0x3f) << 5
10695 | (ctx->opcode & 0x1f));
10697 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
10698 counterparts. */
10699 switch (op) {
10700 case M16_OPC_ADDIUSP:
10701 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
10702 break;
10703 case M16_OPC_ADDIUPC:
10704 gen_addiupc(ctx, rx, imm, 0, 1);
10705 break;
10706 case M16_OPC_B:
10707 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1, 0);
10708 /* No delay slot, so just process as a normal instruction */
10709 break;
10710 case M16_OPC_BEQZ:
10711 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1, 0);
10712 /* No delay slot, so just process as a normal instruction */
10713 break;
10714 case M16_OPC_BNEQZ:
10715 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1, 0);
10716 /* No delay slot, so just process as a normal instruction */
10717 break;
10718 case M16_OPC_SHIFT:
10719 switch (ctx->opcode & 0x3) {
10720 case 0x0:
10721 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
10722 break;
10723 case 0x1:
10724 #if defined(TARGET_MIPS64)
10725 check_mips_64(ctx);
10726 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
10727 #else
10728 generate_exception(ctx, EXCP_RI);
10729 #endif
10730 break;
10731 case 0x2:
10732 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
10733 break;
10734 case 0x3:
10735 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
10736 break;
10738 break;
10739 #if defined(TARGET_MIPS64)
10740 case M16_OPC_LD:
10741 check_mips_64(ctx);
10742 gen_ld(ctx, OPC_LD, ry, rx, offset);
10743 break;
10744 #endif
10745 case M16_OPC_RRIA:
10746 imm = ctx->opcode & 0xf;
10747 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
10748 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
10749 imm = (int16_t) (imm << 1) >> 1;
10750 if ((ctx->opcode >> 4) & 0x1) {
10751 #if defined(TARGET_MIPS64)
10752 check_mips_64(ctx);
10753 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
10754 #else
10755 generate_exception(ctx, EXCP_RI);
10756 #endif
10757 } else {
10758 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
10760 break;
10761 case M16_OPC_ADDIU8:
10762 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
10763 break;
10764 case M16_OPC_SLTI:
10765 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
10766 break;
10767 case M16_OPC_SLTIU:
10768 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
10769 break;
10770 case M16_OPC_I8:
10771 switch (funct) {
10772 case I8_BTEQZ:
10773 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1, 0);
10774 break;
10775 case I8_BTNEZ:
10776 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1, 0);
10777 break;
10778 case I8_SWRASP:
10779 gen_st(ctx, OPC_SW, 31, 29, imm);
10780 break;
10781 case I8_ADJSP:
10782 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
10783 break;
10784 case I8_SVRS:
10786 int xsregs = (ctx->opcode >> 24) & 0x7;
10787 int aregs = (ctx->opcode >> 16) & 0xf;
10788 int do_ra = (ctx->opcode >> 6) & 0x1;
10789 int do_s0 = (ctx->opcode >> 5) & 0x1;
10790 int do_s1 = (ctx->opcode >> 4) & 0x1;
10791 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
10792 | (ctx->opcode & 0xf)) << 3;
10794 if (ctx->opcode & (1 << 7)) {
10795 gen_mips16_save(ctx, xsregs, aregs,
10796 do_ra, do_s0, do_s1,
10797 framesize);
10798 } else {
10799 gen_mips16_restore(ctx, xsregs, aregs,
10800 do_ra, do_s0, do_s1,
10801 framesize);
10804 break;
10805 default:
10806 generate_exception(ctx, EXCP_RI);
10807 break;
10809 break;
10810 case M16_OPC_LI:
10811 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
10812 break;
10813 case M16_OPC_CMPI:
10814 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
10815 break;
10816 #if defined(TARGET_MIPS64)
10817 case M16_OPC_SD:
10818 gen_st(ctx, OPC_SD, ry, rx, offset);
10819 break;
10820 #endif
10821 case M16_OPC_LB:
10822 gen_ld(ctx, OPC_LB, ry, rx, offset);
10823 break;
10824 case M16_OPC_LH:
10825 gen_ld(ctx, OPC_LH, ry, rx, offset);
10826 break;
10827 case M16_OPC_LWSP:
10828 gen_ld(ctx, OPC_LW, rx, 29, offset);
10829 break;
10830 case M16_OPC_LW:
10831 gen_ld(ctx, OPC_LW, ry, rx, offset);
10832 break;
10833 case M16_OPC_LBU:
10834 gen_ld(ctx, OPC_LBU, ry, rx, offset);
10835 break;
10836 case M16_OPC_LHU:
10837 gen_ld(ctx, OPC_LHU, ry, rx, offset);
10838 break;
10839 case M16_OPC_LWPC:
10840 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
10841 break;
10842 #if defined(TARGET_MIPS64)
10843 case M16_OPC_LWU:
10844 gen_ld(ctx, OPC_LWU, ry, rx, offset);
10845 break;
10846 #endif
10847 case M16_OPC_SB:
10848 gen_st(ctx, OPC_SB, ry, rx, offset);
10849 break;
10850 case M16_OPC_SH:
10851 gen_st(ctx, OPC_SH, ry, rx, offset);
10852 break;
10853 case M16_OPC_SWSP:
10854 gen_st(ctx, OPC_SW, rx, 29, offset);
10855 break;
10856 case M16_OPC_SW:
10857 gen_st(ctx, OPC_SW, ry, rx, offset);
10858 break;
10859 #if defined(TARGET_MIPS64)
10860 case M16_OPC_I64:
10861 decode_i64_mips16(ctx, ry, funct, offset, 1);
10862 break;
10863 #endif
10864 default:
10865 generate_exception(ctx, EXCP_RI);
10866 break;
10869 return 4;
10872 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
10874 int rx, ry;
10875 int sa;
10876 int op, cnvt_op, op1, offset;
10877 int funct;
10878 int n_bytes;
10880 op = (ctx->opcode >> 11) & 0x1f;
10881 sa = (ctx->opcode >> 2) & 0x7;
10882 sa = sa == 0 ? 8 : sa;
10883 rx = xlat((ctx->opcode >> 8) & 0x7);
10884 cnvt_op = (ctx->opcode >> 5) & 0x7;
10885 ry = xlat((ctx->opcode >> 5) & 0x7);
10886 op1 = offset = ctx->opcode & 0x1f;
10888 n_bytes = 2;
10890 switch (op) {
10891 case M16_OPC_ADDIUSP:
10893 int16_t imm = ((uint8_t) ctx->opcode) << 2;
10895 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
10897 break;
10898 case M16_OPC_ADDIUPC:
10899 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
10900 break;
10901 case M16_OPC_B:
10902 offset = (ctx->opcode & 0x7ff) << 1;
10903 offset = (int16_t)(offset << 4) >> 4;
10904 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset, 0);
10905 /* No delay slot, so just process as a normal instruction */
10906 break;
10907 case M16_OPC_JAL:
10908 offset = cpu_lduw_code(env, ctx->pc + 2);
10909 offset = (((ctx->opcode & 0x1f) << 21)
10910 | ((ctx->opcode >> 5) & 0x1f) << 16
10911 | offset) << 2;
10912 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
10913 gen_compute_branch(ctx, op, 4, rx, ry, offset, 2);
10914 n_bytes = 4;
10915 break;
10916 case M16_OPC_BEQZ:
10917 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0,
10918 ((int8_t)ctx->opcode) << 1, 0);
10919 /* No delay slot, so just process as a normal instruction */
10920 break;
10921 case M16_OPC_BNEQZ:
10922 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0,
10923 ((int8_t)ctx->opcode) << 1, 0);
10924 /* No delay slot, so just process as a normal instruction */
10925 break;
10926 case M16_OPC_SHIFT:
10927 switch (ctx->opcode & 0x3) {
10928 case 0x0:
10929 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
10930 break;
10931 case 0x1:
10932 #if defined(TARGET_MIPS64)
10933 check_mips_64(ctx);
10934 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
10935 #else
10936 generate_exception(ctx, EXCP_RI);
10937 #endif
10938 break;
10939 case 0x2:
10940 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
10941 break;
10942 case 0x3:
10943 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
10944 break;
10946 break;
10947 #if defined(TARGET_MIPS64)
10948 case M16_OPC_LD:
10949 check_mips_64(ctx);
10950 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
10951 break;
10952 #endif
10953 case M16_OPC_RRIA:
10955 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
10957 if ((ctx->opcode >> 4) & 1) {
10958 #if defined(TARGET_MIPS64)
10959 check_mips_64(ctx);
10960 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
10961 #else
10962 generate_exception(ctx, EXCP_RI);
10963 #endif
10964 } else {
10965 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
10968 break;
10969 case M16_OPC_ADDIU8:
10971 int16_t imm = (int8_t) ctx->opcode;
10973 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
10975 break;
10976 case M16_OPC_SLTI:
10978 int16_t imm = (uint8_t) ctx->opcode;
10979 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
10981 break;
10982 case M16_OPC_SLTIU:
10984 int16_t imm = (uint8_t) ctx->opcode;
10985 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
10987 break;
10988 case M16_OPC_I8:
10990 int reg32;
10992 funct = (ctx->opcode >> 8) & 0x7;
10993 switch (funct) {
10994 case I8_BTEQZ:
10995 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
10996 ((int8_t)ctx->opcode) << 1, 0);
10997 break;
10998 case I8_BTNEZ:
10999 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
11000 ((int8_t)ctx->opcode) << 1, 0);
11001 break;
11002 case I8_SWRASP:
11003 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
11004 break;
11005 case I8_ADJSP:
11006 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
11007 ((int8_t)ctx->opcode) << 3);
11008 break;
11009 case I8_SVRS:
11011 int do_ra = ctx->opcode & (1 << 6);
11012 int do_s0 = ctx->opcode & (1 << 5);
11013 int do_s1 = ctx->opcode & (1 << 4);
11014 int framesize = ctx->opcode & 0xf;
11016 if (framesize == 0) {
11017 framesize = 128;
11018 } else {
11019 framesize = framesize << 3;
11022 if (ctx->opcode & (1 << 7)) {
11023 gen_mips16_save(ctx, 0, 0,
11024 do_ra, do_s0, do_s1, framesize);
11025 } else {
11026 gen_mips16_restore(ctx, 0, 0,
11027 do_ra, do_s0, do_s1, framesize);
11030 break;
11031 case I8_MOV32R:
11033 int rz = xlat(ctx->opcode & 0x7);
11035 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
11036 ((ctx->opcode >> 5) & 0x7);
11037 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
11039 break;
11040 case I8_MOVR32:
11041 reg32 = ctx->opcode & 0x1f;
11042 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
11043 break;
11044 default:
11045 generate_exception(ctx, EXCP_RI);
11046 break;
11049 break;
11050 case M16_OPC_LI:
11052 int16_t imm = (uint8_t) ctx->opcode;
11054 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
11056 break;
11057 case M16_OPC_CMPI:
11059 int16_t imm = (uint8_t) ctx->opcode;
11060 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
11062 break;
11063 #if defined(TARGET_MIPS64)
11064 case M16_OPC_SD:
11065 check_mips_64(ctx);
11066 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
11067 break;
11068 #endif
11069 case M16_OPC_LB:
11070 gen_ld(ctx, OPC_LB, ry, rx, offset);
11071 break;
11072 case M16_OPC_LH:
11073 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
11074 break;
11075 case M16_OPC_LWSP:
11076 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11077 break;
11078 case M16_OPC_LW:
11079 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
11080 break;
11081 case M16_OPC_LBU:
11082 gen_ld(ctx, OPC_LBU, ry, rx, offset);
11083 break;
11084 case M16_OPC_LHU:
11085 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
11086 break;
11087 case M16_OPC_LWPC:
11088 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
11089 break;
11090 #if defined (TARGET_MIPS64)
11091 case M16_OPC_LWU:
11092 check_mips_64(ctx);
11093 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
11094 break;
11095 #endif
11096 case M16_OPC_SB:
11097 gen_st(ctx, OPC_SB, ry, rx, offset);
11098 break;
11099 case M16_OPC_SH:
11100 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
11101 break;
11102 case M16_OPC_SWSP:
11103 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
11104 break;
11105 case M16_OPC_SW:
11106 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
11107 break;
11108 case M16_OPC_RRR:
11110 int rz = xlat((ctx->opcode >> 2) & 0x7);
11111 int mips32_op;
11113 switch (ctx->opcode & 0x3) {
11114 case RRR_ADDU:
11115 mips32_op = OPC_ADDU;
11116 break;
11117 case RRR_SUBU:
11118 mips32_op = OPC_SUBU;
11119 break;
11120 #if defined(TARGET_MIPS64)
11121 case RRR_DADDU:
11122 mips32_op = OPC_DADDU;
11123 check_mips_64(ctx);
11124 break;
11125 case RRR_DSUBU:
11126 mips32_op = OPC_DSUBU;
11127 check_mips_64(ctx);
11128 break;
11129 #endif
11130 default:
11131 generate_exception(ctx, EXCP_RI);
11132 goto done;
11135 gen_arith(ctx, mips32_op, rz, rx, ry);
11136 done:
11139 break;
11140 case M16_OPC_RR:
11141 switch (op1) {
11142 case RR_JR:
11144 int nd = (ctx->opcode >> 7) & 0x1;
11145 int link = (ctx->opcode >> 6) & 0x1;
11146 int ra = (ctx->opcode >> 5) & 0x1;
11148 if (link) {
11149 op = OPC_JALR;
11150 } else {
11151 op = OPC_JR;
11154 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0,
11155 (nd ? 0 : 2));
11157 break;
11158 case RR_SDBBP:
11159 /* XXX: not clear which exception should be raised
11160 * when in debug mode...
11162 check_insn(ctx, ISA_MIPS32);
11163 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11164 generate_exception(ctx, EXCP_DBp);
11165 } else {
11166 generate_exception(ctx, EXCP_DBp);
11168 break;
11169 case RR_SLT:
11170 gen_slt(ctx, OPC_SLT, 24, rx, ry);
11171 break;
11172 case RR_SLTU:
11173 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
11174 break;
11175 case RR_BREAK:
11176 generate_exception(ctx, EXCP_BREAK);
11177 break;
11178 case RR_SLLV:
11179 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
11180 break;
11181 case RR_SRLV:
11182 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
11183 break;
11184 case RR_SRAV:
11185 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
11186 break;
11187 #if defined (TARGET_MIPS64)
11188 case RR_DSRL:
11189 check_mips_64(ctx);
11190 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
11191 break;
11192 #endif
11193 case RR_CMP:
11194 gen_logic(ctx, OPC_XOR, 24, rx, ry);
11195 break;
11196 case RR_NEG:
11197 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
11198 break;
11199 case RR_AND:
11200 gen_logic(ctx, OPC_AND, rx, rx, ry);
11201 break;
11202 case RR_OR:
11203 gen_logic(ctx, OPC_OR, rx, rx, ry);
11204 break;
11205 case RR_XOR:
11206 gen_logic(ctx, OPC_XOR, rx, rx, ry);
11207 break;
11208 case RR_NOT:
11209 gen_logic(ctx, OPC_NOR, rx, ry, 0);
11210 break;
11211 case RR_MFHI:
11212 gen_HILO(ctx, OPC_MFHI, 0, rx);
11213 break;
11214 case RR_CNVT:
11215 switch (cnvt_op) {
11216 case RR_RY_CNVT_ZEB:
11217 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11218 break;
11219 case RR_RY_CNVT_ZEH:
11220 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11221 break;
11222 case RR_RY_CNVT_SEB:
11223 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11224 break;
11225 case RR_RY_CNVT_SEH:
11226 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11227 break;
11228 #if defined (TARGET_MIPS64)
11229 case RR_RY_CNVT_ZEW:
11230 check_mips_64(ctx);
11231 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
11232 break;
11233 case RR_RY_CNVT_SEW:
11234 check_mips_64(ctx);
11235 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
11236 break;
11237 #endif
11238 default:
11239 generate_exception(ctx, EXCP_RI);
11240 break;
11242 break;
11243 case RR_MFLO:
11244 gen_HILO(ctx, OPC_MFLO, 0, rx);
11245 break;
11246 #if defined (TARGET_MIPS64)
11247 case RR_DSRA:
11248 check_mips_64(ctx);
11249 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
11250 break;
11251 case RR_DSLLV:
11252 check_mips_64(ctx);
11253 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
11254 break;
11255 case RR_DSRLV:
11256 check_mips_64(ctx);
11257 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
11258 break;
11259 case RR_DSRAV:
11260 check_mips_64(ctx);
11261 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
11262 break;
11263 #endif
11264 case RR_MULT:
11265 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
11266 break;
11267 case RR_MULTU:
11268 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
11269 break;
11270 case RR_DIV:
11271 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
11272 break;
11273 case RR_DIVU:
11274 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
11275 break;
11276 #if defined (TARGET_MIPS64)
11277 case RR_DMULT:
11278 check_mips_64(ctx);
11279 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
11280 break;
11281 case RR_DMULTU:
11282 check_mips_64(ctx);
11283 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
11284 break;
11285 case RR_DDIV:
11286 check_mips_64(ctx);
11287 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
11288 break;
11289 case RR_DDIVU:
11290 check_mips_64(ctx);
11291 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
11292 break;
11293 #endif
11294 default:
11295 generate_exception(ctx, EXCP_RI);
11296 break;
11298 break;
11299 case M16_OPC_EXTEND:
11300 decode_extended_mips16_opc(env, ctx);
11301 n_bytes = 4;
11302 break;
11303 #if defined(TARGET_MIPS64)
11304 case M16_OPC_I64:
11305 funct = (ctx->opcode >> 8) & 0x7;
11306 decode_i64_mips16(ctx, ry, funct, offset, 0);
11307 break;
11308 #endif
11309 default:
11310 generate_exception(ctx, EXCP_RI);
11311 break;
11314 return n_bytes;
11317 /* microMIPS extension to MIPS32/MIPS64 */
11320 * microMIPS32/microMIPS64 major opcodes
11322 * 1. MIPS Architecture for Programmers Volume II-B:
11323 * The microMIPS32 Instruction Set (Revision 3.05)
11325 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
11327 * 2. MIPS Architecture For Programmers Volume II-A:
11328 * The MIPS64 Instruction Set (Revision 3.51)
11331 enum {
11332 POOL32A = 0x00,
11333 POOL16A = 0x01,
11334 LBU16 = 0x02,
11335 MOVE16 = 0x03,
11336 ADDI32 = 0x04,
11337 LBU32 = 0x05,
11338 SB32 = 0x06,
11339 LB32 = 0x07,
11341 POOL32B = 0x08,
11342 POOL16B = 0x09,
11343 LHU16 = 0x0a,
11344 ANDI16 = 0x0b,
11345 ADDIU32 = 0x0c,
11346 LHU32 = 0x0d,
11347 SH32 = 0x0e,
11348 LH32 = 0x0f,
11350 POOL32I = 0x10,
11351 POOL16C = 0x11,
11352 LWSP16 = 0x12,
11353 POOL16D = 0x13,
11354 ORI32 = 0x14,
11355 POOL32F = 0x15,
11356 POOL32S = 0x16, /* MIPS64 */
11357 DADDIU32 = 0x17, /* MIPS64 */
11359 /* 0x1f is reserved */
11360 POOL32C = 0x18,
11361 LWGP16 = 0x19,
11362 LW16 = 0x1a,
11363 POOL16E = 0x1b,
11364 XORI32 = 0x1c,
11365 JALS32 = 0x1d,
11366 ADDIUPC = 0x1e,
11368 /* 0x20 is reserved */
11369 RES_20 = 0x20,
11370 POOL16F = 0x21,
11371 SB16 = 0x22,
11372 BEQZ16 = 0x23,
11373 SLTI32 = 0x24,
11374 BEQ32 = 0x25,
11375 SWC132 = 0x26,
11376 LWC132 = 0x27,
11378 /* 0x28 and 0x29 are reserved */
11379 RES_28 = 0x28,
11380 RES_29 = 0x29,
11381 SH16 = 0x2a,
11382 BNEZ16 = 0x2b,
11383 SLTIU32 = 0x2c,
11384 BNE32 = 0x2d,
11385 SDC132 = 0x2e,
11386 LDC132 = 0x2f,
11388 /* 0x30 and 0x31 are reserved */
11389 RES_30 = 0x30,
11390 RES_31 = 0x31,
11391 SWSP16 = 0x32,
11392 B16 = 0x33,
11393 ANDI32 = 0x34,
11394 J32 = 0x35,
11395 SD32 = 0x36, /* MIPS64 */
11396 LD32 = 0x37, /* MIPS64 */
11398 /* 0x38 and 0x39 are reserved */
11399 RES_38 = 0x38,
11400 RES_39 = 0x39,
11401 SW16 = 0x3a,
11402 LI16 = 0x3b,
11403 JALX32 = 0x3c,
11404 JAL32 = 0x3d,
11405 SW32 = 0x3e,
11406 LW32 = 0x3f
11409 /* POOL32A encoding of minor opcode field */
11411 enum {
11412 /* These opcodes are distinguished only by bits 9..6; those bits are
11413 * what are recorded below. */
11414 SLL32 = 0x0,
11415 SRL32 = 0x1,
11416 SRA = 0x2,
11417 ROTR = 0x3,
11419 SLLV = 0x0,
11420 SRLV = 0x1,
11421 SRAV = 0x2,
11422 ROTRV = 0x3,
11423 ADD = 0x4,
11424 ADDU32 = 0x5,
11425 SUB = 0x6,
11426 SUBU32 = 0x7,
11427 MUL = 0x8,
11428 AND = 0x9,
11429 OR32 = 0xa,
11430 NOR = 0xb,
11431 XOR32 = 0xc,
11432 SLT = 0xd,
11433 SLTU = 0xe,
11435 MOVN = 0x0,
11436 MOVZ = 0x1,
11437 LWXS = 0x4,
11439 /* The following can be distinguished by their lower 6 bits. */
11440 INS = 0x0c,
11441 EXT = 0x2c,
11442 POOL32AXF = 0x3c
11445 /* POOL32AXF encoding of minor opcode field extension */
11448 * 1. MIPS Architecture for Programmers Volume II-B:
11449 * The microMIPS32 Instruction Set (Revision 3.05)
11451 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
11453 * 2. MIPS Architecture for Programmers VolumeIV-e:
11454 * The MIPS DSP Application-Specific Extension
11455 * to the microMIPS32 Architecture (Revision 2.34)
11457 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
11460 enum {
11461 /* bits 11..6 */
11462 TEQ = 0x00,
11463 TGE = 0x08,
11464 TGEU = 0x10,
11465 TLT = 0x20,
11466 TLTU = 0x28,
11467 TNE = 0x30,
11469 MFC0 = 0x03,
11470 MTC0 = 0x0b,
11472 /* begin of microMIPS32 DSP */
11474 /* bits 13..12 for 0x01 */
11475 MFHI_ACC = 0x0,
11476 MFLO_ACC = 0x1,
11477 MTHI_ACC = 0x2,
11478 MTLO_ACC = 0x3,
11480 /* bits 13..12 for 0x2a */
11481 MADD_ACC = 0x0,
11482 MADDU_ACC = 0x1,
11483 MSUB_ACC = 0x2,
11484 MSUBU_ACC = 0x3,
11486 /* bits 13..12 for 0x32 */
11487 MULT_ACC = 0x0,
11488 MULTU_ACC = 0x1,
11490 /* end of microMIPS32 DSP */
11492 /* bits 15..12 for 0x2c */
11493 SEB = 0x2,
11494 SEH = 0x3,
11495 CLO = 0x4,
11496 CLZ = 0x5,
11497 RDHWR = 0x6,
11498 WSBH = 0x7,
11499 MULT = 0x8,
11500 MULTU = 0x9,
11501 DIV = 0xa,
11502 DIVU = 0xb,
11503 MADD = 0xc,
11504 MADDU = 0xd,
11505 MSUB = 0xe,
11506 MSUBU = 0xf,
11508 /* bits 15..12 for 0x34 */
11509 MFC2 = 0x4,
11510 MTC2 = 0x5,
11511 MFHC2 = 0x8,
11512 MTHC2 = 0x9,
11513 CFC2 = 0xc,
11514 CTC2 = 0xd,
11516 /* bits 15..12 for 0x3c */
11517 JALR = 0x0,
11518 JR = 0x0, /* alias */
11519 JALR_HB = 0x1,
11520 JALRS = 0x4,
11521 JALRS_HB = 0x5,
11523 /* bits 15..12 for 0x05 */
11524 RDPGPR = 0xe,
11525 WRPGPR = 0xf,
11527 /* bits 15..12 for 0x0d */
11528 TLBP = 0x0,
11529 TLBR = 0x1,
11530 TLBWI = 0x2,
11531 TLBWR = 0x3,
11532 WAIT = 0x9,
11533 IRET = 0xd,
11534 DERET = 0xe,
11535 ERET = 0xf,
11537 /* bits 15..12 for 0x15 */
11538 DMT = 0x0,
11539 DVPE = 0x1,
11540 EMT = 0x2,
11541 EVPE = 0x3,
11543 /* bits 15..12 for 0x1d */
11544 DI = 0x4,
11545 EI = 0x5,
11547 /* bits 15..12 for 0x2d */
11548 SYNC = 0x6,
11549 SYSCALL = 0x8,
11550 SDBBP = 0xd,
11552 /* bits 15..12 for 0x35 */
11553 MFHI32 = 0x0,
11554 MFLO32 = 0x1,
11555 MTHI32 = 0x2,
11556 MTLO32 = 0x3,
11559 /* POOL32B encoding of minor opcode field (bits 15..12) */
11561 enum {
11562 LWC2 = 0x0,
11563 LWP = 0x1,
11564 LDP = 0x4,
11565 LWM32 = 0x5,
11566 CACHE = 0x6,
11567 LDM = 0x7,
11568 SWC2 = 0x8,
11569 SWP = 0x9,
11570 SDP = 0xc,
11571 SWM32 = 0xd,
11572 SDM = 0xf
11575 /* POOL32C encoding of minor opcode field (bits 15..12) */
11577 enum {
11578 LWL = 0x0,
11579 SWL = 0x8,
11580 LWR = 0x1,
11581 SWR = 0x9,
11582 PREF = 0x2,
11583 /* 0xa is reserved */
11584 LL = 0x3,
11585 SC = 0xb,
11586 LDL = 0x4,
11587 SDL = 0xc,
11588 LDR = 0x5,
11589 SDR = 0xd,
11590 /* 0x6 is reserved */
11591 LWU = 0xe,
11592 LLD = 0x7,
11593 SCD = 0xf
11596 /* POOL32F encoding of minor opcode field (bits 5..0) */
11598 enum {
11599 /* These are the bit 7..6 values */
11600 ADD_FMT = 0x0,
11601 MOVN_FMT = 0x0,
11603 SUB_FMT = 0x1,
11604 MOVZ_FMT = 0x1,
11606 MUL_FMT = 0x2,
11608 DIV_FMT = 0x3,
11610 /* These are the bit 8..6 values */
11611 RSQRT2_FMT = 0x0,
11612 MOVF_FMT = 0x0,
11614 LWXC1 = 0x1,
11615 MOVT_FMT = 0x1,
11617 PLL_PS = 0x2,
11618 SWXC1 = 0x2,
11620 PLU_PS = 0x3,
11621 LDXC1 = 0x3,
11623 PUL_PS = 0x4,
11624 SDXC1 = 0x4,
11625 RECIP2_FMT = 0x4,
11627 PUU_PS = 0x5,
11628 LUXC1 = 0x5,
11630 CVT_PS_S = 0x6,
11631 SUXC1 = 0x6,
11632 ADDR_PS = 0x6,
11633 PREFX = 0x6,
11635 MULR_PS = 0x7,
11637 MADD_S = 0x01,
11638 MADD_D = 0x09,
11639 MADD_PS = 0x11,
11640 ALNV_PS = 0x19,
11641 MSUB_S = 0x21,
11642 MSUB_D = 0x29,
11643 MSUB_PS = 0x31,
11645 NMADD_S = 0x02,
11646 NMADD_D = 0x0a,
11647 NMADD_PS = 0x12,
11648 NMSUB_S = 0x22,
11649 NMSUB_D = 0x2a,
11650 NMSUB_PS = 0x32,
11652 POOL32FXF = 0x3b,
11654 CABS_COND_FMT = 0x1c, /* MIPS3D */
11655 C_COND_FMT = 0x3c
11658 /* POOL32Fxf encoding of minor opcode extension field */
11660 enum {
11661 CVT_L = 0x04,
11662 RSQRT_FMT = 0x08,
11663 FLOOR_L = 0x0c,
11664 CVT_PW_PS = 0x1c,
11665 CVT_W = 0x24,
11666 SQRT_FMT = 0x28,
11667 FLOOR_W = 0x2c,
11668 CVT_PS_PW = 0x3c,
11669 CFC1 = 0x40,
11670 RECIP_FMT = 0x48,
11671 CEIL_L = 0x4c,
11672 CTC1 = 0x60,
11673 CEIL_W = 0x6c,
11674 MFC1 = 0x80,
11675 CVT_S_PL = 0x84,
11676 TRUNC_L = 0x8c,
11677 MTC1 = 0xa0,
11678 CVT_S_PU = 0xa4,
11679 TRUNC_W = 0xac,
11680 MFHC1 = 0xc0,
11681 ROUND_L = 0xcc,
11682 MTHC1 = 0xe0,
11683 ROUND_W = 0xec,
11685 MOV_FMT = 0x01,
11686 MOVF = 0x05,
11687 ABS_FMT = 0x0d,
11688 RSQRT1_FMT = 0x1d,
11689 MOVT = 0x25,
11690 NEG_FMT = 0x2d,
11691 CVT_D = 0x4d,
11692 RECIP1_FMT = 0x5d,
11693 CVT_S = 0x6d
11696 /* POOL32I encoding of minor opcode field (bits 25..21) */
11698 enum {
11699 BLTZ = 0x00,
11700 BLTZAL = 0x01,
11701 BGEZ = 0x02,
11702 BGEZAL = 0x03,
11703 BLEZ = 0x04,
11704 BNEZC = 0x05,
11705 BGTZ = 0x06,
11706 BEQZC = 0x07,
11707 TLTI = 0x08,
11708 TGEI = 0x09,
11709 TLTIU = 0x0a,
11710 TGEIU = 0x0b,
11711 TNEI = 0x0c,
11712 LUI = 0x0d,
11713 TEQI = 0x0e,
11714 SYNCI = 0x10,
11715 BLTZALS = 0x11,
11716 BGEZALS = 0x13,
11717 BC2F = 0x14,
11718 BC2T = 0x15,
11719 BPOSGE64 = 0x1a,
11720 BPOSGE32 = 0x1b,
11721 /* These overlap and are distinguished by bit16 of the instruction */
11722 BC1F = 0x1c,
11723 BC1T = 0x1d,
11724 BC1ANY2F = 0x1c,
11725 BC1ANY2T = 0x1d,
11726 BC1ANY4F = 0x1e,
11727 BC1ANY4T = 0x1f
11730 /* POOL16A encoding of minor opcode field */
11732 enum {
11733 ADDU16 = 0x0,
11734 SUBU16 = 0x1
11737 /* POOL16B encoding of minor opcode field */
11739 enum {
11740 SLL16 = 0x0,
11741 SRL16 = 0x1
11744 /* POOL16C encoding of minor opcode field */
11746 enum {
11747 NOT16 = 0x00,
11748 XOR16 = 0x04,
11749 AND16 = 0x08,
11750 OR16 = 0x0c,
11751 LWM16 = 0x10,
11752 SWM16 = 0x14,
11753 JR16 = 0x18,
11754 JRC16 = 0x1a,
11755 JALR16 = 0x1c,
11756 JALR16S = 0x1e,
11757 MFHI16 = 0x20,
11758 MFLO16 = 0x24,
11759 BREAK16 = 0x28,
11760 SDBBP16 = 0x2c,
11761 JRADDIUSP = 0x30
11764 /* POOL16D encoding of minor opcode field */
11766 enum {
11767 ADDIUS5 = 0x0,
11768 ADDIUSP = 0x1
11771 /* POOL16E encoding of minor opcode field */
11773 enum {
11774 ADDIUR2 = 0x0,
11775 ADDIUR1SP = 0x1
11778 static int mmreg (int r)
11780 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
11782 return map[r];
11785 /* Used for 16-bit store instructions. */
11786 static int mmreg2 (int r)
11788 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
11790 return map[r];
11793 #define uMIPS_RD(op) ((op >> 7) & 0x7)
11794 #define uMIPS_RS(op) ((op >> 4) & 0x7)
11795 #define uMIPS_RS2(op) uMIPS_RS(op)
11796 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
11797 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
11798 #define uMIPS_RS5(op) (op & 0x1f)
11800 /* Signed immediate */
11801 #define SIMM(op, start, width) \
11802 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
11803 << (32-width)) \
11804 >> (32-width))
11805 /* Zero-extended immediate */
11806 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
11808 static void gen_addiur1sp(DisasContext *ctx)
11810 int rd = mmreg(uMIPS_RD(ctx->opcode));
11812 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
11815 static void gen_addiur2(DisasContext *ctx)
11817 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
11818 int rd = mmreg(uMIPS_RD(ctx->opcode));
11819 int rs = mmreg(uMIPS_RS(ctx->opcode));
11821 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
11824 static void gen_addiusp(DisasContext *ctx)
11826 int encoded = ZIMM(ctx->opcode, 1, 9);
11827 int decoded;
11829 if (encoded <= 1) {
11830 decoded = 256 + encoded;
11831 } else if (encoded <= 255) {
11832 decoded = encoded;
11833 } else if (encoded <= 509) {
11834 decoded = encoded - 512;
11835 } else {
11836 decoded = encoded - 768;
11839 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
11842 static void gen_addius5(DisasContext *ctx)
11844 int imm = SIMM(ctx->opcode, 1, 4);
11845 int rd = (ctx->opcode >> 5) & 0x1f;
11847 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
11850 static void gen_andi16(DisasContext *ctx)
11852 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
11853 31, 32, 63, 64, 255, 32768, 65535 };
11854 int rd = mmreg(uMIPS_RD(ctx->opcode));
11855 int rs = mmreg(uMIPS_RS(ctx->opcode));
11856 int encoded = ZIMM(ctx->opcode, 0, 4);
11858 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
11861 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
11862 int base, int16_t offset)
11864 const char *opn = "ldst_multiple";
11865 TCGv t0, t1;
11866 TCGv_i32 t2;
11868 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11869 generate_exception(ctx, EXCP_RI);
11870 return;
11873 t0 = tcg_temp_new();
11875 gen_base_offset_addr(ctx, t0, base, offset);
11877 t1 = tcg_const_tl(reglist);
11878 t2 = tcg_const_i32(ctx->mem_idx);
11880 save_cpu_state(ctx, 1);
11881 switch (opc) {
11882 case LWM32:
11883 gen_helper_lwm(cpu_env, t0, t1, t2);
11884 opn = "lwm";
11885 break;
11886 case SWM32:
11887 gen_helper_swm(cpu_env, t0, t1, t2);
11888 opn = "swm";
11889 break;
11890 #ifdef TARGET_MIPS64
11891 case LDM:
11892 gen_helper_ldm(cpu_env, t0, t1, t2);
11893 opn = "ldm";
11894 break;
11895 case SDM:
11896 gen_helper_sdm(cpu_env, t0, t1, t2);
11897 opn = "sdm";
11898 break;
11899 #endif
11901 (void)opn;
11902 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
11903 tcg_temp_free(t0);
11904 tcg_temp_free(t1);
11905 tcg_temp_free_i32(t2);
11909 static void gen_pool16c_insn(DisasContext *ctx)
11911 int rd = mmreg((ctx->opcode >> 3) & 0x7);
11912 int rs = mmreg(ctx->opcode & 0x7);
11914 switch (((ctx->opcode) >> 4) & 0x3f) {
11915 case NOT16 + 0:
11916 case NOT16 + 1:
11917 case NOT16 + 2:
11918 case NOT16 + 3:
11919 gen_logic(ctx, OPC_NOR, rd, rs, 0);
11920 break;
11921 case XOR16 + 0:
11922 case XOR16 + 1:
11923 case XOR16 + 2:
11924 case XOR16 + 3:
11925 gen_logic(ctx, OPC_XOR, rd, rd, rs);
11926 break;
11927 case AND16 + 0:
11928 case AND16 + 1:
11929 case AND16 + 2:
11930 case AND16 + 3:
11931 gen_logic(ctx, OPC_AND, rd, rd, rs);
11932 break;
11933 case OR16 + 0:
11934 case OR16 + 1:
11935 case OR16 + 2:
11936 case OR16 + 3:
11937 gen_logic(ctx, OPC_OR, rd, rd, rs);
11938 break;
11939 case LWM16 + 0:
11940 case LWM16 + 1:
11941 case LWM16 + 2:
11942 case LWM16 + 3:
11944 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
11945 int offset = ZIMM(ctx->opcode, 0, 4);
11947 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
11948 29, offset << 2);
11950 break;
11951 case SWM16 + 0:
11952 case SWM16 + 1:
11953 case SWM16 + 2:
11954 case SWM16 + 3:
11956 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
11957 int offset = ZIMM(ctx->opcode, 0, 4);
11959 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
11960 29, offset << 2);
11962 break;
11963 case JR16 + 0:
11964 case JR16 + 1:
11966 int reg = ctx->opcode & 0x1f;
11968 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 4);
11970 break;
11971 case JRC16 + 0:
11972 case JRC16 + 1:
11974 int reg = ctx->opcode & 0x1f;
11975 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0, 0);
11976 /* Let normal delay slot handling in our caller take us
11977 to the branch target. */
11979 break;
11980 case JALR16 + 0:
11981 case JALR16 + 1:
11982 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 4);
11983 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
11984 break;
11985 case JALR16S + 0:
11986 case JALR16S + 1:
11987 gen_compute_branch(ctx, OPC_JALR, 2, ctx->opcode & 0x1f, 31, 0, 2);
11988 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
11989 break;
11990 case MFHI16 + 0:
11991 case MFHI16 + 1:
11992 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
11993 break;
11994 case MFLO16 + 0:
11995 case MFLO16 + 1:
11996 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
11997 break;
11998 case BREAK16:
11999 generate_exception(ctx, EXCP_BREAK);
12000 break;
12001 case SDBBP16:
12002 /* XXX: not clear which exception should be raised
12003 * when in debug mode...
12005 check_insn(ctx, ISA_MIPS32);
12006 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12007 generate_exception(ctx, EXCP_DBp);
12008 } else {
12009 generate_exception(ctx, EXCP_DBp);
12011 break;
12012 case JRADDIUSP + 0:
12013 case JRADDIUSP + 1:
12015 int imm = ZIMM(ctx->opcode, 0, 5);
12016 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0, 0);
12017 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
12018 /* Let normal delay slot handling in our caller take us
12019 to the branch target. */
12021 break;
12022 default:
12023 generate_exception(ctx, EXCP_RI);
12024 break;
12028 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
12030 TCGv t0 = tcg_temp_new();
12031 TCGv t1 = tcg_temp_new();
12033 gen_load_gpr(t0, base);
12035 if (index != 0) {
12036 gen_load_gpr(t1, index);
12037 tcg_gen_shli_tl(t1, t1, 2);
12038 gen_op_addr_add(ctx, t0, t1, t0);
12041 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12042 gen_store_gpr(t1, rd);
12044 tcg_temp_free(t0);
12045 tcg_temp_free(t1);
12048 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
12049 int base, int16_t offset)
12051 const char *opn = "ldst_pair";
12052 TCGv t0, t1;
12054 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
12055 generate_exception(ctx, EXCP_RI);
12056 return;
12059 t0 = tcg_temp_new();
12060 t1 = tcg_temp_new();
12062 gen_base_offset_addr(ctx, t0, base, offset);
12064 switch (opc) {
12065 case LWP:
12066 if (rd == base) {
12067 generate_exception(ctx, EXCP_RI);
12068 return;
12070 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12071 gen_store_gpr(t1, rd);
12072 tcg_gen_movi_tl(t1, 4);
12073 gen_op_addr_add(ctx, t0, t0, t1);
12074 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
12075 gen_store_gpr(t1, rd+1);
12076 opn = "lwp";
12077 break;
12078 case SWP:
12079 gen_load_gpr(t1, rd);
12080 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12081 tcg_gen_movi_tl(t1, 4);
12082 gen_op_addr_add(ctx, t0, t0, t1);
12083 gen_load_gpr(t1, rd+1);
12084 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
12085 opn = "swp";
12086 break;
12087 #ifdef TARGET_MIPS64
12088 case LDP:
12089 if (rd == base) {
12090 generate_exception(ctx, EXCP_RI);
12091 return;
12093 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12094 gen_store_gpr(t1, rd);
12095 tcg_gen_movi_tl(t1, 8);
12096 gen_op_addr_add(ctx, t0, t0, t1);
12097 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12098 gen_store_gpr(t1, rd+1);
12099 opn = "ldp";
12100 break;
12101 case SDP:
12102 gen_load_gpr(t1, rd);
12103 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12104 tcg_gen_movi_tl(t1, 8);
12105 gen_op_addr_add(ctx, t0, t0, t1);
12106 gen_load_gpr(t1, rd+1);
12107 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
12108 opn = "sdp";
12109 break;
12110 #endif
12112 (void)opn; /* avoid a compiler warning */
12113 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
12114 tcg_temp_free(t0);
12115 tcg_temp_free(t1);
12118 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
12120 int extension = (ctx->opcode >> 6) & 0x3f;
12121 int minor = (ctx->opcode >> 12) & 0xf;
12122 uint32_t mips32_op;
12124 switch (extension) {
12125 case TEQ:
12126 mips32_op = OPC_TEQ;
12127 goto do_trap;
12128 case TGE:
12129 mips32_op = OPC_TGE;
12130 goto do_trap;
12131 case TGEU:
12132 mips32_op = OPC_TGEU;
12133 goto do_trap;
12134 case TLT:
12135 mips32_op = OPC_TLT;
12136 goto do_trap;
12137 case TLTU:
12138 mips32_op = OPC_TLTU;
12139 goto do_trap;
12140 case TNE:
12141 mips32_op = OPC_TNE;
12142 do_trap:
12143 gen_trap(ctx, mips32_op, rs, rt, -1);
12144 break;
12145 #ifndef CONFIG_USER_ONLY
12146 case MFC0:
12147 case MFC0 + 32:
12148 check_cp0_enabled(ctx);
12149 if (rt == 0) {
12150 /* Treat as NOP. */
12151 break;
12153 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
12154 break;
12155 case MTC0:
12156 case MTC0 + 32:
12157 check_cp0_enabled(ctx);
12159 TCGv t0 = tcg_temp_new();
12161 gen_load_gpr(t0, rt);
12162 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
12163 tcg_temp_free(t0);
12165 break;
12166 #endif
12167 case 0x2a:
12168 switch (minor & 3) {
12169 case MADD_ACC:
12170 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
12171 break;
12172 case MADDU_ACC:
12173 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
12174 break;
12175 case MSUB_ACC:
12176 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
12177 break;
12178 case MSUBU_ACC:
12179 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
12180 break;
12181 default:
12182 goto pool32axf_invalid;
12184 break;
12185 case 0x32:
12186 switch (minor & 3) {
12187 case MULT_ACC:
12188 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
12189 break;
12190 case MULTU_ACC:
12191 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
12192 break;
12193 default:
12194 goto pool32axf_invalid;
12196 break;
12197 case 0x2c:
12198 switch (minor) {
12199 case SEB:
12200 gen_bshfl(ctx, OPC_SEB, rs, rt);
12201 break;
12202 case SEH:
12203 gen_bshfl(ctx, OPC_SEH, rs, rt);
12204 break;
12205 case CLO:
12206 mips32_op = OPC_CLO;
12207 goto do_cl;
12208 case CLZ:
12209 mips32_op = OPC_CLZ;
12210 do_cl:
12211 check_insn(ctx, ISA_MIPS32);
12212 gen_cl(ctx, mips32_op, rt, rs);
12213 break;
12214 case RDHWR:
12215 gen_rdhwr(ctx, rt, rs);
12216 break;
12217 case WSBH:
12218 gen_bshfl(ctx, OPC_WSBH, rs, rt);
12219 break;
12220 case MULT:
12221 mips32_op = OPC_MULT;
12222 goto do_mul;
12223 case MULTU:
12224 mips32_op = OPC_MULTU;
12225 goto do_mul;
12226 case DIV:
12227 mips32_op = OPC_DIV;
12228 goto do_div;
12229 case DIVU:
12230 mips32_op = OPC_DIVU;
12231 goto do_div;
12232 do_div:
12233 check_insn(ctx, ISA_MIPS32);
12234 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12235 break;
12236 case MADD:
12237 mips32_op = OPC_MADD;
12238 goto do_mul;
12239 case MADDU:
12240 mips32_op = OPC_MADDU;
12241 goto do_mul;
12242 case MSUB:
12243 mips32_op = OPC_MSUB;
12244 goto do_mul;
12245 case MSUBU:
12246 mips32_op = OPC_MSUBU;
12247 do_mul:
12248 check_insn(ctx, ISA_MIPS32);
12249 gen_muldiv(ctx, mips32_op, 0, rs, rt);
12250 break;
12251 default:
12252 goto pool32axf_invalid;
12254 break;
12255 case 0x34:
12256 switch (minor) {
12257 case MFC2:
12258 case MTC2:
12259 case MFHC2:
12260 case MTHC2:
12261 case CFC2:
12262 case CTC2:
12263 generate_exception_err(ctx, EXCP_CpU, 2);
12264 break;
12265 default:
12266 goto pool32axf_invalid;
12268 break;
12269 case 0x3c:
12270 switch (minor) {
12271 case JALR:
12272 case JALR_HB:
12273 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 4);
12274 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12275 break;
12276 case JALRS:
12277 case JALRS_HB:
12278 gen_compute_branch(ctx, OPC_JALR, 4, rs, rt, 0, 2);
12279 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
12280 break;
12281 default:
12282 goto pool32axf_invalid;
12284 break;
12285 case 0x05:
12286 switch (minor) {
12287 case RDPGPR:
12288 check_cp0_enabled(ctx);
12289 check_insn(ctx, ISA_MIPS32R2);
12290 gen_load_srsgpr(rt, rs);
12291 break;
12292 case WRPGPR:
12293 check_cp0_enabled(ctx);
12294 check_insn(ctx, ISA_MIPS32R2);
12295 gen_store_srsgpr(rt, rs);
12296 break;
12297 default:
12298 goto pool32axf_invalid;
12300 break;
12301 #ifndef CONFIG_USER_ONLY
12302 case 0x0d:
12303 switch (minor) {
12304 case TLBP:
12305 mips32_op = OPC_TLBP;
12306 goto do_cp0;
12307 case TLBR:
12308 mips32_op = OPC_TLBR;
12309 goto do_cp0;
12310 case TLBWI:
12311 mips32_op = OPC_TLBWI;
12312 goto do_cp0;
12313 case TLBWR:
12314 mips32_op = OPC_TLBWR;
12315 goto do_cp0;
12316 case WAIT:
12317 mips32_op = OPC_WAIT;
12318 goto do_cp0;
12319 case DERET:
12320 mips32_op = OPC_DERET;
12321 goto do_cp0;
12322 case ERET:
12323 mips32_op = OPC_ERET;
12324 do_cp0:
12325 gen_cp0(env, ctx, mips32_op, rt, rs);
12326 break;
12327 default:
12328 goto pool32axf_invalid;
12330 break;
12331 case 0x1d:
12332 switch (minor) {
12333 case DI:
12334 check_cp0_enabled(ctx);
12336 TCGv t0 = tcg_temp_new();
12338 save_cpu_state(ctx, 1);
12339 gen_helper_di(t0, cpu_env);
12340 gen_store_gpr(t0, rs);
12341 /* Stop translation as we may have switched the execution mode */
12342 ctx->bstate = BS_STOP;
12343 tcg_temp_free(t0);
12345 break;
12346 case EI:
12347 check_cp0_enabled(ctx);
12349 TCGv t0 = tcg_temp_new();
12351 save_cpu_state(ctx, 1);
12352 gen_helper_ei(t0, cpu_env);
12353 gen_store_gpr(t0, rs);
12354 /* Stop translation as we may have switched the execution mode */
12355 ctx->bstate = BS_STOP;
12356 tcg_temp_free(t0);
12358 break;
12359 default:
12360 goto pool32axf_invalid;
12362 break;
12363 #endif
12364 case 0x2d:
12365 switch (minor) {
12366 case SYNC:
12367 /* NOP */
12368 break;
12369 case SYSCALL:
12370 generate_exception(ctx, EXCP_SYSCALL);
12371 ctx->bstate = BS_STOP;
12372 break;
12373 case SDBBP:
12374 check_insn(ctx, ISA_MIPS32);
12375 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
12376 generate_exception(ctx, EXCP_DBp);
12377 } else {
12378 generate_exception(ctx, EXCP_DBp);
12380 break;
12381 default:
12382 goto pool32axf_invalid;
12384 break;
12385 case 0x01:
12386 switch (minor & 3) {
12387 case MFHI_ACC:
12388 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
12389 break;
12390 case MFLO_ACC:
12391 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
12392 break;
12393 case MTHI_ACC:
12394 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
12395 break;
12396 case MTLO_ACC:
12397 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
12398 break;
12399 default:
12400 goto pool32axf_invalid;
12402 break;
12403 case 0x35:
12404 switch (minor) {
12405 case MFHI32:
12406 gen_HILO(ctx, OPC_MFHI, 0, rs);
12407 break;
12408 case MFLO32:
12409 gen_HILO(ctx, OPC_MFLO, 0, rs);
12410 break;
12411 case MTHI32:
12412 gen_HILO(ctx, OPC_MTHI, 0, rs);
12413 break;
12414 case MTLO32:
12415 gen_HILO(ctx, OPC_MTLO, 0, rs);
12416 break;
12417 default:
12418 goto pool32axf_invalid;
12420 break;
12421 default:
12422 pool32axf_invalid:
12423 MIPS_INVAL("pool32axf");
12424 generate_exception(ctx, EXCP_RI);
12425 break;
12429 /* Values for microMIPS fmt field. Variable-width, depending on which
12430 formats the instruction supports. */
12432 enum {
12433 FMT_SD_S = 0,
12434 FMT_SD_D = 1,
12436 FMT_SDPS_S = 0,
12437 FMT_SDPS_D = 1,
12438 FMT_SDPS_PS = 2,
12440 FMT_SWL_S = 0,
12441 FMT_SWL_W = 1,
12442 FMT_SWL_L = 2,
12444 FMT_DWL_D = 0,
12445 FMT_DWL_W = 1,
12446 FMT_DWL_L = 2
12449 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
12451 int extension = (ctx->opcode >> 6) & 0x3ff;
12452 uint32_t mips32_op;
12454 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
12455 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
12456 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
12458 switch (extension) {
12459 case FLOAT_1BIT_FMT(CFC1, 0):
12460 mips32_op = OPC_CFC1;
12461 goto do_cp1;
12462 case FLOAT_1BIT_FMT(CTC1, 0):
12463 mips32_op = OPC_CTC1;
12464 goto do_cp1;
12465 case FLOAT_1BIT_FMT(MFC1, 0):
12466 mips32_op = OPC_MFC1;
12467 goto do_cp1;
12468 case FLOAT_1BIT_FMT(MTC1, 0):
12469 mips32_op = OPC_MTC1;
12470 goto do_cp1;
12471 case FLOAT_1BIT_FMT(MFHC1, 0):
12472 mips32_op = OPC_MFHC1;
12473 goto do_cp1;
12474 case FLOAT_1BIT_FMT(MTHC1, 0):
12475 mips32_op = OPC_MTHC1;
12476 do_cp1:
12477 gen_cp1(ctx, mips32_op, rt, rs);
12478 break;
12480 /* Reciprocal square root */
12481 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
12482 mips32_op = OPC_RSQRT_S;
12483 goto do_unaryfp;
12484 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
12485 mips32_op = OPC_RSQRT_D;
12486 goto do_unaryfp;
12488 /* Square root */
12489 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
12490 mips32_op = OPC_SQRT_S;
12491 goto do_unaryfp;
12492 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
12493 mips32_op = OPC_SQRT_D;
12494 goto do_unaryfp;
12496 /* Reciprocal */
12497 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
12498 mips32_op = OPC_RECIP_S;
12499 goto do_unaryfp;
12500 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
12501 mips32_op = OPC_RECIP_D;
12502 goto do_unaryfp;
12504 /* Floor */
12505 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
12506 mips32_op = OPC_FLOOR_L_S;
12507 goto do_unaryfp;
12508 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
12509 mips32_op = OPC_FLOOR_L_D;
12510 goto do_unaryfp;
12511 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
12512 mips32_op = OPC_FLOOR_W_S;
12513 goto do_unaryfp;
12514 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
12515 mips32_op = OPC_FLOOR_W_D;
12516 goto do_unaryfp;
12518 /* Ceiling */
12519 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
12520 mips32_op = OPC_CEIL_L_S;
12521 goto do_unaryfp;
12522 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
12523 mips32_op = OPC_CEIL_L_D;
12524 goto do_unaryfp;
12525 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
12526 mips32_op = OPC_CEIL_W_S;
12527 goto do_unaryfp;
12528 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
12529 mips32_op = OPC_CEIL_W_D;
12530 goto do_unaryfp;
12532 /* Truncation */
12533 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
12534 mips32_op = OPC_TRUNC_L_S;
12535 goto do_unaryfp;
12536 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
12537 mips32_op = OPC_TRUNC_L_D;
12538 goto do_unaryfp;
12539 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
12540 mips32_op = OPC_TRUNC_W_S;
12541 goto do_unaryfp;
12542 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
12543 mips32_op = OPC_TRUNC_W_D;
12544 goto do_unaryfp;
12546 /* Round */
12547 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
12548 mips32_op = OPC_ROUND_L_S;
12549 goto do_unaryfp;
12550 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
12551 mips32_op = OPC_ROUND_L_D;
12552 goto do_unaryfp;
12553 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
12554 mips32_op = OPC_ROUND_W_S;
12555 goto do_unaryfp;
12556 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
12557 mips32_op = OPC_ROUND_W_D;
12558 goto do_unaryfp;
12560 /* Integer to floating-point conversion */
12561 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
12562 mips32_op = OPC_CVT_L_S;
12563 goto do_unaryfp;
12564 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
12565 mips32_op = OPC_CVT_L_D;
12566 goto do_unaryfp;
12567 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
12568 mips32_op = OPC_CVT_W_S;
12569 goto do_unaryfp;
12570 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
12571 mips32_op = OPC_CVT_W_D;
12572 goto do_unaryfp;
12574 /* Paired-foo conversions */
12575 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
12576 mips32_op = OPC_CVT_S_PL;
12577 goto do_unaryfp;
12578 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
12579 mips32_op = OPC_CVT_S_PU;
12580 goto do_unaryfp;
12581 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
12582 mips32_op = OPC_CVT_PW_PS;
12583 goto do_unaryfp;
12584 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
12585 mips32_op = OPC_CVT_PS_PW;
12586 goto do_unaryfp;
12588 /* Floating-point moves */
12589 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
12590 mips32_op = OPC_MOV_S;
12591 goto do_unaryfp;
12592 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
12593 mips32_op = OPC_MOV_D;
12594 goto do_unaryfp;
12595 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
12596 mips32_op = OPC_MOV_PS;
12597 goto do_unaryfp;
12599 /* Absolute value */
12600 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
12601 mips32_op = OPC_ABS_S;
12602 goto do_unaryfp;
12603 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
12604 mips32_op = OPC_ABS_D;
12605 goto do_unaryfp;
12606 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
12607 mips32_op = OPC_ABS_PS;
12608 goto do_unaryfp;
12610 /* Negation */
12611 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
12612 mips32_op = OPC_NEG_S;
12613 goto do_unaryfp;
12614 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
12615 mips32_op = OPC_NEG_D;
12616 goto do_unaryfp;
12617 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
12618 mips32_op = OPC_NEG_PS;
12619 goto do_unaryfp;
12621 /* Reciprocal square root step */
12622 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
12623 mips32_op = OPC_RSQRT1_S;
12624 goto do_unaryfp;
12625 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
12626 mips32_op = OPC_RSQRT1_D;
12627 goto do_unaryfp;
12628 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
12629 mips32_op = OPC_RSQRT1_PS;
12630 goto do_unaryfp;
12632 /* Reciprocal step */
12633 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
12634 mips32_op = OPC_RECIP1_S;
12635 goto do_unaryfp;
12636 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
12637 mips32_op = OPC_RECIP1_S;
12638 goto do_unaryfp;
12639 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
12640 mips32_op = OPC_RECIP1_PS;
12641 goto do_unaryfp;
12643 /* Conversions from double */
12644 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
12645 mips32_op = OPC_CVT_D_S;
12646 goto do_unaryfp;
12647 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
12648 mips32_op = OPC_CVT_D_W;
12649 goto do_unaryfp;
12650 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
12651 mips32_op = OPC_CVT_D_L;
12652 goto do_unaryfp;
12654 /* Conversions from single */
12655 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
12656 mips32_op = OPC_CVT_S_D;
12657 goto do_unaryfp;
12658 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
12659 mips32_op = OPC_CVT_S_W;
12660 goto do_unaryfp;
12661 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
12662 mips32_op = OPC_CVT_S_L;
12663 do_unaryfp:
12664 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
12665 break;
12667 /* Conditional moves on floating-point codes */
12668 case COND_FLOAT_MOV(MOVT, 0):
12669 case COND_FLOAT_MOV(MOVT, 1):
12670 case COND_FLOAT_MOV(MOVT, 2):
12671 case COND_FLOAT_MOV(MOVT, 3):
12672 case COND_FLOAT_MOV(MOVT, 4):
12673 case COND_FLOAT_MOV(MOVT, 5):
12674 case COND_FLOAT_MOV(MOVT, 6):
12675 case COND_FLOAT_MOV(MOVT, 7):
12676 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
12677 break;
12678 case COND_FLOAT_MOV(MOVF, 0):
12679 case COND_FLOAT_MOV(MOVF, 1):
12680 case COND_FLOAT_MOV(MOVF, 2):
12681 case COND_FLOAT_MOV(MOVF, 3):
12682 case COND_FLOAT_MOV(MOVF, 4):
12683 case COND_FLOAT_MOV(MOVF, 5):
12684 case COND_FLOAT_MOV(MOVF, 6):
12685 case COND_FLOAT_MOV(MOVF, 7):
12686 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
12687 break;
12688 default:
12689 MIPS_INVAL("pool32fxf");
12690 generate_exception(ctx, EXCP_RI);
12691 break;
12695 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
12696 uint16_t insn_hw1)
12698 int32_t offset;
12699 uint16_t insn;
12700 int rt, rs, rd, rr;
12701 int16_t imm;
12702 uint32_t op, minor, mips32_op;
12703 uint32_t cond, fmt, cc;
12705 insn = cpu_lduw_code(env, ctx->pc + 2);
12706 ctx->opcode = (ctx->opcode << 16) | insn;
12708 rt = (ctx->opcode >> 21) & 0x1f;
12709 rs = (ctx->opcode >> 16) & 0x1f;
12710 rd = (ctx->opcode >> 11) & 0x1f;
12711 rr = (ctx->opcode >> 6) & 0x1f;
12712 imm = (int16_t) ctx->opcode;
12714 op = (ctx->opcode >> 26) & 0x3f;
12715 switch (op) {
12716 case POOL32A:
12717 minor = ctx->opcode & 0x3f;
12718 switch (minor) {
12719 case 0x00:
12720 minor = (ctx->opcode >> 6) & 0xf;
12721 switch (minor) {
12722 case SLL32:
12723 mips32_op = OPC_SLL;
12724 goto do_shifti;
12725 case SRA:
12726 mips32_op = OPC_SRA;
12727 goto do_shifti;
12728 case SRL32:
12729 mips32_op = OPC_SRL;
12730 goto do_shifti;
12731 case ROTR:
12732 mips32_op = OPC_ROTR;
12733 do_shifti:
12734 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
12735 break;
12736 default:
12737 goto pool32a_invalid;
12739 break;
12740 case 0x10:
12741 minor = (ctx->opcode >> 6) & 0xf;
12742 switch (minor) {
12743 /* Arithmetic */
12744 case ADD:
12745 mips32_op = OPC_ADD;
12746 goto do_arith;
12747 case ADDU32:
12748 mips32_op = OPC_ADDU;
12749 goto do_arith;
12750 case SUB:
12751 mips32_op = OPC_SUB;
12752 goto do_arith;
12753 case SUBU32:
12754 mips32_op = OPC_SUBU;
12755 goto do_arith;
12756 case MUL:
12757 mips32_op = OPC_MUL;
12758 do_arith:
12759 gen_arith(ctx, mips32_op, rd, rs, rt);
12760 break;
12761 /* Shifts */
12762 case SLLV:
12763 mips32_op = OPC_SLLV;
12764 goto do_shift;
12765 case SRLV:
12766 mips32_op = OPC_SRLV;
12767 goto do_shift;
12768 case SRAV:
12769 mips32_op = OPC_SRAV;
12770 goto do_shift;
12771 case ROTRV:
12772 mips32_op = OPC_ROTRV;
12773 do_shift:
12774 gen_shift(ctx, mips32_op, rd, rs, rt);
12775 break;
12776 /* Logical operations */
12777 case AND:
12778 mips32_op = OPC_AND;
12779 goto do_logic;
12780 case OR32:
12781 mips32_op = OPC_OR;
12782 goto do_logic;
12783 case NOR:
12784 mips32_op = OPC_NOR;
12785 goto do_logic;
12786 case XOR32:
12787 mips32_op = OPC_XOR;
12788 do_logic:
12789 gen_logic(ctx, mips32_op, rd, rs, rt);
12790 break;
12791 /* Set less than */
12792 case SLT:
12793 mips32_op = OPC_SLT;
12794 goto do_slt;
12795 case SLTU:
12796 mips32_op = OPC_SLTU;
12797 do_slt:
12798 gen_slt(ctx, mips32_op, rd, rs, rt);
12799 break;
12800 default:
12801 goto pool32a_invalid;
12803 break;
12804 case 0x18:
12805 minor = (ctx->opcode >> 6) & 0xf;
12806 switch (minor) {
12807 /* Conditional moves */
12808 case MOVN:
12809 mips32_op = OPC_MOVN;
12810 goto do_cmov;
12811 case MOVZ:
12812 mips32_op = OPC_MOVZ;
12813 do_cmov:
12814 gen_cond_move(ctx, mips32_op, rd, rs, rt);
12815 break;
12816 case LWXS:
12817 gen_ldxs(ctx, rs, rt, rd);
12818 break;
12819 default:
12820 goto pool32a_invalid;
12822 break;
12823 case INS:
12824 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
12825 return;
12826 case EXT:
12827 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
12828 return;
12829 case POOL32AXF:
12830 gen_pool32axf(env, ctx, rt, rs);
12831 break;
12832 case 0x07:
12833 generate_exception(ctx, EXCP_BREAK);
12834 break;
12835 default:
12836 pool32a_invalid:
12837 MIPS_INVAL("pool32a");
12838 generate_exception(ctx, EXCP_RI);
12839 break;
12841 break;
12842 case POOL32B:
12843 minor = (ctx->opcode >> 12) & 0xf;
12844 switch (minor) {
12845 case CACHE:
12846 check_cp0_enabled(ctx);
12847 /* Treat as no-op. */
12848 break;
12849 case LWC2:
12850 case SWC2:
12851 /* COP2: Not implemented. */
12852 generate_exception_err(ctx, EXCP_CpU, 2);
12853 break;
12854 case LWP:
12855 case SWP:
12856 #ifdef TARGET_MIPS64
12857 case LDP:
12858 case SDP:
12859 #endif
12860 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
12861 break;
12862 case LWM32:
12863 case SWM32:
12864 #ifdef TARGET_MIPS64
12865 case LDM:
12866 case SDM:
12867 #endif
12868 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
12869 break;
12870 default:
12871 MIPS_INVAL("pool32b");
12872 generate_exception(ctx, EXCP_RI);
12873 break;
12875 break;
12876 case POOL32F:
12877 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
12878 minor = ctx->opcode & 0x3f;
12879 check_cp1_enabled(ctx);
12880 switch (minor) {
12881 case ALNV_PS:
12882 mips32_op = OPC_ALNV_PS;
12883 goto do_madd;
12884 case MADD_S:
12885 mips32_op = OPC_MADD_S;
12886 goto do_madd;
12887 case MADD_D:
12888 mips32_op = OPC_MADD_D;
12889 goto do_madd;
12890 case MADD_PS:
12891 mips32_op = OPC_MADD_PS;
12892 goto do_madd;
12893 case MSUB_S:
12894 mips32_op = OPC_MSUB_S;
12895 goto do_madd;
12896 case MSUB_D:
12897 mips32_op = OPC_MSUB_D;
12898 goto do_madd;
12899 case MSUB_PS:
12900 mips32_op = OPC_MSUB_PS;
12901 goto do_madd;
12902 case NMADD_S:
12903 mips32_op = OPC_NMADD_S;
12904 goto do_madd;
12905 case NMADD_D:
12906 mips32_op = OPC_NMADD_D;
12907 goto do_madd;
12908 case NMADD_PS:
12909 mips32_op = OPC_NMADD_PS;
12910 goto do_madd;
12911 case NMSUB_S:
12912 mips32_op = OPC_NMSUB_S;
12913 goto do_madd;
12914 case NMSUB_D:
12915 mips32_op = OPC_NMSUB_D;
12916 goto do_madd;
12917 case NMSUB_PS:
12918 mips32_op = OPC_NMSUB_PS;
12919 do_madd:
12920 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
12921 break;
12922 case CABS_COND_FMT:
12923 cond = (ctx->opcode >> 6) & 0xf;
12924 cc = (ctx->opcode >> 13) & 0x7;
12925 fmt = (ctx->opcode >> 10) & 0x3;
12926 switch (fmt) {
12927 case 0x0:
12928 gen_cmpabs_s(ctx, cond, rt, rs, cc);
12929 break;
12930 case 0x1:
12931 gen_cmpabs_d(ctx, cond, rt, rs, cc);
12932 break;
12933 case 0x2:
12934 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
12935 break;
12936 default:
12937 goto pool32f_invalid;
12939 break;
12940 case C_COND_FMT:
12941 cond = (ctx->opcode >> 6) & 0xf;
12942 cc = (ctx->opcode >> 13) & 0x7;
12943 fmt = (ctx->opcode >> 10) & 0x3;
12944 switch (fmt) {
12945 case 0x0:
12946 gen_cmp_s(ctx, cond, rt, rs, cc);
12947 break;
12948 case 0x1:
12949 gen_cmp_d(ctx, cond, rt, rs, cc);
12950 break;
12951 case 0x2:
12952 gen_cmp_ps(ctx, cond, rt, rs, cc);
12953 break;
12954 default:
12955 goto pool32f_invalid;
12957 break;
12958 case POOL32FXF:
12959 gen_pool32fxf(ctx, rt, rs);
12960 break;
12961 case 0x00:
12962 /* PLL foo */
12963 switch ((ctx->opcode >> 6) & 0x7) {
12964 case PLL_PS:
12965 mips32_op = OPC_PLL_PS;
12966 goto do_ps;
12967 case PLU_PS:
12968 mips32_op = OPC_PLU_PS;
12969 goto do_ps;
12970 case PUL_PS:
12971 mips32_op = OPC_PUL_PS;
12972 goto do_ps;
12973 case PUU_PS:
12974 mips32_op = OPC_PUU_PS;
12975 goto do_ps;
12976 case CVT_PS_S:
12977 mips32_op = OPC_CVT_PS_S;
12978 do_ps:
12979 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12980 break;
12981 default:
12982 goto pool32f_invalid;
12984 break;
12985 case 0x08:
12986 /* [LS][WDU]XC1 */
12987 switch ((ctx->opcode >> 6) & 0x7) {
12988 case LWXC1:
12989 mips32_op = OPC_LWXC1;
12990 goto do_ldst_cp1;
12991 case SWXC1:
12992 mips32_op = OPC_SWXC1;
12993 goto do_ldst_cp1;
12994 case LDXC1:
12995 mips32_op = OPC_LDXC1;
12996 goto do_ldst_cp1;
12997 case SDXC1:
12998 mips32_op = OPC_SDXC1;
12999 goto do_ldst_cp1;
13000 case LUXC1:
13001 mips32_op = OPC_LUXC1;
13002 goto do_ldst_cp1;
13003 case SUXC1:
13004 mips32_op = OPC_SUXC1;
13005 do_ldst_cp1:
13006 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
13007 break;
13008 default:
13009 goto pool32f_invalid;
13011 break;
13012 case 0x18:
13013 /* 3D insns */
13014 fmt = (ctx->opcode >> 9) & 0x3;
13015 switch ((ctx->opcode >> 6) & 0x7) {
13016 case RSQRT2_FMT:
13017 switch (fmt) {
13018 case FMT_SDPS_S:
13019 mips32_op = OPC_RSQRT2_S;
13020 goto do_3d;
13021 case FMT_SDPS_D:
13022 mips32_op = OPC_RSQRT2_D;
13023 goto do_3d;
13024 case FMT_SDPS_PS:
13025 mips32_op = OPC_RSQRT2_PS;
13026 goto do_3d;
13027 default:
13028 goto pool32f_invalid;
13030 break;
13031 case RECIP2_FMT:
13032 switch (fmt) {
13033 case FMT_SDPS_S:
13034 mips32_op = OPC_RECIP2_S;
13035 goto do_3d;
13036 case FMT_SDPS_D:
13037 mips32_op = OPC_RECIP2_D;
13038 goto do_3d;
13039 case FMT_SDPS_PS:
13040 mips32_op = OPC_RECIP2_PS;
13041 goto do_3d;
13042 default:
13043 goto pool32f_invalid;
13045 break;
13046 case ADDR_PS:
13047 mips32_op = OPC_ADDR_PS;
13048 goto do_3d;
13049 case MULR_PS:
13050 mips32_op = OPC_MULR_PS;
13051 do_3d:
13052 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13053 break;
13054 default:
13055 goto pool32f_invalid;
13057 break;
13058 case 0x20:
13059 /* MOV[FT].fmt and PREFX */
13060 cc = (ctx->opcode >> 13) & 0x7;
13061 fmt = (ctx->opcode >> 9) & 0x3;
13062 switch ((ctx->opcode >> 6) & 0x7) {
13063 case MOVF_FMT:
13064 switch (fmt) {
13065 case FMT_SDPS_S:
13066 gen_movcf_s(rs, rt, cc, 0);
13067 break;
13068 case FMT_SDPS_D:
13069 gen_movcf_d(ctx, rs, rt, cc, 0);
13070 break;
13071 case FMT_SDPS_PS:
13072 gen_movcf_ps(ctx, rs, rt, cc, 0);
13073 break;
13074 default:
13075 goto pool32f_invalid;
13077 break;
13078 case MOVT_FMT:
13079 switch (fmt) {
13080 case FMT_SDPS_S:
13081 gen_movcf_s(rs, rt, cc, 1);
13082 break;
13083 case FMT_SDPS_D:
13084 gen_movcf_d(ctx, rs, rt, cc, 1);
13085 break;
13086 case FMT_SDPS_PS:
13087 gen_movcf_ps(ctx, rs, rt, cc, 1);
13088 break;
13089 default:
13090 goto pool32f_invalid;
13092 break;
13093 case PREFX:
13094 break;
13095 default:
13096 goto pool32f_invalid;
13098 break;
13099 #define FINSN_3ARG_SDPS(prfx) \
13100 switch ((ctx->opcode >> 8) & 0x3) { \
13101 case FMT_SDPS_S: \
13102 mips32_op = OPC_##prfx##_S; \
13103 goto do_fpop; \
13104 case FMT_SDPS_D: \
13105 mips32_op = OPC_##prfx##_D; \
13106 goto do_fpop; \
13107 case FMT_SDPS_PS: \
13108 mips32_op = OPC_##prfx##_PS; \
13109 goto do_fpop; \
13110 default: \
13111 goto pool32f_invalid; \
13113 case 0x30:
13114 /* regular FP ops */
13115 switch ((ctx->opcode >> 6) & 0x3) {
13116 case ADD_FMT:
13117 FINSN_3ARG_SDPS(ADD);
13118 break;
13119 case SUB_FMT:
13120 FINSN_3ARG_SDPS(SUB);
13121 break;
13122 case MUL_FMT:
13123 FINSN_3ARG_SDPS(MUL);
13124 break;
13125 case DIV_FMT:
13126 fmt = (ctx->opcode >> 8) & 0x3;
13127 if (fmt == 1) {
13128 mips32_op = OPC_DIV_D;
13129 } else if (fmt == 0) {
13130 mips32_op = OPC_DIV_S;
13131 } else {
13132 goto pool32f_invalid;
13134 goto do_fpop;
13135 default:
13136 goto pool32f_invalid;
13138 break;
13139 case 0x38:
13140 /* cmovs */
13141 switch ((ctx->opcode >> 6) & 0x3) {
13142 case MOVN_FMT:
13143 FINSN_3ARG_SDPS(MOVN);
13144 break;
13145 case MOVZ_FMT:
13146 FINSN_3ARG_SDPS(MOVZ);
13147 break;
13148 default:
13149 goto pool32f_invalid;
13151 break;
13152 do_fpop:
13153 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
13154 break;
13155 default:
13156 pool32f_invalid:
13157 MIPS_INVAL("pool32f");
13158 generate_exception(ctx, EXCP_RI);
13159 break;
13161 } else {
13162 generate_exception_err(ctx, EXCP_CpU, 1);
13164 break;
13165 case POOL32I:
13166 minor = (ctx->opcode >> 21) & 0x1f;
13167 switch (minor) {
13168 case BLTZ:
13169 gen_compute_branch(ctx, OPC_BLTZ, 4, rs, -1, imm << 1, 4);
13170 break;
13171 case BLTZAL:
13172 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 4);
13173 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13174 break;
13175 case BLTZALS:
13176 gen_compute_branch(ctx, OPC_BLTZAL, 4, rs, -1, imm << 1, 2);
13177 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13178 break;
13179 case BGEZ:
13180 gen_compute_branch(ctx, OPC_BGEZ, 4, rs, -1, imm << 1, 4);
13181 break;
13182 case BGEZAL:
13183 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 4);
13184 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13185 break;
13186 case BGEZALS:
13187 gen_compute_branch(ctx, OPC_BGEZAL, 4, rs, -1, imm << 1, 2);
13188 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13189 break;
13190 case BLEZ:
13191 gen_compute_branch(ctx, OPC_BLEZ, 4, rs, -1, imm << 1, 4);
13192 break;
13193 case BGTZ:
13194 gen_compute_branch(ctx, OPC_BGTZ, 4, rs, -1, imm << 1, 4);
13195 break;
13197 /* Traps */
13198 case TLTI:
13199 mips32_op = OPC_TLTI;
13200 goto do_trapi;
13201 case TGEI:
13202 mips32_op = OPC_TGEI;
13203 goto do_trapi;
13204 case TLTIU:
13205 mips32_op = OPC_TLTIU;
13206 goto do_trapi;
13207 case TGEIU:
13208 mips32_op = OPC_TGEIU;
13209 goto do_trapi;
13210 case TNEI:
13211 mips32_op = OPC_TNEI;
13212 goto do_trapi;
13213 case TEQI:
13214 mips32_op = OPC_TEQI;
13215 do_trapi:
13216 gen_trap(ctx, mips32_op, rs, -1, imm);
13217 break;
13219 case BNEZC:
13220 case BEQZC:
13221 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
13222 4, rs, 0, imm << 1, 0);
13223 /* Compact branches don't have a delay slot, so just let
13224 the normal delay slot handling take us to the branch
13225 target. */
13226 break;
13227 case LUI:
13228 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
13229 break;
13230 case SYNCI:
13231 /* Break the TB to be able to sync copied instructions
13232 immediately */
13233 ctx->bstate = BS_STOP;
13234 break;
13235 case BC2F:
13236 case BC2T:
13237 /* COP2: Not implemented. */
13238 generate_exception_err(ctx, EXCP_CpU, 2);
13239 break;
13240 case BC1F:
13241 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
13242 goto do_cp1branch;
13243 case BC1T:
13244 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
13245 goto do_cp1branch;
13246 case BC1ANY4F:
13247 mips32_op = OPC_BC1FANY4;
13248 goto do_cp1mips3d;
13249 case BC1ANY4T:
13250 mips32_op = OPC_BC1TANY4;
13251 do_cp1mips3d:
13252 check_cop1x(ctx);
13253 check_insn(ctx, ASE_MIPS3D);
13254 /* Fall through */
13255 do_cp1branch:
13256 gen_compute_branch1(ctx, mips32_op,
13257 (ctx->opcode >> 18) & 0x7, imm << 1);
13258 break;
13259 case BPOSGE64:
13260 case BPOSGE32:
13261 /* MIPS DSP: not implemented */
13262 /* Fall through */
13263 default:
13264 MIPS_INVAL("pool32i");
13265 generate_exception(ctx, EXCP_RI);
13266 break;
13268 break;
13269 case POOL32C:
13270 minor = (ctx->opcode >> 12) & 0xf;
13271 switch (minor) {
13272 case LWL:
13273 mips32_op = OPC_LWL;
13274 goto do_ld_lr;
13275 case SWL:
13276 mips32_op = OPC_SWL;
13277 goto do_st_lr;
13278 case LWR:
13279 mips32_op = OPC_LWR;
13280 goto do_ld_lr;
13281 case SWR:
13282 mips32_op = OPC_SWR;
13283 goto do_st_lr;
13284 #if defined(TARGET_MIPS64)
13285 case LDL:
13286 mips32_op = OPC_LDL;
13287 goto do_ld_lr;
13288 case SDL:
13289 mips32_op = OPC_SDL;
13290 goto do_st_lr;
13291 case LDR:
13292 mips32_op = OPC_LDR;
13293 goto do_ld_lr;
13294 case SDR:
13295 mips32_op = OPC_SDR;
13296 goto do_st_lr;
13297 case LWU:
13298 mips32_op = OPC_LWU;
13299 goto do_ld_lr;
13300 case LLD:
13301 mips32_op = OPC_LLD;
13302 goto do_ld_lr;
13303 #endif
13304 case LL:
13305 mips32_op = OPC_LL;
13306 goto do_ld_lr;
13307 do_ld_lr:
13308 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13309 break;
13310 do_st_lr:
13311 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
13312 break;
13313 case SC:
13314 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
13315 break;
13316 #if defined(TARGET_MIPS64)
13317 case SCD:
13318 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
13319 break;
13320 #endif
13321 case PREF:
13322 /* Treat as no-op */
13323 break;
13324 default:
13325 MIPS_INVAL("pool32c");
13326 generate_exception(ctx, EXCP_RI);
13327 break;
13329 break;
13330 case ADDI32:
13331 mips32_op = OPC_ADDI;
13332 goto do_addi;
13333 case ADDIU32:
13334 mips32_op = OPC_ADDIU;
13335 do_addi:
13336 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
13337 break;
13339 /* Logical operations */
13340 case ORI32:
13341 mips32_op = OPC_ORI;
13342 goto do_logici;
13343 case XORI32:
13344 mips32_op = OPC_XORI;
13345 goto do_logici;
13346 case ANDI32:
13347 mips32_op = OPC_ANDI;
13348 do_logici:
13349 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
13350 break;
13352 /* Set less than immediate */
13353 case SLTI32:
13354 mips32_op = OPC_SLTI;
13355 goto do_slti;
13356 case SLTIU32:
13357 mips32_op = OPC_SLTIU;
13358 do_slti:
13359 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
13360 break;
13361 case JALX32:
13362 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
13363 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset, 4);
13364 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13365 break;
13366 case JALS32:
13367 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
13368 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs, offset, 2);
13369 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13370 break;
13371 case BEQ32:
13372 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1, 4);
13373 break;
13374 case BNE32:
13375 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1, 4);
13376 break;
13377 case J32:
13378 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
13379 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13380 break;
13381 case JAL32:
13382 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
13383 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1, 4);
13384 ctx->hflags |= MIPS_HFLAG_BDS_STRICT;
13385 break;
13386 /* Floating point (COP1) */
13387 case LWC132:
13388 mips32_op = OPC_LWC1;
13389 goto do_cop1;
13390 case LDC132:
13391 mips32_op = OPC_LDC1;
13392 goto do_cop1;
13393 case SWC132:
13394 mips32_op = OPC_SWC1;
13395 goto do_cop1;
13396 case SDC132:
13397 mips32_op = OPC_SDC1;
13398 do_cop1:
13399 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
13400 break;
13401 case ADDIUPC:
13403 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
13404 int offset = SIMM(ctx->opcode, 0, 23) << 2;
13406 gen_addiupc(ctx, reg, offset, 0, 0);
13408 break;
13409 /* Loads and stores */
13410 case LB32:
13411 mips32_op = OPC_LB;
13412 goto do_ld;
13413 case LBU32:
13414 mips32_op = OPC_LBU;
13415 goto do_ld;
13416 case LH32:
13417 mips32_op = OPC_LH;
13418 goto do_ld;
13419 case LHU32:
13420 mips32_op = OPC_LHU;
13421 goto do_ld;
13422 case LW32:
13423 mips32_op = OPC_LW;
13424 goto do_ld;
13425 #ifdef TARGET_MIPS64
13426 case LD32:
13427 mips32_op = OPC_LD;
13428 goto do_ld;
13429 case SD32:
13430 mips32_op = OPC_SD;
13431 goto do_st;
13432 #endif
13433 case SB32:
13434 mips32_op = OPC_SB;
13435 goto do_st;
13436 case SH32:
13437 mips32_op = OPC_SH;
13438 goto do_st;
13439 case SW32:
13440 mips32_op = OPC_SW;
13441 goto do_st;
13442 do_ld:
13443 gen_ld(ctx, mips32_op, rt, rs, imm);
13444 break;
13445 do_st:
13446 gen_st(ctx, mips32_op, rt, rs, imm);
13447 break;
13448 default:
13449 generate_exception(ctx, EXCP_RI);
13450 break;
13454 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
13456 uint32_t op;
13458 /* make sure instructions are on a halfword boundary */
13459 if (ctx->pc & 0x1) {
13460 env->CP0_BadVAddr = ctx->pc;
13461 generate_exception(ctx, EXCP_AdEL);
13462 ctx->bstate = BS_STOP;
13463 return 2;
13466 op = (ctx->opcode >> 10) & 0x3f;
13467 /* Enforce properly-sized instructions in a delay slot */
13468 if (ctx->hflags & MIPS_HFLAG_BDS_STRICT) {
13469 switch (op & 0x7) { /* MSB-3..MSB-5 */
13470 case 0:
13471 /* POOL32A, POOL32B, POOL32I, POOL32C */
13472 case 4:
13473 /* ADDI32, ADDIU32, ORI32, XORI32, SLTI32, SLTIU32, ANDI32, JALX32 */
13474 case 5:
13475 /* LBU32, LHU32, POOL32F, JALS32, BEQ32, BNE32, J32, JAL32 */
13476 case 6:
13477 /* SB32, SH32, ADDIUPC, SWC132, SDC132, SW32 */
13478 case 7:
13479 /* LB32, LH32, LWC132, LDC132, LW32 */
13480 if (ctx->hflags & MIPS_HFLAG_BDS16) {
13481 generate_exception(ctx, EXCP_RI);
13482 /* Just stop translation; the user is confused. */
13483 ctx->bstate = BS_STOP;
13484 return 2;
13486 break;
13487 case 1:
13488 /* POOL16A, POOL16B, POOL16C, LWGP16, POOL16F */
13489 case 2:
13490 /* LBU16, LHU16, LWSP16, LW16, SB16, SH16, SWSP16, SW16 */
13491 case 3:
13492 /* MOVE16, ANDI16, POOL16D, POOL16E, BEQZ16, BNEZ16, B16, LI16 */
13493 if (ctx->hflags & MIPS_HFLAG_BDS32) {
13494 generate_exception(ctx, EXCP_RI);
13495 /* Just stop translation; the user is confused. */
13496 ctx->bstate = BS_STOP;
13497 return 2;
13499 break;
13503 switch (op) {
13504 case POOL16A:
13506 int rd = mmreg(uMIPS_RD(ctx->opcode));
13507 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
13508 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
13509 uint32_t opc = 0;
13511 switch (ctx->opcode & 0x1) {
13512 case ADDU16:
13513 opc = OPC_ADDU;
13514 break;
13515 case SUBU16:
13516 opc = OPC_SUBU;
13517 break;
13520 gen_arith(ctx, opc, rd, rs1, rs2);
13522 break;
13523 case POOL16B:
13525 int rd = mmreg(uMIPS_RD(ctx->opcode));
13526 int rs = mmreg(uMIPS_RS(ctx->opcode));
13527 int amount = (ctx->opcode >> 1) & 0x7;
13528 uint32_t opc = 0;
13529 amount = amount == 0 ? 8 : amount;
13531 switch (ctx->opcode & 0x1) {
13532 case SLL16:
13533 opc = OPC_SLL;
13534 break;
13535 case SRL16:
13536 opc = OPC_SRL;
13537 break;
13540 gen_shift_imm(ctx, opc, rd, rs, amount);
13542 break;
13543 case POOL16C:
13544 gen_pool16c_insn(ctx);
13545 break;
13546 case LWGP16:
13548 int rd = mmreg(uMIPS_RD(ctx->opcode));
13549 int rb = 28; /* GP */
13550 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
13552 gen_ld(ctx, OPC_LW, rd, rb, offset);
13554 break;
13555 case POOL16F:
13556 if (ctx->opcode & 1) {
13557 generate_exception(ctx, EXCP_RI);
13558 } else {
13559 /* MOVEP */
13560 int enc_dest = uMIPS_RD(ctx->opcode);
13561 int enc_rt = uMIPS_RS2(ctx->opcode);
13562 int enc_rs = uMIPS_RS1(ctx->opcode);
13563 int rd, rs, re, rt;
13564 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
13565 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
13566 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
13568 rd = rd_enc[enc_dest];
13569 re = re_enc[enc_dest];
13570 rs = rs_rt_enc[enc_rs];
13571 rt = rs_rt_enc[enc_rt];
13573 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
13574 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
13576 break;
13577 case LBU16:
13579 int rd = mmreg(uMIPS_RD(ctx->opcode));
13580 int rb = mmreg(uMIPS_RS(ctx->opcode));
13581 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13582 offset = (offset == 0xf ? -1 : offset);
13584 gen_ld(ctx, OPC_LBU, rd, rb, offset);
13586 break;
13587 case LHU16:
13589 int rd = mmreg(uMIPS_RD(ctx->opcode));
13590 int rb = mmreg(uMIPS_RS(ctx->opcode));
13591 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13593 gen_ld(ctx, OPC_LHU, rd, rb, offset);
13595 break;
13596 case LWSP16:
13598 int rd = (ctx->opcode >> 5) & 0x1f;
13599 int rb = 29; /* SP */
13600 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
13602 gen_ld(ctx, OPC_LW, rd, rb, offset);
13604 break;
13605 case LW16:
13607 int rd = mmreg(uMIPS_RD(ctx->opcode));
13608 int rb = mmreg(uMIPS_RS(ctx->opcode));
13609 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
13611 gen_ld(ctx, OPC_LW, rd, rb, offset);
13613 break;
13614 case SB16:
13616 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13617 int rb = mmreg(uMIPS_RS(ctx->opcode));
13618 int16_t offset = ZIMM(ctx->opcode, 0, 4);
13620 gen_st(ctx, OPC_SB, rd, rb, offset);
13622 break;
13623 case SH16:
13625 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13626 int rb = mmreg(uMIPS_RS(ctx->opcode));
13627 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
13629 gen_st(ctx, OPC_SH, rd, rb, offset);
13631 break;
13632 case SWSP16:
13634 int rd = (ctx->opcode >> 5) & 0x1f;
13635 int rb = 29; /* SP */
13636 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
13638 gen_st(ctx, OPC_SW, rd, rb, offset);
13640 break;
13641 case SW16:
13643 int rd = mmreg2(uMIPS_RD(ctx->opcode));
13644 int rb = mmreg(uMIPS_RS(ctx->opcode));
13645 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
13647 gen_st(ctx, OPC_SW, rd, rb, offset);
13649 break;
13650 case MOVE16:
13652 int rd = uMIPS_RD5(ctx->opcode);
13653 int rs = uMIPS_RS5(ctx->opcode);
13655 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
13657 break;
13658 case ANDI16:
13659 gen_andi16(ctx);
13660 break;
13661 case POOL16D:
13662 switch (ctx->opcode & 0x1) {
13663 case ADDIUS5:
13664 gen_addius5(ctx);
13665 break;
13666 case ADDIUSP:
13667 gen_addiusp(ctx);
13668 break;
13670 break;
13671 case POOL16E:
13672 switch (ctx->opcode & 0x1) {
13673 case ADDIUR2:
13674 gen_addiur2(ctx);
13675 break;
13676 case ADDIUR1SP:
13677 gen_addiur1sp(ctx);
13678 break;
13680 break;
13681 case B16:
13682 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
13683 SIMM(ctx->opcode, 0, 10) << 1, 4);
13684 break;
13685 case BNEZ16:
13686 case BEQZ16:
13687 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
13688 mmreg(uMIPS_RD(ctx->opcode)),
13689 0, SIMM(ctx->opcode, 0, 7) << 1, 4);
13690 break;
13691 case LI16:
13693 int reg = mmreg(uMIPS_RD(ctx->opcode));
13694 int imm = ZIMM(ctx->opcode, 0, 7);
13696 imm = (imm == 0x7f ? -1 : imm);
13697 tcg_gen_movi_tl(cpu_gpr[reg], imm);
13699 break;
13700 case RES_20:
13701 case RES_28:
13702 case RES_29:
13703 case RES_30:
13704 case RES_31:
13705 case RES_38:
13706 case RES_39:
13707 generate_exception(ctx, EXCP_RI);
13708 break;
13709 default:
13710 decode_micromips32_opc (env, ctx, op);
13711 return 4;
13714 return 2;
13717 /* SmartMIPS extension to MIPS32 */
13719 #if defined(TARGET_MIPS64)
13721 /* MDMX extension to MIPS64 */
13723 #endif
13725 /* MIPSDSP functions. */
13726 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
13727 int rd, int base, int offset)
13729 const char *opn = "ldx";
13730 TCGv t0;
13732 check_dsp(ctx);
13733 t0 = tcg_temp_new();
13735 if (base == 0) {
13736 gen_load_gpr(t0, offset);
13737 } else if (offset == 0) {
13738 gen_load_gpr(t0, base);
13739 } else {
13740 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
13743 switch (opc) {
13744 case OPC_LBUX:
13745 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
13746 gen_store_gpr(t0, rd);
13747 opn = "lbux";
13748 break;
13749 case OPC_LHX:
13750 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
13751 gen_store_gpr(t0, rd);
13752 opn = "lhx";
13753 break;
13754 case OPC_LWX:
13755 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
13756 gen_store_gpr(t0, rd);
13757 opn = "lwx";
13758 break;
13759 #if defined(TARGET_MIPS64)
13760 case OPC_LDX:
13761 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
13762 gen_store_gpr(t0, rd);
13763 opn = "ldx";
13764 break;
13765 #endif
13767 (void)opn; /* avoid a compiler warning */
13768 MIPS_DEBUG("%s %s, %s(%s)", opn,
13769 regnames[rd], regnames[offset], regnames[base]);
13770 tcg_temp_free(t0);
13773 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
13774 int ret, int v1, int v2)
13776 const char *opn = "mipsdsp arith";
13777 TCGv v1_t;
13778 TCGv v2_t;
13780 if (ret == 0) {
13781 /* Treat as NOP. */
13782 MIPS_DEBUG("NOP");
13783 return;
13786 v1_t = tcg_temp_new();
13787 v2_t = tcg_temp_new();
13789 gen_load_gpr(v1_t, v1);
13790 gen_load_gpr(v2_t, v2);
13792 switch (op1) {
13793 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
13794 case OPC_MULT_G_2E:
13795 check_dspr2(ctx);
13796 switch (op2) {
13797 case OPC_ADDUH_QB:
13798 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
13799 break;
13800 case OPC_ADDUH_R_QB:
13801 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
13802 break;
13803 case OPC_ADDQH_PH:
13804 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
13805 break;
13806 case OPC_ADDQH_R_PH:
13807 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
13808 break;
13809 case OPC_ADDQH_W:
13810 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
13811 break;
13812 case OPC_ADDQH_R_W:
13813 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
13814 break;
13815 case OPC_SUBUH_QB:
13816 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
13817 break;
13818 case OPC_SUBUH_R_QB:
13819 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
13820 break;
13821 case OPC_SUBQH_PH:
13822 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
13823 break;
13824 case OPC_SUBQH_R_PH:
13825 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
13826 break;
13827 case OPC_SUBQH_W:
13828 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
13829 break;
13830 case OPC_SUBQH_R_W:
13831 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
13832 break;
13834 break;
13835 case OPC_ABSQ_S_PH_DSP:
13836 switch (op2) {
13837 case OPC_ABSQ_S_QB:
13838 check_dspr2(ctx);
13839 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
13840 break;
13841 case OPC_ABSQ_S_PH:
13842 check_dsp(ctx);
13843 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
13844 break;
13845 case OPC_ABSQ_S_W:
13846 check_dsp(ctx);
13847 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
13848 break;
13849 case OPC_PRECEQ_W_PHL:
13850 check_dsp(ctx);
13851 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
13852 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13853 break;
13854 case OPC_PRECEQ_W_PHR:
13855 check_dsp(ctx);
13856 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
13857 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
13858 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13859 break;
13860 case OPC_PRECEQU_PH_QBL:
13861 check_dsp(ctx);
13862 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
13863 break;
13864 case OPC_PRECEQU_PH_QBR:
13865 check_dsp(ctx);
13866 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
13867 break;
13868 case OPC_PRECEQU_PH_QBLA:
13869 check_dsp(ctx);
13870 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
13871 break;
13872 case OPC_PRECEQU_PH_QBRA:
13873 check_dsp(ctx);
13874 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
13875 break;
13876 case OPC_PRECEU_PH_QBL:
13877 check_dsp(ctx);
13878 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
13879 break;
13880 case OPC_PRECEU_PH_QBR:
13881 check_dsp(ctx);
13882 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
13883 break;
13884 case OPC_PRECEU_PH_QBLA:
13885 check_dsp(ctx);
13886 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
13887 break;
13888 case OPC_PRECEU_PH_QBRA:
13889 check_dsp(ctx);
13890 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
13891 break;
13893 break;
13894 case OPC_ADDU_QB_DSP:
13895 switch (op2) {
13896 case OPC_ADDQ_PH:
13897 check_dsp(ctx);
13898 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13899 break;
13900 case OPC_ADDQ_S_PH:
13901 check_dsp(ctx);
13902 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13903 break;
13904 case OPC_ADDQ_S_W:
13905 check_dsp(ctx);
13906 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13907 break;
13908 case OPC_ADDU_QB:
13909 check_dsp(ctx);
13910 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13911 break;
13912 case OPC_ADDU_S_QB:
13913 check_dsp(ctx);
13914 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13915 break;
13916 case OPC_ADDU_PH:
13917 check_dspr2(ctx);
13918 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13919 break;
13920 case OPC_ADDU_S_PH:
13921 check_dspr2(ctx);
13922 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13923 break;
13924 case OPC_SUBQ_PH:
13925 check_dsp(ctx);
13926 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13927 break;
13928 case OPC_SUBQ_S_PH:
13929 check_dsp(ctx);
13930 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13931 break;
13932 case OPC_SUBQ_S_W:
13933 check_dsp(ctx);
13934 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13935 break;
13936 case OPC_SUBU_QB:
13937 check_dsp(ctx);
13938 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13939 break;
13940 case OPC_SUBU_S_QB:
13941 check_dsp(ctx);
13942 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13943 break;
13944 case OPC_SUBU_PH:
13945 check_dspr2(ctx);
13946 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13947 break;
13948 case OPC_SUBU_S_PH:
13949 check_dspr2(ctx);
13950 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13951 break;
13952 case OPC_ADDSC:
13953 check_dsp(ctx);
13954 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13955 break;
13956 case OPC_ADDWC:
13957 check_dsp(ctx);
13958 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13959 break;
13960 case OPC_MODSUB:
13961 check_dsp(ctx);
13962 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
13963 break;
13964 case OPC_RADDU_W_QB:
13965 check_dsp(ctx);
13966 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
13967 break;
13969 break;
13970 case OPC_CMPU_EQ_QB_DSP:
13971 switch (op2) {
13972 case OPC_PRECR_QB_PH:
13973 check_dspr2(ctx);
13974 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
13975 break;
13976 case OPC_PRECRQ_QB_PH:
13977 check_dsp(ctx);
13978 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
13979 break;
13980 case OPC_PRECR_SRA_PH_W:
13981 check_dspr2(ctx);
13983 TCGv_i32 sa_t = tcg_const_i32(v2);
13984 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
13985 cpu_gpr[ret]);
13986 tcg_temp_free_i32(sa_t);
13987 break;
13989 case OPC_PRECR_SRA_R_PH_W:
13990 check_dspr2(ctx);
13992 TCGv_i32 sa_t = tcg_const_i32(v2);
13993 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
13994 cpu_gpr[ret]);
13995 tcg_temp_free_i32(sa_t);
13996 break;
13998 case OPC_PRECRQ_PH_W:
13999 check_dsp(ctx);
14000 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
14001 break;
14002 case OPC_PRECRQ_RS_PH_W:
14003 check_dsp(ctx);
14004 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14005 break;
14006 case OPC_PRECRQU_S_QB_PH:
14007 check_dsp(ctx);
14008 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14009 break;
14011 break;
14012 #ifdef TARGET_MIPS64
14013 case OPC_ABSQ_S_QH_DSP:
14014 switch (op2) {
14015 case OPC_PRECEQ_L_PWL:
14016 check_dsp(ctx);
14017 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
14018 break;
14019 case OPC_PRECEQ_L_PWR:
14020 check_dsp(ctx);
14021 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
14022 break;
14023 case OPC_PRECEQ_PW_QHL:
14024 check_dsp(ctx);
14025 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
14026 break;
14027 case OPC_PRECEQ_PW_QHR:
14028 check_dsp(ctx);
14029 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
14030 break;
14031 case OPC_PRECEQ_PW_QHLA:
14032 check_dsp(ctx);
14033 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
14034 break;
14035 case OPC_PRECEQ_PW_QHRA:
14036 check_dsp(ctx);
14037 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
14038 break;
14039 case OPC_PRECEQU_QH_OBL:
14040 check_dsp(ctx);
14041 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
14042 break;
14043 case OPC_PRECEQU_QH_OBR:
14044 check_dsp(ctx);
14045 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
14046 break;
14047 case OPC_PRECEQU_QH_OBLA:
14048 check_dsp(ctx);
14049 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
14050 break;
14051 case OPC_PRECEQU_QH_OBRA:
14052 check_dsp(ctx);
14053 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
14054 break;
14055 case OPC_PRECEU_QH_OBL:
14056 check_dsp(ctx);
14057 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
14058 break;
14059 case OPC_PRECEU_QH_OBR:
14060 check_dsp(ctx);
14061 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
14062 break;
14063 case OPC_PRECEU_QH_OBLA:
14064 check_dsp(ctx);
14065 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
14066 break;
14067 case OPC_PRECEU_QH_OBRA:
14068 check_dsp(ctx);
14069 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
14070 break;
14071 case OPC_ABSQ_S_OB:
14072 check_dspr2(ctx);
14073 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
14074 break;
14075 case OPC_ABSQ_S_PW:
14076 check_dsp(ctx);
14077 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
14078 break;
14079 case OPC_ABSQ_S_QH:
14080 check_dsp(ctx);
14081 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
14082 break;
14084 break;
14085 case OPC_ADDU_OB_DSP:
14086 switch (op2) {
14087 case OPC_RADDU_L_OB:
14088 check_dsp(ctx);
14089 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
14090 break;
14091 case OPC_SUBQ_PW:
14092 check_dsp(ctx);
14093 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14094 break;
14095 case OPC_SUBQ_S_PW:
14096 check_dsp(ctx);
14097 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14098 break;
14099 case OPC_SUBQ_QH:
14100 check_dsp(ctx);
14101 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14102 break;
14103 case OPC_SUBQ_S_QH:
14104 check_dsp(ctx);
14105 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14106 break;
14107 case OPC_SUBU_OB:
14108 check_dsp(ctx);
14109 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14110 break;
14111 case OPC_SUBU_S_OB:
14112 check_dsp(ctx);
14113 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14114 break;
14115 case OPC_SUBU_QH:
14116 check_dspr2(ctx);
14117 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14118 break;
14119 case OPC_SUBU_S_QH:
14120 check_dspr2(ctx);
14121 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14122 break;
14123 case OPC_SUBUH_OB:
14124 check_dspr2(ctx);
14125 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
14126 break;
14127 case OPC_SUBUH_R_OB:
14128 check_dspr2(ctx);
14129 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14130 break;
14131 case OPC_ADDQ_PW:
14132 check_dsp(ctx);
14133 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14134 break;
14135 case OPC_ADDQ_S_PW:
14136 check_dsp(ctx);
14137 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14138 break;
14139 case OPC_ADDQ_QH:
14140 check_dsp(ctx);
14141 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14142 break;
14143 case OPC_ADDQ_S_QH:
14144 check_dsp(ctx);
14145 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14146 break;
14147 case OPC_ADDU_OB:
14148 check_dsp(ctx);
14149 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14150 break;
14151 case OPC_ADDU_S_OB:
14152 check_dsp(ctx);
14153 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14154 break;
14155 case OPC_ADDU_QH:
14156 check_dspr2(ctx);
14157 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14158 break;
14159 case OPC_ADDU_S_QH:
14160 check_dspr2(ctx);
14161 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14162 break;
14163 case OPC_ADDUH_OB:
14164 check_dspr2(ctx);
14165 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
14166 break;
14167 case OPC_ADDUH_R_OB:
14168 check_dspr2(ctx);
14169 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
14170 break;
14172 break;
14173 case OPC_CMPU_EQ_OB_DSP:
14174 switch (op2) {
14175 case OPC_PRECR_OB_QH:
14176 check_dspr2(ctx);
14177 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14178 break;
14179 case OPC_PRECR_SRA_QH_PW:
14180 check_dspr2(ctx);
14182 TCGv_i32 ret_t = tcg_const_i32(ret);
14183 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
14184 tcg_temp_free_i32(ret_t);
14185 break;
14187 case OPC_PRECR_SRA_R_QH_PW:
14188 check_dspr2(ctx);
14190 TCGv_i32 sa_v = tcg_const_i32(ret);
14191 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
14192 tcg_temp_free_i32(sa_v);
14193 break;
14195 case OPC_PRECRQ_OB_QH:
14196 check_dsp(ctx);
14197 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
14198 break;
14199 case OPC_PRECRQ_PW_L:
14200 check_dsp(ctx);
14201 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
14202 break;
14203 case OPC_PRECRQ_QH_PW:
14204 check_dsp(ctx);
14205 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
14206 break;
14207 case OPC_PRECRQ_RS_QH_PW:
14208 check_dsp(ctx);
14209 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14210 break;
14211 case OPC_PRECRQU_S_OB_QH:
14212 check_dsp(ctx);
14213 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14214 break;
14216 break;
14217 #endif
14220 tcg_temp_free(v1_t);
14221 tcg_temp_free(v2_t);
14223 (void)opn; /* avoid a compiler warning */
14224 MIPS_DEBUG("%s", opn);
14227 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
14228 int ret, int v1, int v2)
14230 uint32_t op2;
14231 const char *opn = "mipsdsp shift";
14232 TCGv t0;
14233 TCGv v1_t;
14234 TCGv v2_t;
14236 if (ret == 0) {
14237 /* Treat as NOP. */
14238 MIPS_DEBUG("NOP");
14239 return;
14242 t0 = tcg_temp_new();
14243 v1_t = tcg_temp_new();
14244 v2_t = tcg_temp_new();
14246 tcg_gen_movi_tl(t0, v1);
14247 gen_load_gpr(v1_t, v1);
14248 gen_load_gpr(v2_t, v2);
14250 switch (opc) {
14251 case OPC_SHLL_QB_DSP:
14253 op2 = MASK_SHLL_QB(ctx->opcode);
14254 switch (op2) {
14255 case OPC_SHLL_QB:
14256 check_dsp(ctx);
14257 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
14258 break;
14259 case OPC_SHLLV_QB:
14260 check_dsp(ctx);
14261 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14262 break;
14263 case OPC_SHLL_PH:
14264 check_dsp(ctx);
14265 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14266 break;
14267 case OPC_SHLLV_PH:
14268 check_dsp(ctx);
14269 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14270 break;
14271 case OPC_SHLL_S_PH:
14272 check_dsp(ctx);
14273 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
14274 break;
14275 case OPC_SHLLV_S_PH:
14276 check_dsp(ctx);
14277 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14278 break;
14279 case OPC_SHLL_S_W:
14280 check_dsp(ctx);
14281 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
14282 break;
14283 case OPC_SHLLV_S_W:
14284 check_dsp(ctx);
14285 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14286 break;
14287 case OPC_SHRL_QB:
14288 check_dsp(ctx);
14289 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
14290 break;
14291 case OPC_SHRLV_QB:
14292 check_dsp(ctx);
14293 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
14294 break;
14295 case OPC_SHRL_PH:
14296 check_dspr2(ctx);
14297 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
14298 break;
14299 case OPC_SHRLV_PH:
14300 check_dspr2(ctx);
14301 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
14302 break;
14303 case OPC_SHRA_QB:
14304 check_dspr2(ctx);
14305 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
14306 break;
14307 case OPC_SHRA_R_QB:
14308 check_dspr2(ctx);
14309 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
14310 break;
14311 case OPC_SHRAV_QB:
14312 check_dspr2(ctx);
14313 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
14314 break;
14315 case OPC_SHRAV_R_QB:
14316 check_dspr2(ctx);
14317 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
14318 break;
14319 case OPC_SHRA_PH:
14320 check_dsp(ctx);
14321 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
14322 break;
14323 case OPC_SHRA_R_PH:
14324 check_dsp(ctx);
14325 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
14326 break;
14327 case OPC_SHRAV_PH:
14328 check_dsp(ctx);
14329 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
14330 break;
14331 case OPC_SHRAV_R_PH:
14332 check_dsp(ctx);
14333 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
14334 break;
14335 case OPC_SHRA_R_W:
14336 check_dsp(ctx);
14337 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
14338 break;
14339 case OPC_SHRAV_R_W:
14340 check_dsp(ctx);
14341 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
14342 break;
14343 default: /* Invalid */
14344 MIPS_INVAL("MASK SHLL.QB");
14345 generate_exception(ctx, EXCP_RI);
14346 break;
14348 break;
14350 #ifdef TARGET_MIPS64
14351 case OPC_SHLL_OB_DSP:
14352 op2 = MASK_SHLL_OB(ctx->opcode);
14353 switch (op2) {
14354 case OPC_SHLL_PW:
14355 check_dsp(ctx);
14356 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14357 break;
14358 case OPC_SHLLV_PW:
14359 check_dsp(ctx);
14360 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14361 break;
14362 case OPC_SHLL_S_PW:
14363 check_dsp(ctx);
14364 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
14365 break;
14366 case OPC_SHLLV_S_PW:
14367 check_dsp(ctx);
14368 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14369 break;
14370 case OPC_SHLL_OB:
14371 check_dsp(ctx);
14372 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
14373 break;
14374 case OPC_SHLLV_OB:
14375 check_dsp(ctx);
14376 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14377 break;
14378 case OPC_SHLL_QH:
14379 check_dsp(ctx);
14380 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14381 break;
14382 case OPC_SHLLV_QH:
14383 check_dsp(ctx);
14384 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14385 break;
14386 case OPC_SHLL_S_QH:
14387 check_dsp(ctx);
14388 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
14389 break;
14390 case OPC_SHLLV_S_QH:
14391 check_dsp(ctx);
14392 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
14393 break;
14394 case OPC_SHRA_OB:
14395 check_dspr2(ctx);
14396 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
14397 break;
14398 case OPC_SHRAV_OB:
14399 check_dspr2(ctx);
14400 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
14401 break;
14402 case OPC_SHRA_R_OB:
14403 check_dspr2(ctx);
14404 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
14405 break;
14406 case OPC_SHRAV_R_OB:
14407 check_dspr2(ctx);
14408 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
14409 break;
14410 case OPC_SHRA_PW:
14411 check_dsp(ctx);
14412 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
14413 break;
14414 case OPC_SHRAV_PW:
14415 check_dsp(ctx);
14416 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
14417 break;
14418 case OPC_SHRA_R_PW:
14419 check_dsp(ctx);
14420 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
14421 break;
14422 case OPC_SHRAV_R_PW:
14423 check_dsp(ctx);
14424 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
14425 break;
14426 case OPC_SHRA_QH:
14427 check_dsp(ctx);
14428 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
14429 break;
14430 case OPC_SHRAV_QH:
14431 check_dsp(ctx);
14432 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
14433 break;
14434 case OPC_SHRA_R_QH:
14435 check_dsp(ctx);
14436 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
14437 break;
14438 case OPC_SHRAV_R_QH:
14439 check_dsp(ctx);
14440 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
14441 break;
14442 case OPC_SHRL_OB:
14443 check_dsp(ctx);
14444 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
14445 break;
14446 case OPC_SHRLV_OB:
14447 check_dsp(ctx);
14448 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
14449 break;
14450 case OPC_SHRL_QH:
14451 check_dspr2(ctx);
14452 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
14453 break;
14454 case OPC_SHRLV_QH:
14455 check_dspr2(ctx);
14456 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
14457 break;
14458 default: /* Invalid */
14459 MIPS_INVAL("MASK SHLL.OB");
14460 generate_exception(ctx, EXCP_RI);
14461 break;
14463 break;
14464 #endif
14467 tcg_temp_free(t0);
14468 tcg_temp_free(v1_t);
14469 tcg_temp_free(v2_t);
14470 (void)opn; /* avoid a compiler warning */
14471 MIPS_DEBUG("%s", opn);
14474 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
14475 int ret, int v1, int v2, int check_ret)
14477 const char *opn = "mipsdsp multiply";
14478 TCGv_i32 t0;
14479 TCGv v1_t;
14480 TCGv v2_t;
14482 if ((ret == 0) && (check_ret == 1)) {
14483 /* Treat as NOP. */
14484 MIPS_DEBUG("NOP");
14485 return;
14488 t0 = tcg_temp_new_i32();
14489 v1_t = tcg_temp_new();
14490 v2_t = tcg_temp_new();
14492 tcg_gen_movi_i32(t0, ret);
14493 gen_load_gpr(v1_t, v1);
14494 gen_load_gpr(v2_t, v2);
14496 switch (op1) {
14497 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14498 * the same mask and op1. */
14499 case OPC_MULT_G_2E:
14500 check_dspr2(ctx);
14501 switch (op2) {
14502 case OPC_MUL_PH:
14503 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14504 break;
14505 case OPC_MUL_S_PH:
14506 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14507 break;
14508 case OPC_MULQ_S_W:
14509 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14510 break;
14511 case OPC_MULQ_RS_W:
14512 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14513 break;
14515 break;
14516 case OPC_DPA_W_PH_DSP:
14517 switch (op2) {
14518 case OPC_DPAU_H_QBL:
14519 check_dsp(ctx);
14520 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
14521 break;
14522 case OPC_DPAU_H_QBR:
14523 check_dsp(ctx);
14524 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
14525 break;
14526 case OPC_DPSU_H_QBL:
14527 check_dsp(ctx);
14528 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
14529 break;
14530 case OPC_DPSU_H_QBR:
14531 check_dsp(ctx);
14532 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
14533 break;
14534 case OPC_DPA_W_PH:
14535 check_dspr2(ctx);
14536 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
14537 break;
14538 case OPC_DPAX_W_PH:
14539 check_dspr2(ctx);
14540 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
14541 break;
14542 case OPC_DPAQ_S_W_PH:
14543 check_dsp(ctx);
14544 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14545 break;
14546 case OPC_DPAQX_S_W_PH:
14547 check_dspr2(ctx);
14548 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14549 break;
14550 case OPC_DPAQX_SA_W_PH:
14551 check_dspr2(ctx);
14552 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14553 break;
14554 case OPC_DPS_W_PH:
14555 check_dspr2(ctx);
14556 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
14557 break;
14558 case OPC_DPSX_W_PH:
14559 check_dspr2(ctx);
14560 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
14561 break;
14562 case OPC_DPSQ_S_W_PH:
14563 check_dsp(ctx);
14564 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14565 break;
14566 case OPC_DPSQX_S_W_PH:
14567 check_dspr2(ctx);
14568 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
14569 break;
14570 case OPC_DPSQX_SA_W_PH:
14571 check_dspr2(ctx);
14572 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
14573 break;
14574 case OPC_MULSAQ_S_W_PH:
14575 check_dsp(ctx);
14576 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
14577 break;
14578 case OPC_DPAQ_SA_L_W:
14579 check_dsp(ctx);
14580 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14581 break;
14582 case OPC_DPSQ_SA_L_W:
14583 check_dsp(ctx);
14584 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
14585 break;
14586 case OPC_MAQ_S_W_PHL:
14587 check_dsp(ctx);
14588 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
14589 break;
14590 case OPC_MAQ_S_W_PHR:
14591 check_dsp(ctx);
14592 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
14593 break;
14594 case OPC_MAQ_SA_W_PHL:
14595 check_dsp(ctx);
14596 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
14597 break;
14598 case OPC_MAQ_SA_W_PHR:
14599 check_dsp(ctx);
14600 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
14601 break;
14602 case OPC_MULSA_W_PH:
14603 check_dspr2(ctx);
14604 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
14605 break;
14607 break;
14608 #ifdef TARGET_MIPS64
14609 case OPC_DPAQ_W_QH_DSP:
14611 int ac = ret & 0x03;
14612 tcg_gen_movi_i32(t0, ac);
14614 switch (op2) {
14615 case OPC_DMADD:
14616 check_dsp(ctx);
14617 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
14618 break;
14619 case OPC_DMADDU:
14620 check_dsp(ctx);
14621 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
14622 break;
14623 case OPC_DMSUB:
14624 check_dsp(ctx);
14625 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
14626 break;
14627 case OPC_DMSUBU:
14628 check_dsp(ctx);
14629 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
14630 break;
14631 case OPC_DPA_W_QH:
14632 check_dspr2(ctx);
14633 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
14634 break;
14635 case OPC_DPAQ_S_W_QH:
14636 check_dsp(ctx);
14637 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14638 break;
14639 case OPC_DPAQ_SA_L_PW:
14640 check_dsp(ctx);
14641 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
14642 break;
14643 case OPC_DPAU_H_OBL:
14644 check_dsp(ctx);
14645 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
14646 break;
14647 case OPC_DPAU_H_OBR:
14648 check_dsp(ctx);
14649 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
14650 break;
14651 case OPC_DPS_W_QH:
14652 check_dspr2(ctx);
14653 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
14654 break;
14655 case OPC_DPSQ_S_W_QH:
14656 check_dsp(ctx);
14657 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14658 break;
14659 case OPC_DPSQ_SA_L_PW:
14660 check_dsp(ctx);
14661 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
14662 break;
14663 case OPC_DPSU_H_OBL:
14664 check_dsp(ctx);
14665 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
14666 break;
14667 case OPC_DPSU_H_OBR:
14668 check_dsp(ctx);
14669 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
14670 break;
14671 case OPC_MAQ_S_L_PWL:
14672 check_dsp(ctx);
14673 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
14674 break;
14675 case OPC_MAQ_S_L_PWR:
14676 check_dsp(ctx);
14677 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
14678 break;
14679 case OPC_MAQ_S_W_QHLL:
14680 check_dsp(ctx);
14681 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
14682 break;
14683 case OPC_MAQ_SA_W_QHLL:
14684 check_dsp(ctx);
14685 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
14686 break;
14687 case OPC_MAQ_S_W_QHLR:
14688 check_dsp(ctx);
14689 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
14690 break;
14691 case OPC_MAQ_SA_W_QHLR:
14692 check_dsp(ctx);
14693 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
14694 break;
14695 case OPC_MAQ_S_W_QHRL:
14696 check_dsp(ctx);
14697 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
14698 break;
14699 case OPC_MAQ_SA_W_QHRL:
14700 check_dsp(ctx);
14701 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
14702 break;
14703 case OPC_MAQ_S_W_QHRR:
14704 check_dsp(ctx);
14705 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
14706 break;
14707 case OPC_MAQ_SA_W_QHRR:
14708 check_dsp(ctx);
14709 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
14710 break;
14711 case OPC_MULSAQ_S_L_PW:
14712 check_dsp(ctx);
14713 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
14714 break;
14715 case OPC_MULSAQ_S_W_QH:
14716 check_dsp(ctx);
14717 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
14718 break;
14721 break;
14722 #endif
14723 case OPC_ADDU_QB_DSP:
14724 switch (op2) {
14725 case OPC_MULEU_S_PH_QBL:
14726 check_dsp(ctx);
14727 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14728 break;
14729 case OPC_MULEU_S_PH_QBR:
14730 check_dsp(ctx);
14731 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14732 break;
14733 case OPC_MULQ_RS_PH:
14734 check_dsp(ctx);
14735 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14736 break;
14737 case OPC_MULEQ_S_W_PHL:
14738 check_dsp(ctx);
14739 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14740 break;
14741 case OPC_MULEQ_S_W_PHR:
14742 check_dsp(ctx);
14743 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14744 break;
14745 case OPC_MULQ_S_PH:
14746 check_dspr2(ctx);
14747 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14748 break;
14750 break;
14751 #ifdef TARGET_MIPS64
14752 case OPC_ADDU_OB_DSP:
14753 switch (op2) {
14754 case OPC_MULEQ_S_PW_QHL:
14755 check_dsp(ctx);
14756 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14757 break;
14758 case OPC_MULEQ_S_PW_QHR:
14759 check_dsp(ctx);
14760 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14761 break;
14762 case OPC_MULEU_S_QH_OBL:
14763 check_dsp(ctx);
14764 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14765 break;
14766 case OPC_MULEU_S_QH_OBR:
14767 check_dsp(ctx);
14768 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14769 break;
14770 case OPC_MULQ_RS_QH:
14771 check_dsp(ctx);
14772 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14773 break;
14775 break;
14776 #endif
14779 tcg_temp_free_i32(t0);
14780 tcg_temp_free(v1_t);
14781 tcg_temp_free(v2_t);
14783 (void)opn; /* avoid a compiler warning */
14784 MIPS_DEBUG("%s", opn);
14788 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
14789 int ret, int val)
14791 const char *opn = "mipsdsp Bit/ Manipulation";
14792 int16_t imm;
14793 TCGv t0;
14794 TCGv val_t;
14796 if (ret == 0) {
14797 /* Treat as NOP. */
14798 MIPS_DEBUG("NOP");
14799 return;
14802 t0 = tcg_temp_new();
14803 val_t = tcg_temp_new();
14804 gen_load_gpr(val_t, val);
14806 switch (op1) {
14807 case OPC_ABSQ_S_PH_DSP:
14808 switch (op2) {
14809 case OPC_BITREV:
14810 check_dsp(ctx);
14811 gen_helper_bitrev(cpu_gpr[ret], val_t);
14812 break;
14813 case OPC_REPL_QB:
14814 check_dsp(ctx);
14816 target_long result;
14817 imm = (ctx->opcode >> 16) & 0xFF;
14818 result = (uint32_t)imm << 24 |
14819 (uint32_t)imm << 16 |
14820 (uint32_t)imm << 8 |
14821 (uint32_t)imm;
14822 result = (int32_t)result;
14823 tcg_gen_movi_tl(cpu_gpr[ret], result);
14825 break;
14826 case OPC_REPLV_QB:
14827 check_dsp(ctx);
14828 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
14829 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
14830 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14831 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14832 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14833 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14834 break;
14835 case OPC_REPL_PH:
14836 check_dsp(ctx);
14838 imm = (ctx->opcode >> 16) & 0x03FF;
14839 imm = (int16_t)(imm << 6) >> 6;
14840 tcg_gen_movi_tl(cpu_gpr[ret], \
14841 (target_long)((int32_t)imm << 16 | \
14842 (uint16_t)imm));
14844 break;
14845 case OPC_REPLV_PH:
14846 check_dsp(ctx);
14847 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
14848 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14849 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14850 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
14851 break;
14853 break;
14854 #ifdef TARGET_MIPS64
14855 case OPC_ABSQ_S_QH_DSP:
14856 switch (op2) {
14857 case OPC_REPL_OB:
14858 check_dsp(ctx);
14860 target_long temp;
14862 imm = (ctx->opcode >> 16) & 0xFF;
14863 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
14864 temp = (temp << 16) | temp;
14865 temp = (temp << 32) | temp;
14866 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14867 break;
14869 case OPC_REPL_PW:
14870 check_dsp(ctx);
14872 target_long temp;
14874 imm = (ctx->opcode >> 16) & 0x03FF;
14875 imm = (int16_t)(imm << 6) >> 6;
14876 temp = ((target_long)imm << 32) \
14877 | ((target_long)imm & 0xFFFFFFFF);
14878 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14879 break;
14881 case OPC_REPL_QH:
14882 check_dsp(ctx);
14884 target_long temp;
14886 imm = (ctx->opcode >> 16) & 0x03FF;
14887 imm = (int16_t)(imm << 6) >> 6;
14889 temp = ((uint64_t)(uint16_t)imm << 48) |
14890 ((uint64_t)(uint16_t)imm << 32) |
14891 ((uint64_t)(uint16_t)imm << 16) |
14892 (uint64_t)(uint16_t)imm;
14893 tcg_gen_movi_tl(cpu_gpr[ret], temp);
14894 break;
14896 case OPC_REPLV_OB:
14897 check_dsp(ctx);
14898 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
14899 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
14900 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14901 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14902 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14903 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14904 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14905 break;
14906 case OPC_REPLV_PW:
14907 check_dsp(ctx);
14908 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
14909 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14910 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14911 break;
14912 case OPC_REPLV_QH:
14913 check_dsp(ctx);
14914 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
14915 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
14916 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14917 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
14918 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
14919 break;
14921 break;
14922 #endif
14924 tcg_temp_free(t0);
14925 tcg_temp_free(val_t);
14927 (void)opn; /* avoid a compiler warning */
14928 MIPS_DEBUG("%s", opn);
14931 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
14932 uint32_t op1, uint32_t op2,
14933 int ret, int v1, int v2, int check_ret)
14935 const char *opn = "mipsdsp add compare pick";
14936 TCGv t1;
14937 TCGv v1_t;
14938 TCGv v2_t;
14940 if ((ret == 0) && (check_ret == 1)) {
14941 /* Treat as NOP. */
14942 MIPS_DEBUG("NOP");
14943 return;
14946 t1 = tcg_temp_new();
14947 v1_t = tcg_temp_new();
14948 v2_t = tcg_temp_new();
14950 gen_load_gpr(v1_t, v1);
14951 gen_load_gpr(v2_t, v2);
14953 switch (op1) {
14954 case OPC_CMPU_EQ_QB_DSP:
14955 switch (op2) {
14956 case OPC_CMPU_EQ_QB:
14957 check_dsp(ctx);
14958 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
14959 break;
14960 case OPC_CMPU_LT_QB:
14961 check_dsp(ctx);
14962 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
14963 break;
14964 case OPC_CMPU_LE_QB:
14965 check_dsp(ctx);
14966 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
14967 break;
14968 case OPC_CMPGU_EQ_QB:
14969 check_dsp(ctx);
14970 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
14971 break;
14972 case OPC_CMPGU_LT_QB:
14973 check_dsp(ctx);
14974 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
14975 break;
14976 case OPC_CMPGU_LE_QB:
14977 check_dsp(ctx);
14978 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
14979 break;
14980 case OPC_CMPGDU_EQ_QB:
14981 check_dspr2(ctx);
14982 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
14983 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14984 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14985 tcg_gen_shli_tl(t1, t1, 24);
14986 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14987 break;
14988 case OPC_CMPGDU_LT_QB:
14989 check_dspr2(ctx);
14990 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
14991 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14992 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14993 tcg_gen_shli_tl(t1, t1, 24);
14994 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14995 break;
14996 case OPC_CMPGDU_LE_QB:
14997 check_dspr2(ctx);
14998 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
14999 tcg_gen_mov_tl(cpu_gpr[ret], t1);
15000 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
15001 tcg_gen_shli_tl(t1, t1, 24);
15002 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
15003 break;
15004 case OPC_CMP_EQ_PH:
15005 check_dsp(ctx);
15006 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
15007 break;
15008 case OPC_CMP_LT_PH:
15009 check_dsp(ctx);
15010 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
15011 break;
15012 case OPC_CMP_LE_PH:
15013 check_dsp(ctx);
15014 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
15015 break;
15016 case OPC_PICK_QB:
15017 check_dsp(ctx);
15018 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15019 break;
15020 case OPC_PICK_PH:
15021 check_dsp(ctx);
15022 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15023 break;
15024 case OPC_PACKRL_PH:
15025 check_dsp(ctx);
15026 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
15027 break;
15029 break;
15030 #ifdef TARGET_MIPS64
15031 case OPC_CMPU_EQ_OB_DSP:
15032 switch (op2) {
15033 case OPC_CMP_EQ_PW:
15034 check_dsp(ctx);
15035 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
15036 break;
15037 case OPC_CMP_LT_PW:
15038 check_dsp(ctx);
15039 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
15040 break;
15041 case OPC_CMP_LE_PW:
15042 check_dsp(ctx);
15043 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
15044 break;
15045 case OPC_CMP_EQ_QH:
15046 check_dsp(ctx);
15047 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
15048 break;
15049 case OPC_CMP_LT_QH:
15050 check_dsp(ctx);
15051 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
15052 break;
15053 case OPC_CMP_LE_QH:
15054 check_dsp(ctx);
15055 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
15056 break;
15057 case OPC_CMPGDU_EQ_OB:
15058 check_dspr2(ctx);
15059 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15060 break;
15061 case OPC_CMPGDU_LT_OB:
15062 check_dspr2(ctx);
15063 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15064 break;
15065 case OPC_CMPGDU_LE_OB:
15066 check_dspr2(ctx);
15067 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15068 break;
15069 case OPC_CMPGU_EQ_OB:
15070 check_dsp(ctx);
15071 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
15072 break;
15073 case OPC_CMPGU_LT_OB:
15074 check_dsp(ctx);
15075 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
15076 break;
15077 case OPC_CMPGU_LE_OB:
15078 check_dsp(ctx);
15079 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
15080 break;
15081 case OPC_CMPU_EQ_OB:
15082 check_dsp(ctx);
15083 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
15084 break;
15085 case OPC_CMPU_LT_OB:
15086 check_dsp(ctx);
15087 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
15088 break;
15089 case OPC_CMPU_LE_OB:
15090 check_dsp(ctx);
15091 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
15092 break;
15093 case OPC_PACKRL_PW:
15094 check_dsp(ctx);
15095 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
15096 break;
15097 case OPC_PICK_OB:
15098 check_dsp(ctx);
15099 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15100 break;
15101 case OPC_PICK_PW:
15102 check_dsp(ctx);
15103 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15104 break;
15105 case OPC_PICK_QH:
15106 check_dsp(ctx);
15107 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
15108 break;
15110 break;
15111 #endif
15114 tcg_temp_free(t1);
15115 tcg_temp_free(v1_t);
15116 tcg_temp_free(v2_t);
15118 (void)opn; /* avoid a compiler warning */
15119 MIPS_DEBUG("%s", opn);
15122 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
15123 uint32_t op1, int rt, int rs, int sa)
15125 const char *opn = "mipsdsp append/dappend";
15126 TCGv t0;
15128 check_dspr2(ctx);
15130 if (rt == 0) {
15131 /* Treat as NOP. */
15132 MIPS_DEBUG("NOP");
15133 return;
15136 t0 = tcg_temp_new();
15137 gen_load_gpr(t0, rs);
15139 switch (op1) {
15140 case OPC_APPEND_DSP:
15141 switch (MASK_APPEND(ctx->opcode)) {
15142 case OPC_APPEND:
15143 if (sa != 0) {
15144 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
15146 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15147 break;
15148 case OPC_PREPEND:
15149 if (sa != 0) {
15150 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
15151 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15152 tcg_gen_shli_tl(t0, t0, 32 - sa);
15153 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15155 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15156 break;
15157 case OPC_BALIGN:
15158 sa &= 3;
15159 if (sa != 0 && sa != 2) {
15160 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15161 tcg_gen_ext32u_tl(t0, t0);
15162 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
15163 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15165 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
15166 break;
15167 default: /* Invalid */
15168 MIPS_INVAL("MASK APPEND");
15169 generate_exception(ctx, EXCP_RI);
15170 break;
15172 break;
15173 #ifdef TARGET_MIPS64
15174 case OPC_DAPPEND_DSP:
15175 switch (MASK_DAPPEND(ctx->opcode)) {
15176 case OPC_DAPPEND:
15177 if (sa != 0) {
15178 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
15180 break;
15181 case OPC_PREPENDD:
15182 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
15183 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
15184 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
15185 break;
15186 case OPC_PREPENDW:
15187 if (sa != 0) {
15188 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
15189 tcg_gen_shli_tl(t0, t0, 64 - sa);
15190 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15192 break;
15193 case OPC_DBALIGN:
15194 sa &= 7;
15195 if (sa != 0 && sa != 2 && sa != 4) {
15196 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
15197 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
15198 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
15200 break;
15201 default: /* Invalid */
15202 MIPS_INVAL("MASK DAPPEND");
15203 generate_exception(ctx, EXCP_RI);
15204 break;
15206 break;
15207 #endif
15209 tcg_temp_free(t0);
15210 (void)opn; /* avoid a compiler warning */
15211 MIPS_DEBUG("%s", opn);
15214 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
15215 int ret, int v1, int v2, int check_ret)
15218 const char *opn = "mipsdsp accumulator";
15219 TCGv t0;
15220 TCGv t1;
15221 TCGv v1_t;
15222 TCGv v2_t;
15223 int16_t imm;
15225 if ((ret == 0) && (check_ret == 1)) {
15226 /* Treat as NOP. */
15227 MIPS_DEBUG("NOP");
15228 return;
15231 t0 = tcg_temp_new();
15232 t1 = tcg_temp_new();
15233 v1_t = tcg_temp_new();
15234 v2_t = tcg_temp_new();
15236 gen_load_gpr(v1_t, v1);
15237 gen_load_gpr(v2_t, v2);
15239 switch (op1) {
15240 case OPC_EXTR_W_DSP:
15241 check_dsp(ctx);
15242 switch (op2) {
15243 case OPC_EXTR_W:
15244 tcg_gen_movi_tl(t0, v2);
15245 tcg_gen_movi_tl(t1, v1);
15246 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
15247 break;
15248 case OPC_EXTR_R_W:
15249 tcg_gen_movi_tl(t0, v2);
15250 tcg_gen_movi_tl(t1, v1);
15251 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15252 break;
15253 case OPC_EXTR_RS_W:
15254 tcg_gen_movi_tl(t0, v2);
15255 tcg_gen_movi_tl(t1, v1);
15256 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15257 break;
15258 case OPC_EXTR_S_H:
15259 tcg_gen_movi_tl(t0, v2);
15260 tcg_gen_movi_tl(t1, v1);
15261 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15262 break;
15263 case OPC_EXTRV_S_H:
15264 tcg_gen_movi_tl(t0, v2);
15265 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
15266 break;
15267 case OPC_EXTRV_W:
15268 tcg_gen_movi_tl(t0, v2);
15269 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15270 break;
15271 case OPC_EXTRV_R_W:
15272 tcg_gen_movi_tl(t0, v2);
15273 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15274 break;
15275 case OPC_EXTRV_RS_W:
15276 tcg_gen_movi_tl(t0, v2);
15277 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15278 break;
15279 case OPC_EXTP:
15280 tcg_gen_movi_tl(t0, v2);
15281 tcg_gen_movi_tl(t1, v1);
15282 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
15283 break;
15284 case OPC_EXTPV:
15285 tcg_gen_movi_tl(t0, v2);
15286 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
15287 break;
15288 case OPC_EXTPDP:
15289 tcg_gen_movi_tl(t0, v2);
15290 tcg_gen_movi_tl(t1, v1);
15291 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
15292 break;
15293 case OPC_EXTPDPV:
15294 tcg_gen_movi_tl(t0, v2);
15295 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15296 break;
15297 case OPC_SHILO:
15298 imm = (ctx->opcode >> 20) & 0x3F;
15299 tcg_gen_movi_tl(t0, ret);
15300 tcg_gen_movi_tl(t1, imm);
15301 gen_helper_shilo(t0, t1, cpu_env);
15302 break;
15303 case OPC_SHILOV:
15304 tcg_gen_movi_tl(t0, ret);
15305 gen_helper_shilo(t0, v1_t, cpu_env);
15306 break;
15307 case OPC_MTHLIP:
15308 tcg_gen_movi_tl(t0, ret);
15309 gen_helper_mthlip(t0, v1_t, cpu_env);
15310 break;
15311 case OPC_WRDSP:
15312 imm = (ctx->opcode >> 11) & 0x3FF;
15313 tcg_gen_movi_tl(t0, imm);
15314 gen_helper_wrdsp(v1_t, t0, cpu_env);
15315 break;
15316 case OPC_RDDSP:
15317 imm = (ctx->opcode >> 16) & 0x03FF;
15318 tcg_gen_movi_tl(t0, imm);
15319 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
15320 break;
15322 break;
15323 #ifdef TARGET_MIPS64
15324 case OPC_DEXTR_W_DSP:
15325 check_dsp(ctx);
15326 switch (op2) {
15327 case OPC_DMTHLIP:
15328 tcg_gen_movi_tl(t0, ret);
15329 gen_helper_dmthlip(v1_t, t0, cpu_env);
15330 break;
15331 case OPC_DSHILO:
15333 int shift = (ctx->opcode >> 19) & 0x7F;
15334 int ac = (ctx->opcode >> 11) & 0x03;
15335 tcg_gen_movi_tl(t0, shift);
15336 tcg_gen_movi_tl(t1, ac);
15337 gen_helper_dshilo(t0, t1, cpu_env);
15338 break;
15340 case OPC_DSHILOV:
15342 int ac = (ctx->opcode >> 11) & 0x03;
15343 tcg_gen_movi_tl(t0, ac);
15344 gen_helper_dshilo(v1_t, t0, cpu_env);
15345 break;
15347 case OPC_DEXTP:
15348 tcg_gen_movi_tl(t0, v2);
15349 tcg_gen_movi_tl(t1, v1);
15351 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
15352 break;
15353 case OPC_DEXTPV:
15354 tcg_gen_movi_tl(t0, v2);
15355 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
15356 break;
15357 case OPC_DEXTPDP:
15358 tcg_gen_movi_tl(t0, v2);
15359 tcg_gen_movi_tl(t1, v1);
15360 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
15361 break;
15362 case OPC_DEXTPDPV:
15363 tcg_gen_movi_tl(t0, v2);
15364 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
15365 break;
15366 case OPC_DEXTR_L:
15367 tcg_gen_movi_tl(t0, v2);
15368 tcg_gen_movi_tl(t1, v1);
15369 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
15370 break;
15371 case OPC_DEXTR_R_L:
15372 tcg_gen_movi_tl(t0, v2);
15373 tcg_gen_movi_tl(t1, v1);
15374 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
15375 break;
15376 case OPC_DEXTR_RS_L:
15377 tcg_gen_movi_tl(t0, v2);
15378 tcg_gen_movi_tl(t1, v1);
15379 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
15380 break;
15381 case OPC_DEXTR_W:
15382 tcg_gen_movi_tl(t0, v2);
15383 tcg_gen_movi_tl(t1, v1);
15384 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
15385 break;
15386 case OPC_DEXTR_R_W:
15387 tcg_gen_movi_tl(t0, v2);
15388 tcg_gen_movi_tl(t1, v1);
15389 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
15390 break;
15391 case OPC_DEXTR_RS_W:
15392 tcg_gen_movi_tl(t0, v2);
15393 tcg_gen_movi_tl(t1, v1);
15394 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
15395 break;
15396 case OPC_DEXTR_S_H:
15397 tcg_gen_movi_tl(t0, v2);
15398 tcg_gen_movi_tl(t1, v1);
15399 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15400 break;
15401 case OPC_DEXTRV_S_H:
15402 tcg_gen_movi_tl(t0, v2);
15403 tcg_gen_movi_tl(t1, v1);
15404 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
15405 break;
15406 case OPC_DEXTRV_L:
15407 tcg_gen_movi_tl(t0, v2);
15408 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15409 break;
15410 case OPC_DEXTRV_R_L:
15411 tcg_gen_movi_tl(t0, v2);
15412 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15413 break;
15414 case OPC_DEXTRV_RS_L:
15415 tcg_gen_movi_tl(t0, v2);
15416 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
15417 break;
15418 case OPC_DEXTRV_W:
15419 tcg_gen_movi_tl(t0, v2);
15420 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15421 break;
15422 case OPC_DEXTRV_R_W:
15423 tcg_gen_movi_tl(t0, v2);
15424 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15425 break;
15426 case OPC_DEXTRV_RS_W:
15427 tcg_gen_movi_tl(t0, v2);
15428 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
15429 break;
15431 break;
15432 #endif
15435 tcg_temp_free(t0);
15436 tcg_temp_free(t1);
15437 tcg_temp_free(v1_t);
15438 tcg_temp_free(v2_t);
15440 (void)opn; /* avoid a compiler warning */
15441 MIPS_DEBUG("%s", opn);
15444 /* End MIPSDSP functions. */
15446 /* Compact Branches */
15447 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
15448 int rs, int rt, int32_t offset)
15450 int bcond_compute = 0;
15451 TCGv t0 = tcg_temp_new();
15452 TCGv t1 = tcg_temp_new();
15454 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15455 #ifdef MIPS_DEBUG_DISAS
15456 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
15457 #endif
15458 generate_exception(ctx, EXCP_RI);
15459 goto out;
15462 /* Load needed operands and calculate btarget */
15463 switch (opc) {
15464 /* compact branch */
15465 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15466 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15467 gen_load_gpr(t0, rs);
15468 gen_load_gpr(t1, rt);
15469 bcond_compute = 1;
15470 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15471 if (rs <= rt && rs == 0) {
15472 /* OPC_BEQZALC, OPC_BNEZALC */
15473 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15475 break;
15476 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15477 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15478 gen_load_gpr(t0, rs);
15479 gen_load_gpr(t1, rt);
15480 bcond_compute = 1;
15481 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15482 break;
15483 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15484 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15485 if (rs == 0 || rs == rt) {
15486 /* OPC_BLEZALC, OPC_BGEZALC */
15487 /* OPC_BGTZALC, OPC_BLTZALC */
15488 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15490 gen_load_gpr(t0, rs);
15491 gen_load_gpr(t1, rt);
15492 bcond_compute = 1;
15493 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15494 break;
15495 case OPC_BC:
15496 case OPC_BALC:
15497 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15498 break;
15499 case OPC_BEQZC:
15500 case OPC_BNEZC:
15501 if (rs != 0) {
15502 /* OPC_BEQZC, OPC_BNEZC */
15503 gen_load_gpr(t0, rs);
15504 bcond_compute = 1;
15505 ctx->btarget = addr_add(ctx, ctx->pc + 4, offset);
15506 } else {
15507 /* OPC_JIC, OPC_JIALC */
15508 TCGv tbase = tcg_temp_new();
15509 TCGv toffset = tcg_temp_new();
15511 gen_load_gpr(tbase, rt);
15512 tcg_gen_movi_tl(toffset, offset);
15513 gen_op_addr_add(ctx, btarget, tbase, toffset);
15514 tcg_temp_free(tbase);
15515 tcg_temp_free(toffset);
15517 break;
15518 default:
15519 MIPS_INVAL("Compact branch/jump");
15520 generate_exception(ctx, EXCP_RI);
15521 goto out;
15524 if (bcond_compute == 0) {
15525 /* Uncoditional compact branch */
15526 switch (opc) {
15527 case OPC_JIALC:
15528 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15529 /* Fallthrough */
15530 case OPC_JIC:
15531 ctx->hflags |= MIPS_HFLAG_BR;
15532 break;
15533 case OPC_BALC:
15534 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 4);
15535 /* Fallthrough */
15536 case OPC_BC:
15537 ctx->hflags |= MIPS_HFLAG_B;
15538 break;
15539 default:
15540 MIPS_INVAL("Compact branch/jump");
15541 generate_exception(ctx, EXCP_RI);
15542 goto out;
15545 /* Generating branch here as compact branches don't have delay slot */
15546 gen_branch(ctx, 4);
15547 } else {
15548 /* Conditional compact branch */
15549 int l1 = gen_new_label();
15550 save_cpu_state(ctx, 0);
15552 switch (opc) {
15553 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
15554 if (rs == 0 && rt != 0) {
15555 /* OPC_BLEZALC */
15556 tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15557 } else if (rs != 0 && rt != 0 && rs == rt) {
15558 /* OPC_BGEZALC */
15559 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15560 } else {
15561 /* OPC_BGEUC */
15562 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
15564 break;
15565 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
15566 if (rs == 0 && rt != 0) {
15567 /* OPC_BGTZALC */
15568 tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15569 } else if (rs != 0 && rt != 0 && rs == rt) {
15570 /* OPC_BLTZALC */
15571 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15572 } else {
15573 /* OPC_BLTUC */
15574 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
15576 break;
15577 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
15578 if (rs == 0 && rt != 0) {
15579 /* OPC_BLEZC */
15580 tcg_gen_brcondi_tl(TCG_COND_LE, t1, 0, l1);
15581 } else if (rs != 0 && rt != 0 && rs == rt) {
15582 /* OPC_BGEZC */
15583 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
15584 } else {
15585 /* OPC_BGEC */
15586 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
15588 break;
15589 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
15590 if (rs == 0 && rt != 0) {
15591 /* OPC_BGTZC */
15592 tcg_gen_brcondi_tl(TCG_COND_GT, t1, 0, l1);
15593 } else if (rs != 0 && rt != 0 && rs == rt) {
15594 /* OPC_BLTZC */
15595 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
15596 } else {
15597 /* OPC_BLTC */
15598 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
15600 break;
15601 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
15602 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
15603 if (rs >= rt) {
15604 /* OPC_BOVC, OPC_BNVC */
15605 TCGv t2 = tcg_temp_new();
15606 TCGv t3 = tcg_temp_new();
15607 TCGv t4 = tcg_temp_new();
15608 TCGv input_overflow = tcg_temp_new();
15610 gen_load_gpr(t0, rs);
15611 gen_load_gpr(t1, rt);
15612 tcg_gen_ext32s_tl(t2, t0);
15613 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
15614 tcg_gen_ext32s_tl(t3, t1);
15615 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
15616 tcg_gen_or_tl(input_overflow, input_overflow, t4);
15618 tcg_gen_add_tl(t4, t2, t3);
15619 tcg_gen_ext32s_tl(t4, t4);
15620 tcg_gen_xor_tl(t2, t2, t3);
15621 tcg_gen_xor_tl(t3, t4, t3);
15622 tcg_gen_andc_tl(t2, t3, t2);
15623 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
15624 tcg_gen_or_tl(t4, t4, input_overflow);
15625 if (opc == OPC_BOVC) {
15626 /* OPC_BOVC */
15627 tcg_gen_brcondi_tl(TCG_COND_NE, t4, 0, l1);
15628 } else {
15629 /* OPC_BNVC */
15630 tcg_gen_brcondi_tl(TCG_COND_EQ, t4, 0, l1);
15632 tcg_temp_free(input_overflow);
15633 tcg_temp_free(t4);
15634 tcg_temp_free(t3);
15635 tcg_temp_free(t2);
15636 } else if (rs < rt && rs == 0) {
15637 /* OPC_BEQZALC, OPC_BNEZALC */
15638 if (opc == OPC_BEQZALC) {
15639 /* OPC_BEQZALC */
15640 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
15641 } else {
15642 /* OPC_BNEZALC */
15643 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
15645 } else {
15646 /* OPC_BEQC, OPC_BNEC */
15647 if (opc == OPC_BEQC) {
15648 /* OPC_BEQC */
15649 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
15650 } else {
15651 /* OPC_BNEC */
15652 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
15655 break;
15656 case OPC_BEQZC:
15657 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
15658 break;
15659 case OPC_BNEZC:
15660 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
15661 break;
15662 default:
15663 MIPS_INVAL("Compact conditional branch/jump");
15664 generate_exception(ctx, EXCP_RI);
15665 goto out;
15668 /* Generating branch here as compact branches don't have delay slot */
15669 /* TODO: implement forbidden slot */
15670 gen_goto_tb(ctx, 1, ctx->pc + 4);
15671 gen_set_label(l1);
15672 gen_goto_tb(ctx, 0, ctx->btarget);
15673 MIPS_DEBUG("Compact conditional branch");
15674 ctx->bstate = BS_BRANCH;
15677 out:
15678 tcg_temp_free(t0);
15679 tcg_temp_free(t1);
15682 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
15684 int rs, rt, rd, sa;
15685 uint32_t op1, op2;
15687 rs = (ctx->opcode >> 21) & 0x1f;
15688 rt = (ctx->opcode >> 16) & 0x1f;
15689 rd = (ctx->opcode >> 11) & 0x1f;
15690 sa = (ctx->opcode >> 6) & 0x1f;
15692 op1 = MASK_SPECIAL(ctx->opcode);
15693 switch (op1) {
15694 case OPC_LSA:
15695 if (rd != 0) {
15696 int imm2 = extract32(ctx->opcode, 6, 3);
15697 TCGv t0 = tcg_temp_new();
15698 TCGv t1 = tcg_temp_new();
15699 gen_load_gpr(t0, rs);
15700 gen_load_gpr(t1, rt);
15701 tcg_gen_shli_tl(t0, t0, imm2 + 1);
15702 tcg_gen_add_tl(t0, t0, t1);
15703 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
15704 tcg_temp_free(t1);
15705 tcg_temp_free(t0);
15707 break;
15708 case OPC_MULT ... OPC_DIVU:
15709 op2 = MASK_R6_MULDIV(ctx->opcode);
15710 switch (op2) {
15711 case R6_OPC_MUL:
15712 case R6_OPC_MUH:
15713 case R6_OPC_MULU:
15714 case R6_OPC_MUHU:
15715 case R6_OPC_DIV:
15716 case R6_OPC_MOD:
15717 case R6_OPC_DIVU:
15718 case R6_OPC_MODU:
15719 gen_r6_muldiv(ctx, op2, rd, rs, rt);
15720 break;
15721 default:
15722 MIPS_INVAL("special_r6 muldiv");
15723 generate_exception(ctx, EXCP_RI);
15724 break;
15726 break;
15727 case OPC_SELEQZ:
15728 case OPC_SELNEZ:
15729 gen_cond_move(ctx, op1, rd, rs, rt);
15730 break;
15731 case R6_OPC_CLO:
15732 case R6_OPC_CLZ:
15733 if (rt == 0 && sa == 1) {
15734 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
15735 We need additionally to check other fields */
15736 gen_cl(ctx, op1, rd, rs);
15737 } else {
15738 generate_exception(ctx, EXCP_RI);
15740 break;
15741 case R6_OPC_SDBBP:
15742 generate_exception(ctx, EXCP_DBp);
15743 break;
15744 #if defined(TARGET_MIPS64)
15745 case OPC_DLSA:
15746 check_mips_64(ctx);
15747 if (rd != 0) {
15748 int imm2 = extract32(ctx->opcode, 6, 3);
15749 TCGv t0 = tcg_temp_new();
15750 TCGv t1 = tcg_temp_new();
15751 gen_load_gpr(t0, rs);
15752 gen_load_gpr(t1, rt);
15753 tcg_gen_shli_tl(t0, t0, imm2 + 1);
15754 tcg_gen_add_tl(cpu_gpr[rd], t0, t1);
15755 tcg_temp_free(t1);
15756 tcg_temp_free(t0);
15758 break;
15759 case R6_OPC_DCLO:
15760 case R6_OPC_DCLZ:
15761 if (rt == 0 && sa == 1) {
15762 /* Major opcode and function field is shared with preR6 MFHI/MTHI.
15763 We need additionally to check other fields */
15764 check_mips_64(ctx);
15765 gen_cl(ctx, op1, rd, rs);
15766 } else {
15767 generate_exception(ctx, EXCP_RI);
15769 break;
15770 case OPC_DMULT ... OPC_DDIVU:
15771 op2 = MASK_R6_MULDIV(ctx->opcode);
15772 switch (op2) {
15773 case R6_OPC_DMUL:
15774 case R6_OPC_DMUH:
15775 case R6_OPC_DMULU:
15776 case R6_OPC_DMUHU:
15777 case R6_OPC_DDIV:
15778 case R6_OPC_DMOD:
15779 case R6_OPC_DDIVU:
15780 case R6_OPC_DMODU:
15781 check_mips_64(ctx);
15782 gen_r6_muldiv(ctx, op2, rd, rs, rt);
15783 break;
15784 default:
15785 MIPS_INVAL("special_r6 muldiv");
15786 generate_exception(ctx, EXCP_RI);
15787 break;
15789 break;
15790 #endif
15791 default: /* Invalid */
15792 MIPS_INVAL("special_r6");
15793 generate_exception(ctx, EXCP_RI);
15794 break;
15798 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
15800 int rs, rt, rd, sa;
15801 uint32_t op1;
15803 rs = (ctx->opcode >> 21) & 0x1f;
15804 rt = (ctx->opcode >> 16) & 0x1f;
15805 rd = (ctx->opcode >> 11) & 0x1f;
15806 sa = (ctx->opcode >> 6) & 0x1f;
15808 op1 = MASK_SPECIAL(ctx->opcode);
15809 switch (op1) {
15810 case OPC_MOVN: /* Conditional move */
15811 case OPC_MOVZ:
15812 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
15813 INSN_LOONGSON2E | INSN_LOONGSON2F);
15814 gen_cond_move(ctx, op1, rd, rs, rt);
15815 break;
15816 case OPC_MFHI: /* Move from HI/LO */
15817 case OPC_MFLO:
15818 gen_HILO(ctx, op1, rs & 3, rd);
15819 break;
15820 case OPC_MTHI:
15821 case OPC_MTLO: /* Move to HI/LO */
15822 gen_HILO(ctx, op1, rd & 3, rs);
15823 break;
15824 case OPC_MOVCI:
15825 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
15826 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
15827 check_cp1_enabled(ctx);
15828 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
15829 (ctx->opcode >> 16) & 1);
15830 } else {
15831 generate_exception_err(ctx, EXCP_CpU, 1);
15833 break;
15834 case OPC_MULT:
15835 case OPC_MULTU:
15836 if (sa) {
15837 check_insn(ctx, INSN_VR54XX);
15838 op1 = MASK_MUL_VR54XX(ctx->opcode);
15839 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
15840 } else {
15841 gen_muldiv(ctx, op1, rd & 3, rs, rt);
15843 break;
15844 case OPC_DIV:
15845 case OPC_DIVU:
15846 gen_muldiv(ctx, op1, 0, rs, rt);
15847 break;
15848 #if defined(TARGET_MIPS64)
15849 case OPC_DMULT ... OPC_DDIVU:
15850 check_insn(ctx, ISA_MIPS3);
15851 check_mips_64(ctx);
15852 gen_muldiv(ctx, op1, 0, rs, rt);
15853 break;
15854 #endif
15855 case OPC_JR:
15856 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
15857 break;
15858 case OPC_SPIM:
15859 #ifdef MIPS_STRICT_STANDARD
15860 MIPS_INVAL("SPIM");
15861 generate_exception(ctx, EXCP_RI);
15862 #else
15863 /* Implemented as RI exception for now. */
15864 MIPS_INVAL("spim (unofficial)");
15865 generate_exception(ctx, EXCP_RI);
15866 #endif
15867 break;
15868 default: /* Invalid */
15869 MIPS_INVAL("special_legacy");
15870 generate_exception(ctx, EXCP_RI);
15871 break;
15875 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
15877 int rs, rt, rd, sa;
15878 uint32_t op1;
15880 rs = (ctx->opcode >> 21) & 0x1f;
15881 rt = (ctx->opcode >> 16) & 0x1f;
15882 rd = (ctx->opcode >> 11) & 0x1f;
15883 sa = (ctx->opcode >> 6) & 0x1f;
15885 op1 = MASK_SPECIAL(ctx->opcode);
15886 switch (op1) {
15887 case OPC_SLL: /* Shift with immediate */
15888 case OPC_SRA:
15889 gen_shift_imm(ctx, op1, rd, rt, sa);
15890 break;
15891 case OPC_SRL:
15892 switch ((ctx->opcode >> 21) & 0x1f) {
15893 case 1:
15894 /* rotr is decoded as srl on non-R2 CPUs */
15895 if (ctx->insn_flags & ISA_MIPS32R2) {
15896 op1 = OPC_ROTR;
15898 /* Fallthrough */
15899 case 0:
15900 gen_shift_imm(ctx, op1, rd, rt, sa);
15901 break;
15902 default:
15903 generate_exception(ctx, EXCP_RI);
15904 break;
15906 break;
15907 case OPC_ADD ... OPC_SUBU:
15908 gen_arith(ctx, op1, rd, rs, rt);
15909 break;
15910 case OPC_SLLV: /* Shifts */
15911 case OPC_SRAV:
15912 gen_shift(ctx, op1, rd, rs, rt);
15913 break;
15914 case OPC_SRLV:
15915 switch ((ctx->opcode >> 6) & 0x1f) {
15916 case 1:
15917 /* rotrv is decoded as srlv on non-R2 CPUs */
15918 if (ctx->insn_flags & ISA_MIPS32R2) {
15919 op1 = OPC_ROTRV;
15921 /* Fallthrough */
15922 case 0:
15923 gen_shift(ctx, op1, rd, rs, rt);
15924 break;
15925 default:
15926 generate_exception(ctx, EXCP_RI);
15927 break;
15929 break;
15930 case OPC_SLT: /* Set on less than */
15931 case OPC_SLTU:
15932 gen_slt(ctx, op1, rd, rs, rt);
15933 break;
15934 case OPC_AND: /* Logic*/
15935 case OPC_OR:
15936 case OPC_NOR:
15937 case OPC_XOR:
15938 gen_logic(ctx, op1, rd, rs, rt);
15939 break;
15940 case OPC_JALR:
15941 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
15942 break;
15943 case OPC_TGE ... OPC_TEQ: /* Traps */
15944 case OPC_TNE:
15945 gen_trap(ctx, op1, rs, rt, -1);
15946 break;
15947 case OPC_LSA: /* OPC_PMON */
15948 if (ctx->insn_flags & ISA_MIPS32R6) {
15949 decode_opc_special_r6(env, ctx);
15950 } else {
15951 /* Pmon entry point, also R4010 selsl */
15952 #ifdef MIPS_STRICT_STANDARD
15953 MIPS_INVAL("PMON / selsl");
15954 generate_exception(ctx, EXCP_RI);
15955 #else
15956 gen_helper_0e0i(pmon, sa);
15957 #endif
15959 break;
15960 case OPC_SYSCALL:
15961 generate_exception(ctx, EXCP_SYSCALL);
15962 ctx->bstate = BS_STOP;
15963 break;
15964 case OPC_BREAK:
15965 generate_exception(ctx, EXCP_BREAK);
15966 break;
15967 case OPC_SYNC:
15968 /* Treat as NOP. */
15969 break;
15971 #if defined(TARGET_MIPS64)
15972 /* MIPS64 specific opcodes */
15973 case OPC_DSLL:
15974 case OPC_DSRA:
15975 case OPC_DSLL32:
15976 case OPC_DSRA32:
15977 check_insn(ctx, ISA_MIPS3);
15978 check_mips_64(ctx);
15979 gen_shift_imm(ctx, op1, rd, rt, sa);
15980 break;
15981 case OPC_DSRL:
15982 switch ((ctx->opcode >> 21) & 0x1f) {
15983 case 1:
15984 /* drotr is decoded as dsrl on non-R2 CPUs */
15985 if (ctx->insn_flags & ISA_MIPS32R2) {
15986 op1 = OPC_DROTR;
15988 /* Fallthrough */
15989 case 0:
15990 check_insn(ctx, ISA_MIPS3);
15991 check_mips_64(ctx);
15992 gen_shift_imm(ctx, op1, rd, rt, sa);
15993 break;
15994 default:
15995 generate_exception(ctx, EXCP_RI);
15996 break;
15998 break;
15999 case OPC_DSRL32:
16000 switch ((ctx->opcode >> 21) & 0x1f) {
16001 case 1:
16002 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
16003 if (ctx->insn_flags & ISA_MIPS32R2) {
16004 op1 = OPC_DROTR32;
16006 /* Fallthrough */
16007 case 0:
16008 check_insn(ctx, ISA_MIPS3);
16009 check_mips_64(ctx);
16010 gen_shift_imm(ctx, op1, rd, rt, sa);
16011 break;
16012 default:
16013 generate_exception(ctx, EXCP_RI);
16014 break;
16016 break;
16017 case OPC_DADD ... OPC_DSUBU:
16018 check_insn(ctx, ISA_MIPS3);
16019 check_mips_64(ctx);
16020 gen_arith(ctx, op1, rd, rs, rt);
16021 break;
16022 case OPC_DSLLV:
16023 case OPC_DSRAV:
16024 check_insn(ctx, ISA_MIPS3);
16025 check_mips_64(ctx);
16026 gen_shift(ctx, op1, rd, rs, rt);
16027 break;
16028 case OPC_DSRLV:
16029 switch ((ctx->opcode >> 6) & 0x1f) {
16030 case 1:
16031 /* drotrv is decoded as dsrlv on non-R2 CPUs */
16032 if (ctx->insn_flags & ISA_MIPS32R2) {
16033 op1 = OPC_DROTRV;
16035 /* Fallthrough */
16036 case 0:
16037 check_insn(ctx, ISA_MIPS3);
16038 check_mips_64(ctx);
16039 gen_shift(ctx, op1, rd, rs, rt);
16040 break;
16041 default:
16042 generate_exception(ctx, EXCP_RI);
16043 break;
16045 break;
16046 #endif
16047 default:
16048 if (ctx->insn_flags & ISA_MIPS32R6) {
16049 decode_opc_special_r6(env, ctx);
16050 } else {
16051 decode_opc_special_legacy(env, ctx);
16056 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
16058 int rs, rt, rd;
16059 uint32_t op1;
16061 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16063 rs = (ctx->opcode >> 21) & 0x1f;
16064 rt = (ctx->opcode >> 16) & 0x1f;
16065 rd = (ctx->opcode >> 11) & 0x1f;
16067 op1 = MASK_SPECIAL2(ctx->opcode);
16068 switch (op1) {
16069 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
16070 case OPC_MSUB ... OPC_MSUBU:
16071 check_insn(ctx, ISA_MIPS32);
16072 gen_muldiv(ctx, op1, rd & 3, rs, rt);
16073 break;
16074 case OPC_MUL:
16075 gen_arith(ctx, op1, rd, rs, rt);
16076 break;
16077 case OPC_DIV_G_2F:
16078 case OPC_DIVU_G_2F:
16079 case OPC_MULT_G_2F:
16080 case OPC_MULTU_G_2F:
16081 case OPC_MOD_G_2F:
16082 case OPC_MODU_G_2F:
16083 check_insn(ctx, INSN_LOONGSON2F);
16084 gen_loongson_integer(ctx, op1, rd, rs, rt);
16085 break;
16086 case OPC_CLO:
16087 case OPC_CLZ:
16088 check_insn(ctx, ISA_MIPS32);
16089 gen_cl(ctx, op1, rd, rs);
16090 break;
16091 case OPC_SDBBP:
16092 /* XXX: not clear which exception should be raised
16093 * when in debug mode...
16095 check_insn(ctx, ISA_MIPS32);
16096 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
16097 generate_exception(ctx, EXCP_DBp);
16098 } else {
16099 generate_exception(ctx, EXCP_DBp);
16101 /* Treat as NOP. */
16102 break;
16103 #if defined(TARGET_MIPS64)
16104 case OPC_DCLO:
16105 case OPC_DCLZ:
16106 check_insn(ctx, ISA_MIPS64);
16107 check_mips_64(ctx);
16108 gen_cl(ctx, op1, rd, rs);
16109 break;
16110 case OPC_DMULT_G_2F:
16111 case OPC_DMULTU_G_2F:
16112 case OPC_DDIV_G_2F:
16113 case OPC_DDIVU_G_2F:
16114 case OPC_DMOD_G_2F:
16115 case OPC_DMODU_G_2F:
16116 check_insn(ctx, INSN_LOONGSON2F);
16117 gen_loongson_integer(ctx, op1, rd, rs, rt);
16118 break;
16119 #endif
16120 default: /* Invalid */
16121 MIPS_INVAL("special2_legacy");
16122 generate_exception(ctx, EXCP_RI);
16123 break;
16127 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
16129 int rs, rt, rd, sa;
16130 uint32_t op1, op2;
16131 int16_t imm;
16133 rs = (ctx->opcode >> 21) & 0x1f;
16134 rt = (ctx->opcode >> 16) & 0x1f;
16135 rd = (ctx->opcode >> 11) & 0x1f;
16136 sa = (ctx->opcode >> 6) & 0x1f;
16137 imm = (int16_t)ctx->opcode >> 7;
16139 op1 = MASK_SPECIAL3(ctx->opcode);
16140 switch (op1) {
16141 case R6_OPC_PREF:
16142 if (rt >= 24) {
16143 /* hint codes 24-31 are reserved and signal RI */
16144 generate_exception(ctx, EXCP_RI);
16146 /* Treat as NOP. */
16147 break;
16148 case R6_OPC_CACHE:
16149 /* Treat as NOP. */
16150 break;
16151 case R6_OPC_SC:
16152 gen_st_cond(ctx, op1, rt, rs, imm);
16153 break;
16154 case R6_OPC_LL:
16155 gen_ld(ctx, op1, rt, rs, imm);
16156 break;
16157 case OPC_BSHFL:
16159 if (rd == 0) {
16160 /* Treat as NOP. */
16161 break;
16163 TCGv t0 = tcg_temp_new();
16164 gen_load_gpr(t0, rt);
16166 op2 = MASK_BSHFL(ctx->opcode);
16167 switch (op2) {
16168 case OPC_ALIGN ... OPC_ALIGN_END:
16169 sa &= 3;
16170 if (sa == 0) {
16171 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16172 } else {
16173 TCGv t1 = tcg_temp_new();
16174 TCGv_i64 t2 = tcg_temp_new_i64();
16175 gen_load_gpr(t1, rs);
16176 tcg_gen_concat_tl_i64(t2, t1, t0);
16177 tcg_gen_shri_i64(t2, t2, 8 * (4 - sa));
16178 #if defined(TARGET_MIPS64)
16179 tcg_gen_ext32s_i64(cpu_gpr[rd], t2);
16180 #else
16181 tcg_gen_trunc_i64_i32(cpu_gpr[rd], t2);
16182 #endif
16183 tcg_temp_free_i64(t2);
16184 tcg_temp_free(t1);
16186 break;
16187 case OPC_BITSWAP:
16188 gen_helper_bitswap(cpu_gpr[rd], t0);
16189 break;
16191 tcg_temp_free(t0);
16193 break;
16194 #if defined(TARGET_MIPS64)
16195 case R6_OPC_SCD:
16196 gen_st_cond(ctx, op1, rt, rs, imm);
16197 break;
16198 case R6_OPC_LLD:
16199 gen_ld(ctx, op1, rt, rs, imm);
16200 break;
16201 case OPC_DBSHFL:
16202 check_mips_64(ctx);
16204 if (rd == 0) {
16205 /* Treat as NOP. */
16206 break;
16208 TCGv t0 = tcg_temp_new();
16209 gen_load_gpr(t0, rt);
16211 op2 = MASK_DBSHFL(ctx->opcode);
16212 switch (op2) {
16213 case OPC_DALIGN ... OPC_DALIGN_END:
16214 sa &= 7;
16215 if (sa == 0) {
16216 tcg_gen_mov_tl(cpu_gpr[rd], t0);
16217 } else {
16218 TCGv t1 = tcg_temp_new();
16219 gen_load_gpr(t1, rs);
16220 tcg_gen_shli_tl(t0, t0, 8 * sa);
16221 tcg_gen_shri_tl(t1, t1, 8 * (8 - sa));
16222 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
16223 tcg_temp_free(t1);
16225 break;
16226 case OPC_DBITSWAP:
16227 gen_helper_dbitswap(cpu_gpr[rd], t0);
16228 break;
16230 tcg_temp_free(t0);
16232 break;
16233 #endif
16234 default: /* Invalid */
16235 MIPS_INVAL("special3_r6");
16236 generate_exception(ctx, EXCP_RI);
16237 break;
16241 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
16243 int rs, rt, rd;
16244 uint32_t op1, op2;
16246 rs = (ctx->opcode >> 21) & 0x1f;
16247 rt = (ctx->opcode >> 16) & 0x1f;
16248 rd = (ctx->opcode >> 11) & 0x1f;
16250 op1 = MASK_SPECIAL3(ctx->opcode);
16251 switch (op1) {
16252 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
16253 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
16254 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
16255 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
16256 * the same mask and op1. */
16257 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
16258 op2 = MASK_ADDUH_QB(ctx->opcode);
16259 switch (op2) {
16260 case OPC_ADDUH_QB:
16261 case OPC_ADDUH_R_QB:
16262 case OPC_ADDQH_PH:
16263 case OPC_ADDQH_R_PH:
16264 case OPC_ADDQH_W:
16265 case OPC_ADDQH_R_W:
16266 case OPC_SUBUH_QB:
16267 case OPC_SUBUH_R_QB:
16268 case OPC_SUBQH_PH:
16269 case OPC_SUBQH_R_PH:
16270 case OPC_SUBQH_W:
16271 case OPC_SUBQH_R_W:
16272 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16273 break;
16274 case OPC_MUL_PH:
16275 case OPC_MUL_S_PH:
16276 case OPC_MULQ_S_W:
16277 case OPC_MULQ_RS_W:
16278 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16279 break;
16280 default:
16281 MIPS_INVAL("MASK ADDUH.QB");
16282 generate_exception(ctx, EXCP_RI);
16283 break;
16285 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
16286 gen_loongson_integer(ctx, op1, rd, rs, rt);
16287 } else {
16288 generate_exception(ctx, EXCP_RI);
16290 break;
16291 case OPC_LX_DSP:
16292 op2 = MASK_LX(ctx->opcode);
16293 switch (op2) {
16294 #if defined(TARGET_MIPS64)
16295 case OPC_LDX:
16296 #endif
16297 case OPC_LBUX:
16298 case OPC_LHX:
16299 case OPC_LWX:
16300 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
16301 break;
16302 default: /* Invalid */
16303 MIPS_INVAL("MASK LX");
16304 generate_exception(ctx, EXCP_RI);
16305 break;
16307 break;
16308 case OPC_ABSQ_S_PH_DSP:
16309 op2 = MASK_ABSQ_S_PH(ctx->opcode);
16310 switch (op2) {
16311 case OPC_ABSQ_S_QB:
16312 case OPC_ABSQ_S_PH:
16313 case OPC_ABSQ_S_W:
16314 case OPC_PRECEQ_W_PHL:
16315 case OPC_PRECEQ_W_PHR:
16316 case OPC_PRECEQU_PH_QBL:
16317 case OPC_PRECEQU_PH_QBR:
16318 case OPC_PRECEQU_PH_QBLA:
16319 case OPC_PRECEQU_PH_QBRA:
16320 case OPC_PRECEU_PH_QBL:
16321 case OPC_PRECEU_PH_QBR:
16322 case OPC_PRECEU_PH_QBLA:
16323 case OPC_PRECEU_PH_QBRA:
16324 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16325 break;
16326 case OPC_BITREV:
16327 case OPC_REPL_QB:
16328 case OPC_REPLV_QB:
16329 case OPC_REPL_PH:
16330 case OPC_REPLV_PH:
16331 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16332 break;
16333 default:
16334 MIPS_INVAL("MASK ABSQ_S.PH");
16335 generate_exception(ctx, EXCP_RI);
16336 break;
16338 break;
16339 case OPC_ADDU_QB_DSP:
16340 op2 = MASK_ADDU_QB(ctx->opcode);
16341 switch (op2) {
16342 case OPC_ADDQ_PH:
16343 case OPC_ADDQ_S_PH:
16344 case OPC_ADDQ_S_W:
16345 case OPC_ADDU_QB:
16346 case OPC_ADDU_S_QB:
16347 case OPC_ADDU_PH:
16348 case OPC_ADDU_S_PH:
16349 case OPC_SUBQ_PH:
16350 case OPC_SUBQ_S_PH:
16351 case OPC_SUBQ_S_W:
16352 case OPC_SUBU_QB:
16353 case OPC_SUBU_S_QB:
16354 case OPC_SUBU_PH:
16355 case OPC_SUBU_S_PH:
16356 case OPC_ADDSC:
16357 case OPC_ADDWC:
16358 case OPC_MODSUB:
16359 case OPC_RADDU_W_QB:
16360 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16361 break;
16362 case OPC_MULEU_S_PH_QBL:
16363 case OPC_MULEU_S_PH_QBR:
16364 case OPC_MULQ_RS_PH:
16365 case OPC_MULEQ_S_W_PHL:
16366 case OPC_MULEQ_S_W_PHR:
16367 case OPC_MULQ_S_PH:
16368 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16369 break;
16370 default: /* Invalid */
16371 MIPS_INVAL("MASK ADDU.QB");
16372 generate_exception(ctx, EXCP_RI);
16373 break;
16376 break;
16377 case OPC_CMPU_EQ_QB_DSP:
16378 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
16379 switch (op2) {
16380 case OPC_PRECR_SRA_PH_W:
16381 case OPC_PRECR_SRA_R_PH_W:
16382 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
16383 break;
16384 case OPC_PRECR_QB_PH:
16385 case OPC_PRECRQ_QB_PH:
16386 case OPC_PRECRQ_PH_W:
16387 case OPC_PRECRQ_RS_PH_W:
16388 case OPC_PRECRQU_S_QB_PH:
16389 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16390 break;
16391 case OPC_CMPU_EQ_QB:
16392 case OPC_CMPU_LT_QB:
16393 case OPC_CMPU_LE_QB:
16394 case OPC_CMP_EQ_PH:
16395 case OPC_CMP_LT_PH:
16396 case OPC_CMP_LE_PH:
16397 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
16398 break;
16399 case OPC_CMPGU_EQ_QB:
16400 case OPC_CMPGU_LT_QB:
16401 case OPC_CMPGU_LE_QB:
16402 case OPC_CMPGDU_EQ_QB:
16403 case OPC_CMPGDU_LT_QB:
16404 case OPC_CMPGDU_LE_QB:
16405 case OPC_PICK_QB:
16406 case OPC_PICK_PH:
16407 case OPC_PACKRL_PH:
16408 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
16409 break;
16410 default: /* Invalid */
16411 MIPS_INVAL("MASK CMPU.EQ.QB");
16412 generate_exception(ctx, EXCP_RI);
16413 break;
16415 break;
16416 case OPC_SHLL_QB_DSP:
16417 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16418 break;
16419 case OPC_DPA_W_PH_DSP:
16420 op2 = MASK_DPA_W_PH(ctx->opcode);
16421 switch (op2) {
16422 case OPC_DPAU_H_QBL:
16423 case OPC_DPAU_H_QBR:
16424 case OPC_DPSU_H_QBL:
16425 case OPC_DPSU_H_QBR:
16426 case OPC_DPA_W_PH:
16427 case OPC_DPAX_W_PH:
16428 case OPC_DPAQ_S_W_PH:
16429 case OPC_DPAQX_S_W_PH:
16430 case OPC_DPAQX_SA_W_PH:
16431 case OPC_DPS_W_PH:
16432 case OPC_DPSX_W_PH:
16433 case OPC_DPSQ_S_W_PH:
16434 case OPC_DPSQX_S_W_PH:
16435 case OPC_DPSQX_SA_W_PH:
16436 case OPC_MULSAQ_S_W_PH:
16437 case OPC_DPAQ_SA_L_W:
16438 case OPC_DPSQ_SA_L_W:
16439 case OPC_MAQ_S_W_PHL:
16440 case OPC_MAQ_S_W_PHR:
16441 case OPC_MAQ_SA_W_PHL:
16442 case OPC_MAQ_SA_W_PHR:
16443 case OPC_MULSA_W_PH:
16444 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16445 break;
16446 default: /* Invalid */
16447 MIPS_INVAL("MASK DPAW.PH");
16448 generate_exception(ctx, EXCP_RI);
16449 break;
16451 break;
16452 case OPC_INSV_DSP:
16453 op2 = MASK_INSV(ctx->opcode);
16454 switch (op2) {
16455 case OPC_INSV:
16456 check_dsp(ctx);
16458 TCGv t0, t1;
16460 if (rt == 0) {
16461 MIPS_DEBUG("NOP");
16462 break;
16465 t0 = tcg_temp_new();
16466 t1 = tcg_temp_new();
16468 gen_load_gpr(t0, rt);
16469 gen_load_gpr(t1, rs);
16471 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
16473 tcg_temp_free(t0);
16474 tcg_temp_free(t1);
16475 break;
16477 default: /* Invalid */
16478 MIPS_INVAL("MASK INSV");
16479 generate_exception(ctx, EXCP_RI);
16480 break;
16482 break;
16483 case OPC_APPEND_DSP:
16484 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16485 break;
16486 case OPC_EXTR_W_DSP:
16487 op2 = MASK_EXTR_W(ctx->opcode);
16488 switch (op2) {
16489 case OPC_EXTR_W:
16490 case OPC_EXTR_R_W:
16491 case OPC_EXTR_RS_W:
16492 case OPC_EXTR_S_H:
16493 case OPC_EXTRV_S_H:
16494 case OPC_EXTRV_W:
16495 case OPC_EXTRV_R_W:
16496 case OPC_EXTRV_RS_W:
16497 case OPC_EXTP:
16498 case OPC_EXTPV:
16499 case OPC_EXTPDP:
16500 case OPC_EXTPDPV:
16501 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
16502 break;
16503 case OPC_RDDSP:
16504 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
16505 break;
16506 case OPC_SHILO:
16507 case OPC_SHILOV:
16508 case OPC_MTHLIP:
16509 case OPC_WRDSP:
16510 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
16511 break;
16512 default: /* Invalid */
16513 MIPS_INVAL("MASK EXTR.W");
16514 generate_exception(ctx, EXCP_RI);
16515 break;
16517 break;
16518 #if defined(TARGET_MIPS64)
16519 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
16520 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
16521 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
16522 check_insn(ctx, INSN_LOONGSON2E);
16523 gen_loongson_integer(ctx, op1, rd, rs, rt);
16524 break;
16525 case OPC_ABSQ_S_QH_DSP:
16526 op2 = MASK_ABSQ_S_QH(ctx->opcode);
16527 switch (op2) {
16528 case OPC_PRECEQ_L_PWL:
16529 case OPC_PRECEQ_L_PWR:
16530 case OPC_PRECEQ_PW_QHL:
16531 case OPC_PRECEQ_PW_QHR:
16532 case OPC_PRECEQ_PW_QHLA:
16533 case OPC_PRECEQ_PW_QHRA:
16534 case OPC_PRECEQU_QH_OBL:
16535 case OPC_PRECEQU_QH_OBR:
16536 case OPC_PRECEQU_QH_OBLA:
16537 case OPC_PRECEQU_QH_OBRA:
16538 case OPC_PRECEU_QH_OBL:
16539 case OPC_PRECEU_QH_OBR:
16540 case OPC_PRECEU_QH_OBLA:
16541 case OPC_PRECEU_QH_OBRA:
16542 case OPC_ABSQ_S_OB:
16543 case OPC_ABSQ_S_PW:
16544 case OPC_ABSQ_S_QH:
16545 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16546 break;
16547 case OPC_REPL_OB:
16548 case OPC_REPL_PW:
16549 case OPC_REPL_QH:
16550 case OPC_REPLV_OB:
16551 case OPC_REPLV_PW:
16552 case OPC_REPLV_QH:
16553 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
16554 break;
16555 default: /* Invalid */
16556 MIPS_INVAL("MASK ABSQ_S.QH");
16557 generate_exception(ctx, EXCP_RI);
16558 break;
16560 break;
16561 case OPC_ADDU_OB_DSP:
16562 op2 = MASK_ADDU_OB(ctx->opcode);
16563 switch (op2) {
16564 case OPC_RADDU_L_OB:
16565 case OPC_SUBQ_PW:
16566 case OPC_SUBQ_S_PW:
16567 case OPC_SUBQ_QH:
16568 case OPC_SUBQ_S_QH:
16569 case OPC_SUBU_OB:
16570 case OPC_SUBU_S_OB:
16571 case OPC_SUBU_QH:
16572 case OPC_SUBU_S_QH:
16573 case OPC_SUBUH_OB:
16574 case OPC_SUBUH_R_OB:
16575 case OPC_ADDQ_PW:
16576 case OPC_ADDQ_S_PW:
16577 case OPC_ADDQ_QH:
16578 case OPC_ADDQ_S_QH:
16579 case OPC_ADDU_OB:
16580 case OPC_ADDU_S_OB:
16581 case OPC_ADDU_QH:
16582 case OPC_ADDU_S_QH:
16583 case OPC_ADDUH_OB:
16584 case OPC_ADDUH_R_OB:
16585 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16586 break;
16587 case OPC_MULEQ_S_PW_QHL:
16588 case OPC_MULEQ_S_PW_QHR:
16589 case OPC_MULEU_S_QH_OBL:
16590 case OPC_MULEU_S_QH_OBR:
16591 case OPC_MULQ_RS_QH:
16592 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
16593 break;
16594 default: /* Invalid */
16595 MIPS_INVAL("MASK ADDU.OB");
16596 generate_exception(ctx, EXCP_RI);
16597 break;
16599 break;
16600 case OPC_CMPU_EQ_OB_DSP:
16601 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
16602 switch (op2) {
16603 case OPC_PRECR_SRA_QH_PW:
16604 case OPC_PRECR_SRA_R_QH_PW:
16605 /* Return value is rt. */
16606 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
16607 break;
16608 case OPC_PRECR_OB_QH:
16609 case OPC_PRECRQ_OB_QH:
16610 case OPC_PRECRQ_PW_L:
16611 case OPC_PRECRQ_QH_PW:
16612 case OPC_PRECRQ_RS_QH_PW:
16613 case OPC_PRECRQU_S_OB_QH:
16614 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
16615 break;
16616 case OPC_CMPU_EQ_OB:
16617 case OPC_CMPU_LT_OB:
16618 case OPC_CMPU_LE_OB:
16619 case OPC_CMP_EQ_QH:
16620 case OPC_CMP_LT_QH:
16621 case OPC_CMP_LE_QH:
16622 case OPC_CMP_EQ_PW:
16623 case OPC_CMP_LT_PW:
16624 case OPC_CMP_LE_PW:
16625 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
16626 break;
16627 case OPC_CMPGDU_EQ_OB:
16628 case OPC_CMPGDU_LT_OB:
16629 case OPC_CMPGDU_LE_OB:
16630 case OPC_CMPGU_EQ_OB:
16631 case OPC_CMPGU_LT_OB:
16632 case OPC_CMPGU_LE_OB:
16633 case OPC_PACKRL_PW:
16634 case OPC_PICK_OB:
16635 case OPC_PICK_PW:
16636 case OPC_PICK_QH:
16637 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
16638 break;
16639 default: /* Invalid */
16640 MIPS_INVAL("MASK CMPU_EQ.OB");
16641 generate_exception(ctx, EXCP_RI);
16642 break;
16644 break;
16645 case OPC_DAPPEND_DSP:
16646 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
16647 break;
16648 case OPC_DEXTR_W_DSP:
16649 op2 = MASK_DEXTR_W(ctx->opcode);
16650 switch (op2) {
16651 case OPC_DEXTP:
16652 case OPC_DEXTPDP:
16653 case OPC_DEXTPDPV:
16654 case OPC_DEXTPV:
16655 case OPC_DEXTR_L:
16656 case OPC_DEXTR_R_L:
16657 case OPC_DEXTR_RS_L:
16658 case OPC_DEXTR_W:
16659 case OPC_DEXTR_R_W:
16660 case OPC_DEXTR_RS_W:
16661 case OPC_DEXTR_S_H:
16662 case OPC_DEXTRV_L:
16663 case OPC_DEXTRV_R_L:
16664 case OPC_DEXTRV_RS_L:
16665 case OPC_DEXTRV_S_H:
16666 case OPC_DEXTRV_W:
16667 case OPC_DEXTRV_R_W:
16668 case OPC_DEXTRV_RS_W:
16669 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
16670 break;
16671 case OPC_DMTHLIP:
16672 case OPC_DSHILO:
16673 case OPC_DSHILOV:
16674 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
16675 break;
16676 default: /* Invalid */
16677 MIPS_INVAL("MASK EXTR.W");
16678 generate_exception(ctx, EXCP_RI);
16679 break;
16681 break;
16682 case OPC_DPAQ_W_QH_DSP:
16683 op2 = MASK_DPAQ_W_QH(ctx->opcode);
16684 switch (op2) {
16685 case OPC_DPAU_H_OBL:
16686 case OPC_DPAU_H_OBR:
16687 case OPC_DPSU_H_OBL:
16688 case OPC_DPSU_H_OBR:
16689 case OPC_DPA_W_QH:
16690 case OPC_DPAQ_S_W_QH:
16691 case OPC_DPS_W_QH:
16692 case OPC_DPSQ_S_W_QH:
16693 case OPC_MULSAQ_S_W_QH:
16694 case OPC_DPAQ_SA_L_PW:
16695 case OPC_DPSQ_SA_L_PW:
16696 case OPC_MULSAQ_S_L_PW:
16697 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16698 break;
16699 case OPC_MAQ_S_W_QHLL:
16700 case OPC_MAQ_S_W_QHLR:
16701 case OPC_MAQ_S_W_QHRL:
16702 case OPC_MAQ_S_W_QHRR:
16703 case OPC_MAQ_SA_W_QHLL:
16704 case OPC_MAQ_SA_W_QHLR:
16705 case OPC_MAQ_SA_W_QHRL:
16706 case OPC_MAQ_SA_W_QHRR:
16707 case OPC_MAQ_S_L_PWL:
16708 case OPC_MAQ_S_L_PWR:
16709 case OPC_DMADD:
16710 case OPC_DMADDU:
16711 case OPC_DMSUB:
16712 case OPC_DMSUBU:
16713 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
16714 break;
16715 default: /* Invalid */
16716 MIPS_INVAL("MASK DPAQ.W.QH");
16717 generate_exception(ctx, EXCP_RI);
16718 break;
16720 break;
16721 case OPC_DINSV_DSP:
16722 op2 = MASK_INSV(ctx->opcode);
16723 switch (op2) {
16724 case OPC_DINSV:
16726 TCGv t0, t1;
16728 if (rt == 0) {
16729 MIPS_DEBUG("NOP");
16730 break;
16732 check_dsp(ctx);
16734 t0 = tcg_temp_new();
16735 t1 = tcg_temp_new();
16737 gen_load_gpr(t0, rt);
16738 gen_load_gpr(t1, rs);
16740 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
16742 tcg_temp_free(t0);
16743 tcg_temp_free(t1);
16744 break;
16746 default: /* Invalid */
16747 MIPS_INVAL("MASK DINSV");
16748 generate_exception(ctx, EXCP_RI);
16749 break;
16751 break;
16752 case OPC_SHLL_OB_DSP:
16753 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
16754 break;
16755 #endif
16756 default: /* Invalid */
16757 MIPS_INVAL("special3_legacy");
16758 generate_exception(ctx, EXCP_RI);
16759 break;
16763 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
16765 int rs, rt, rd, sa;
16766 uint32_t op1, op2;
16768 rs = (ctx->opcode >> 21) & 0x1f;
16769 rt = (ctx->opcode >> 16) & 0x1f;
16770 rd = (ctx->opcode >> 11) & 0x1f;
16771 sa = (ctx->opcode >> 6) & 0x1f;
16773 op1 = MASK_SPECIAL3(ctx->opcode);
16774 switch (op1) {
16775 case OPC_EXT:
16776 case OPC_INS:
16777 check_insn(ctx, ISA_MIPS32R2);
16778 gen_bitops(ctx, op1, rt, rs, sa, rd);
16779 break;
16780 case OPC_BSHFL:
16781 op2 = MASK_BSHFL(ctx->opcode);
16782 switch (op2) {
16783 case OPC_ALIGN ... OPC_ALIGN_END:
16784 case OPC_BITSWAP:
16785 check_insn(ctx, ISA_MIPS32R6);
16786 decode_opc_special3_r6(env, ctx);
16787 break;
16788 default:
16789 check_insn(ctx, ISA_MIPS32R2);
16790 gen_bshfl(ctx, op2, rt, rd);
16791 break;
16793 break;
16794 #if defined(TARGET_MIPS64)
16795 case OPC_DEXTM ... OPC_DEXT:
16796 case OPC_DINSM ... OPC_DINS:
16797 check_insn(ctx, ISA_MIPS64R2);
16798 check_mips_64(ctx);
16799 gen_bitops(ctx, op1, rt, rs, sa, rd);
16800 break;
16801 case OPC_DBSHFL:
16802 op2 = MASK_DBSHFL(ctx->opcode);
16803 switch (op2) {
16804 case OPC_DALIGN ... OPC_DALIGN_END:
16805 case OPC_DBITSWAP:
16806 check_insn(ctx, ISA_MIPS32R6);
16807 decode_opc_special3_r6(env, ctx);
16808 break;
16809 default:
16810 check_insn(ctx, ISA_MIPS64R2);
16811 check_mips_64(ctx);
16812 op2 = MASK_DBSHFL(ctx->opcode);
16813 gen_bshfl(ctx, op2, rt, rd);
16814 break;
16816 break;
16817 #endif
16818 case OPC_RDHWR:
16819 gen_rdhwr(ctx, rt, rd);
16820 break;
16821 case OPC_FORK:
16822 check_insn(ctx, ASE_MT);
16824 TCGv t0 = tcg_temp_new();
16825 TCGv t1 = tcg_temp_new();
16827 gen_load_gpr(t0, rt);
16828 gen_load_gpr(t1, rs);
16829 gen_helper_fork(t0, t1);
16830 tcg_temp_free(t0);
16831 tcg_temp_free(t1);
16833 break;
16834 case OPC_YIELD:
16835 check_insn(ctx, ASE_MT);
16837 TCGv t0 = tcg_temp_new();
16839 save_cpu_state(ctx, 1);
16840 gen_load_gpr(t0, rs);
16841 gen_helper_yield(t0, cpu_env, t0);
16842 gen_store_gpr(t0, rd);
16843 tcg_temp_free(t0);
16845 break;
16846 default:
16847 if (ctx->insn_flags & ISA_MIPS32R6) {
16848 decode_opc_special3_r6(env, ctx);
16849 } else {
16850 decode_opc_special3_legacy(env, ctx);
16855 static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
16857 int32_t offset;
16858 int rs, rt, rd, sa;
16859 uint32_t op, op1;
16860 int16_t imm;
16862 /* make sure instructions are on a word boundary */
16863 if (ctx->pc & 0x3) {
16864 env->CP0_BadVAddr = ctx->pc;
16865 generate_exception(ctx, EXCP_AdEL);
16866 return;
16869 /* Handle blikely not taken case */
16870 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
16871 int l1 = gen_new_label();
16873 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
16874 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
16875 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
16876 gen_goto_tb(ctx, 1, ctx->pc + 4);
16877 gen_set_label(l1);
16880 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
16881 tcg_gen_debug_insn_start(ctx->pc);
16884 op = MASK_OP_MAJOR(ctx->opcode);
16885 rs = (ctx->opcode >> 21) & 0x1f;
16886 rt = (ctx->opcode >> 16) & 0x1f;
16887 rd = (ctx->opcode >> 11) & 0x1f;
16888 sa = (ctx->opcode >> 6) & 0x1f;
16889 imm = (int16_t)ctx->opcode;
16890 switch (op) {
16891 case OPC_SPECIAL:
16892 decode_opc_special(env, ctx);
16893 break;
16894 case OPC_SPECIAL2:
16895 decode_opc_special2_legacy(env, ctx);
16896 break;
16897 case OPC_SPECIAL3:
16898 decode_opc_special3(env, ctx);
16899 break;
16900 case OPC_REGIMM:
16901 op1 = MASK_REGIMM(ctx->opcode);
16902 switch (op1) {
16903 case OPC_BLTZL: /* REGIMM branches */
16904 case OPC_BGEZL:
16905 case OPC_BLTZALL:
16906 case OPC_BGEZALL:
16907 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16908 case OPC_BLTZ:
16909 case OPC_BGEZ:
16910 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
16911 break;
16912 case OPC_BLTZAL:
16913 case OPC_BGEZAL:
16914 if (ctx->insn_flags & ISA_MIPS32R6) {
16915 if (rs == 0) {
16916 /* OPC_NAL, OPC_BAL */
16917 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
16918 } else {
16919 generate_exception(ctx, EXCP_RI);
16921 } else {
16922 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
16924 break;
16925 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
16926 case OPC_TNEI:
16927 check_insn_opc_removed(ctx, ISA_MIPS32R6);
16928 gen_trap(ctx, op1, rs, -1, imm);
16929 break;
16930 case OPC_SYNCI:
16931 check_insn(ctx, ISA_MIPS32R2);
16932 /* Break the TB to be able to sync copied instructions
16933 immediately */
16934 ctx->bstate = BS_STOP;
16935 break;
16936 case OPC_BPOSGE32: /* MIPS DSP branch */
16937 #if defined(TARGET_MIPS64)
16938 case OPC_BPOSGE64:
16939 #endif
16940 check_dsp(ctx);
16941 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
16942 break;
16943 #if defined(TARGET_MIPS64)
16944 case OPC_DAHI:
16945 check_insn(ctx, ISA_MIPS32R6);
16946 check_mips_64(ctx);
16947 if (rs != 0) {
16948 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
16950 MIPS_DEBUG("dahi %s, %04x", regnames[rs], imm);
16951 break;
16952 case OPC_DATI:
16953 check_insn(ctx, ISA_MIPS32R6);
16954 check_mips_64(ctx);
16955 if (rs != 0) {
16956 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
16958 MIPS_DEBUG("dati %s, %04x", regnames[rs], imm);
16959 break;
16960 #endif
16961 default: /* Invalid */
16962 MIPS_INVAL("regimm");
16963 generate_exception(ctx, EXCP_RI);
16964 break;
16966 break;
16967 case OPC_CP0:
16968 check_cp0_enabled(ctx);
16969 op1 = MASK_CP0(ctx->opcode);
16970 switch (op1) {
16971 case OPC_MFC0:
16972 case OPC_MTC0:
16973 case OPC_MFTR:
16974 case OPC_MTTR:
16975 #if defined(TARGET_MIPS64)
16976 case OPC_DMFC0:
16977 case OPC_DMTC0:
16978 #endif
16979 #ifndef CONFIG_USER_ONLY
16980 gen_cp0(env, ctx, op1, rt, rd);
16981 #endif /* !CONFIG_USER_ONLY */
16982 break;
16983 case OPC_C0_FIRST ... OPC_C0_LAST:
16984 #ifndef CONFIG_USER_ONLY
16985 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
16986 #endif /* !CONFIG_USER_ONLY */
16987 break;
16988 case OPC_MFMC0:
16989 #ifndef CONFIG_USER_ONLY
16991 uint32_t op2;
16992 TCGv t0 = tcg_temp_new();
16994 op2 = MASK_MFMC0(ctx->opcode);
16995 switch (op2) {
16996 case OPC_DMT:
16997 check_insn(ctx, ASE_MT);
16998 gen_helper_dmt(t0);
16999 gen_store_gpr(t0, rt);
17000 break;
17001 case OPC_EMT:
17002 check_insn(ctx, ASE_MT);
17003 gen_helper_emt(t0);
17004 gen_store_gpr(t0, rt);
17005 break;
17006 case OPC_DVPE:
17007 check_insn(ctx, ASE_MT);
17008 gen_helper_dvpe(t0, cpu_env);
17009 gen_store_gpr(t0, rt);
17010 break;
17011 case OPC_EVPE:
17012 check_insn(ctx, ASE_MT);
17013 gen_helper_evpe(t0, cpu_env);
17014 gen_store_gpr(t0, rt);
17015 break;
17016 case OPC_DI:
17017 check_insn(ctx, ISA_MIPS32R2);
17018 save_cpu_state(ctx, 1);
17019 gen_helper_di(t0, cpu_env);
17020 gen_store_gpr(t0, rt);
17021 /* Stop translation as we may have switched the execution mode */
17022 ctx->bstate = BS_STOP;
17023 break;
17024 case OPC_EI:
17025 check_insn(ctx, ISA_MIPS32R2);
17026 save_cpu_state(ctx, 1);
17027 gen_helper_ei(t0, cpu_env);
17028 gen_store_gpr(t0, rt);
17029 /* Stop translation as we may have switched the execution mode */
17030 ctx->bstate = BS_STOP;
17031 break;
17032 default: /* Invalid */
17033 MIPS_INVAL("mfmc0");
17034 generate_exception(ctx, EXCP_RI);
17035 break;
17037 tcg_temp_free(t0);
17039 #endif /* !CONFIG_USER_ONLY */
17040 break;
17041 case OPC_RDPGPR:
17042 check_insn(ctx, ISA_MIPS32R2);
17043 gen_load_srsgpr(rt, rd);
17044 break;
17045 case OPC_WRPGPR:
17046 check_insn(ctx, ISA_MIPS32R2);
17047 gen_store_srsgpr(rt, rd);
17048 break;
17049 default:
17050 MIPS_INVAL("cp0");
17051 generate_exception(ctx, EXCP_RI);
17052 break;
17054 break;
17055 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
17056 if (ctx->insn_flags & ISA_MIPS32R6) {
17057 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
17058 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17059 } else {
17060 /* OPC_ADDI */
17061 /* Arithmetic with immediate opcode */
17062 gen_arith_imm(ctx, op, rt, rs, imm);
17064 break;
17065 case OPC_ADDIU:
17066 gen_arith_imm(ctx, op, rt, rs, imm);
17067 break;
17068 case OPC_SLTI: /* Set on less than with immediate opcode */
17069 case OPC_SLTIU:
17070 gen_slt_imm(ctx, op, rt, rs, imm);
17071 break;
17072 case OPC_ANDI: /* Arithmetic with immediate opcode */
17073 case OPC_LUI: /* OPC_AUI */
17074 case OPC_ORI:
17075 case OPC_XORI:
17076 gen_logic_imm(ctx, op, rt, rs, imm);
17077 break;
17078 case OPC_J ... OPC_JAL: /* Jump */
17079 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17080 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
17081 break;
17082 /* Branch */
17083 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
17084 if (ctx->insn_flags & ISA_MIPS32R6) {
17085 if (rt == 0) {
17086 generate_exception(ctx, EXCP_RI);
17087 break;
17089 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
17090 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17091 } else {
17092 /* OPC_BLEZL */
17093 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17095 break;
17096 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
17097 if (ctx->insn_flags & ISA_MIPS32R6) {
17098 if (rt == 0) {
17099 generate_exception(ctx, EXCP_RI);
17100 break;
17102 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
17103 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17104 } else {
17105 /* OPC_BGTZL */
17106 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17108 break;
17109 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
17110 if (rt == 0) {
17111 /* OPC_BLEZ */
17112 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17113 } else {
17114 check_insn(ctx, ISA_MIPS32R6);
17115 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
17116 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17118 break;
17119 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
17120 if (rt == 0) {
17121 /* OPC_BGTZ */
17122 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17123 } else {
17124 check_insn(ctx, ISA_MIPS32R6);
17125 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
17126 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17128 break;
17129 case OPC_BEQL:
17130 case OPC_BNEL:
17131 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17132 case OPC_BEQ:
17133 case OPC_BNE:
17134 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
17135 break;
17136 case OPC_LWL: /* Load and stores */
17137 case OPC_LWR:
17138 case OPC_LL:
17139 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17140 case OPC_LB ... OPC_LH:
17141 case OPC_LW ... OPC_LHU:
17142 gen_ld(ctx, op, rt, rs, imm);
17143 break;
17144 case OPC_SWL:
17145 case OPC_SWR:
17146 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17147 case OPC_SB ... OPC_SH:
17148 case OPC_SW:
17149 gen_st(ctx, op, rt, rs, imm);
17150 break;
17151 case OPC_SC:
17152 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17153 gen_st_cond(ctx, op, rt, rs, imm);
17154 break;
17155 case OPC_CACHE:
17156 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17157 check_cp0_enabled(ctx);
17158 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
17159 /* Treat as NOP. */
17160 break;
17161 case OPC_PREF:
17162 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17163 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
17164 /* Treat as NOP. */
17165 break;
17167 /* Floating point (COP1). */
17168 case OPC_LWC1:
17169 case OPC_LDC1:
17170 case OPC_SWC1:
17171 case OPC_SDC1:
17172 gen_cop1_ldst(ctx, op, rt, rs, imm);
17173 break;
17175 case OPC_CP1:
17176 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
17177 check_cp1_enabled(ctx);
17178 op1 = MASK_CP1(ctx->opcode);
17179 switch (op1) {
17180 case OPC_MFHC1:
17181 case OPC_MTHC1:
17182 check_insn(ctx, ISA_MIPS32R2);
17183 case OPC_MFC1:
17184 case OPC_CFC1:
17185 case OPC_MTC1:
17186 case OPC_CTC1:
17187 gen_cp1(ctx, op1, rt, rd);
17188 break;
17189 #if defined(TARGET_MIPS64)
17190 case OPC_DMFC1:
17191 case OPC_DMTC1:
17192 check_insn(ctx, ISA_MIPS3);
17193 gen_cp1(ctx, op1, rt, rd);
17194 break;
17195 #endif
17196 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
17197 if (ctx->insn_flags & ISA_MIPS32R6) {
17198 /* OPC_BC1EQZ */
17199 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
17200 rt, imm << 2);
17201 } else {
17202 /* OPC_BC1ANY2 */
17203 check_cop1x(ctx);
17204 check_insn(ctx, ASE_MIPS3D);
17205 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
17206 (rt >> 2) & 0x7, imm << 2);
17208 break;
17209 case OPC_BC1NEZ:
17210 check_insn(ctx, ISA_MIPS32R6);
17211 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
17212 rt, imm << 2);
17213 break;
17214 case OPC_BC1ANY4:
17215 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17216 check_cop1x(ctx);
17217 check_insn(ctx, ASE_MIPS3D);
17218 /* fall through */
17219 case OPC_BC1:
17220 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17221 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
17222 (rt >> 2) & 0x7, imm << 2);
17223 break;
17224 case OPC_PS_FMT:
17225 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17226 case OPC_S_FMT:
17227 case OPC_D_FMT:
17228 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17229 (imm >> 8) & 0x7);
17230 break;
17231 case OPC_W_FMT:
17232 case OPC_L_FMT:
17234 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
17235 if (ctx->insn_flags & ISA_MIPS32R6) {
17236 switch (r6_op) {
17237 case R6_OPC_CMP_AF_S:
17238 case R6_OPC_CMP_UN_S:
17239 case R6_OPC_CMP_EQ_S:
17240 case R6_OPC_CMP_UEQ_S:
17241 case R6_OPC_CMP_LT_S:
17242 case R6_OPC_CMP_ULT_S:
17243 case R6_OPC_CMP_LE_S:
17244 case R6_OPC_CMP_ULE_S:
17245 case R6_OPC_CMP_SAF_S:
17246 case R6_OPC_CMP_SUN_S:
17247 case R6_OPC_CMP_SEQ_S:
17248 case R6_OPC_CMP_SEUQ_S:
17249 case R6_OPC_CMP_SLT_S:
17250 case R6_OPC_CMP_SULT_S:
17251 case R6_OPC_CMP_SLE_S:
17252 case R6_OPC_CMP_SULE_S:
17253 case R6_OPC_CMP_OR_S:
17254 case R6_OPC_CMP_UNE_S:
17255 case R6_OPC_CMP_NE_S:
17256 case R6_OPC_CMP_SOR_S:
17257 case R6_OPC_CMP_SUNE_S:
17258 case R6_OPC_CMP_SNE_S:
17259 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
17260 break;
17261 case R6_OPC_CMP_AF_D:
17262 case R6_OPC_CMP_UN_D:
17263 case R6_OPC_CMP_EQ_D:
17264 case R6_OPC_CMP_UEQ_D:
17265 case R6_OPC_CMP_LT_D:
17266 case R6_OPC_CMP_ULT_D:
17267 case R6_OPC_CMP_LE_D:
17268 case R6_OPC_CMP_ULE_D:
17269 case R6_OPC_CMP_SAF_D:
17270 case R6_OPC_CMP_SUN_D:
17271 case R6_OPC_CMP_SEQ_D:
17272 case R6_OPC_CMP_SEUQ_D:
17273 case R6_OPC_CMP_SLT_D:
17274 case R6_OPC_CMP_SULT_D:
17275 case R6_OPC_CMP_SLE_D:
17276 case R6_OPC_CMP_SULE_D:
17277 case R6_OPC_CMP_OR_D:
17278 case R6_OPC_CMP_UNE_D:
17279 case R6_OPC_CMP_NE_D:
17280 case R6_OPC_CMP_SOR_D:
17281 case R6_OPC_CMP_SUNE_D:
17282 case R6_OPC_CMP_SNE_D:
17283 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
17284 break;
17285 default:
17286 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17287 (imm >> 8) & 0x7);
17288 break;
17290 } else {
17291 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
17292 (imm >> 8) & 0x7);
17294 break;
17296 default:
17297 MIPS_INVAL("cp1");
17298 generate_exception (ctx, EXCP_RI);
17299 break;
17301 } else {
17302 generate_exception_err(ctx, EXCP_CpU, 1);
17304 break;
17306 /* Compact branches [R6] and COP2 [non-R6] */
17307 case OPC_BC: /* OPC_LWC2 */
17308 case OPC_BALC: /* OPC_SWC2 */
17309 if (ctx->insn_flags & ISA_MIPS32R6) {
17310 /* OPC_BC, OPC_BALC */
17311 gen_compute_compact_branch(ctx, op, 0, 0,
17312 sextract32(ctx->opcode << 2, 0, 28));
17313 } else {
17314 /* OPC_LWC2, OPC_SWC2 */
17315 /* COP2: Not implemented. */
17316 generate_exception_err(ctx, EXCP_CpU, 2);
17318 break;
17319 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
17320 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
17321 if (ctx->insn_flags & ISA_MIPS32R6) {
17322 if (rs != 0) {
17323 /* OPC_BEQZC, OPC_BNEZC */
17324 gen_compute_compact_branch(ctx, op, rs, 0,
17325 sextract32(ctx->opcode << 2, 0, 23));
17326 } else {
17327 /* OPC_JIC, OPC_JIALC */
17328 gen_compute_compact_branch(ctx, op, 0, rt, imm);
17330 } else {
17331 /* OPC_LWC2, OPC_SWC2 */
17332 /* COP2: Not implemented. */
17333 generate_exception_err(ctx, EXCP_CpU, 2);
17335 break;
17336 case OPC_CP2:
17337 check_insn(ctx, INSN_LOONGSON2F);
17338 /* Note that these instructions use different fields. */
17339 gen_loongson_multimedia(ctx, sa, rd, rt);
17340 break;
17342 case OPC_CP3:
17343 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17344 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
17345 check_cp1_enabled(ctx);
17346 op1 = MASK_CP3(ctx->opcode);
17347 switch (op1) {
17348 case OPC_LWXC1:
17349 case OPC_LDXC1:
17350 case OPC_LUXC1:
17351 case OPC_SWXC1:
17352 case OPC_SDXC1:
17353 case OPC_SUXC1:
17354 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
17355 break;
17356 case OPC_PREFX:
17357 /* Treat as NOP. */
17358 break;
17359 case OPC_ALNV_PS:
17360 case OPC_MADD_S:
17361 case OPC_MADD_D:
17362 case OPC_MADD_PS:
17363 case OPC_MSUB_S:
17364 case OPC_MSUB_D:
17365 case OPC_MSUB_PS:
17366 case OPC_NMADD_S:
17367 case OPC_NMADD_D:
17368 case OPC_NMADD_PS:
17369 case OPC_NMSUB_S:
17370 case OPC_NMSUB_D:
17371 case OPC_NMSUB_PS:
17372 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
17373 break;
17374 default:
17375 MIPS_INVAL("cp3");
17376 generate_exception (ctx, EXCP_RI);
17377 break;
17379 } else {
17380 generate_exception_err(ctx, EXCP_CpU, 1);
17382 break;
17384 #if defined(TARGET_MIPS64)
17385 /* MIPS64 opcodes */
17386 case OPC_LDL ... OPC_LDR:
17387 case OPC_LLD:
17388 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17389 case OPC_LWU:
17390 case OPC_LD:
17391 check_insn(ctx, ISA_MIPS3);
17392 check_mips_64(ctx);
17393 gen_ld(ctx, op, rt, rs, imm);
17394 break;
17395 case OPC_SDL ... OPC_SDR:
17396 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17397 case OPC_SD:
17398 check_insn(ctx, ISA_MIPS3);
17399 check_mips_64(ctx);
17400 gen_st(ctx, op, rt, rs, imm);
17401 break;
17402 case OPC_SCD:
17403 check_insn_opc_removed(ctx, ISA_MIPS32R6);
17404 check_insn(ctx, ISA_MIPS3);
17405 check_mips_64(ctx);
17406 gen_st_cond(ctx, op, rt, rs, imm);
17407 break;
17408 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
17409 if (ctx->insn_flags & ISA_MIPS32R6) {
17410 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
17411 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17412 } else {
17413 /* OPC_DADDI */
17414 check_insn(ctx, ISA_MIPS3);
17415 check_mips_64(ctx);
17416 gen_arith_imm(ctx, op, rt, rs, imm);
17418 break;
17419 case OPC_DADDIU:
17420 check_insn(ctx, ISA_MIPS3);
17421 check_mips_64(ctx);
17422 gen_arith_imm(ctx, op, rt, rs, imm);
17423 break;
17424 #else
17425 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
17426 if (ctx->insn_flags & ISA_MIPS32R6) {
17427 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
17428 } else {
17429 MIPS_INVAL("major opcode");
17430 generate_exception(ctx, EXCP_RI);
17432 break;
17433 #endif
17434 case OPC_DAUI: /* OPC_JALX */
17435 if (ctx->insn_flags & ISA_MIPS32R6) {
17436 #if defined(TARGET_MIPS64)
17437 /* OPC_DAUI */
17438 check_mips_64(ctx);
17439 if (rt != 0) {
17440 TCGv t0 = tcg_temp_new();
17441 gen_load_gpr(t0, rs);
17442 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
17443 tcg_temp_free(t0);
17445 MIPS_DEBUG("daui %s, %s, %04x", regnames[rt], regnames[rs], imm);
17446 #else
17447 generate_exception(ctx, EXCP_RI);
17448 MIPS_INVAL("major opcode");
17449 #endif
17450 } else {
17451 /* OPC_JALX */
17452 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
17453 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
17454 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
17456 break;
17457 case OPC_MDMX:
17458 check_insn(ctx, ASE_MDMX);
17459 /* MDMX: Not implemented. */
17460 break;
17461 case OPC_PCREL:
17462 check_insn(ctx, ISA_MIPS32R6);
17463 gen_pcrel(ctx, rs, imm);
17464 break;
17465 default: /* Invalid */
17466 MIPS_INVAL("major opcode");
17467 generate_exception(ctx, EXCP_RI);
17468 break;
17472 static inline void
17473 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
17474 bool search_pc)
17476 CPUState *cs = CPU(cpu);
17477 CPUMIPSState *env = &cpu->env;
17478 DisasContext ctx;
17479 target_ulong pc_start;
17480 uint16_t *gen_opc_end;
17481 CPUBreakpoint *bp;
17482 int j, lj = -1;
17483 int num_insns;
17484 int max_insns;
17485 int insn_bytes;
17486 int is_delay;
17488 if (search_pc)
17489 qemu_log("search pc %d\n", search_pc);
17491 pc_start = tb->pc;
17492 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
17493 ctx.pc = pc_start;
17494 ctx.saved_pc = -1;
17495 ctx.singlestep_enabled = cs->singlestep_enabled;
17496 ctx.insn_flags = env->insn_flags;
17497 ctx.CP0_Config1 = env->CP0_Config1;
17498 ctx.tb = tb;
17499 ctx.bstate = BS_NONE;
17500 ctx.kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
17501 ctx.rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
17502 ctx.ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
17503 /* Restore delay slot state from the tb context. */
17504 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
17505 ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
17506 restore_cpu_state(env, &ctx);
17507 #ifdef CONFIG_USER_ONLY
17508 ctx.mem_idx = MIPS_HFLAG_UM;
17509 #else
17510 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
17511 #endif
17512 num_insns = 0;
17513 max_insns = tb->cflags & CF_COUNT_MASK;
17514 if (max_insns == 0)
17515 max_insns = CF_COUNT_MASK;
17516 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
17517 gen_tb_start();
17518 while (ctx.bstate == BS_NONE) {
17519 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
17520 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
17521 if (bp->pc == ctx.pc) {
17522 save_cpu_state(&ctx, 1);
17523 ctx.bstate = BS_BRANCH;
17524 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
17525 /* Include the breakpoint location or the tb won't
17526 * be flushed when it must be. */
17527 ctx.pc += 4;
17528 goto done_generating;
17533 if (search_pc) {
17534 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
17535 if (lj < j) {
17536 lj++;
17537 while (lj < j)
17538 tcg_ctx.gen_opc_instr_start[lj++] = 0;
17540 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
17541 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
17542 gen_opc_btarget[lj] = ctx.btarget;
17543 tcg_ctx.gen_opc_instr_start[lj] = 1;
17544 tcg_ctx.gen_opc_icount[lj] = num_insns;
17546 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
17547 gen_io_start();
17549 is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
17550 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
17551 ctx.opcode = cpu_ldl_code(env, ctx.pc);
17552 insn_bytes = 4;
17553 decode_opc(env, &ctx);
17554 } else if (ctx.insn_flags & ASE_MICROMIPS) {
17555 ctx.opcode = cpu_lduw_code(env, ctx.pc);
17556 insn_bytes = decode_micromips_opc(env, &ctx);
17557 } else if (ctx.insn_flags & ASE_MIPS16) {
17558 ctx.opcode = cpu_lduw_code(env, ctx.pc);
17559 insn_bytes = decode_mips16_opc(env, &ctx);
17560 } else {
17561 generate_exception(&ctx, EXCP_RI);
17562 ctx.bstate = BS_STOP;
17563 break;
17566 if (ctx.hflags & MIPS_HFLAG_BMASK) {
17567 if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32))) {
17568 is_delay = 1;
17569 /* force to generate branch as no delay slot is required */
17572 if (is_delay) {
17573 gen_branch(&ctx, insn_bytes);
17575 ctx.pc += insn_bytes;
17577 num_insns++;
17579 /* Execute a branch and its delay slot as a single instruction.
17580 This is what GDB expects and is consistent with what the
17581 hardware does (e.g. if a delay slot instruction faults, the
17582 reported PC is the PC of the branch). */
17583 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
17584 break;
17587 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
17588 break;
17590 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
17591 break;
17594 if (num_insns >= max_insns)
17595 break;
17597 if (singlestep)
17598 break;
17600 if (tb->cflags & CF_LAST_IO) {
17601 gen_io_end();
17603 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
17604 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
17605 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
17606 } else {
17607 switch (ctx.bstate) {
17608 case BS_STOP:
17609 gen_goto_tb(&ctx, 0, ctx.pc);
17610 break;
17611 case BS_NONE:
17612 save_cpu_state(&ctx, 0);
17613 gen_goto_tb(&ctx, 0, ctx.pc);
17614 break;
17615 case BS_EXCP:
17616 tcg_gen_exit_tb(0);
17617 break;
17618 case BS_BRANCH:
17619 default:
17620 break;
17623 done_generating:
17624 gen_tb_end(tb, num_insns);
17625 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
17626 if (search_pc) {
17627 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
17628 lj++;
17629 while (lj <= j)
17630 tcg_ctx.gen_opc_instr_start[lj++] = 0;
17631 } else {
17632 tb->size = ctx.pc - pc_start;
17633 tb->icount = num_insns;
17635 #ifdef DEBUG_DISAS
17636 LOG_DISAS("\n");
17637 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
17638 qemu_log("IN: %s\n", lookup_symbol(pc_start));
17639 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
17640 qemu_log("\n");
17642 #endif
17645 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
17647 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
17650 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
17652 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
17655 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
17656 int flags)
17658 int i;
17659 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
17661 #define printfpr(fp) \
17662 do { \
17663 if (is_fpu64) \
17664 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
17665 " fd:%13g fs:%13g psu: %13g\n", \
17666 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
17667 (double)(fp)->fd, \
17668 (double)(fp)->fs[FP_ENDIAN_IDX], \
17669 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
17670 else { \
17671 fpr_t tmp; \
17672 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
17673 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
17674 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
17675 " fd:%13g fs:%13g psu:%13g\n", \
17676 tmp.w[FP_ENDIAN_IDX], tmp.d, \
17677 (double)tmp.fd, \
17678 (double)tmp.fs[FP_ENDIAN_IDX], \
17679 (double)tmp.fs[!FP_ENDIAN_IDX]); \
17681 } while(0)
17684 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
17685 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
17686 get_float_exception_flags(&env->active_fpu.fp_status));
17687 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
17688 fpu_fprintf(f, "%3s: ", fregnames[i]);
17689 printfpr(&env->active_fpu.fpr[i]);
17692 #undef printfpr
17695 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
17696 /* Debug help: The architecture requires 32bit code to maintain proper
17697 sign-extended values on 64bit machines. */
17699 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
17701 static void
17702 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
17703 fprintf_function cpu_fprintf,
17704 int flags)
17706 int i;
17708 if (!SIGN_EXT_P(env->active_tc.PC))
17709 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
17710 if (!SIGN_EXT_P(env->active_tc.HI[0]))
17711 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
17712 if (!SIGN_EXT_P(env->active_tc.LO[0]))
17713 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
17714 if (!SIGN_EXT_P(env->btarget))
17715 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
17717 for (i = 0; i < 32; i++) {
17718 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
17719 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
17722 if (!SIGN_EXT_P(env->CP0_EPC))
17723 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
17724 if (!SIGN_EXT_P(env->lladdr))
17725 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
17727 #endif
17729 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
17730 int flags)
17732 MIPSCPU *cpu = MIPS_CPU(cs);
17733 CPUMIPSState *env = &cpu->env;
17734 int i;
17736 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
17737 " LO=0x" TARGET_FMT_lx " ds %04x "
17738 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
17739 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
17740 env->hflags, env->btarget, env->bcond);
17741 for (i = 0; i < 32; i++) {
17742 if ((i & 3) == 0)
17743 cpu_fprintf(f, "GPR%02d:", i);
17744 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
17745 if ((i & 3) == 3)
17746 cpu_fprintf(f, "\n");
17749 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
17750 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
17751 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
17752 env->CP0_Config0, env->CP0_Config1, env->lladdr);
17753 if (env->hflags & MIPS_HFLAG_FPU)
17754 fpu_dump_state(env, f, cpu_fprintf, flags);
17755 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
17756 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
17757 #endif
17760 void mips_tcg_init(void)
17762 int i;
17763 static int inited;
17765 /* Initialize various static tables. */
17766 if (inited)
17767 return;
17769 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
17770 TCGV_UNUSED(cpu_gpr[0]);
17771 for (i = 1; i < 32; i++)
17772 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
17773 offsetof(CPUMIPSState, active_tc.gpr[i]),
17774 regnames[i]);
17776 for (i = 0; i < 32; i++) {
17777 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
17778 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
17781 cpu_PC = tcg_global_mem_new(TCG_AREG0,
17782 offsetof(CPUMIPSState, active_tc.PC), "PC");
17783 for (i = 0; i < MIPS_DSP_ACC; i++) {
17784 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
17785 offsetof(CPUMIPSState, active_tc.HI[i]),
17786 regnames_HI[i]);
17787 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
17788 offsetof(CPUMIPSState, active_tc.LO[i]),
17789 regnames_LO[i]);
17791 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
17792 offsetof(CPUMIPSState, active_tc.DSPControl),
17793 "DSPControl");
17794 bcond = tcg_global_mem_new(TCG_AREG0,
17795 offsetof(CPUMIPSState, bcond), "bcond");
17796 btarget = tcg_global_mem_new(TCG_AREG0,
17797 offsetof(CPUMIPSState, btarget), "btarget");
17798 hflags = tcg_global_mem_new_i32(TCG_AREG0,
17799 offsetof(CPUMIPSState, hflags), "hflags");
17801 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
17802 offsetof(CPUMIPSState, active_fpu.fcr0),
17803 "fcr0");
17804 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
17805 offsetof(CPUMIPSState, active_fpu.fcr31),
17806 "fcr31");
17808 inited = 1;
17811 #include "translate_init.c"
17813 MIPSCPU *cpu_mips_init(const char *cpu_model)
17815 MIPSCPU *cpu;
17816 CPUMIPSState *env;
17817 const mips_def_t *def;
17819 def = cpu_mips_find_by_name(cpu_model);
17820 if (!def)
17821 return NULL;
17822 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
17823 env = &cpu->env;
17824 env->cpu_model = def;
17826 #ifndef CONFIG_USER_ONLY
17827 mmu_init(env, def);
17828 #endif
17829 fpu_init(env, def);
17830 mvp_init(env, def);
17832 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
17834 return cpu;
17837 void cpu_state_reset(CPUMIPSState *env)
17839 MIPSCPU *cpu = mips_env_get_cpu(env);
17840 CPUState *cs = CPU(cpu);
17842 /* Reset registers to their default values */
17843 env->CP0_PRid = env->cpu_model->CP0_PRid;
17844 env->CP0_Config0 = env->cpu_model->CP0_Config0;
17845 #ifdef TARGET_WORDS_BIGENDIAN
17846 env->CP0_Config0 |= (1 << CP0C0_BE);
17847 #endif
17848 env->CP0_Config1 = env->cpu_model->CP0_Config1;
17849 env->CP0_Config2 = env->cpu_model->CP0_Config2;
17850 env->CP0_Config3 = env->cpu_model->CP0_Config3;
17851 env->CP0_Config4 = env->cpu_model->CP0_Config4;
17852 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
17853 env->CP0_Config5 = env->cpu_model->CP0_Config5;
17854 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
17855 env->CP0_Config6 = env->cpu_model->CP0_Config6;
17856 env->CP0_Config7 = env->cpu_model->CP0_Config7;
17857 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
17858 << env->cpu_model->CP0_LLAddr_shift;
17859 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
17860 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
17861 env->CCRes = env->cpu_model->CCRes;
17862 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
17863 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
17864 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
17865 env->current_tc = 0;
17866 env->SEGBITS = env->cpu_model->SEGBITS;
17867 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
17868 #if defined(TARGET_MIPS64)
17869 if (env->cpu_model->insn_flags & ISA_MIPS3) {
17870 env->SEGMask |= 3ULL << 62;
17872 #endif
17873 env->PABITS = env->cpu_model->PABITS;
17874 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
17875 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
17876 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
17877 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
17878 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
17879 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
17880 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
17881 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
17882 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
17883 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
17884 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
17885 env->CP0_PageGrain_rw_bitmask = env->cpu_model->CP0_PageGrain_rw_bitmask;
17886 env->CP0_PageGrain = env->cpu_model->CP0_PageGrain;
17887 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
17888 env->insn_flags = env->cpu_model->insn_flags;
17890 #if defined(CONFIG_USER_ONLY)
17891 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
17892 # ifdef TARGET_MIPS64
17893 /* Enable 64-bit register mode. */
17894 env->CP0_Status |= (1 << CP0St_PX);
17895 # endif
17896 # ifdef TARGET_ABI_MIPSN64
17897 /* Enable 64-bit address mode. */
17898 env->CP0_Status |= (1 << CP0St_UX);
17899 # endif
17900 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
17901 hardware registers. */
17902 env->CP0_HWREna |= 0x0000000F;
17903 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
17904 env->CP0_Status |= (1 << CP0St_CU1);
17906 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
17907 env->CP0_Status |= (1 << CP0St_MX);
17909 # if defined(TARGET_MIPS64)
17910 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
17911 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
17912 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
17913 env->CP0_Status |= (1 << CP0St_FR);
17915 # endif
17916 #else
17917 if (env->hflags & MIPS_HFLAG_BMASK) {
17918 /* If the exception was raised from a delay slot,
17919 come back to the jump. */
17920 env->CP0_ErrorEPC = env->active_tc.PC - 4;
17921 } else {
17922 env->CP0_ErrorEPC = env->active_tc.PC;
17924 env->active_tc.PC = (int32_t)0xBFC00000;
17925 env->CP0_Random = env->tlb->nb_tlb - 1;
17926 env->tlb->tlb_in_use = env->tlb->nb_tlb;
17927 env->CP0_Wired = 0;
17928 env->CP0_EBase = (cs->cpu_index & 0x3FF);
17929 if (kvm_enabled()) {
17930 env->CP0_EBase |= 0x40000000;
17931 } else {
17932 env->CP0_EBase |= 0x80000000;
17934 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
17935 /* vectored interrupts not implemented, timer on int 7,
17936 no performance counters. */
17937 env->CP0_IntCtl = 0xe0000000;
17939 int i;
17941 for (i = 0; i < 7; i++) {
17942 env->CP0_WatchLo[i] = 0;
17943 env->CP0_WatchHi[i] = 0x80000000;
17945 env->CP0_WatchLo[7] = 0;
17946 env->CP0_WatchHi[7] = 0;
17948 /* Count register increments in debug mode, EJTAG version 1 */
17949 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
17951 cpu_mips_store_count(env, 1);
17953 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
17954 int i;
17956 /* Only TC0 on VPE 0 starts as active. */
17957 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
17958 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
17959 env->tcs[i].CP0_TCHalt = 1;
17961 env->active_tc.CP0_TCHalt = 1;
17962 cs->halted = 1;
17964 if (cs->cpu_index == 0) {
17965 /* VPE0 starts up enabled. */
17966 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
17967 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
17969 /* TC0 starts up unhalted. */
17970 cs->halted = 0;
17971 env->active_tc.CP0_TCHalt = 0;
17972 env->tcs[0].CP0_TCHalt = 0;
17973 /* With thread 0 active. */
17974 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
17975 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
17978 #endif
17979 if ((env->insn_flags & ISA_MIPS32R6) &&
17980 (env->active_fpu.fcr0 & (1 << FCR0_F64))) {
17981 /* Status.FR = 0 mode in 64-bit FPU not allowed in R6 */
17982 env->CP0_Status |= (1 << CP0St_FR);
17985 compute_hflags(env);
17986 cs->exception_index = EXCP_NONE;
17989 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
17991 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
17992 env->hflags &= ~MIPS_HFLAG_BMASK;
17993 env->hflags |= gen_opc_hflags[pc_pos];
17994 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
17995 case MIPS_HFLAG_BR:
17996 break;
17997 case MIPS_HFLAG_BC:
17998 case MIPS_HFLAG_BL:
17999 case MIPS_HFLAG_B:
18000 env->btarget = gen_opc_btarget[pc_pos];
18001 break;