hw/arm/virt: formatting: memory map
[qemu/ar7.git] / target-mips / translate.c
blobc3813665062f5cc2d0df8342ed794d928029b059
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 #define MIPS_DEBUG_DISAS 0
34 //#define MIPS_DEBUG_SIGN_EXTENSIONS
36 /* MIPS major opcodes */
37 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
39 enum {
40 /* indirect opcode tables */
41 OPC_SPECIAL = (0x00 << 26),
42 OPC_REGIMM = (0x01 << 26),
43 OPC_CP0 = (0x10 << 26),
44 OPC_CP1 = (0x11 << 26),
45 OPC_CP2 = (0x12 << 26),
46 OPC_CP3 = (0x13 << 26),
47 OPC_SPECIAL2 = (0x1C << 26),
48 OPC_SPECIAL3 = (0x1F << 26),
49 /* arithmetic with immediate */
50 OPC_ADDI = (0x08 << 26),
51 OPC_ADDIU = (0x09 << 26),
52 OPC_SLTI = (0x0A << 26),
53 OPC_SLTIU = (0x0B << 26),
54 /* logic with immediate */
55 OPC_ANDI = (0x0C << 26),
56 OPC_ORI = (0x0D << 26),
57 OPC_XORI = (0x0E << 26),
58 OPC_LUI = (0x0F << 26),
59 /* arithmetic with immediate */
60 OPC_DADDI = (0x18 << 26),
61 OPC_DADDIU = (0x19 << 26),
62 /* Jump and branches */
63 OPC_J = (0x02 << 26),
64 OPC_JAL = (0x03 << 26),
65 OPC_JALS = OPC_JAL | 0x5,
66 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
67 OPC_BEQL = (0x14 << 26),
68 OPC_BNE = (0x05 << 26),
69 OPC_BNEL = (0x15 << 26),
70 OPC_BLEZ = (0x06 << 26),
71 OPC_BLEZL = (0x16 << 26),
72 OPC_BGTZ = (0x07 << 26),
73 OPC_BGTZL = (0x17 << 26),
74 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
75 OPC_JALXS = OPC_JALX | 0x5,
76 /* Load and stores */
77 OPC_LDL = (0x1A << 26),
78 OPC_LDR = (0x1B << 26),
79 OPC_LB = (0x20 << 26),
80 OPC_LH = (0x21 << 26),
81 OPC_LWL = (0x22 << 26),
82 OPC_LW = (0x23 << 26),
83 OPC_LWPC = OPC_LW | 0x5,
84 OPC_LBU = (0x24 << 26),
85 OPC_LHU = (0x25 << 26),
86 OPC_LWR = (0x26 << 26),
87 OPC_LWU = (0x27 << 26),
88 OPC_SB = (0x28 << 26),
89 OPC_SH = (0x29 << 26),
90 OPC_SWL = (0x2A << 26),
91 OPC_SW = (0x2B << 26),
92 OPC_SDL = (0x2C << 26),
93 OPC_SDR = (0x2D << 26),
94 OPC_SWR = (0x2E << 26),
95 OPC_LL = (0x30 << 26),
96 OPC_LLD = (0x34 << 26),
97 OPC_LD = (0x37 << 26),
98 OPC_LDPC = OPC_LD | 0x5,
99 OPC_SC = (0x38 << 26),
100 OPC_SCD = (0x3C << 26),
101 OPC_SD = (0x3F << 26),
102 /* Floating point load/store */
103 OPC_LWC1 = (0x31 << 26),
104 OPC_LWC2 = (0x32 << 26),
105 OPC_LDC1 = (0x35 << 26),
106 OPC_LDC2 = (0x36 << 26),
107 OPC_SWC1 = (0x39 << 26),
108 OPC_SWC2 = (0x3A << 26),
109 OPC_SDC1 = (0x3D << 26),
110 OPC_SDC2 = (0x3E << 26),
111 /* MDMX ASE specific */
112 OPC_MDMX = (0x1E << 26),
113 /* Cache and prefetch */
114 OPC_CACHE = (0x2F << 26),
115 OPC_PREF = (0x33 << 26),
116 /* Reserved major opcode */
117 OPC_MAJOR3B_RESERVED = (0x3B << 26),
120 /* MIPS special opcodes */
121 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
123 enum {
124 /* Shifts */
125 OPC_SLL = 0x00 | OPC_SPECIAL,
126 /* NOP is SLL r0, r0, 0 */
127 /* SSNOP is SLL r0, r0, 1 */
128 /* EHB is SLL r0, r0, 3 */
129 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
130 OPC_ROTR = OPC_SRL | (1 << 21),
131 OPC_SRA = 0x03 | OPC_SPECIAL,
132 OPC_SLLV = 0x04 | OPC_SPECIAL,
133 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
134 OPC_ROTRV = OPC_SRLV | (1 << 6),
135 OPC_SRAV = 0x07 | OPC_SPECIAL,
136 OPC_DSLLV = 0x14 | OPC_SPECIAL,
137 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
138 OPC_DROTRV = OPC_DSRLV | (1 << 6),
139 OPC_DSRAV = 0x17 | OPC_SPECIAL,
140 OPC_DSLL = 0x38 | OPC_SPECIAL,
141 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
142 OPC_DROTR = OPC_DSRL | (1 << 21),
143 OPC_DSRA = 0x3B | OPC_SPECIAL,
144 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
145 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
146 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
147 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
148 /* Multiplication / division */
149 OPC_MULT = 0x18 | OPC_SPECIAL,
150 OPC_MULTU = 0x19 | OPC_SPECIAL,
151 OPC_DIV = 0x1A | OPC_SPECIAL,
152 OPC_DIVU = 0x1B | OPC_SPECIAL,
153 OPC_DMULT = 0x1C | OPC_SPECIAL,
154 OPC_DMULTU = 0x1D | OPC_SPECIAL,
155 OPC_DDIV = 0x1E | OPC_SPECIAL,
156 OPC_DDIVU = 0x1F | OPC_SPECIAL,
157 /* 2 registers arithmetic / logic */
158 OPC_ADD = 0x20 | OPC_SPECIAL,
159 OPC_ADDU = 0x21 | OPC_SPECIAL,
160 OPC_SUB = 0x22 | OPC_SPECIAL,
161 OPC_SUBU = 0x23 | OPC_SPECIAL,
162 OPC_AND = 0x24 | OPC_SPECIAL,
163 OPC_OR = 0x25 | OPC_SPECIAL,
164 OPC_XOR = 0x26 | OPC_SPECIAL,
165 OPC_NOR = 0x27 | OPC_SPECIAL,
166 OPC_SLT = 0x2A | OPC_SPECIAL,
167 OPC_SLTU = 0x2B | OPC_SPECIAL,
168 OPC_DADD = 0x2C | OPC_SPECIAL,
169 OPC_DADDU = 0x2D | OPC_SPECIAL,
170 OPC_DSUB = 0x2E | OPC_SPECIAL,
171 OPC_DSUBU = 0x2F | OPC_SPECIAL,
172 /* Jumps */
173 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
174 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
175 OPC_JALRC = OPC_JALR | (0x5 << 6),
176 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
177 /* Traps */
178 OPC_TGE = 0x30 | OPC_SPECIAL,
179 OPC_TGEU = 0x31 | OPC_SPECIAL,
180 OPC_TLT = 0x32 | OPC_SPECIAL,
181 OPC_TLTU = 0x33 | OPC_SPECIAL,
182 OPC_TEQ = 0x34 | OPC_SPECIAL,
183 OPC_TNE = 0x36 | OPC_SPECIAL,
184 /* HI / LO registers load & stores */
185 OPC_MFHI = 0x10 | OPC_SPECIAL,
186 OPC_MTHI = 0x11 | OPC_SPECIAL,
187 OPC_MFLO = 0x12 | OPC_SPECIAL,
188 OPC_MTLO = 0x13 | OPC_SPECIAL,
189 /* Conditional moves */
190 OPC_MOVZ = 0x0A | OPC_SPECIAL,
191 OPC_MOVN = 0x0B | OPC_SPECIAL,
193 OPC_MOVCI = 0x01 | OPC_SPECIAL,
195 /* Special */
196 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
197 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
198 OPC_BREAK = 0x0D | OPC_SPECIAL,
199 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
200 OPC_SYNC = 0x0F | OPC_SPECIAL,
202 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
203 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
204 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
205 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
206 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
207 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
208 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
211 /* Multiplication variants of the vr54xx. */
212 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
214 enum {
215 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
216 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
217 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
218 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
219 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
220 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
221 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
222 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
223 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
224 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
225 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
226 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
227 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
228 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
231 /* REGIMM (rt field) opcodes */
232 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
234 enum {
235 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
236 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
237 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
238 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
239 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
240 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
241 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
242 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
243 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
244 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
245 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
246 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
247 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
248 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
249 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
250 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
251 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
254 /* Special2 opcodes */
255 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
257 enum {
258 /* Multiply & xxx operations */
259 OPC_MADD = 0x00 | OPC_SPECIAL2,
260 OPC_MADDU = 0x01 | OPC_SPECIAL2,
261 OPC_MUL = 0x02 | OPC_SPECIAL2,
262 OPC_MSUB = 0x04 | OPC_SPECIAL2,
263 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
264 /* Loongson 2F */
265 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
266 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
267 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
268 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
269 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
270 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
271 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
272 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
273 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
274 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
275 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
276 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
277 /* Misc */
278 OPC_CLZ = 0x20 | OPC_SPECIAL2,
279 OPC_CLO = 0x21 | OPC_SPECIAL2,
280 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
281 OPC_DCLO = 0x25 | OPC_SPECIAL2,
282 /* Special */
283 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
286 /* Special3 opcodes */
287 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
289 enum {
290 OPC_EXT = 0x00 | OPC_SPECIAL3,
291 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
292 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
293 OPC_DEXT = 0x03 | OPC_SPECIAL3,
294 OPC_INS = 0x04 | OPC_SPECIAL3,
295 OPC_DINSM = 0x05 | OPC_SPECIAL3,
296 OPC_DINSU = 0x06 | OPC_SPECIAL3,
297 OPC_DINS = 0x07 | OPC_SPECIAL3,
298 OPC_FORK = 0x08 | OPC_SPECIAL3,
299 OPC_YIELD = 0x09 | OPC_SPECIAL3,
300 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
301 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
302 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
304 /* Loongson 2E */
305 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
306 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
307 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
308 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
309 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
310 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
311 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
312 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
313 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
314 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
315 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
316 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
318 /* MIPS DSP Load */
319 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
320 /* MIPS DSP Arithmetic */
321 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
322 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
323 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
324 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
325 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
326 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
327 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
328 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
329 /* MIPS DSP GPR-Based Shift Sub-class */
330 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
331 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
332 /* MIPS DSP Multiply Sub-class insns */
333 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
334 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
335 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
336 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
337 /* DSP Bit/Manipulation Sub-class */
338 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
339 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
340 /* MIPS DSP Append Sub-class */
341 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
342 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
343 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
344 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
345 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
348 /* BSHFL opcodes */
349 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
351 enum {
352 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
353 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
354 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
357 /* DBSHFL opcodes */
358 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
360 enum {
361 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
362 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
365 /* MIPS DSP REGIMM opcodes */
366 enum {
367 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
368 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
371 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
372 /* MIPS DSP Load */
373 enum {
374 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
375 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
376 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
377 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
380 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
381 enum {
382 /* MIPS DSP Arithmetic Sub-class */
383 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
384 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
385 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
386 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
387 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
388 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
389 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
390 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
391 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
392 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
393 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
394 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
395 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
396 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
397 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
398 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
399 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
400 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
401 /* MIPS DSP Multiply Sub-class insns */
402 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
403 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
404 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
405 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
406 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
407 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
410 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
411 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
412 enum {
413 /* MIPS DSP Arithmetic Sub-class */
414 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
415 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
416 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
417 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
418 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
419 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
420 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
421 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
422 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
423 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
424 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
425 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
426 /* MIPS DSP Multiply Sub-class insns */
427 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
428 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
429 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
430 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
433 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
434 enum {
435 /* MIPS DSP Arithmetic Sub-class */
436 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
437 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
438 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
439 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
440 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
441 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
442 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
443 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
444 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
445 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
446 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
447 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
448 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
449 /* DSP Bit/Manipulation Sub-class */
450 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
451 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
452 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
453 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
454 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
457 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
458 enum {
459 /* MIPS DSP Arithmetic Sub-class */
460 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
461 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
462 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
463 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
464 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
465 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
466 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
467 /* DSP Compare-Pick Sub-class */
468 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
469 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
470 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
471 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
472 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
473 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
474 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
475 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
476 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
477 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
478 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
479 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
480 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
481 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
482 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
485 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
486 enum {
487 /* MIPS DSP GPR-Based Shift Sub-class */
488 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
489 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
490 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
491 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
492 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
493 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
494 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
495 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
496 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
497 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
498 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
499 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
500 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
501 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
502 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
503 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
504 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
505 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
506 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
507 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
508 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
509 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
512 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
513 enum {
514 /* MIPS DSP Multiply Sub-class insns */
515 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
516 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
517 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
518 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
519 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
520 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
521 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
522 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
523 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
524 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
525 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
526 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
527 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
528 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
529 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
530 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
531 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
532 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
533 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
534 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
535 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
536 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
539 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
540 enum {
541 /* DSP Bit/Manipulation Sub-class */
542 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
545 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
546 enum {
547 /* MIPS DSP Append Sub-class */
548 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
549 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
550 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
553 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
554 enum {
555 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
556 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
557 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
558 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
559 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
560 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
561 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
562 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
563 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
564 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
565 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
566 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
567 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
568 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
569 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
570 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
571 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
572 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
575 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
576 enum {
577 /* MIPS DSP Arithmetic Sub-class */
578 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
579 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
580 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
581 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
582 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
583 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
584 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
585 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
586 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
587 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
588 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
589 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
590 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
591 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
592 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
593 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
594 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
595 /* DSP Bit/Manipulation Sub-class */
596 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
597 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
598 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
599 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
600 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
601 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
604 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
605 enum {
606 /* MIPS DSP Multiply Sub-class insns */
607 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
608 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
609 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
610 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
611 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
612 /* MIPS DSP Arithmetic Sub-class */
613 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
614 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
615 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
616 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
617 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
618 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
619 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
620 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
621 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
622 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
623 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
624 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
625 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
626 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
627 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
628 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
629 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
630 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
631 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
632 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
633 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
636 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
637 enum {
638 /* DSP Compare-Pick Sub-class */
639 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
640 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
641 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
642 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
643 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
644 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
645 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
646 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
647 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
648 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
649 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
650 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
651 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
652 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
653 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
654 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
655 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
656 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
657 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
658 /* MIPS DSP Arithmetic Sub-class */
659 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
660 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
661 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
662 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
663 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
664 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
665 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
666 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
669 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
670 enum {
671 /* DSP Append Sub-class */
672 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
673 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
674 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
675 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
678 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
679 enum {
680 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
681 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
682 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
683 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
684 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
685 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
686 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
687 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
688 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
689 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
690 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
691 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
692 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
693 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
694 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
695 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
696 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
697 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
698 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
699 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
700 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
701 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
704 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
705 enum {
706 /* DSP Bit/Manipulation Sub-class */
707 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
710 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
711 enum {
712 /* MIPS DSP Multiply Sub-class insns */
713 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
714 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
715 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
716 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
717 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
718 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
719 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
720 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
721 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
722 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
723 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
724 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
725 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
726 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
727 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
728 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
729 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
730 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
731 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
732 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
733 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
734 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
735 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
736 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
737 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
738 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
741 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
742 enum {
743 /* MIPS DSP GPR-Based Shift Sub-class */
744 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
745 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
746 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
747 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
748 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
749 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
750 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
751 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
752 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
753 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
754 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
755 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
756 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
757 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
758 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
759 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
760 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
761 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
762 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
763 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
764 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
765 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
766 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
767 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
768 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
769 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
772 /* Coprocessor 0 (rs field) */
773 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
775 enum {
776 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
777 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
778 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
779 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
780 OPC_MFTR = (0x08 << 21) | OPC_CP0,
781 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
782 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
783 OPC_MTTR = (0x0C << 21) | OPC_CP0,
784 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
785 OPC_C0 = (0x10 << 21) | OPC_CP0,
786 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
787 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
790 /* MFMC0 opcodes */
791 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
793 enum {
794 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
795 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
796 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
797 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
798 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
799 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
802 /* Coprocessor 0 (with rs == C0) */
803 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
805 enum {
806 OPC_TLBR = 0x01 | OPC_C0,
807 OPC_TLBWI = 0x02 | OPC_C0,
808 OPC_TLBWR = 0x06 | OPC_C0,
809 OPC_TLBP = 0x08 | OPC_C0,
810 OPC_RFE = 0x10 | OPC_C0,
811 OPC_ERET = 0x18 | OPC_C0,
812 OPC_DERET = 0x1F | OPC_C0,
813 OPC_WAIT = 0x20 | OPC_C0,
816 /* Coprocessor 1 (rs field) */
817 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
819 /* Values for the fmt field in FP instructions */
820 enum {
821 /* 0 - 15 are reserved */
822 FMT_S = 16, /* single fp */
823 FMT_D = 17, /* double fp */
824 FMT_E = 18, /* extended fp */
825 FMT_Q = 19, /* quad fp */
826 FMT_W = 20, /* 32-bit fixed */
827 FMT_L = 21, /* 64-bit fixed */
828 FMT_PS = 22, /* paired single fp */
829 /* 23 - 31 are reserved */
832 enum {
833 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
834 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
835 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
836 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
837 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
838 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
839 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
840 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
841 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
842 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
843 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
844 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
845 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
846 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
847 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
848 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
849 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
850 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
853 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
854 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
856 enum {
857 OPC_BC1F = (0x00 << 16) | OPC_BC1,
858 OPC_BC1T = (0x01 << 16) | OPC_BC1,
859 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
860 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
863 enum {
864 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
865 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
868 enum {
869 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
870 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
873 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
875 enum {
876 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
877 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
878 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
879 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
880 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
881 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
882 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
883 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
884 OPC_BC2 = (0x08 << 21) | OPC_CP2,
887 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
889 enum {
890 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
891 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
892 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
893 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
894 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
895 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
896 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
897 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
899 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
900 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
901 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
902 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
903 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
904 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
905 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
906 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
908 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
909 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
910 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
911 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
912 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
913 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
914 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
915 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
917 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
918 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
919 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
920 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
921 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
922 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
923 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
924 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
926 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
927 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
928 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
929 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
930 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
931 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
933 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
934 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
935 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
936 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
937 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
938 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
940 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
941 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
942 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
943 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
944 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
945 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
947 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
948 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
949 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
950 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
951 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
952 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
954 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
955 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
956 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
957 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
958 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
959 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
961 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
962 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
963 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
964 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
965 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
966 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
968 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
969 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
970 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
971 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
972 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
973 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
975 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
976 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
977 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
978 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
979 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
980 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
984 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
986 enum {
987 OPC_LWXC1 = 0x00 | OPC_CP3,
988 OPC_LDXC1 = 0x01 | OPC_CP3,
989 OPC_LUXC1 = 0x05 | OPC_CP3,
990 OPC_SWXC1 = 0x08 | OPC_CP3,
991 OPC_SDXC1 = 0x09 | OPC_CP3,
992 OPC_SUXC1 = 0x0D | OPC_CP3,
993 OPC_PREFX = 0x0F | OPC_CP3,
994 OPC_ALNV_PS = 0x1E | OPC_CP3,
995 OPC_MADD_S = 0x20 | OPC_CP3,
996 OPC_MADD_D = 0x21 | OPC_CP3,
997 OPC_MADD_PS = 0x26 | OPC_CP3,
998 OPC_MSUB_S = 0x28 | OPC_CP3,
999 OPC_MSUB_D = 0x29 | OPC_CP3,
1000 OPC_MSUB_PS = 0x2E | OPC_CP3,
1001 OPC_NMADD_S = 0x30 | OPC_CP3,
1002 OPC_NMADD_D = 0x31 | OPC_CP3,
1003 OPC_NMADD_PS= 0x36 | OPC_CP3,
1004 OPC_NMSUB_S = 0x38 | OPC_CP3,
1005 OPC_NMSUB_D = 0x39 | OPC_CP3,
1006 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1009 /* global register indices */
1010 static TCGv_ptr cpu_env;
1011 static TCGv cpu_gpr[32], cpu_PC;
1012 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
1013 static TCGv cpu_dspctrl, btarget, bcond;
1014 static TCGv_i32 hflags;
1015 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1016 static TCGv_i64 fpu_f64[32];
1018 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1019 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1021 #include "exec/gen-icount.h"
1023 #define gen_helper_0e0i(name, arg) do { \
1024 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1025 gen_helper_##name(cpu_env, helper_tmp); \
1026 tcg_temp_free_i32(helper_tmp); \
1027 } while(0)
1029 #define gen_helper_0e1i(name, arg1, arg2) do { \
1030 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1031 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1032 tcg_temp_free_i32(helper_tmp); \
1033 } while(0)
1035 #define gen_helper_1e0i(name, ret, arg1) do { \
1036 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1037 gen_helper_##name(ret, cpu_env, helper_tmp); \
1038 tcg_temp_free_i32(helper_tmp); \
1039 } while(0)
1041 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1042 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1043 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1044 tcg_temp_free_i32(helper_tmp); \
1045 } while(0)
1047 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1048 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1049 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1050 tcg_temp_free_i32(helper_tmp); \
1051 } while(0)
1053 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1054 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1055 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1056 tcg_temp_free_i32(helper_tmp); \
1057 } while(0)
1059 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1060 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1061 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1062 tcg_temp_free_i32(helper_tmp); \
1063 } while(0)
1065 typedef struct DisasContext {
1066 struct TranslationBlock *tb;
1067 target_ulong pc, saved_pc;
1068 uint32_t opcode;
1069 int singlestep_enabled;
1070 int insn_flags;
1071 int32_t CP0_Config1;
1072 /* Routine used to access memory */
1073 int mem_idx;
1074 uint32_t hflags, saved_hflags;
1075 int bstate;
1076 target_ulong btarget;
1077 bool ulri;
1078 } DisasContext;
1080 enum {
1081 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1082 * exception condition */
1083 BS_STOP = 1, /* We want to stop translation for any reason */
1084 BS_BRANCH = 2, /* We reached a branch condition */
1085 BS_EXCP = 3, /* We reached an exception condition */
1088 static const char * const regnames[] = {
1089 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1090 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1091 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1092 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1095 static const char * const regnames_HI[] = {
1096 "HI0", "HI1", "HI2", "HI3",
1099 static const char * const regnames_LO[] = {
1100 "LO0", "LO1", "LO2", "LO3",
1103 static const char * const regnames_ACX[] = {
1104 "ACX0", "ACX1", "ACX2", "ACX3",
1107 static const char * const fregnames[] = {
1108 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1109 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1110 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1111 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1114 #define MIPS_DEBUG(fmt, ...) \
1115 do { \
1116 if (MIPS_DEBUG_DISAS) { \
1117 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1118 TARGET_FMT_lx ": %08x " fmt "\n", \
1119 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1121 } while (0)
1123 #define LOG_DISAS(...) \
1124 do { \
1125 if (MIPS_DEBUG_DISAS) { \
1126 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1128 } while (0)
1130 #define MIPS_INVAL(op) \
1131 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1132 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1134 /* General purpose registers moves. */
1135 static inline void gen_load_gpr (TCGv t, int reg)
1137 if (reg == 0)
1138 tcg_gen_movi_tl(t, 0);
1139 else
1140 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1143 static inline void gen_store_gpr (TCGv t, int reg)
1145 if (reg != 0)
1146 tcg_gen_mov_tl(cpu_gpr[reg], t);
1149 /* Moves to/from ACX register. */
1150 static inline void gen_load_ACX (TCGv t, int reg)
1152 tcg_gen_mov_tl(t, cpu_ACX[reg]);
1155 static inline void gen_store_ACX (TCGv t, int reg)
1157 tcg_gen_mov_tl(cpu_ACX[reg], t);
1160 /* Moves to/from shadow registers. */
1161 static inline void gen_load_srsgpr (int from, int to)
1163 TCGv t0 = tcg_temp_new();
1165 if (from == 0)
1166 tcg_gen_movi_tl(t0, 0);
1167 else {
1168 TCGv_i32 t2 = tcg_temp_new_i32();
1169 TCGv_ptr addr = tcg_temp_new_ptr();
1171 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1172 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1173 tcg_gen_andi_i32(t2, t2, 0xf);
1174 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1175 tcg_gen_ext_i32_ptr(addr, t2);
1176 tcg_gen_add_ptr(addr, cpu_env, addr);
1178 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1179 tcg_temp_free_ptr(addr);
1180 tcg_temp_free_i32(t2);
1182 gen_store_gpr(t0, to);
1183 tcg_temp_free(t0);
1186 static inline void gen_store_srsgpr (int from, int to)
1188 if (to != 0) {
1189 TCGv t0 = tcg_temp_new();
1190 TCGv_i32 t2 = tcg_temp_new_i32();
1191 TCGv_ptr addr = tcg_temp_new_ptr();
1193 gen_load_gpr(t0, from);
1194 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1195 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1196 tcg_gen_andi_i32(t2, t2, 0xf);
1197 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1198 tcg_gen_ext_i32_ptr(addr, t2);
1199 tcg_gen_add_ptr(addr, cpu_env, addr);
1201 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1202 tcg_temp_free_ptr(addr);
1203 tcg_temp_free_i32(t2);
1204 tcg_temp_free(t0);
1208 /* Floating point register moves. */
1209 static void gen_load_fpr32(TCGv_i32 t, int reg)
1211 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1214 static void gen_store_fpr32(TCGv_i32 t, int reg)
1216 TCGv_i64 t64 = tcg_temp_new_i64();
1217 tcg_gen_extu_i32_i64(t64, t);
1218 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1219 tcg_temp_free_i64(t64);
1222 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1224 if (ctx->hflags & MIPS_HFLAG_F64) {
1225 TCGv_i64 t64 = tcg_temp_new_i64();
1226 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1227 tcg_gen_trunc_i64_i32(t, t64);
1228 tcg_temp_free_i64(t64);
1229 } else {
1230 gen_load_fpr32(t, reg | 1);
1234 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1236 if (ctx->hflags & MIPS_HFLAG_F64) {
1237 TCGv_i64 t64 = tcg_temp_new_i64();
1238 tcg_gen_extu_i32_i64(t64, t);
1239 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1240 tcg_temp_free_i64(t64);
1241 } else {
1242 gen_store_fpr32(t, reg | 1);
1246 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1248 if (ctx->hflags & MIPS_HFLAG_F64) {
1249 tcg_gen_mov_i64(t, fpu_f64[reg]);
1250 } else {
1251 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1255 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1257 if (ctx->hflags & MIPS_HFLAG_F64) {
1258 tcg_gen_mov_i64(fpu_f64[reg], t);
1259 } else {
1260 TCGv_i64 t0;
1261 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1262 t0 = tcg_temp_new_i64();
1263 tcg_gen_shri_i64(t0, t, 32);
1264 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1265 tcg_temp_free_i64(t0);
1269 static inline int get_fp_bit (int cc)
1271 if (cc)
1272 return 24 + cc;
1273 else
1274 return 23;
1277 /* Tests */
1278 static inline void gen_save_pc(target_ulong pc)
1280 tcg_gen_movi_tl(cpu_PC, pc);
1283 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1285 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1286 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1287 gen_save_pc(ctx->pc);
1288 ctx->saved_pc = ctx->pc;
1290 if (ctx->hflags != ctx->saved_hflags) {
1291 tcg_gen_movi_i32(hflags, ctx->hflags);
1292 ctx->saved_hflags = ctx->hflags;
1293 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1294 case MIPS_HFLAG_BR:
1295 break;
1296 case MIPS_HFLAG_BC:
1297 case MIPS_HFLAG_BL:
1298 case MIPS_HFLAG_B:
1299 tcg_gen_movi_tl(btarget, ctx->btarget);
1300 break;
1305 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1307 ctx->saved_hflags = ctx->hflags;
1308 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1309 case MIPS_HFLAG_BR:
1310 break;
1311 case MIPS_HFLAG_BC:
1312 case MIPS_HFLAG_BL:
1313 case MIPS_HFLAG_B:
1314 ctx->btarget = env->btarget;
1315 break;
1319 static inline void
1320 generate_exception_err (DisasContext *ctx, int excp, int err)
1322 TCGv_i32 texcp = tcg_const_i32(excp);
1323 TCGv_i32 terr = tcg_const_i32(err);
1324 save_cpu_state(ctx, 1);
1325 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1326 tcg_temp_free_i32(terr);
1327 tcg_temp_free_i32(texcp);
1330 static inline void
1331 generate_exception (DisasContext *ctx, int excp)
1333 save_cpu_state(ctx, 1);
1334 gen_helper_0e0i(raise_exception, excp);
1337 /* Addresses computation */
1338 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1340 tcg_gen_add_tl(ret, arg0, arg1);
1342 #if defined(TARGET_MIPS64)
1343 /* For compatibility with 32-bit code, data reference in user mode
1344 with Status_UX = 0 should be casted to 32-bit and sign extended.
1345 See the MIPS64 PRA manual, section 4.10. */
1346 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
1347 !(ctx->hflags & MIPS_HFLAG_UX)) {
1348 tcg_gen_ext32s_i64(ret, ret);
1350 #endif
1353 static inline void check_cp0_enabled(DisasContext *ctx)
1355 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1356 generate_exception_err(ctx, EXCP_CpU, 0);
1359 static inline void check_cp1_enabled(DisasContext *ctx)
1361 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1362 generate_exception_err(ctx, EXCP_CpU, 1);
1365 /* Verify that the processor is running with COP1X instructions enabled.
1366 This is associated with the nabla symbol in the MIPS32 and MIPS64
1367 opcode tables. */
1369 static inline void check_cop1x(DisasContext *ctx)
1371 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1372 generate_exception(ctx, EXCP_RI);
1375 /* Verify that the processor is running with 64-bit floating-point
1376 operations enabled. */
1378 static inline void check_cp1_64bitmode(DisasContext *ctx)
1380 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1381 generate_exception(ctx, EXCP_RI);
1385 * Verify if floating point register is valid; an operation is not defined
1386 * if bit 0 of any register specification is set and the FR bit in the
1387 * Status register equals zero, since the register numbers specify an
1388 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1389 * in the Status register equals one, both even and odd register numbers
1390 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1392 * Multiple 64 bit wide registers can be checked by calling
1393 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1395 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1397 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1398 generate_exception(ctx, EXCP_RI);
1401 /* Verify that the processor is running with DSP instructions enabled.
1402 This is enabled by CP0 Status register MX(24) bit.
1405 static inline void check_dsp(DisasContext *ctx)
1407 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1408 if (ctx->insn_flags & ASE_DSP) {
1409 generate_exception(ctx, EXCP_DSPDIS);
1410 } else {
1411 generate_exception(ctx, EXCP_RI);
1416 static inline void check_dspr2(DisasContext *ctx)
1418 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1419 if (ctx->insn_flags & ASE_DSP) {
1420 generate_exception(ctx, EXCP_DSPDIS);
1421 } else {
1422 generate_exception(ctx, EXCP_RI);
1427 /* This code generates a "reserved instruction" exception if the
1428 CPU does not support the instruction set corresponding to flags. */
1429 static inline void check_insn(DisasContext *ctx, int flags)
1431 if (unlikely(!(ctx->insn_flags & flags))) {
1432 generate_exception(ctx, EXCP_RI);
1436 /* This code generates a "reserved instruction" exception if 64-bit
1437 instructions are not enabled. */
1438 static inline void check_mips_64(DisasContext *ctx)
1440 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1441 generate_exception(ctx, EXCP_RI);
1444 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1445 calling interface for 32 and 64-bit FPRs. No sense in changing
1446 all callers for gen_load_fpr32 when we need the CTX parameter for
1447 this one use. */
1448 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1449 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1450 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1451 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1452 int ft, int fs, int cc) \
1454 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1455 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1456 switch (ifmt) { \
1457 case FMT_PS: \
1458 check_cp1_64bitmode(ctx); \
1459 break; \
1460 case FMT_D: \
1461 if (abs) { \
1462 check_cop1x(ctx); \
1464 check_cp1_registers(ctx, fs | ft); \
1465 break; \
1466 case FMT_S: \
1467 if (abs) { \
1468 check_cop1x(ctx); \
1470 break; \
1472 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1473 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1474 switch (n) { \
1475 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1476 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1477 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1478 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1479 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1480 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1481 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1482 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1483 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1484 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1485 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1486 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1487 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1488 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1489 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1490 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1491 default: abort(); \
1493 tcg_temp_free_i##bits (fp0); \
1494 tcg_temp_free_i##bits (fp1); \
1497 FOP_CONDS(, 0, d, FMT_D, 64)
1498 FOP_CONDS(abs, 1, d, FMT_D, 64)
1499 FOP_CONDS(, 0, s, FMT_S, 32)
1500 FOP_CONDS(abs, 1, s, FMT_S, 32)
1501 FOP_CONDS(, 0, ps, FMT_PS, 64)
1502 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1503 #undef FOP_CONDS
1504 #undef gen_ldcmp_fpr32
1505 #undef gen_ldcmp_fpr64
1507 /* load/store instructions. */
1508 #ifdef CONFIG_USER_ONLY
1509 #define OP_LD_ATOMIC(insn,fname) \
1510 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1512 TCGv t0 = tcg_temp_new(); \
1513 tcg_gen_mov_tl(t0, arg1); \
1514 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1515 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1516 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1517 tcg_temp_free(t0); \
1519 #else
1520 #define OP_LD_ATOMIC(insn,fname) \
1521 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1523 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1525 #endif
1526 OP_LD_ATOMIC(ll,ld32s);
1527 #if defined(TARGET_MIPS64)
1528 OP_LD_ATOMIC(lld,ld64);
1529 #endif
1530 #undef OP_LD_ATOMIC
1532 #ifdef CONFIG_USER_ONLY
1533 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1534 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1536 TCGv t0 = tcg_temp_new(); \
1537 int l1 = gen_new_label(); \
1538 int l2 = gen_new_label(); \
1540 tcg_gen_andi_tl(t0, arg2, almask); \
1541 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
1542 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
1543 generate_exception(ctx, EXCP_AdES); \
1544 gen_set_label(l1); \
1545 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1546 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1547 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
1548 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1549 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
1550 gen_helper_0e0i(raise_exception, EXCP_SC); \
1551 gen_set_label(l2); \
1552 tcg_gen_movi_tl(t0, 0); \
1553 gen_store_gpr(t0, rt); \
1554 tcg_temp_free(t0); \
1556 #else
1557 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1558 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1560 TCGv t0 = tcg_temp_new(); \
1561 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
1562 gen_store_gpr(t0, rt); \
1563 tcg_temp_free(t0); \
1565 #endif
1566 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1567 #if defined(TARGET_MIPS64)
1568 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1569 #endif
1570 #undef OP_ST_ATOMIC
1572 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1573 int base, int16_t offset)
1575 if (base == 0) {
1576 tcg_gen_movi_tl(addr, offset);
1577 } else if (offset == 0) {
1578 gen_load_gpr(addr, base);
1579 } else {
1580 tcg_gen_movi_tl(addr, offset);
1581 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1585 static target_ulong pc_relative_pc (DisasContext *ctx)
1587 target_ulong pc = ctx->pc;
1589 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1590 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1592 pc -= branch_bytes;
1595 pc &= ~(target_ulong)3;
1596 return pc;
1599 /* Load */
1600 static void gen_ld(DisasContext *ctx, uint32_t opc,
1601 int rt, int base, int16_t offset)
1603 const char *opn = "ld";
1604 TCGv t0, t1, t2;
1606 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1607 /* Loongson CPU uses a load to zero register for prefetch.
1608 We emulate it as a NOP. On other CPU we must perform the
1609 actual memory access. */
1610 MIPS_DEBUG("NOP");
1611 return;
1614 t0 = tcg_temp_new();
1615 gen_base_offset_addr(ctx, t0, base, offset);
1617 switch (opc) {
1618 #if defined(TARGET_MIPS64)
1619 case OPC_LWU:
1620 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1621 gen_store_gpr(t0, rt);
1622 opn = "lwu";
1623 break;
1624 case OPC_LD:
1625 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1626 gen_store_gpr(t0, rt);
1627 opn = "ld";
1628 break;
1629 case OPC_LLD:
1630 save_cpu_state(ctx, 1);
1631 op_ld_lld(t0, t0, ctx);
1632 gen_store_gpr(t0, rt);
1633 opn = "lld";
1634 break;
1635 case OPC_LDL:
1636 t1 = tcg_temp_new();
1637 tcg_gen_andi_tl(t1, t0, 7);
1638 #ifndef TARGET_WORDS_BIGENDIAN
1639 tcg_gen_xori_tl(t1, t1, 7);
1640 #endif
1641 tcg_gen_shli_tl(t1, t1, 3);
1642 tcg_gen_andi_tl(t0, t0, ~7);
1643 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1644 tcg_gen_shl_tl(t0, t0, t1);
1645 tcg_gen_xori_tl(t1, t1, 63);
1646 t2 = tcg_const_tl(0x7fffffffffffffffull);
1647 tcg_gen_shr_tl(t2, t2, t1);
1648 gen_load_gpr(t1, rt);
1649 tcg_gen_and_tl(t1, t1, t2);
1650 tcg_temp_free(t2);
1651 tcg_gen_or_tl(t0, t0, t1);
1652 tcg_temp_free(t1);
1653 gen_store_gpr(t0, rt);
1654 opn = "ldl";
1655 break;
1656 case OPC_LDR:
1657 t1 = tcg_temp_new();
1658 tcg_gen_andi_tl(t1, t0, 7);
1659 #ifdef TARGET_WORDS_BIGENDIAN
1660 tcg_gen_xori_tl(t1, t1, 7);
1661 #endif
1662 tcg_gen_shli_tl(t1, t1, 3);
1663 tcg_gen_andi_tl(t0, t0, ~7);
1664 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1665 tcg_gen_shr_tl(t0, t0, t1);
1666 tcg_gen_xori_tl(t1, t1, 63);
1667 t2 = tcg_const_tl(0xfffffffffffffffeull);
1668 tcg_gen_shl_tl(t2, t2, t1);
1669 gen_load_gpr(t1, rt);
1670 tcg_gen_and_tl(t1, t1, t2);
1671 tcg_temp_free(t2);
1672 tcg_gen_or_tl(t0, t0, t1);
1673 tcg_temp_free(t1);
1674 gen_store_gpr(t0, rt);
1675 opn = "ldr";
1676 break;
1677 case OPC_LDPC:
1678 t1 = tcg_const_tl(pc_relative_pc(ctx));
1679 gen_op_addr_add(ctx, t0, t0, t1);
1680 tcg_temp_free(t1);
1681 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1682 gen_store_gpr(t0, rt);
1683 opn = "ldpc";
1684 break;
1685 #endif
1686 case OPC_LWPC:
1687 t1 = tcg_const_tl(pc_relative_pc(ctx));
1688 gen_op_addr_add(ctx, t0, t0, t1);
1689 tcg_temp_free(t1);
1690 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1691 gen_store_gpr(t0, rt);
1692 opn = "lwpc";
1693 break;
1694 case OPC_LW:
1695 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1696 gen_store_gpr(t0, rt);
1697 opn = "lw";
1698 break;
1699 case OPC_LH:
1700 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
1701 gen_store_gpr(t0, rt);
1702 opn = "lh";
1703 break;
1704 case OPC_LHU:
1705 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
1706 gen_store_gpr(t0, rt);
1707 opn = "lhu";
1708 break;
1709 case OPC_LB:
1710 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
1711 gen_store_gpr(t0, rt);
1712 opn = "lb";
1713 break;
1714 case OPC_LBU:
1715 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
1716 gen_store_gpr(t0, rt);
1717 opn = "lbu";
1718 break;
1719 case OPC_LWL:
1720 t1 = tcg_temp_new();
1721 tcg_gen_andi_tl(t1, t0, 3);
1722 #ifndef TARGET_WORDS_BIGENDIAN
1723 tcg_gen_xori_tl(t1, t1, 3);
1724 #endif
1725 tcg_gen_shli_tl(t1, t1, 3);
1726 tcg_gen_andi_tl(t0, t0, ~3);
1727 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1728 tcg_gen_shl_tl(t0, t0, t1);
1729 tcg_gen_xori_tl(t1, t1, 31);
1730 t2 = tcg_const_tl(0x7fffffffull);
1731 tcg_gen_shr_tl(t2, t2, t1);
1732 gen_load_gpr(t1, rt);
1733 tcg_gen_and_tl(t1, t1, t2);
1734 tcg_temp_free(t2);
1735 tcg_gen_or_tl(t0, t0, t1);
1736 tcg_temp_free(t1);
1737 tcg_gen_ext32s_tl(t0, t0);
1738 gen_store_gpr(t0, rt);
1739 opn = "lwl";
1740 break;
1741 case OPC_LWR:
1742 t1 = tcg_temp_new();
1743 tcg_gen_andi_tl(t1, t0, 3);
1744 #ifdef TARGET_WORDS_BIGENDIAN
1745 tcg_gen_xori_tl(t1, t1, 3);
1746 #endif
1747 tcg_gen_shli_tl(t1, t1, 3);
1748 tcg_gen_andi_tl(t0, t0, ~3);
1749 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1750 tcg_gen_shr_tl(t0, t0, t1);
1751 tcg_gen_xori_tl(t1, t1, 31);
1752 t2 = tcg_const_tl(0xfffffffeull);
1753 tcg_gen_shl_tl(t2, t2, t1);
1754 gen_load_gpr(t1, rt);
1755 tcg_gen_and_tl(t1, t1, t2);
1756 tcg_temp_free(t2);
1757 tcg_gen_or_tl(t0, t0, t1);
1758 tcg_temp_free(t1);
1759 tcg_gen_ext32s_tl(t0, t0);
1760 gen_store_gpr(t0, rt);
1761 opn = "lwr";
1762 break;
1763 case OPC_LL:
1764 save_cpu_state(ctx, 1);
1765 op_ld_ll(t0, t0, ctx);
1766 gen_store_gpr(t0, rt);
1767 opn = "ll";
1768 break;
1770 (void)opn; /* avoid a compiler warning */
1771 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1772 tcg_temp_free(t0);
1775 /* Store */
1776 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1777 int base, int16_t offset)
1779 const char *opn = "st";
1780 TCGv t0 = tcg_temp_new();
1781 TCGv t1 = tcg_temp_new();
1783 gen_base_offset_addr(ctx, t0, base, offset);
1784 gen_load_gpr(t1, rt);
1785 switch (opc) {
1786 #if defined(TARGET_MIPS64)
1787 case OPC_SD:
1788 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
1789 opn = "sd";
1790 break;
1791 case OPC_SDL:
1792 save_cpu_state(ctx, 1);
1793 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
1794 opn = "sdl";
1795 break;
1796 case OPC_SDR:
1797 save_cpu_state(ctx, 1);
1798 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
1799 opn = "sdr";
1800 break;
1801 #endif
1802 case OPC_SW:
1803 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
1804 opn = "sw";
1805 break;
1806 case OPC_SH:
1807 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
1808 opn = "sh";
1809 break;
1810 case OPC_SB:
1811 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
1812 opn = "sb";
1813 break;
1814 case OPC_SWL:
1815 save_cpu_state(ctx, 1);
1816 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
1817 opn = "swl";
1818 break;
1819 case OPC_SWR:
1820 save_cpu_state(ctx, 1);
1821 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
1822 opn = "swr";
1823 break;
1825 (void)opn; /* avoid a compiler warning */
1826 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1827 tcg_temp_free(t0);
1828 tcg_temp_free(t1);
1832 /* Store conditional */
1833 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1834 int base, int16_t offset)
1836 const char *opn = "st_cond";
1837 TCGv t0, t1;
1839 #ifdef CONFIG_USER_ONLY
1840 t0 = tcg_temp_local_new();
1841 t1 = tcg_temp_local_new();
1842 #else
1843 t0 = tcg_temp_new();
1844 t1 = tcg_temp_new();
1845 #endif
1846 gen_base_offset_addr(ctx, t0, base, offset);
1847 gen_load_gpr(t1, rt);
1848 switch (opc) {
1849 #if defined(TARGET_MIPS64)
1850 case OPC_SCD:
1851 save_cpu_state(ctx, 1);
1852 op_st_scd(t1, t0, rt, ctx);
1853 opn = "scd";
1854 break;
1855 #endif
1856 case OPC_SC:
1857 save_cpu_state(ctx, 1);
1858 op_st_sc(t1, t0, rt, ctx);
1859 opn = "sc";
1860 break;
1862 (void)opn; /* avoid a compiler warning */
1863 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1864 tcg_temp_free(t1);
1865 tcg_temp_free(t0);
1868 /* Load and store */
1869 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1870 int base, int16_t offset)
1872 const char *opn = "flt_ldst";
1873 TCGv t0 = tcg_temp_new();
1875 gen_base_offset_addr(ctx, t0, base, offset);
1876 /* Don't do NOP if destination is zero: we must perform the actual
1877 memory access. */
1878 switch (opc) {
1879 case OPC_LWC1:
1881 TCGv_i32 fp0 = tcg_temp_new_i32();
1882 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
1883 gen_store_fpr32(fp0, ft);
1884 tcg_temp_free_i32(fp0);
1886 opn = "lwc1";
1887 break;
1888 case OPC_SWC1:
1890 TCGv_i32 fp0 = tcg_temp_new_i32();
1891 gen_load_fpr32(fp0, ft);
1892 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
1893 tcg_temp_free_i32(fp0);
1895 opn = "swc1";
1896 break;
1897 case OPC_LDC1:
1899 TCGv_i64 fp0 = tcg_temp_new_i64();
1900 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
1901 gen_store_fpr64(ctx, fp0, ft);
1902 tcg_temp_free_i64(fp0);
1904 opn = "ldc1";
1905 break;
1906 case OPC_SDC1:
1908 TCGv_i64 fp0 = tcg_temp_new_i64();
1909 gen_load_fpr64(ctx, fp0, ft);
1910 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
1911 tcg_temp_free_i64(fp0);
1913 opn = "sdc1";
1914 break;
1915 default:
1916 MIPS_INVAL(opn);
1917 generate_exception(ctx, EXCP_RI);
1918 goto out;
1920 (void)opn; /* avoid a compiler warning */
1921 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1922 out:
1923 tcg_temp_free(t0);
1926 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
1927 int rs, int16_t imm)
1929 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
1930 check_cp1_enabled(ctx);
1931 gen_flt_ldst(ctx, op, rt, rs, imm);
1932 } else {
1933 generate_exception_err(ctx, EXCP_CpU, 1);
1937 /* Arithmetic with immediate operand */
1938 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
1939 int rt, int rs, int16_t imm)
1941 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1942 const char *opn = "imm arith";
1944 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1945 /* If no destination, treat it as a NOP.
1946 For addi, we must generate the overflow exception when needed. */
1947 MIPS_DEBUG("NOP");
1948 return;
1950 switch (opc) {
1951 case OPC_ADDI:
1953 TCGv t0 = tcg_temp_local_new();
1954 TCGv t1 = tcg_temp_new();
1955 TCGv t2 = tcg_temp_new();
1956 int l1 = gen_new_label();
1958 gen_load_gpr(t1, rs);
1959 tcg_gen_addi_tl(t0, t1, uimm);
1960 tcg_gen_ext32s_tl(t0, t0);
1962 tcg_gen_xori_tl(t1, t1, ~uimm);
1963 tcg_gen_xori_tl(t2, t0, uimm);
1964 tcg_gen_and_tl(t1, t1, t2);
1965 tcg_temp_free(t2);
1966 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1967 tcg_temp_free(t1);
1968 /* operands of same sign, result different sign */
1969 generate_exception(ctx, EXCP_OVERFLOW);
1970 gen_set_label(l1);
1971 tcg_gen_ext32s_tl(t0, t0);
1972 gen_store_gpr(t0, rt);
1973 tcg_temp_free(t0);
1975 opn = "addi";
1976 break;
1977 case OPC_ADDIU:
1978 if (rs != 0) {
1979 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1980 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1981 } else {
1982 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1984 opn = "addiu";
1985 break;
1986 #if defined(TARGET_MIPS64)
1987 case OPC_DADDI:
1989 TCGv t0 = tcg_temp_local_new();
1990 TCGv t1 = tcg_temp_new();
1991 TCGv t2 = tcg_temp_new();
1992 int l1 = gen_new_label();
1994 gen_load_gpr(t1, rs);
1995 tcg_gen_addi_tl(t0, t1, uimm);
1997 tcg_gen_xori_tl(t1, t1, ~uimm);
1998 tcg_gen_xori_tl(t2, t0, uimm);
1999 tcg_gen_and_tl(t1, t1, t2);
2000 tcg_temp_free(t2);
2001 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2002 tcg_temp_free(t1);
2003 /* operands of same sign, result different sign */
2004 generate_exception(ctx, EXCP_OVERFLOW);
2005 gen_set_label(l1);
2006 gen_store_gpr(t0, rt);
2007 tcg_temp_free(t0);
2009 opn = "daddi";
2010 break;
2011 case OPC_DADDIU:
2012 if (rs != 0) {
2013 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2014 } else {
2015 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2017 opn = "daddiu";
2018 break;
2019 #endif
2021 (void)opn; /* avoid a compiler warning */
2022 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2025 /* Logic with immediate operand */
2026 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2027 int rt, int rs, int16_t imm)
2029 target_ulong uimm;
2031 if (rt == 0) {
2032 /* If no destination, treat it as a NOP. */
2033 MIPS_DEBUG("NOP");
2034 return;
2036 uimm = (uint16_t)imm;
2037 switch (opc) {
2038 case OPC_ANDI:
2039 if (likely(rs != 0))
2040 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2041 else
2042 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2043 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2044 regnames[rs], uimm);
2045 break;
2046 case OPC_ORI:
2047 if (rs != 0)
2048 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2049 else
2050 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2051 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2052 regnames[rs], uimm);
2053 break;
2054 case OPC_XORI:
2055 if (likely(rs != 0))
2056 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2057 else
2058 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2059 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2060 regnames[rs], uimm);
2061 break;
2062 case OPC_LUI:
2063 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2064 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2065 break;
2067 default:
2068 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2069 break;
2073 /* Set on less than with immediate operand */
2074 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2075 int rt, int rs, int16_t imm)
2077 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2078 const char *opn = "imm arith";
2079 TCGv t0;
2081 if (rt == 0) {
2082 /* If no destination, treat it as a NOP. */
2083 MIPS_DEBUG("NOP");
2084 return;
2086 t0 = tcg_temp_new();
2087 gen_load_gpr(t0, rs);
2088 switch (opc) {
2089 case OPC_SLTI:
2090 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2091 opn = "slti";
2092 break;
2093 case OPC_SLTIU:
2094 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2095 opn = "sltiu";
2096 break;
2098 (void)opn; /* avoid a compiler warning */
2099 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2100 tcg_temp_free(t0);
2103 /* Shifts with immediate operand */
2104 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2105 int rt, int rs, int16_t imm)
2107 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2108 const char *opn = "imm shift";
2109 TCGv t0;
2111 if (rt == 0) {
2112 /* If no destination, treat it as a NOP. */
2113 MIPS_DEBUG("NOP");
2114 return;
2117 t0 = tcg_temp_new();
2118 gen_load_gpr(t0, rs);
2119 switch (opc) {
2120 case OPC_SLL:
2121 tcg_gen_shli_tl(t0, t0, uimm);
2122 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2123 opn = "sll";
2124 break;
2125 case OPC_SRA:
2126 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2127 opn = "sra";
2128 break;
2129 case OPC_SRL:
2130 if (uimm != 0) {
2131 tcg_gen_ext32u_tl(t0, t0);
2132 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2133 } else {
2134 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2136 opn = "srl";
2137 break;
2138 case OPC_ROTR:
2139 if (uimm != 0) {
2140 TCGv_i32 t1 = tcg_temp_new_i32();
2142 tcg_gen_trunc_tl_i32(t1, t0);
2143 tcg_gen_rotri_i32(t1, t1, uimm);
2144 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2145 tcg_temp_free_i32(t1);
2146 } else {
2147 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2149 opn = "rotr";
2150 break;
2151 #if defined(TARGET_MIPS64)
2152 case OPC_DSLL:
2153 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2154 opn = "dsll";
2155 break;
2156 case OPC_DSRA:
2157 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2158 opn = "dsra";
2159 break;
2160 case OPC_DSRL:
2161 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2162 opn = "dsrl";
2163 break;
2164 case OPC_DROTR:
2165 if (uimm != 0) {
2166 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2167 } else {
2168 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2170 opn = "drotr";
2171 break;
2172 case OPC_DSLL32:
2173 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2174 opn = "dsll32";
2175 break;
2176 case OPC_DSRA32:
2177 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2178 opn = "dsra32";
2179 break;
2180 case OPC_DSRL32:
2181 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2182 opn = "dsrl32";
2183 break;
2184 case OPC_DROTR32:
2185 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2186 opn = "drotr32";
2187 break;
2188 #endif
2190 (void)opn; /* avoid a compiler warning */
2191 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2192 tcg_temp_free(t0);
2195 /* Arithmetic */
2196 static void gen_arith(DisasContext *ctx, uint32_t opc,
2197 int rd, int rs, int rt)
2199 const char *opn = "arith";
2201 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2202 && opc != OPC_DADD && opc != OPC_DSUB) {
2203 /* If no destination, treat it as a NOP.
2204 For add & sub, we must generate the overflow exception when needed. */
2205 MIPS_DEBUG("NOP");
2206 return;
2209 switch (opc) {
2210 case OPC_ADD:
2212 TCGv t0 = tcg_temp_local_new();
2213 TCGv t1 = tcg_temp_new();
2214 TCGv t2 = tcg_temp_new();
2215 int l1 = gen_new_label();
2217 gen_load_gpr(t1, rs);
2218 gen_load_gpr(t2, rt);
2219 tcg_gen_add_tl(t0, t1, t2);
2220 tcg_gen_ext32s_tl(t0, t0);
2221 tcg_gen_xor_tl(t1, t1, t2);
2222 tcg_gen_xor_tl(t2, t0, t2);
2223 tcg_gen_andc_tl(t1, t2, t1);
2224 tcg_temp_free(t2);
2225 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2226 tcg_temp_free(t1);
2227 /* operands of same sign, result different sign */
2228 generate_exception(ctx, EXCP_OVERFLOW);
2229 gen_set_label(l1);
2230 gen_store_gpr(t0, rd);
2231 tcg_temp_free(t0);
2233 opn = "add";
2234 break;
2235 case OPC_ADDU:
2236 if (rs != 0 && rt != 0) {
2237 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2238 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2239 } else if (rs == 0 && rt != 0) {
2240 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2241 } else if (rs != 0 && rt == 0) {
2242 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2243 } else {
2244 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2246 opn = "addu";
2247 break;
2248 case OPC_SUB:
2250 TCGv t0 = tcg_temp_local_new();
2251 TCGv t1 = tcg_temp_new();
2252 TCGv t2 = tcg_temp_new();
2253 int l1 = gen_new_label();
2255 gen_load_gpr(t1, rs);
2256 gen_load_gpr(t2, rt);
2257 tcg_gen_sub_tl(t0, t1, t2);
2258 tcg_gen_ext32s_tl(t0, t0);
2259 tcg_gen_xor_tl(t2, t1, t2);
2260 tcg_gen_xor_tl(t1, t0, t1);
2261 tcg_gen_and_tl(t1, t1, t2);
2262 tcg_temp_free(t2);
2263 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2264 tcg_temp_free(t1);
2265 /* operands of different sign, first operand and result different sign */
2266 generate_exception(ctx, EXCP_OVERFLOW);
2267 gen_set_label(l1);
2268 gen_store_gpr(t0, rd);
2269 tcg_temp_free(t0);
2271 opn = "sub";
2272 break;
2273 case OPC_SUBU:
2274 if (rs != 0 && rt != 0) {
2275 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2276 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2277 } else if (rs == 0 && rt != 0) {
2278 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2279 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2280 } else if (rs != 0 && rt == 0) {
2281 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2282 } else {
2283 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2285 opn = "subu";
2286 break;
2287 #if defined(TARGET_MIPS64)
2288 case OPC_DADD:
2290 TCGv t0 = tcg_temp_local_new();
2291 TCGv t1 = tcg_temp_new();
2292 TCGv t2 = tcg_temp_new();
2293 int l1 = gen_new_label();
2295 gen_load_gpr(t1, rs);
2296 gen_load_gpr(t2, rt);
2297 tcg_gen_add_tl(t0, t1, t2);
2298 tcg_gen_xor_tl(t1, t1, t2);
2299 tcg_gen_xor_tl(t2, t0, t2);
2300 tcg_gen_andc_tl(t1, t2, t1);
2301 tcg_temp_free(t2);
2302 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2303 tcg_temp_free(t1);
2304 /* operands of same sign, result different sign */
2305 generate_exception(ctx, EXCP_OVERFLOW);
2306 gen_set_label(l1);
2307 gen_store_gpr(t0, rd);
2308 tcg_temp_free(t0);
2310 opn = "dadd";
2311 break;
2312 case OPC_DADDU:
2313 if (rs != 0 && rt != 0) {
2314 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2315 } else if (rs == 0 && rt != 0) {
2316 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2317 } else if (rs != 0 && rt == 0) {
2318 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2319 } else {
2320 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2322 opn = "daddu";
2323 break;
2324 case OPC_DSUB:
2326 TCGv t0 = tcg_temp_local_new();
2327 TCGv t1 = tcg_temp_new();
2328 TCGv t2 = tcg_temp_new();
2329 int l1 = gen_new_label();
2331 gen_load_gpr(t1, rs);
2332 gen_load_gpr(t2, rt);
2333 tcg_gen_sub_tl(t0, t1, t2);
2334 tcg_gen_xor_tl(t2, t1, t2);
2335 tcg_gen_xor_tl(t1, t0, t1);
2336 tcg_gen_and_tl(t1, t1, t2);
2337 tcg_temp_free(t2);
2338 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2339 tcg_temp_free(t1);
2340 /* operands of different sign, first operand and result different sign */
2341 generate_exception(ctx, EXCP_OVERFLOW);
2342 gen_set_label(l1);
2343 gen_store_gpr(t0, rd);
2344 tcg_temp_free(t0);
2346 opn = "dsub";
2347 break;
2348 case OPC_DSUBU:
2349 if (rs != 0 && rt != 0) {
2350 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2351 } else if (rs == 0 && rt != 0) {
2352 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2353 } else if (rs != 0 && rt == 0) {
2354 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2355 } else {
2356 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2358 opn = "dsubu";
2359 break;
2360 #endif
2361 case OPC_MUL:
2362 if (likely(rs != 0 && rt != 0)) {
2363 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2364 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2365 } else {
2366 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2368 opn = "mul";
2369 break;
2371 (void)opn; /* avoid a compiler warning */
2372 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2375 /* Conditional move */
2376 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2377 int rd, int rs, int rt)
2379 const char *opn = "cond move";
2380 TCGv t0, t1, t2;
2382 if (rd == 0) {
2383 /* If no destination, treat it as a NOP. */
2384 MIPS_DEBUG("NOP");
2385 return;
2388 t0 = tcg_temp_new();
2389 gen_load_gpr(t0, rt);
2390 t1 = tcg_const_tl(0);
2391 t2 = tcg_temp_new();
2392 gen_load_gpr(t2, rs);
2393 switch (opc) {
2394 case OPC_MOVN:
2395 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2396 opn = "movn";
2397 break;
2398 case OPC_MOVZ:
2399 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2400 opn = "movz";
2401 break;
2403 tcg_temp_free(t2);
2404 tcg_temp_free(t1);
2405 tcg_temp_free(t0);
2407 (void)opn; /* avoid a compiler warning */
2408 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2411 /* Logic */
2412 static void gen_logic(DisasContext *ctx, uint32_t opc,
2413 int rd, int rs, int rt)
2415 const char *opn = "logic";
2417 if (rd == 0) {
2418 /* If no destination, treat it as a NOP. */
2419 MIPS_DEBUG("NOP");
2420 return;
2423 switch (opc) {
2424 case OPC_AND:
2425 if (likely(rs != 0 && rt != 0)) {
2426 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2427 } else {
2428 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2430 opn = "and";
2431 break;
2432 case OPC_NOR:
2433 if (rs != 0 && rt != 0) {
2434 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2435 } else if (rs == 0 && rt != 0) {
2436 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2437 } else if (rs != 0 && rt == 0) {
2438 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2439 } else {
2440 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2442 opn = "nor";
2443 break;
2444 case OPC_OR:
2445 if (likely(rs != 0 && rt != 0)) {
2446 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2447 } else if (rs == 0 && rt != 0) {
2448 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2449 } else if (rs != 0 && rt == 0) {
2450 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2451 } else {
2452 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2454 opn = "or";
2455 break;
2456 case OPC_XOR:
2457 if (likely(rs != 0 && rt != 0)) {
2458 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2459 } else if (rs == 0 && rt != 0) {
2460 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2461 } else if (rs != 0 && rt == 0) {
2462 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2463 } else {
2464 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2466 opn = "xor";
2467 break;
2469 (void)opn; /* avoid a compiler warning */
2470 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2473 /* Set on lower than */
2474 static void gen_slt(DisasContext *ctx, uint32_t opc,
2475 int rd, int rs, int rt)
2477 const char *opn = "slt";
2478 TCGv t0, t1;
2480 if (rd == 0) {
2481 /* If no destination, treat it as a NOP. */
2482 MIPS_DEBUG("NOP");
2483 return;
2486 t0 = tcg_temp_new();
2487 t1 = tcg_temp_new();
2488 gen_load_gpr(t0, rs);
2489 gen_load_gpr(t1, rt);
2490 switch (opc) {
2491 case OPC_SLT:
2492 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2493 opn = "slt";
2494 break;
2495 case OPC_SLTU:
2496 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2497 opn = "sltu";
2498 break;
2500 (void)opn; /* avoid a compiler warning */
2501 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2502 tcg_temp_free(t0);
2503 tcg_temp_free(t1);
2506 /* Shifts */
2507 static void gen_shift(DisasContext *ctx, uint32_t opc,
2508 int rd, int rs, int rt)
2510 const char *opn = "shifts";
2511 TCGv t0, t1;
2513 if (rd == 0) {
2514 /* If no destination, treat it as a NOP.
2515 For add & sub, we must generate the overflow exception when needed. */
2516 MIPS_DEBUG("NOP");
2517 return;
2520 t0 = tcg_temp_new();
2521 t1 = tcg_temp_new();
2522 gen_load_gpr(t0, rs);
2523 gen_load_gpr(t1, rt);
2524 switch (opc) {
2525 case OPC_SLLV:
2526 tcg_gen_andi_tl(t0, t0, 0x1f);
2527 tcg_gen_shl_tl(t0, t1, t0);
2528 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2529 opn = "sllv";
2530 break;
2531 case OPC_SRAV:
2532 tcg_gen_andi_tl(t0, t0, 0x1f);
2533 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2534 opn = "srav";
2535 break;
2536 case OPC_SRLV:
2537 tcg_gen_ext32u_tl(t1, t1);
2538 tcg_gen_andi_tl(t0, t0, 0x1f);
2539 tcg_gen_shr_tl(t0, t1, t0);
2540 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2541 opn = "srlv";
2542 break;
2543 case OPC_ROTRV:
2545 TCGv_i32 t2 = tcg_temp_new_i32();
2546 TCGv_i32 t3 = tcg_temp_new_i32();
2548 tcg_gen_trunc_tl_i32(t2, t0);
2549 tcg_gen_trunc_tl_i32(t3, t1);
2550 tcg_gen_andi_i32(t2, t2, 0x1f);
2551 tcg_gen_rotr_i32(t2, t3, t2);
2552 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2553 tcg_temp_free_i32(t2);
2554 tcg_temp_free_i32(t3);
2555 opn = "rotrv";
2557 break;
2558 #if defined(TARGET_MIPS64)
2559 case OPC_DSLLV:
2560 tcg_gen_andi_tl(t0, t0, 0x3f);
2561 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2562 opn = "dsllv";
2563 break;
2564 case OPC_DSRAV:
2565 tcg_gen_andi_tl(t0, t0, 0x3f);
2566 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2567 opn = "dsrav";
2568 break;
2569 case OPC_DSRLV:
2570 tcg_gen_andi_tl(t0, t0, 0x3f);
2571 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2572 opn = "dsrlv";
2573 break;
2574 case OPC_DROTRV:
2575 tcg_gen_andi_tl(t0, t0, 0x3f);
2576 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2577 opn = "drotrv";
2578 break;
2579 #endif
2581 (void)opn; /* avoid a compiler warning */
2582 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2583 tcg_temp_free(t0);
2584 tcg_temp_free(t1);
2587 /* Arithmetic on HI/LO registers */
2588 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2590 const char *opn = "hilo";
2592 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2593 /* Treat as NOP. */
2594 MIPS_DEBUG("NOP");
2595 return;
2598 if (acc != 0) {
2599 check_dsp(ctx);
2602 switch (opc) {
2603 case OPC_MFHI:
2604 #if defined(TARGET_MIPS64)
2605 if (acc != 0) {
2606 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2607 } else
2608 #endif
2610 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2612 opn = "mfhi";
2613 break;
2614 case OPC_MFLO:
2615 #if defined(TARGET_MIPS64)
2616 if (acc != 0) {
2617 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2618 } else
2619 #endif
2621 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2623 opn = "mflo";
2624 break;
2625 case OPC_MTHI:
2626 if (reg != 0) {
2627 #if defined(TARGET_MIPS64)
2628 if (acc != 0) {
2629 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2630 } else
2631 #endif
2633 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2635 } else {
2636 tcg_gen_movi_tl(cpu_HI[acc], 0);
2638 opn = "mthi";
2639 break;
2640 case OPC_MTLO:
2641 if (reg != 0) {
2642 #if defined(TARGET_MIPS64)
2643 if (acc != 0) {
2644 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2645 } else
2646 #endif
2648 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2650 } else {
2651 tcg_gen_movi_tl(cpu_LO[acc], 0);
2653 opn = "mtlo";
2654 break;
2656 (void)opn; /* avoid a compiler warning */
2657 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2660 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
2661 int acc, int rs, int rt)
2663 const char *opn = "mul/div";
2664 TCGv t0, t1;
2666 t0 = tcg_temp_new();
2667 t1 = tcg_temp_new();
2669 gen_load_gpr(t0, rs);
2670 gen_load_gpr(t1, rt);
2672 if (acc != 0) {
2673 check_dsp(ctx);
2676 switch (opc) {
2677 case OPC_DIV:
2679 TCGv t2 = tcg_temp_new();
2680 TCGv t3 = tcg_temp_new();
2681 tcg_gen_ext32s_tl(t0, t0);
2682 tcg_gen_ext32s_tl(t1, t1);
2683 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2684 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2685 tcg_gen_and_tl(t2, t2, t3);
2686 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2687 tcg_gen_or_tl(t2, t2, t3);
2688 tcg_gen_movi_tl(t3, 0);
2689 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2690 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
2691 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
2692 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
2693 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
2694 tcg_temp_free(t3);
2695 tcg_temp_free(t2);
2697 opn = "div";
2698 break;
2699 case OPC_DIVU:
2701 TCGv t2 = tcg_const_tl(0);
2702 TCGv t3 = tcg_const_tl(1);
2703 tcg_gen_ext32u_tl(t0, t0);
2704 tcg_gen_ext32u_tl(t1, t1);
2705 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
2706 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
2707 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
2708 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
2709 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
2710 tcg_temp_free(t3);
2711 tcg_temp_free(t2);
2713 opn = "divu";
2714 break;
2715 case OPC_MULT:
2717 TCGv_i32 t2 = tcg_temp_new_i32();
2718 TCGv_i32 t3 = tcg_temp_new_i32();
2719 tcg_gen_trunc_tl_i32(t2, t0);
2720 tcg_gen_trunc_tl_i32(t3, t1);
2721 tcg_gen_muls2_i32(t2, t3, t2, t3);
2722 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2723 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2724 tcg_temp_free_i32(t2);
2725 tcg_temp_free_i32(t3);
2727 opn = "mult";
2728 break;
2729 case OPC_MULTU:
2731 TCGv_i32 t2 = tcg_temp_new_i32();
2732 TCGv_i32 t3 = tcg_temp_new_i32();
2733 tcg_gen_trunc_tl_i32(t2, t0);
2734 tcg_gen_trunc_tl_i32(t3, t1);
2735 tcg_gen_mulu2_i32(t2, t3, t2, t3);
2736 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2737 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2738 tcg_temp_free_i32(t2);
2739 tcg_temp_free_i32(t3);
2741 opn = "multu";
2742 break;
2743 #if defined(TARGET_MIPS64)
2744 case OPC_DDIV:
2746 TCGv t2 = tcg_temp_new();
2747 TCGv t3 = tcg_temp_new();
2748 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
2749 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
2750 tcg_gen_and_tl(t2, t2, t3);
2751 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2752 tcg_gen_or_tl(t2, t2, t3);
2753 tcg_gen_movi_tl(t3, 0);
2754 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2755 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
2756 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
2757 tcg_temp_free(t3);
2758 tcg_temp_free(t2);
2760 opn = "ddiv";
2761 break;
2762 case OPC_DDIVU:
2764 TCGv t2 = tcg_const_tl(0);
2765 TCGv t3 = tcg_const_tl(1);
2766 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
2767 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
2768 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
2769 tcg_temp_free(t3);
2770 tcg_temp_free(t2);
2772 opn = "ddivu";
2773 break;
2774 case OPC_DMULT:
2775 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
2776 opn = "dmult";
2777 break;
2778 case OPC_DMULTU:
2779 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
2780 opn = "dmultu";
2781 break;
2782 #endif
2783 case OPC_MADD:
2785 TCGv_i64 t2 = tcg_temp_new_i64();
2786 TCGv_i64 t3 = tcg_temp_new_i64();
2788 tcg_gen_ext_tl_i64(t2, t0);
2789 tcg_gen_ext_tl_i64(t3, t1);
2790 tcg_gen_mul_i64(t2, t2, t3);
2791 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2792 tcg_gen_add_i64(t2, t2, t3);
2793 tcg_temp_free_i64(t3);
2794 tcg_gen_trunc_i64_tl(t0, t2);
2795 tcg_gen_shri_i64(t2, t2, 32);
2796 tcg_gen_trunc_i64_tl(t1, t2);
2797 tcg_temp_free_i64(t2);
2798 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2799 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2801 opn = "madd";
2802 break;
2803 case OPC_MADDU:
2805 TCGv_i64 t2 = tcg_temp_new_i64();
2806 TCGv_i64 t3 = tcg_temp_new_i64();
2808 tcg_gen_ext32u_tl(t0, t0);
2809 tcg_gen_ext32u_tl(t1, t1);
2810 tcg_gen_extu_tl_i64(t2, t0);
2811 tcg_gen_extu_tl_i64(t3, t1);
2812 tcg_gen_mul_i64(t2, t2, t3);
2813 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2814 tcg_gen_add_i64(t2, t2, t3);
2815 tcg_temp_free_i64(t3);
2816 tcg_gen_trunc_i64_tl(t0, t2);
2817 tcg_gen_shri_i64(t2, t2, 32);
2818 tcg_gen_trunc_i64_tl(t1, t2);
2819 tcg_temp_free_i64(t2);
2820 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2821 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2823 opn = "maddu";
2824 break;
2825 case OPC_MSUB:
2827 TCGv_i64 t2 = tcg_temp_new_i64();
2828 TCGv_i64 t3 = tcg_temp_new_i64();
2830 tcg_gen_ext_tl_i64(t2, t0);
2831 tcg_gen_ext_tl_i64(t3, t1);
2832 tcg_gen_mul_i64(t2, t2, t3);
2833 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2834 tcg_gen_sub_i64(t2, t3, t2);
2835 tcg_temp_free_i64(t3);
2836 tcg_gen_trunc_i64_tl(t0, t2);
2837 tcg_gen_shri_i64(t2, t2, 32);
2838 tcg_gen_trunc_i64_tl(t1, t2);
2839 tcg_temp_free_i64(t2);
2840 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2841 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2843 opn = "msub";
2844 break;
2845 case OPC_MSUBU:
2847 TCGv_i64 t2 = tcg_temp_new_i64();
2848 TCGv_i64 t3 = tcg_temp_new_i64();
2850 tcg_gen_ext32u_tl(t0, t0);
2851 tcg_gen_ext32u_tl(t1, t1);
2852 tcg_gen_extu_tl_i64(t2, t0);
2853 tcg_gen_extu_tl_i64(t3, t1);
2854 tcg_gen_mul_i64(t2, t2, t3);
2855 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2856 tcg_gen_sub_i64(t2, t3, t2);
2857 tcg_temp_free_i64(t3);
2858 tcg_gen_trunc_i64_tl(t0, t2);
2859 tcg_gen_shri_i64(t2, t2, 32);
2860 tcg_gen_trunc_i64_tl(t1, t2);
2861 tcg_temp_free_i64(t2);
2862 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2863 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2865 opn = "msubu";
2866 break;
2867 default:
2868 MIPS_INVAL(opn);
2869 generate_exception(ctx, EXCP_RI);
2870 goto out;
2872 (void)opn; /* avoid a compiler warning */
2873 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2874 out:
2875 tcg_temp_free(t0);
2876 tcg_temp_free(t1);
2879 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2880 int rd, int rs, int rt)
2882 const char *opn = "mul vr54xx";
2883 TCGv t0 = tcg_temp_new();
2884 TCGv t1 = tcg_temp_new();
2886 gen_load_gpr(t0, rs);
2887 gen_load_gpr(t1, rt);
2889 switch (opc) {
2890 case OPC_VR54XX_MULS:
2891 gen_helper_muls(t0, cpu_env, t0, t1);
2892 opn = "muls";
2893 break;
2894 case OPC_VR54XX_MULSU:
2895 gen_helper_mulsu(t0, cpu_env, t0, t1);
2896 opn = "mulsu";
2897 break;
2898 case OPC_VR54XX_MACC:
2899 gen_helper_macc(t0, cpu_env, t0, t1);
2900 opn = "macc";
2901 break;
2902 case OPC_VR54XX_MACCU:
2903 gen_helper_maccu(t0, cpu_env, t0, t1);
2904 opn = "maccu";
2905 break;
2906 case OPC_VR54XX_MSAC:
2907 gen_helper_msac(t0, cpu_env, t0, t1);
2908 opn = "msac";
2909 break;
2910 case OPC_VR54XX_MSACU:
2911 gen_helper_msacu(t0, cpu_env, t0, t1);
2912 opn = "msacu";
2913 break;
2914 case OPC_VR54XX_MULHI:
2915 gen_helper_mulhi(t0, cpu_env, t0, t1);
2916 opn = "mulhi";
2917 break;
2918 case OPC_VR54XX_MULHIU:
2919 gen_helper_mulhiu(t0, cpu_env, t0, t1);
2920 opn = "mulhiu";
2921 break;
2922 case OPC_VR54XX_MULSHI:
2923 gen_helper_mulshi(t0, cpu_env, t0, t1);
2924 opn = "mulshi";
2925 break;
2926 case OPC_VR54XX_MULSHIU:
2927 gen_helper_mulshiu(t0, cpu_env, t0, t1);
2928 opn = "mulshiu";
2929 break;
2930 case OPC_VR54XX_MACCHI:
2931 gen_helper_macchi(t0, cpu_env, t0, t1);
2932 opn = "macchi";
2933 break;
2934 case OPC_VR54XX_MACCHIU:
2935 gen_helper_macchiu(t0, cpu_env, t0, t1);
2936 opn = "macchiu";
2937 break;
2938 case OPC_VR54XX_MSACHI:
2939 gen_helper_msachi(t0, cpu_env, t0, t1);
2940 opn = "msachi";
2941 break;
2942 case OPC_VR54XX_MSACHIU:
2943 gen_helper_msachiu(t0, cpu_env, t0, t1);
2944 opn = "msachiu";
2945 break;
2946 default:
2947 MIPS_INVAL("mul vr54xx");
2948 generate_exception(ctx, EXCP_RI);
2949 goto out;
2951 gen_store_gpr(t0, rd);
2952 (void)opn; /* avoid a compiler warning */
2953 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2955 out:
2956 tcg_temp_free(t0);
2957 tcg_temp_free(t1);
2960 static void gen_cl (DisasContext *ctx, uint32_t opc,
2961 int rd, int rs)
2963 const char *opn = "CLx";
2964 TCGv t0;
2966 if (rd == 0) {
2967 /* Treat as NOP. */
2968 MIPS_DEBUG("NOP");
2969 return;
2971 t0 = tcg_temp_new();
2972 gen_load_gpr(t0, rs);
2973 switch (opc) {
2974 case OPC_CLO:
2975 gen_helper_clo(cpu_gpr[rd], t0);
2976 opn = "clo";
2977 break;
2978 case OPC_CLZ:
2979 gen_helper_clz(cpu_gpr[rd], t0);
2980 opn = "clz";
2981 break;
2982 #if defined(TARGET_MIPS64)
2983 case OPC_DCLO:
2984 gen_helper_dclo(cpu_gpr[rd], t0);
2985 opn = "dclo";
2986 break;
2987 case OPC_DCLZ:
2988 gen_helper_dclz(cpu_gpr[rd], t0);
2989 opn = "dclz";
2990 break;
2991 #endif
2993 (void)opn; /* avoid a compiler warning */
2994 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2995 tcg_temp_free(t0);
2998 /* Godson integer instructions */
2999 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
3000 int rd, int rs, int rt)
3002 const char *opn = "loongson";
3003 TCGv t0, t1;
3005 if (rd == 0) {
3006 /* Treat as NOP. */
3007 MIPS_DEBUG("NOP");
3008 return;
3011 switch (opc) {
3012 case OPC_MULT_G_2E:
3013 case OPC_MULT_G_2F:
3014 case OPC_MULTU_G_2E:
3015 case OPC_MULTU_G_2F:
3016 #if defined(TARGET_MIPS64)
3017 case OPC_DMULT_G_2E:
3018 case OPC_DMULT_G_2F:
3019 case OPC_DMULTU_G_2E:
3020 case OPC_DMULTU_G_2F:
3021 #endif
3022 t0 = tcg_temp_new();
3023 t1 = tcg_temp_new();
3024 break;
3025 default:
3026 t0 = tcg_temp_local_new();
3027 t1 = tcg_temp_local_new();
3028 break;
3031 gen_load_gpr(t0, rs);
3032 gen_load_gpr(t1, rt);
3034 switch (opc) {
3035 case OPC_MULT_G_2E:
3036 case OPC_MULT_G_2F:
3037 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3038 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3039 opn = "mult.g";
3040 break;
3041 case OPC_MULTU_G_2E:
3042 case OPC_MULTU_G_2F:
3043 tcg_gen_ext32u_tl(t0, t0);
3044 tcg_gen_ext32u_tl(t1, t1);
3045 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3046 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3047 opn = "multu.g";
3048 break;
3049 case OPC_DIV_G_2E:
3050 case OPC_DIV_G_2F:
3052 int l1 = gen_new_label();
3053 int l2 = gen_new_label();
3054 int l3 = gen_new_label();
3055 tcg_gen_ext32s_tl(t0, t0);
3056 tcg_gen_ext32s_tl(t1, t1);
3057 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3058 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3059 tcg_gen_br(l3);
3060 gen_set_label(l1);
3061 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3062 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3063 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3064 tcg_gen_br(l3);
3065 gen_set_label(l2);
3066 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3067 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3068 gen_set_label(l3);
3070 opn = "div.g";
3071 break;
3072 case OPC_DIVU_G_2E:
3073 case OPC_DIVU_G_2F:
3075 int l1 = gen_new_label();
3076 int l2 = gen_new_label();
3077 tcg_gen_ext32u_tl(t0, t0);
3078 tcg_gen_ext32u_tl(t1, t1);
3079 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3080 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3081 tcg_gen_br(l2);
3082 gen_set_label(l1);
3083 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3084 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3085 gen_set_label(l2);
3087 opn = "divu.g";
3088 break;
3089 case OPC_MOD_G_2E:
3090 case OPC_MOD_G_2F:
3092 int l1 = gen_new_label();
3093 int l2 = gen_new_label();
3094 int l3 = gen_new_label();
3095 tcg_gen_ext32u_tl(t0, t0);
3096 tcg_gen_ext32u_tl(t1, t1);
3097 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3098 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3099 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3100 gen_set_label(l1);
3101 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3102 tcg_gen_br(l3);
3103 gen_set_label(l2);
3104 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3105 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3106 gen_set_label(l3);
3108 opn = "mod.g";
3109 break;
3110 case OPC_MODU_G_2E:
3111 case OPC_MODU_G_2F:
3113 int l1 = gen_new_label();
3114 int l2 = gen_new_label();
3115 tcg_gen_ext32u_tl(t0, t0);
3116 tcg_gen_ext32u_tl(t1, t1);
3117 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3118 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3119 tcg_gen_br(l2);
3120 gen_set_label(l1);
3121 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3122 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3123 gen_set_label(l2);
3125 opn = "modu.g";
3126 break;
3127 #if defined(TARGET_MIPS64)
3128 case OPC_DMULT_G_2E:
3129 case OPC_DMULT_G_2F:
3130 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3131 opn = "dmult.g";
3132 break;
3133 case OPC_DMULTU_G_2E:
3134 case OPC_DMULTU_G_2F:
3135 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3136 opn = "dmultu.g";
3137 break;
3138 case OPC_DDIV_G_2E:
3139 case OPC_DDIV_G_2F:
3141 int l1 = gen_new_label();
3142 int l2 = gen_new_label();
3143 int l3 = gen_new_label();
3144 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3145 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3146 tcg_gen_br(l3);
3147 gen_set_label(l1);
3148 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3149 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3150 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3151 tcg_gen_br(l3);
3152 gen_set_label(l2);
3153 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3154 gen_set_label(l3);
3156 opn = "ddiv.g";
3157 break;
3158 case OPC_DDIVU_G_2E:
3159 case OPC_DDIVU_G_2F:
3161 int l1 = gen_new_label();
3162 int l2 = gen_new_label();
3163 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3164 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3165 tcg_gen_br(l2);
3166 gen_set_label(l1);
3167 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3168 gen_set_label(l2);
3170 opn = "ddivu.g";
3171 break;
3172 case OPC_DMOD_G_2E:
3173 case OPC_DMOD_G_2F:
3175 int l1 = gen_new_label();
3176 int l2 = gen_new_label();
3177 int l3 = gen_new_label();
3178 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3179 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3180 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3181 gen_set_label(l1);
3182 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3183 tcg_gen_br(l3);
3184 gen_set_label(l2);
3185 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3186 gen_set_label(l3);
3188 opn = "dmod.g";
3189 break;
3190 case OPC_DMODU_G_2E:
3191 case OPC_DMODU_G_2F:
3193 int l1 = gen_new_label();
3194 int l2 = gen_new_label();
3195 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3196 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3197 tcg_gen_br(l2);
3198 gen_set_label(l1);
3199 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3200 gen_set_label(l2);
3202 opn = "dmodu.g";
3203 break;
3204 #endif
3207 (void)opn; /* avoid a compiler warning */
3208 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3209 tcg_temp_free(t0);
3210 tcg_temp_free(t1);
3213 /* Loongson multimedia instructions */
3214 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3216 const char *opn = "loongson_cp2";
3217 uint32_t opc, shift_max;
3218 TCGv_i64 t0, t1;
3220 opc = MASK_LMI(ctx->opcode);
3221 switch (opc) {
3222 case OPC_ADD_CP2:
3223 case OPC_SUB_CP2:
3224 case OPC_DADD_CP2:
3225 case OPC_DSUB_CP2:
3226 t0 = tcg_temp_local_new_i64();
3227 t1 = tcg_temp_local_new_i64();
3228 break;
3229 default:
3230 t0 = tcg_temp_new_i64();
3231 t1 = tcg_temp_new_i64();
3232 break;
3235 gen_load_fpr64(ctx, t0, rs);
3236 gen_load_fpr64(ctx, t1, rt);
3238 #define LMI_HELPER(UP, LO) \
3239 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3240 #define LMI_HELPER_1(UP, LO) \
3241 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3242 #define LMI_DIRECT(UP, LO, OP) \
3243 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3245 switch (opc) {
3246 LMI_HELPER(PADDSH, paddsh);
3247 LMI_HELPER(PADDUSH, paddush);
3248 LMI_HELPER(PADDH, paddh);
3249 LMI_HELPER(PADDW, paddw);
3250 LMI_HELPER(PADDSB, paddsb);
3251 LMI_HELPER(PADDUSB, paddusb);
3252 LMI_HELPER(PADDB, paddb);
3254 LMI_HELPER(PSUBSH, psubsh);
3255 LMI_HELPER(PSUBUSH, psubush);
3256 LMI_HELPER(PSUBH, psubh);
3257 LMI_HELPER(PSUBW, psubw);
3258 LMI_HELPER(PSUBSB, psubsb);
3259 LMI_HELPER(PSUBUSB, psubusb);
3260 LMI_HELPER(PSUBB, psubb);
3262 LMI_HELPER(PSHUFH, pshufh);
3263 LMI_HELPER(PACKSSWH, packsswh);
3264 LMI_HELPER(PACKSSHB, packsshb);
3265 LMI_HELPER(PACKUSHB, packushb);
3267 LMI_HELPER(PUNPCKLHW, punpcklhw);
3268 LMI_HELPER(PUNPCKHHW, punpckhhw);
3269 LMI_HELPER(PUNPCKLBH, punpcklbh);
3270 LMI_HELPER(PUNPCKHBH, punpckhbh);
3271 LMI_HELPER(PUNPCKLWD, punpcklwd);
3272 LMI_HELPER(PUNPCKHWD, punpckhwd);
3274 LMI_HELPER(PAVGH, pavgh);
3275 LMI_HELPER(PAVGB, pavgb);
3276 LMI_HELPER(PMAXSH, pmaxsh);
3277 LMI_HELPER(PMINSH, pminsh);
3278 LMI_HELPER(PMAXUB, pmaxub);
3279 LMI_HELPER(PMINUB, pminub);
3281 LMI_HELPER(PCMPEQW, pcmpeqw);
3282 LMI_HELPER(PCMPGTW, pcmpgtw);
3283 LMI_HELPER(PCMPEQH, pcmpeqh);
3284 LMI_HELPER(PCMPGTH, pcmpgth);
3285 LMI_HELPER(PCMPEQB, pcmpeqb);
3286 LMI_HELPER(PCMPGTB, pcmpgtb);
3288 LMI_HELPER(PSLLW, psllw);
3289 LMI_HELPER(PSLLH, psllh);
3290 LMI_HELPER(PSRLW, psrlw);
3291 LMI_HELPER(PSRLH, psrlh);
3292 LMI_HELPER(PSRAW, psraw);
3293 LMI_HELPER(PSRAH, psrah);
3295 LMI_HELPER(PMULLH, pmullh);
3296 LMI_HELPER(PMULHH, pmulhh);
3297 LMI_HELPER(PMULHUH, pmulhuh);
3298 LMI_HELPER(PMADDHW, pmaddhw);
3300 LMI_HELPER(PASUBUB, pasubub);
3301 LMI_HELPER_1(BIADD, biadd);
3302 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3304 LMI_DIRECT(PADDD, paddd, add);
3305 LMI_DIRECT(PSUBD, psubd, sub);
3306 LMI_DIRECT(XOR_CP2, xor, xor);
3307 LMI_DIRECT(NOR_CP2, nor, nor);
3308 LMI_DIRECT(AND_CP2, and, and);
3309 LMI_DIRECT(PANDN, pandn, andc);
3310 LMI_DIRECT(OR, or, or);
3312 case OPC_PINSRH_0:
3313 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3314 opn = "pinsrh_0";
3315 break;
3316 case OPC_PINSRH_1:
3317 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3318 opn = "pinsrh_1";
3319 break;
3320 case OPC_PINSRH_2:
3321 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3322 opn = "pinsrh_2";
3323 break;
3324 case OPC_PINSRH_3:
3325 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3326 opn = "pinsrh_3";
3327 break;
3329 case OPC_PEXTRH:
3330 tcg_gen_andi_i64(t1, t1, 3);
3331 tcg_gen_shli_i64(t1, t1, 4);
3332 tcg_gen_shr_i64(t0, t0, t1);
3333 tcg_gen_ext16u_i64(t0, t0);
3334 opn = "pextrh";
3335 break;
3337 case OPC_ADDU_CP2:
3338 tcg_gen_add_i64(t0, t0, t1);
3339 tcg_gen_ext32s_i64(t0, t0);
3340 opn = "addu";
3341 break;
3342 case OPC_SUBU_CP2:
3343 tcg_gen_sub_i64(t0, t0, t1);
3344 tcg_gen_ext32s_i64(t0, t0);
3345 opn = "addu";
3346 break;
3348 case OPC_SLL_CP2:
3349 opn = "sll";
3350 shift_max = 32;
3351 goto do_shift;
3352 case OPC_SRL_CP2:
3353 opn = "srl";
3354 shift_max = 32;
3355 goto do_shift;
3356 case OPC_SRA_CP2:
3357 opn = "sra";
3358 shift_max = 32;
3359 goto do_shift;
3360 case OPC_DSLL_CP2:
3361 opn = "dsll";
3362 shift_max = 64;
3363 goto do_shift;
3364 case OPC_DSRL_CP2:
3365 opn = "dsrl";
3366 shift_max = 64;
3367 goto do_shift;
3368 case OPC_DSRA_CP2:
3369 opn = "dsra";
3370 shift_max = 64;
3371 goto do_shift;
3372 do_shift:
3373 /* Make sure shift count isn't TCG undefined behaviour. */
3374 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3376 switch (opc) {
3377 case OPC_SLL_CP2:
3378 case OPC_DSLL_CP2:
3379 tcg_gen_shl_i64(t0, t0, t1);
3380 break;
3381 case OPC_SRA_CP2:
3382 case OPC_DSRA_CP2:
3383 /* Since SRA is UndefinedResult without sign-extended inputs,
3384 we can treat SRA and DSRA the same. */
3385 tcg_gen_sar_i64(t0, t0, t1);
3386 break;
3387 case OPC_SRL_CP2:
3388 /* We want to shift in zeros for SRL; zero-extend first. */
3389 tcg_gen_ext32u_i64(t0, t0);
3390 /* FALLTHRU */
3391 case OPC_DSRL_CP2:
3392 tcg_gen_shr_i64(t0, t0, t1);
3393 break;
3396 if (shift_max == 32) {
3397 tcg_gen_ext32s_i64(t0, t0);
3400 /* Shifts larger than MAX produce zero. */
3401 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3402 tcg_gen_neg_i64(t1, t1);
3403 tcg_gen_and_i64(t0, t0, t1);
3404 break;
3406 case OPC_ADD_CP2:
3407 case OPC_DADD_CP2:
3409 TCGv_i64 t2 = tcg_temp_new_i64();
3410 int lab = gen_new_label();
3412 tcg_gen_mov_i64(t2, t0);
3413 tcg_gen_add_i64(t0, t1, t2);
3414 if (opc == OPC_ADD_CP2) {
3415 tcg_gen_ext32s_i64(t0, t0);
3417 tcg_gen_xor_i64(t1, t1, t2);
3418 tcg_gen_xor_i64(t2, t2, t0);
3419 tcg_gen_andc_i64(t1, t2, t1);
3420 tcg_temp_free_i64(t2);
3421 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3422 generate_exception(ctx, EXCP_OVERFLOW);
3423 gen_set_label(lab);
3425 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3426 break;
3429 case OPC_SUB_CP2:
3430 case OPC_DSUB_CP2:
3432 TCGv_i64 t2 = tcg_temp_new_i64();
3433 int lab = gen_new_label();
3435 tcg_gen_mov_i64(t2, t0);
3436 tcg_gen_sub_i64(t0, t1, t2);
3437 if (opc == OPC_SUB_CP2) {
3438 tcg_gen_ext32s_i64(t0, t0);
3440 tcg_gen_xor_i64(t1, t1, t2);
3441 tcg_gen_xor_i64(t2, t2, t0);
3442 tcg_gen_and_i64(t1, t1, t2);
3443 tcg_temp_free_i64(t2);
3444 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3445 generate_exception(ctx, EXCP_OVERFLOW);
3446 gen_set_label(lab);
3448 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3449 break;
3452 case OPC_PMULUW:
3453 tcg_gen_ext32u_i64(t0, t0);
3454 tcg_gen_ext32u_i64(t1, t1);
3455 tcg_gen_mul_i64(t0, t0, t1);
3456 opn = "pmuluw";
3457 break;
3459 case OPC_SEQU_CP2:
3460 case OPC_SEQ_CP2:
3461 case OPC_SLTU_CP2:
3462 case OPC_SLT_CP2:
3463 case OPC_SLEU_CP2:
3464 case OPC_SLE_CP2:
3465 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3466 FD field is the CC field? */
3467 default:
3468 MIPS_INVAL(opn);
3469 generate_exception(ctx, EXCP_RI);
3470 return;
3473 #undef LMI_HELPER
3474 #undef LMI_DIRECT
3476 gen_store_fpr64(ctx, t0, rd);
3478 (void)opn; /* avoid a compiler warning */
3479 MIPS_DEBUG("%s %s, %s, %s", opn,
3480 fregnames[rd], fregnames[rs], fregnames[rt]);
3481 tcg_temp_free_i64(t0);
3482 tcg_temp_free_i64(t1);
3485 /* Traps */
3486 static void gen_trap (DisasContext *ctx, uint32_t opc,
3487 int rs, int rt, int16_t imm)
3489 int cond;
3490 TCGv t0 = tcg_temp_new();
3491 TCGv t1 = tcg_temp_new();
3493 cond = 0;
3494 /* Load needed operands */
3495 switch (opc) {
3496 case OPC_TEQ:
3497 case OPC_TGE:
3498 case OPC_TGEU:
3499 case OPC_TLT:
3500 case OPC_TLTU:
3501 case OPC_TNE:
3502 /* Compare two registers */
3503 if (rs != rt) {
3504 gen_load_gpr(t0, rs);
3505 gen_load_gpr(t1, rt);
3506 cond = 1;
3508 break;
3509 case OPC_TEQI:
3510 case OPC_TGEI:
3511 case OPC_TGEIU:
3512 case OPC_TLTI:
3513 case OPC_TLTIU:
3514 case OPC_TNEI:
3515 /* Compare register to immediate */
3516 if (rs != 0 || imm != 0) {
3517 gen_load_gpr(t0, rs);
3518 tcg_gen_movi_tl(t1, (int32_t)imm);
3519 cond = 1;
3521 break;
3523 if (cond == 0) {
3524 switch (opc) {
3525 case OPC_TEQ: /* rs == rs */
3526 case OPC_TEQI: /* r0 == 0 */
3527 case OPC_TGE: /* rs >= rs */
3528 case OPC_TGEI: /* r0 >= 0 */
3529 case OPC_TGEU: /* rs >= rs unsigned */
3530 case OPC_TGEIU: /* r0 >= 0 unsigned */
3531 /* Always trap */
3532 generate_exception(ctx, EXCP_TRAP);
3533 break;
3534 case OPC_TLT: /* rs < rs */
3535 case OPC_TLTI: /* r0 < 0 */
3536 case OPC_TLTU: /* rs < rs unsigned */
3537 case OPC_TLTIU: /* r0 < 0 unsigned */
3538 case OPC_TNE: /* rs != rs */
3539 case OPC_TNEI: /* r0 != 0 */
3540 /* Never trap: treat as NOP. */
3541 break;
3543 } else {
3544 int l1 = gen_new_label();
3546 switch (opc) {
3547 case OPC_TEQ:
3548 case OPC_TEQI:
3549 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
3550 break;
3551 case OPC_TGE:
3552 case OPC_TGEI:
3553 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
3554 break;
3555 case OPC_TGEU:
3556 case OPC_TGEIU:
3557 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
3558 break;
3559 case OPC_TLT:
3560 case OPC_TLTI:
3561 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
3562 break;
3563 case OPC_TLTU:
3564 case OPC_TLTIU:
3565 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
3566 break;
3567 case OPC_TNE:
3568 case OPC_TNEI:
3569 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
3570 break;
3572 generate_exception(ctx, EXCP_TRAP);
3573 gen_set_label(l1);
3575 tcg_temp_free(t0);
3576 tcg_temp_free(t1);
3579 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3581 TranslationBlock *tb;
3582 tb = ctx->tb;
3583 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3584 likely(!ctx->singlestep_enabled)) {
3585 tcg_gen_goto_tb(n);
3586 gen_save_pc(dest);
3587 tcg_gen_exit_tb((uintptr_t)tb + n);
3588 } else {
3589 gen_save_pc(dest);
3590 if (ctx->singlestep_enabled) {
3591 save_cpu_state(ctx, 0);
3592 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
3594 tcg_gen_exit_tb(0);
3598 /* Branches (before delay slot) */
3599 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
3600 int insn_bytes,
3601 int rs, int rt, int32_t offset)
3603 target_ulong btgt = -1;
3604 int blink = 0;
3605 int bcond_compute = 0;
3606 TCGv t0 = tcg_temp_new();
3607 TCGv t1 = tcg_temp_new();
3609 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3610 #ifdef MIPS_DEBUG_DISAS
3611 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
3612 #endif
3613 generate_exception(ctx, EXCP_RI);
3614 goto out;
3617 /* Load needed operands */
3618 switch (opc) {
3619 case OPC_BEQ:
3620 case OPC_BEQL:
3621 case OPC_BNE:
3622 case OPC_BNEL:
3623 /* Compare two registers */
3624 if (rs != rt) {
3625 gen_load_gpr(t0, rs);
3626 gen_load_gpr(t1, rt);
3627 bcond_compute = 1;
3629 btgt = ctx->pc + insn_bytes + offset;
3630 break;
3631 case OPC_BGEZ:
3632 case OPC_BGEZAL:
3633 case OPC_BGEZALS:
3634 case OPC_BGEZALL:
3635 case OPC_BGEZL:
3636 case OPC_BGTZ:
3637 case OPC_BGTZL:
3638 case OPC_BLEZ:
3639 case OPC_BLEZL:
3640 case OPC_BLTZ:
3641 case OPC_BLTZAL:
3642 case OPC_BLTZALS:
3643 case OPC_BLTZALL:
3644 case OPC_BLTZL:
3645 /* Compare to zero */
3646 if (rs != 0) {
3647 gen_load_gpr(t0, rs);
3648 bcond_compute = 1;
3650 btgt = ctx->pc + insn_bytes + offset;
3651 break;
3652 case OPC_BPOSGE32:
3653 #if defined(TARGET_MIPS64)
3654 case OPC_BPOSGE64:
3655 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
3656 #else
3657 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
3658 #endif
3659 bcond_compute = 1;
3660 btgt = ctx->pc + insn_bytes + offset;
3661 break;
3662 case OPC_J:
3663 case OPC_JAL:
3664 case OPC_JALX:
3665 case OPC_JALS:
3666 case OPC_JALXS:
3667 /* Jump to immediate */
3668 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
3669 break;
3670 case OPC_JR:
3671 case OPC_JALR:
3672 case OPC_JALRC:
3673 case OPC_JALRS:
3674 /* Jump to register */
3675 if (offset != 0 && offset != 16) {
3676 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
3677 others are reserved. */
3678 MIPS_INVAL("jump hint");
3679 generate_exception(ctx, EXCP_RI);
3680 goto out;
3682 gen_load_gpr(btarget, rs);
3683 break;
3684 default:
3685 MIPS_INVAL("branch/jump");
3686 generate_exception(ctx, EXCP_RI);
3687 goto out;
3689 if (bcond_compute == 0) {
3690 /* No condition to be computed */
3691 switch (opc) {
3692 case OPC_BEQ: /* rx == rx */
3693 case OPC_BEQL: /* rx == rx likely */
3694 case OPC_BGEZ: /* 0 >= 0 */
3695 case OPC_BGEZL: /* 0 >= 0 likely */
3696 case OPC_BLEZ: /* 0 <= 0 */
3697 case OPC_BLEZL: /* 0 <= 0 likely */
3698 /* Always take */
3699 ctx->hflags |= MIPS_HFLAG_B;
3700 MIPS_DEBUG("balways");
3701 break;
3702 case OPC_BGEZALS:
3703 case OPC_BGEZAL: /* 0 >= 0 */
3704 case OPC_BGEZALL: /* 0 >= 0 likely */
3705 ctx->hflags |= (opc == OPC_BGEZALS
3706 ? MIPS_HFLAG_BDS16
3707 : MIPS_HFLAG_BDS32);
3708 /* Always take and link */
3709 blink = 31;
3710 ctx->hflags |= MIPS_HFLAG_B;
3711 MIPS_DEBUG("balways and link");
3712 break;
3713 case OPC_BNE: /* rx != rx */
3714 case OPC_BGTZ: /* 0 > 0 */
3715 case OPC_BLTZ: /* 0 < 0 */
3716 /* Treat as NOP. */
3717 MIPS_DEBUG("bnever (NOP)");
3718 goto out;
3719 case OPC_BLTZALS:
3720 case OPC_BLTZAL: /* 0 < 0 */
3721 ctx->hflags |= (opc == OPC_BLTZALS
3722 ? MIPS_HFLAG_BDS16
3723 : MIPS_HFLAG_BDS32);
3724 /* Handle as an unconditional branch to get correct delay
3725 slot checking. */
3726 blink = 31;
3727 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3728 ctx->hflags |= MIPS_HFLAG_B;
3729 MIPS_DEBUG("bnever and link");
3730 break;
3731 case OPC_BLTZALL: /* 0 < 0 likely */
3732 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
3733 /* Skip the instruction in the delay slot */
3734 MIPS_DEBUG("bnever, link and skip");
3735 ctx->pc += 4;
3736 goto out;
3737 case OPC_BNEL: /* rx != rx likely */
3738 case OPC_BGTZL: /* 0 > 0 likely */
3739 case OPC_BLTZL: /* 0 < 0 likely */
3740 /* Skip the instruction in the delay slot */
3741 MIPS_DEBUG("bnever and skip");
3742 ctx->pc += 4;
3743 goto out;
3744 case OPC_J:
3745 ctx->hflags |= MIPS_HFLAG_B;
3746 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
3747 break;
3748 case OPC_JALXS:
3749 case OPC_JALX:
3750 ctx->hflags |= MIPS_HFLAG_BX;
3751 /* Fallthrough */
3752 case OPC_JALS:
3753 case OPC_JAL:
3754 blink = 31;
3755 ctx->hflags |= MIPS_HFLAG_B;
3756 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
3757 ? MIPS_HFLAG_BDS16
3758 : MIPS_HFLAG_BDS32);
3759 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
3760 break;
3761 case OPC_JR:
3762 ctx->hflags |= MIPS_HFLAG_BR;
3763 if (insn_bytes == 4)
3764 ctx->hflags |= MIPS_HFLAG_BDS32;
3765 MIPS_DEBUG("jr %s", regnames[rs]);
3766 break;
3767 case OPC_JALRS:
3768 case OPC_JALR:
3769 case OPC_JALRC:
3770 blink = rt;
3771 ctx->hflags |= MIPS_HFLAG_BR;
3772 ctx->hflags |= (opc == OPC_JALRS
3773 ? MIPS_HFLAG_BDS16
3774 : MIPS_HFLAG_BDS32);
3775 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3776 break;
3777 default:
3778 MIPS_INVAL("branch/jump");
3779 generate_exception(ctx, EXCP_RI);
3780 goto out;
3782 } else {
3783 switch (opc) {
3784 case OPC_BEQ:
3785 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
3786 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
3787 regnames[rs], regnames[rt], btgt);
3788 goto not_likely;
3789 case OPC_BEQL:
3790 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
3791 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
3792 regnames[rs], regnames[rt], btgt);
3793 goto likely;
3794 case OPC_BNE:
3795 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
3796 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
3797 regnames[rs], regnames[rt], btgt);
3798 goto not_likely;
3799 case OPC_BNEL:
3800 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
3801 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
3802 regnames[rs], regnames[rt], btgt);
3803 goto likely;
3804 case OPC_BGEZ:
3805 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3806 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
3807 goto not_likely;
3808 case OPC_BGEZL:
3809 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3810 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3811 goto likely;
3812 case OPC_BGEZALS:
3813 case OPC_BGEZAL:
3814 ctx->hflags |= (opc == OPC_BGEZALS
3815 ? MIPS_HFLAG_BDS16
3816 : MIPS_HFLAG_BDS32);
3817 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3818 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
3819 blink = 31;
3820 goto not_likely;
3821 case OPC_BGEZALL:
3822 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3823 blink = 31;
3824 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
3825 goto likely;
3826 case OPC_BGTZ:
3827 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
3828 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
3829 goto not_likely;
3830 case OPC_BGTZL:
3831 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
3832 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3833 goto likely;
3834 case OPC_BLEZ:
3835 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
3836 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
3837 goto not_likely;
3838 case OPC_BLEZL:
3839 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
3840 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3841 goto likely;
3842 case OPC_BLTZ:
3843 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3844 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
3845 goto not_likely;
3846 case OPC_BLTZL:
3847 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3848 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3849 goto likely;
3850 case OPC_BPOSGE32:
3851 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
3852 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
3853 goto not_likely;
3854 #if defined(TARGET_MIPS64)
3855 case OPC_BPOSGE64:
3856 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
3857 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
3858 goto not_likely;
3859 #endif
3860 case OPC_BLTZALS:
3861 case OPC_BLTZAL:
3862 ctx->hflags |= (opc == OPC_BLTZALS
3863 ? MIPS_HFLAG_BDS16
3864 : MIPS_HFLAG_BDS32);
3865 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3866 blink = 31;
3867 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
3868 not_likely:
3869 ctx->hflags |= MIPS_HFLAG_BC;
3870 break;
3871 case OPC_BLTZALL:
3872 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3873 blink = 31;
3874 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
3875 likely:
3876 ctx->hflags |= MIPS_HFLAG_BL;
3877 break;
3878 default:
3879 MIPS_INVAL("conditional branch/jump");
3880 generate_exception(ctx, EXCP_RI);
3881 goto out;
3884 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
3885 blink, ctx->hflags, btgt);
3887 ctx->btarget = btgt;
3888 if (blink > 0) {
3889 int post_delay = insn_bytes;
3890 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3892 if (opc != OPC_JALRC)
3893 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3895 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
3898 out:
3899 if (insn_bytes == 2)
3900 ctx->hflags |= MIPS_HFLAG_B16;
3901 tcg_temp_free(t0);
3902 tcg_temp_free(t1);
3905 /* special3 bitfield operations */
3906 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
3907 int rs, int lsb, int msb)
3909 TCGv t0 = tcg_temp_new();
3910 TCGv t1 = tcg_temp_new();
3912 gen_load_gpr(t1, rs);
3913 switch (opc) {
3914 case OPC_EXT:
3915 if (lsb + msb > 31)
3916 goto fail;
3917 tcg_gen_shri_tl(t0, t1, lsb);
3918 if (msb != 31) {
3919 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3920 } else {
3921 tcg_gen_ext32s_tl(t0, t0);
3923 break;
3924 #if defined(TARGET_MIPS64)
3925 case OPC_DEXTM:
3926 tcg_gen_shri_tl(t0, t1, lsb);
3927 if (msb != 31) {
3928 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3930 break;
3931 case OPC_DEXTU:
3932 tcg_gen_shri_tl(t0, t1, lsb + 32);
3933 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3934 break;
3935 case OPC_DEXT:
3936 tcg_gen_shri_tl(t0, t1, lsb);
3937 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3938 break;
3939 #endif
3940 case OPC_INS:
3941 if (lsb > msb)
3942 goto fail;
3943 gen_load_gpr(t0, rt);
3944 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
3945 tcg_gen_ext32s_tl(t0, t0);
3946 break;
3947 #if defined(TARGET_MIPS64)
3948 case OPC_DINSM:
3949 gen_load_gpr(t0, rt);
3950 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
3951 break;
3952 case OPC_DINSU:
3953 gen_load_gpr(t0, rt);
3954 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
3955 break;
3956 case OPC_DINS:
3957 gen_load_gpr(t0, rt);
3958 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
3959 break;
3960 #endif
3961 default:
3962 fail:
3963 MIPS_INVAL("bitops");
3964 generate_exception(ctx, EXCP_RI);
3965 tcg_temp_free(t0);
3966 tcg_temp_free(t1);
3967 return;
3969 gen_store_gpr(t0, rt);
3970 tcg_temp_free(t0);
3971 tcg_temp_free(t1);
3974 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3976 TCGv t0;
3978 if (rd == 0) {
3979 /* If no destination, treat it as a NOP. */
3980 MIPS_DEBUG("NOP");
3981 return;
3984 t0 = tcg_temp_new();
3985 gen_load_gpr(t0, rt);
3986 switch (op2) {
3987 case OPC_WSBH:
3989 TCGv t1 = tcg_temp_new();
3991 tcg_gen_shri_tl(t1, t0, 8);
3992 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3993 tcg_gen_shli_tl(t0, t0, 8);
3994 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3995 tcg_gen_or_tl(t0, t0, t1);
3996 tcg_temp_free(t1);
3997 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3999 break;
4000 case OPC_SEB:
4001 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4002 break;
4003 case OPC_SEH:
4004 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4005 break;
4006 #if defined(TARGET_MIPS64)
4007 case OPC_DSBH:
4009 TCGv t1 = tcg_temp_new();
4011 tcg_gen_shri_tl(t1, t0, 8);
4012 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4013 tcg_gen_shli_tl(t0, t0, 8);
4014 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4015 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4016 tcg_temp_free(t1);
4018 break;
4019 case OPC_DSHD:
4021 TCGv t1 = tcg_temp_new();
4023 tcg_gen_shri_tl(t1, t0, 16);
4024 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4025 tcg_gen_shli_tl(t0, t0, 16);
4026 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4027 tcg_gen_or_tl(t0, t0, t1);
4028 tcg_gen_shri_tl(t1, t0, 32);
4029 tcg_gen_shli_tl(t0, t0, 32);
4030 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4031 tcg_temp_free(t1);
4033 break;
4034 #endif
4035 default:
4036 MIPS_INVAL("bsfhl");
4037 generate_exception(ctx, EXCP_RI);
4038 tcg_temp_free(t0);
4039 return;
4041 tcg_temp_free(t0);
4044 #ifndef CONFIG_USER_ONLY
4045 /* CP0 (MMU and control) */
4046 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4048 TCGv_i32 t0 = tcg_temp_new_i32();
4050 tcg_gen_ld_i32(t0, cpu_env, off);
4051 tcg_gen_ext_i32_tl(arg, t0);
4052 tcg_temp_free_i32(t0);
4055 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4057 tcg_gen_ld_tl(arg, cpu_env, off);
4058 tcg_gen_ext32s_tl(arg, arg);
4061 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4063 TCGv_i32 t0 = tcg_temp_new_i32();
4065 tcg_gen_trunc_tl_i32(t0, arg);
4066 tcg_gen_st_i32(t0, cpu_env, off);
4067 tcg_temp_free_i32(t0);
4070 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
4072 tcg_gen_ext32s_tl(arg, arg);
4073 tcg_gen_st_tl(arg, cpu_env, off);
4076 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4078 const char *rn = "invalid";
4080 if (sel != 0)
4081 check_insn(ctx, ISA_MIPS32);
4083 switch (reg) {
4084 case 0:
4085 switch (sel) {
4086 case 0:
4087 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4088 rn = "Index";
4089 break;
4090 case 1:
4091 check_insn(ctx, ASE_MT);
4092 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4093 rn = "MVPControl";
4094 break;
4095 case 2:
4096 check_insn(ctx, ASE_MT);
4097 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4098 rn = "MVPConf0";
4099 break;
4100 case 3:
4101 check_insn(ctx, ASE_MT);
4102 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4103 rn = "MVPConf1";
4104 break;
4105 default:
4106 goto die;
4108 break;
4109 case 1:
4110 switch (sel) {
4111 case 0:
4112 gen_helper_mfc0_random(arg, cpu_env);
4113 rn = "Random";
4114 break;
4115 case 1:
4116 check_insn(ctx, ASE_MT);
4117 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4118 rn = "VPEControl";
4119 break;
4120 case 2:
4121 check_insn(ctx, ASE_MT);
4122 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4123 rn = "VPEConf0";
4124 break;
4125 case 3:
4126 check_insn(ctx, ASE_MT);
4127 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4128 rn = "VPEConf1";
4129 break;
4130 case 4:
4131 check_insn(ctx, ASE_MT);
4132 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4133 rn = "YQMask";
4134 break;
4135 case 5:
4136 check_insn(ctx, ASE_MT);
4137 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4138 rn = "VPESchedule";
4139 break;
4140 case 6:
4141 check_insn(ctx, ASE_MT);
4142 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4143 rn = "VPEScheFBack";
4144 break;
4145 case 7:
4146 check_insn(ctx, ASE_MT);
4147 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4148 rn = "VPEOpt";
4149 break;
4150 default:
4151 goto die;
4153 break;
4154 case 2:
4155 switch (sel) {
4156 case 0:
4157 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4158 tcg_gen_ext32s_tl(arg, arg);
4159 rn = "EntryLo0";
4160 break;
4161 case 1:
4162 check_insn(ctx, ASE_MT);
4163 gen_helper_mfc0_tcstatus(arg, cpu_env);
4164 rn = "TCStatus";
4165 break;
4166 case 2:
4167 check_insn(ctx, ASE_MT);
4168 gen_helper_mfc0_tcbind(arg, cpu_env);
4169 rn = "TCBind";
4170 break;
4171 case 3:
4172 check_insn(ctx, ASE_MT);
4173 gen_helper_mfc0_tcrestart(arg, cpu_env);
4174 rn = "TCRestart";
4175 break;
4176 case 4:
4177 check_insn(ctx, ASE_MT);
4178 gen_helper_mfc0_tchalt(arg, cpu_env);
4179 rn = "TCHalt";
4180 break;
4181 case 5:
4182 check_insn(ctx, ASE_MT);
4183 gen_helper_mfc0_tccontext(arg, cpu_env);
4184 rn = "TCContext";
4185 break;
4186 case 6:
4187 check_insn(ctx, ASE_MT);
4188 gen_helper_mfc0_tcschedule(arg, cpu_env);
4189 rn = "TCSchedule";
4190 break;
4191 case 7:
4192 check_insn(ctx, ASE_MT);
4193 gen_helper_mfc0_tcschefback(arg, cpu_env);
4194 rn = "TCScheFBack";
4195 break;
4196 default:
4197 goto die;
4199 break;
4200 case 3:
4201 switch (sel) {
4202 case 0:
4203 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4204 tcg_gen_ext32s_tl(arg, arg);
4205 rn = "EntryLo1";
4206 break;
4207 default:
4208 goto die;
4210 break;
4211 case 4:
4212 switch (sel) {
4213 case 0:
4214 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
4215 tcg_gen_ext32s_tl(arg, arg);
4216 rn = "Context";
4217 break;
4218 case 1:
4219 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
4220 rn = "ContextConfig";
4221 goto die;
4222 // break;
4223 case 2:
4224 if (ctx->ulri) {
4225 tcg_gen_ld32s_tl(arg, cpu_env,
4226 offsetof(CPUMIPSState,
4227 active_tc.CP0_UserLocal));
4228 rn = "UserLocal";
4229 } else {
4230 tcg_gen_movi_tl(arg, 0);
4232 break;
4233 default:
4234 goto die;
4236 break;
4237 case 5:
4238 switch (sel) {
4239 case 0:
4240 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
4241 rn = "PageMask";
4242 break;
4243 case 1:
4244 check_insn(ctx, ISA_MIPS32R2);
4245 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
4246 rn = "PageGrain";
4247 break;
4248 default:
4249 goto die;
4251 break;
4252 case 6:
4253 switch (sel) {
4254 case 0:
4255 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
4256 rn = "Wired";
4257 break;
4258 case 1:
4259 check_insn(ctx, ISA_MIPS32R2);
4260 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
4261 rn = "SRSConf0";
4262 break;
4263 case 2:
4264 check_insn(ctx, ISA_MIPS32R2);
4265 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
4266 rn = "SRSConf1";
4267 break;
4268 case 3:
4269 check_insn(ctx, ISA_MIPS32R2);
4270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
4271 rn = "SRSConf2";
4272 break;
4273 case 4:
4274 check_insn(ctx, ISA_MIPS32R2);
4275 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
4276 rn = "SRSConf3";
4277 break;
4278 case 5:
4279 check_insn(ctx, ISA_MIPS32R2);
4280 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
4281 rn = "SRSConf4";
4282 break;
4283 default:
4284 goto die;
4286 break;
4287 case 7:
4288 switch (sel) {
4289 case 0:
4290 check_insn(ctx, ISA_MIPS32R2);
4291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
4292 rn = "HWREna";
4293 break;
4294 default:
4295 goto die;
4297 break;
4298 case 8:
4299 switch (sel) {
4300 case 0:
4301 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
4302 tcg_gen_ext32s_tl(arg, arg);
4303 rn = "BadVAddr";
4304 break;
4305 default:
4306 goto die;
4308 break;
4309 case 9:
4310 switch (sel) {
4311 case 0:
4312 /* Mark as an IO operation because we read the time. */
4313 if (use_icount)
4314 gen_io_start();
4315 gen_helper_mfc0_count(arg, cpu_env);
4316 if (use_icount) {
4317 gen_io_end();
4319 /* Break the TB to be able to take timer interrupts immediately
4320 after reading count. */
4321 ctx->bstate = BS_STOP;
4322 rn = "Count";
4323 break;
4324 /* 6,7 are implementation dependent */
4325 default:
4326 goto die;
4328 break;
4329 case 10:
4330 switch (sel) {
4331 case 0:
4332 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
4333 tcg_gen_ext32s_tl(arg, arg);
4334 rn = "EntryHi";
4335 break;
4336 default:
4337 goto die;
4339 break;
4340 case 11:
4341 switch (sel) {
4342 case 0:
4343 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
4344 rn = "Compare";
4345 break;
4346 /* 6,7 are implementation dependent */
4347 default:
4348 goto die;
4350 break;
4351 case 12:
4352 switch (sel) {
4353 case 0:
4354 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
4355 rn = "Status";
4356 break;
4357 case 1:
4358 check_insn(ctx, ISA_MIPS32R2);
4359 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
4360 rn = "IntCtl";
4361 break;
4362 case 2:
4363 check_insn(ctx, ISA_MIPS32R2);
4364 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
4365 rn = "SRSCtl";
4366 break;
4367 case 3:
4368 check_insn(ctx, ISA_MIPS32R2);
4369 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4370 rn = "SRSMap";
4371 break;
4372 default:
4373 goto die;
4375 break;
4376 case 13:
4377 switch (sel) {
4378 case 0:
4379 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
4380 rn = "Cause";
4381 break;
4382 default:
4383 goto die;
4385 break;
4386 case 14:
4387 switch (sel) {
4388 case 0:
4389 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
4390 tcg_gen_ext32s_tl(arg, arg);
4391 rn = "EPC";
4392 break;
4393 default:
4394 goto die;
4396 break;
4397 case 15:
4398 switch (sel) {
4399 case 0:
4400 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
4401 rn = "PRid";
4402 break;
4403 case 1:
4404 check_insn(ctx, ISA_MIPS32R2);
4405 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
4406 rn = "EBase";
4407 break;
4408 default:
4409 goto die;
4411 break;
4412 case 16:
4413 switch (sel) {
4414 case 0:
4415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
4416 rn = "Config";
4417 break;
4418 case 1:
4419 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
4420 rn = "Config1";
4421 break;
4422 case 2:
4423 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
4424 rn = "Config2";
4425 break;
4426 case 3:
4427 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
4428 rn = "Config3";
4429 break;
4430 case 4:
4431 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
4432 rn = "Config4";
4433 break;
4434 case 5:
4435 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
4436 rn = "Config5";
4437 break;
4438 /* 6,7 are implementation dependent */
4439 case 6:
4440 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
4441 rn = "Config6";
4442 break;
4443 case 7:
4444 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
4445 rn = "Config7";
4446 break;
4447 default:
4448 goto die;
4450 break;
4451 case 17:
4452 switch (sel) {
4453 case 0:
4454 gen_helper_mfc0_lladdr(arg, cpu_env);
4455 rn = "LLAddr";
4456 break;
4457 default:
4458 goto die;
4460 break;
4461 case 18:
4462 switch (sel) {
4463 case 0 ... 7:
4464 gen_helper_1e0i(mfc0_watchlo, arg, sel);
4465 rn = "WatchLo";
4466 break;
4467 default:
4468 goto die;
4470 break;
4471 case 19:
4472 switch (sel) {
4473 case 0 ...7:
4474 gen_helper_1e0i(mfc0_watchhi, arg, sel);
4475 rn = "WatchHi";
4476 break;
4477 default:
4478 goto die;
4480 break;
4481 case 20:
4482 switch (sel) {
4483 case 0:
4484 #if defined(TARGET_MIPS64)
4485 check_insn(ctx, ISA_MIPS3);
4486 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
4487 tcg_gen_ext32s_tl(arg, arg);
4488 rn = "XContext";
4489 break;
4490 #endif
4491 default:
4492 goto die;
4494 break;
4495 case 21:
4496 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4497 switch (sel) {
4498 case 0:
4499 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
4500 rn = "Framemask";
4501 break;
4502 default:
4503 goto die;
4505 break;
4506 case 22:
4507 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4508 rn = "'Diagnostic"; /* implementation dependent */
4509 break;
4510 case 23:
4511 switch (sel) {
4512 case 0:
4513 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
4514 rn = "Debug";
4515 break;
4516 case 1:
4517 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
4518 rn = "TraceControl";
4519 // break;
4520 case 2:
4521 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
4522 rn = "TraceControl2";
4523 // break;
4524 case 3:
4525 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
4526 rn = "UserTraceData";
4527 // break;
4528 case 4:
4529 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
4530 rn = "TraceBPC";
4531 // break;
4532 default:
4533 goto die;
4535 break;
4536 case 24:
4537 switch (sel) {
4538 case 0:
4539 /* EJTAG support */
4540 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
4541 tcg_gen_ext32s_tl(arg, arg);
4542 rn = "DEPC";
4543 break;
4544 default:
4545 goto die;
4547 break;
4548 case 25:
4549 switch (sel) {
4550 case 0:
4551 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
4552 rn = "Performance0";
4553 break;
4554 case 1:
4555 // gen_helper_mfc0_performance1(arg);
4556 rn = "Performance1";
4557 // break;
4558 case 2:
4559 // gen_helper_mfc0_performance2(arg);
4560 rn = "Performance2";
4561 // break;
4562 case 3:
4563 // gen_helper_mfc0_performance3(arg);
4564 rn = "Performance3";
4565 // break;
4566 case 4:
4567 // gen_helper_mfc0_performance4(arg);
4568 rn = "Performance4";
4569 // break;
4570 case 5:
4571 // gen_helper_mfc0_performance5(arg);
4572 rn = "Performance5";
4573 // break;
4574 case 6:
4575 // gen_helper_mfc0_performance6(arg);
4576 rn = "Performance6";
4577 // break;
4578 case 7:
4579 // gen_helper_mfc0_performance7(arg);
4580 rn = "Performance7";
4581 // break;
4582 default:
4583 goto die;
4585 break;
4586 case 26:
4587 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4588 rn = "ECC";
4589 break;
4590 case 27:
4591 switch (sel) {
4592 case 0 ... 3:
4593 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4594 rn = "CacheErr";
4595 break;
4596 default:
4597 goto die;
4599 break;
4600 case 28:
4601 switch (sel) {
4602 case 0:
4603 case 2:
4604 case 4:
4605 case 6:
4606 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
4607 rn = "TagLo";
4608 break;
4609 case 1:
4610 case 3:
4611 case 5:
4612 case 7:
4613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
4614 rn = "DataLo";
4615 break;
4616 default:
4617 goto die;
4619 break;
4620 case 29:
4621 switch (sel) {
4622 case 0:
4623 case 2:
4624 case 4:
4625 case 6:
4626 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
4627 rn = "TagHi";
4628 break;
4629 case 1:
4630 case 3:
4631 case 5:
4632 case 7:
4633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
4634 rn = "DataHi";
4635 break;
4636 default:
4637 goto die;
4639 break;
4640 case 30:
4641 switch (sel) {
4642 case 0:
4643 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
4644 tcg_gen_ext32s_tl(arg, arg);
4645 rn = "ErrorEPC";
4646 break;
4647 default:
4648 goto die;
4650 break;
4651 case 31:
4652 switch (sel) {
4653 case 0:
4654 /* EJTAG support */
4655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4656 rn = "DESAVE";
4657 break;
4658 default:
4659 goto die;
4661 break;
4662 default:
4663 goto die;
4665 (void)rn; /* avoid a compiler warning */
4666 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4667 return;
4669 die:
4670 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4671 generate_exception(ctx, EXCP_RI);
4674 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4676 const char *rn = "invalid";
4678 if (sel != 0)
4679 check_insn(ctx, ISA_MIPS32);
4681 if (use_icount)
4682 gen_io_start();
4684 switch (reg) {
4685 case 0:
4686 switch (sel) {
4687 case 0:
4688 gen_helper_mtc0_index(cpu_env, arg);
4689 rn = "Index";
4690 break;
4691 case 1:
4692 check_insn(ctx, ASE_MT);
4693 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
4694 rn = "MVPControl";
4695 break;
4696 case 2:
4697 check_insn(ctx, ASE_MT);
4698 /* ignored */
4699 rn = "MVPConf0";
4700 break;
4701 case 3:
4702 check_insn(ctx, ASE_MT);
4703 /* ignored */
4704 rn = "MVPConf1";
4705 break;
4706 default:
4707 goto die;
4709 break;
4710 case 1:
4711 switch (sel) {
4712 case 0:
4713 /* ignored */
4714 rn = "Random";
4715 break;
4716 case 1:
4717 check_insn(ctx, ASE_MT);
4718 gen_helper_mtc0_vpecontrol(cpu_env, arg);
4719 rn = "VPEControl";
4720 break;
4721 case 2:
4722 check_insn(ctx, ASE_MT);
4723 gen_helper_mtc0_vpeconf0(cpu_env, arg);
4724 rn = "VPEConf0";
4725 break;
4726 case 3:
4727 check_insn(ctx, ASE_MT);
4728 gen_helper_mtc0_vpeconf1(cpu_env, arg);
4729 rn = "VPEConf1";
4730 break;
4731 case 4:
4732 check_insn(ctx, ASE_MT);
4733 gen_helper_mtc0_yqmask(cpu_env, arg);
4734 rn = "YQMask";
4735 break;
4736 case 5:
4737 check_insn(ctx, ASE_MT);
4738 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4739 rn = "VPESchedule";
4740 break;
4741 case 6:
4742 check_insn(ctx, ASE_MT);
4743 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4744 rn = "VPEScheFBack";
4745 break;
4746 case 7:
4747 check_insn(ctx, ASE_MT);
4748 gen_helper_mtc0_vpeopt(cpu_env, arg);
4749 rn = "VPEOpt";
4750 break;
4751 default:
4752 goto die;
4754 break;
4755 case 2:
4756 switch (sel) {
4757 case 0:
4758 gen_helper_mtc0_entrylo0(cpu_env, arg);
4759 rn = "EntryLo0";
4760 break;
4761 case 1:
4762 check_insn(ctx, ASE_MT);
4763 gen_helper_mtc0_tcstatus(cpu_env, arg);
4764 rn = "TCStatus";
4765 break;
4766 case 2:
4767 check_insn(ctx, ASE_MT);
4768 gen_helper_mtc0_tcbind(cpu_env, arg);
4769 rn = "TCBind";
4770 break;
4771 case 3:
4772 check_insn(ctx, ASE_MT);
4773 gen_helper_mtc0_tcrestart(cpu_env, arg);
4774 rn = "TCRestart";
4775 break;
4776 case 4:
4777 check_insn(ctx, ASE_MT);
4778 gen_helper_mtc0_tchalt(cpu_env, arg);
4779 rn = "TCHalt";
4780 break;
4781 case 5:
4782 check_insn(ctx, ASE_MT);
4783 gen_helper_mtc0_tccontext(cpu_env, arg);
4784 rn = "TCContext";
4785 break;
4786 case 6:
4787 check_insn(ctx, ASE_MT);
4788 gen_helper_mtc0_tcschedule(cpu_env, arg);
4789 rn = "TCSchedule";
4790 break;
4791 case 7:
4792 check_insn(ctx, ASE_MT);
4793 gen_helper_mtc0_tcschefback(cpu_env, arg);
4794 rn = "TCScheFBack";
4795 break;
4796 default:
4797 goto die;
4799 break;
4800 case 3:
4801 switch (sel) {
4802 case 0:
4803 gen_helper_mtc0_entrylo1(cpu_env, arg);
4804 rn = "EntryLo1";
4805 break;
4806 default:
4807 goto die;
4809 break;
4810 case 4:
4811 switch (sel) {
4812 case 0:
4813 gen_helper_mtc0_context(cpu_env, arg);
4814 rn = "Context";
4815 break;
4816 case 1:
4817 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
4818 rn = "ContextConfig";
4819 goto die;
4820 // break;
4821 case 2:
4822 if (ctx->ulri) {
4823 tcg_gen_st_tl(arg, cpu_env,
4824 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
4825 rn = "UserLocal";
4827 break;
4828 default:
4829 goto die;
4831 break;
4832 case 5:
4833 switch (sel) {
4834 case 0:
4835 gen_helper_mtc0_pagemask(cpu_env, arg);
4836 rn = "PageMask";
4837 break;
4838 case 1:
4839 check_insn(ctx, ISA_MIPS32R2);
4840 gen_helper_mtc0_pagegrain(cpu_env, arg);
4841 rn = "PageGrain";
4842 break;
4843 default:
4844 goto die;
4846 break;
4847 case 6:
4848 switch (sel) {
4849 case 0:
4850 gen_helper_mtc0_wired(cpu_env, arg);
4851 rn = "Wired";
4852 break;
4853 case 1:
4854 check_insn(ctx, ISA_MIPS32R2);
4855 gen_helper_mtc0_srsconf0(cpu_env, arg);
4856 rn = "SRSConf0";
4857 break;
4858 case 2:
4859 check_insn(ctx, ISA_MIPS32R2);
4860 gen_helper_mtc0_srsconf1(cpu_env, arg);
4861 rn = "SRSConf1";
4862 break;
4863 case 3:
4864 check_insn(ctx, ISA_MIPS32R2);
4865 gen_helper_mtc0_srsconf2(cpu_env, arg);
4866 rn = "SRSConf2";
4867 break;
4868 case 4:
4869 check_insn(ctx, ISA_MIPS32R2);
4870 gen_helper_mtc0_srsconf3(cpu_env, arg);
4871 rn = "SRSConf3";
4872 break;
4873 case 5:
4874 check_insn(ctx, ISA_MIPS32R2);
4875 gen_helper_mtc0_srsconf4(cpu_env, arg);
4876 rn = "SRSConf4";
4877 break;
4878 default:
4879 goto die;
4881 break;
4882 case 7:
4883 switch (sel) {
4884 case 0:
4885 check_insn(ctx, ISA_MIPS32R2);
4886 gen_helper_mtc0_hwrena(cpu_env, arg);
4887 ctx->bstate = BS_STOP;
4888 rn = "HWREna";
4889 break;
4890 default:
4891 goto die;
4893 break;
4894 case 8:
4895 /* ignored */
4896 rn = "BadVAddr";
4897 break;
4898 case 9:
4899 switch (sel) {
4900 case 0:
4901 gen_helper_mtc0_count(cpu_env, arg);
4902 rn = "Count";
4903 break;
4904 /* 6,7 are implementation dependent */
4905 default:
4906 goto die;
4908 break;
4909 case 10:
4910 switch (sel) {
4911 case 0:
4912 gen_helper_mtc0_entryhi(cpu_env, arg);
4913 rn = "EntryHi";
4914 break;
4915 default:
4916 goto die;
4918 break;
4919 case 11:
4920 switch (sel) {
4921 case 0:
4922 gen_helper_mtc0_compare(cpu_env, arg);
4923 rn = "Compare";
4924 break;
4925 /* 6,7 are implementation dependent */
4926 default:
4927 goto die;
4929 break;
4930 case 12:
4931 switch (sel) {
4932 case 0:
4933 save_cpu_state(ctx, 1);
4934 gen_helper_mtc0_status(cpu_env, arg);
4935 /* BS_STOP isn't good enough here, hflags may have changed. */
4936 gen_save_pc(ctx->pc + 4);
4937 ctx->bstate = BS_EXCP;
4938 rn = "Status";
4939 break;
4940 case 1:
4941 check_insn(ctx, ISA_MIPS32R2);
4942 gen_helper_mtc0_intctl(cpu_env, arg);
4943 /* Stop translation as we may have switched the execution mode */
4944 ctx->bstate = BS_STOP;
4945 rn = "IntCtl";
4946 break;
4947 case 2:
4948 check_insn(ctx, ISA_MIPS32R2);
4949 gen_helper_mtc0_srsctl(cpu_env, arg);
4950 /* Stop translation as we may have switched the execution mode */
4951 ctx->bstate = BS_STOP;
4952 rn = "SRSCtl";
4953 break;
4954 case 3:
4955 check_insn(ctx, ISA_MIPS32R2);
4956 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4957 /* Stop translation as we may have switched the execution mode */
4958 ctx->bstate = BS_STOP;
4959 rn = "SRSMap";
4960 break;
4961 default:
4962 goto die;
4964 break;
4965 case 13:
4966 switch (sel) {
4967 case 0:
4968 save_cpu_state(ctx, 1);
4969 gen_helper_mtc0_cause(cpu_env, arg);
4970 rn = "Cause";
4971 break;
4972 default:
4973 goto die;
4975 break;
4976 case 14:
4977 switch (sel) {
4978 case 0:
4979 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
4980 rn = "EPC";
4981 break;
4982 default:
4983 goto die;
4985 break;
4986 case 15:
4987 switch (sel) {
4988 case 0:
4989 /* ignored */
4990 rn = "PRid";
4991 break;
4992 case 1:
4993 check_insn(ctx, ISA_MIPS32R2);
4994 gen_helper_mtc0_ebase(cpu_env, arg);
4995 rn = "EBase";
4996 break;
4997 default:
4998 goto die;
5000 break;
5001 case 16:
5002 switch (sel) {
5003 case 0:
5004 gen_helper_mtc0_config0(cpu_env, arg);
5005 rn = "Config";
5006 /* Stop translation as we may have switched the execution mode */
5007 ctx->bstate = BS_STOP;
5008 break;
5009 case 1:
5010 /* ignored, read only */
5011 rn = "Config1";
5012 break;
5013 case 2:
5014 gen_helper_mtc0_config2(cpu_env, arg);
5015 rn = "Config2";
5016 /* Stop translation as we may have switched the execution mode */
5017 ctx->bstate = BS_STOP;
5018 break;
5019 case 3:
5020 /* ignored, read only */
5021 rn = "Config3";
5022 break;
5023 case 4:
5024 gen_helper_mtc0_config4(cpu_env, arg);
5025 rn = "Config4";
5026 ctx->bstate = BS_STOP;
5027 break;
5028 case 5:
5029 gen_helper_mtc0_config5(cpu_env, arg);
5030 rn = "Config5";
5031 /* Stop translation as we may have switched the execution mode */
5032 ctx->bstate = BS_STOP;
5033 break;
5034 /* 6,7 are implementation dependent */
5035 case 6:
5036 /* ignored */
5037 rn = "Config6";
5038 break;
5039 case 7:
5040 /* ignored */
5041 rn = "Config7";
5042 break;
5043 default:
5044 rn = "Invalid config selector";
5045 goto die;
5047 break;
5048 case 17:
5049 switch (sel) {
5050 case 0:
5051 gen_helper_mtc0_lladdr(cpu_env, arg);
5052 rn = "LLAddr";
5053 break;
5054 default:
5055 goto die;
5057 break;
5058 case 18:
5059 switch (sel) {
5060 case 0 ... 7:
5061 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5062 rn = "WatchLo";
5063 break;
5064 default:
5065 goto die;
5067 break;
5068 case 19:
5069 switch (sel) {
5070 case 0 ... 7:
5071 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5072 rn = "WatchHi";
5073 break;
5074 default:
5075 goto die;
5077 break;
5078 case 20:
5079 switch (sel) {
5080 case 0:
5081 #if defined(TARGET_MIPS64)
5082 check_insn(ctx, ISA_MIPS3);
5083 gen_helper_mtc0_xcontext(cpu_env, arg);
5084 rn = "XContext";
5085 break;
5086 #endif
5087 default:
5088 goto die;
5090 break;
5091 case 21:
5092 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5093 switch (sel) {
5094 case 0:
5095 gen_helper_mtc0_framemask(cpu_env, arg);
5096 rn = "Framemask";
5097 break;
5098 default:
5099 goto die;
5101 break;
5102 case 22:
5103 /* ignored */
5104 rn = "Diagnostic"; /* implementation dependent */
5105 break;
5106 case 23:
5107 switch (sel) {
5108 case 0:
5109 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5110 /* BS_STOP isn't good enough here, hflags may have changed. */
5111 gen_save_pc(ctx->pc + 4);
5112 ctx->bstate = BS_EXCP;
5113 rn = "Debug";
5114 break;
5115 case 1:
5116 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5117 rn = "TraceControl";
5118 /* Stop translation as we may have switched the execution mode */
5119 ctx->bstate = BS_STOP;
5120 // break;
5121 case 2:
5122 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5123 rn = "TraceControl2";
5124 /* Stop translation as we may have switched the execution mode */
5125 ctx->bstate = BS_STOP;
5126 // break;
5127 case 3:
5128 /* Stop translation as we may have switched the execution mode */
5129 ctx->bstate = BS_STOP;
5130 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5131 rn = "UserTraceData";
5132 /* Stop translation as we may have switched the execution mode */
5133 ctx->bstate = BS_STOP;
5134 // break;
5135 case 4:
5136 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5137 /* Stop translation as we may have switched the execution mode */
5138 ctx->bstate = BS_STOP;
5139 rn = "TraceBPC";
5140 // break;
5141 default:
5142 goto die;
5144 break;
5145 case 24:
5146 switch (sel) {
5147 case 0:
5148 /* EJTAG support */
5149 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
5150 rn = "DEPC";
5151 break;
5152 default:
5153 goto die;
5155 break;
5156 case 25:
5157 switch (sel) {
5158 case 0:
5159 gen_helper_mtc0_performance0(cpu_env, arg);
5160 rn = "Performance0";
5161 break;
5162 case 1:
5163 // gen_helper_mtc0_performance1(arg);
5164 rn = "Performance1";
5165 // break;
5166 case 2:
5167 // gen_helper_mtc0_performance2(arg);
5168 rn = "Performance2";
5169 // break;
5170 case 3:
5171 // gen_helper_mtc0_performance3(arg);
5172 rn = "Performance3";
5173 // break;
5174 case 4:
5175 // gen_helper_mtc0_performance4(arg);
5176 rn = "Performance4";
5177 // break;
5178 case 5:
5179 // gen_helper_mtc0_performance5(arg);
5180 rn = "Performance5";
5181 // break;
5182 case 6:
5183 // gen_helper_mtc0_performance6(arg);
5184 rn = "Performance6";
5185 // break;
5186 case 7:
5187 // gen_helper_mtc0_performance7(arg);
5188 rn = "Performance7";
5189 // break;
5190 default:
5191 goto die;
5193 break;
5194 case 26:
5195 /* ignored */
5196 rn = "ECC";
5197 break;
5198 case 27:
5199 switch (sel) {
5200 case 0 ... 3:
5201 /* ignored */
5202 rn = "CacheErr";
5203 break;
5204 default:
5205 goto die;
5207 break;
5208 case 28:
5209 switch (sel) {
5210 case 0:
5211 case 2:
5212 case 4:
5213 case 6:
5214 gen_helper_mtc0_taglo(cpu_env, arg);
5215 rn = "TagLo";
5216 break;
5217 case 1:
5218 case 3:
5219 case 5:
5220 case 7:
5221 gen_helper_mtc0_datalo(cpu_env, arg);
5222 rn = "DataLo";
5223 break;
5224 default:
5225 goto die;
5227 break;
5228 case 29:
5229 switch (sel) {
5230 case 0:
5231 case 2:
5232 case 4:
5233 case 6:
5234 gen_helper_mtc0_taghi(cpu_env, arg);
5235 rn = "TagHi";
5236 break;
5237 case 1:
5238 case 3:
5239 case 5:
5240 case 7:
5241 gen_helper_mtc0_datahi(cpu_env, arg);
5242 rn = "DataHi";
5243 break;
5244 default:
5245 rn = "invalid sel";
5246 goto die;
5248 break;
5249 case 30:
5250 switch (sel) {
5251 case 0:
5252 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
5253 rn = "ErrorEPC";
5254 break;
5255 default:
5256 goto die;
5258 break;
5259 case 31:
5260 switch (sel) {
5261 case 0:
5262 /* EJTAG support */
5263 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5264 rn = "DESAVE";
5265 break;
5266 default:
5267 goto die;
5269 /* Stop translation as we may have switched the execution mode */
5270 ctx->bstate = BS_STOP;
5271 break;
5272 default:
5273 goto die;
5275 (void)rn; /* avoid a compiler warning */
5276 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5277 /* For simplicity assume that all writes can cause interrupts. */
5278 if (use_icount) {
5279 gen_io_end();
5280 ctx->bstate = BS_STOP;
5282 return;
5284 die:
5285 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5286 generate_exception(ctx, EXCP_RI);
5289 #if defined(TARGET_MIPS64)
5290 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5292 const char *rn = "invalid";
5294 if (sel != 0)
5295 check_insn(ctx, ISA_MIPS64);
5297 switch (reg) {
5298 case 0:
5299 switch (sel) {
5300 case 0:
5301 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5302 rn = "Index";
5303 break;
5304 case 1:
5305 check_insn(ctx, ASE_MT);
5306 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5307 rn = "MVPControl";
5308 break;
5309 case 2:
5310 check_insn(ctx, ASE_MT);
5311 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5312 rn = "MVPConf0";
5313 break;
5314 case 3:
5315 check_insn(ctx, ASE_MT);
5316 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5317 rn = "MVPConf1";
5318 break;
5319 default:
5320 goto die;
5322 break;
5323 case 1:
5324 switch (sel) {
5325 case 0:
5326 gen_helper_mfc0_random(arg, cpu_env);
5327 rn = "Random";
5328 break;
5329 case 1:
5330 check_insn(ctx, ASE_MT);
5331 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5332 rn = "VPEControl";
5333 break;
5334 case 2:
5335 check_insn(ctx, ASE_MT);
5336 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5337 rn = "VPEConf0";
5338 break;
5339 case 3:
5340 check_insn(ctx, ASE_MT);
5341 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5342 rn = "VPEConf1";
5343 break;
5344 case 4:
5345 check_insn(ctx, ASE_MT);
5346 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
5347 rn = "YQMask";
5348 break;
5349 case 5:
5350 check_insn(ctx, ASE_MT);
5351 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5352 rn = "VPESchedule";
5353 break;
5354 case 6:
5355 check_insn(ctx, ASE_MT);
5356 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5357 rn = "VPEScheFBack";
5358 break;
5359 case 7:
5360 check_insn(ctx, ASE_MT);
5361 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5362 rn = "VPEOpt";
5363 break;
5364 default:
5365 goto die;
5367 break;
5368 case 2:
5369 switch (sel) {
5370 case 0:
5371 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
5372 rn = "EntryLo0";
5373 break;
5374 case 1:
5375 check_insn(ctx, ASE_MT);
5376 gen_helper_mfc0_tcstatus(arg, cpu_env);
5377 rn = "TCStatus";
5378 break;
5379 case 2:
5380 check_insn(ctx, ASE_MT);
5381 gen_helper_mfc0_tcbind(arg, cpu_env);
5382 rn = "TCBind";
5383 break;
5384 case 3:
5385 check_insn(ctx, ASE_MT);
5386 gen_helper_dmfc0_tcrestart(arg, cpu_env);
5387 rn = "TCRestart";
5388 break;
5389 case 4:
5390 check_insn(ctx, ASE_MT);
5391 gen_helper_dmfc0_tchalt(arg, cpu_env);
5392 rn = "TCHalt";
5393 break;
5394 case 5:
5395 check_insn(ctx, ASE_MT);
5396 gen_helper_dmfc0_tccontext(arg, cpu_env);
5397 rn = "TCContext";
5398 break;
5399 case 6:
5400 check_insn(ctx, ASE_MT);
5401 gen_helper_dmfc0_tcschedule(arg, cpu_env);
5402 rn = "TCSchedule";
5403 break;
5404 case 7:
5405 check_insn(ctx, ASE_MT);
5406 gen_helper_dmfc0_tcschefback(arg, cpu_env);
5407 rn = "TCScheFBack";
5408 break;
5409 default:
5410 goto die;
5412 break;
5413 case 3:
5414 switch (sel) {
5415 case 0:
5416 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
5417 rn = "EntryLo1";
5418 break;
5419 default:
5420 goto die;
5422 break;
5423 case 4:
5424 switch (sel) {
5425 case 0:
5426 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5427 rn = "Context";
5428 break;
5429 case 1:
5430 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
5431 rn = "ContextConfig";
5432 goto die;
5433 // break;
5434 case 2:
5435 if (ctx->ulri) {
5436 tcg_gen_ld_tl(arg, cpu_env,
5437 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5438 rn = "UserLocal";
5439 } else {
5440 tcg_gen_movi_tl(arg, 0);
5442 break;
5443 default:
5444 goto die;
5446 break;
5447 case 5:
5448 switch (sel) {
5449 case 0:
5450 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5451 rn = "PageMask";
5452 break;
5453 case 1:
5454 check_insn(ctx, ISA_MIPS32R2);
5455 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5456 rn = "PageGrain";
5457 break;
5458 default:
5459 goto die;
5461 break;
5462 case 6:
5463 switch (sel) {
5464 case 0:
5465 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5466 rn = "Wired";
5467 break;
5468 case 1:
5469 check_insn(ctx, ISA_MIPS32R2);
5470 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5471 rn = "SRSConf0";
5472 break;
5473 case 2:
5474 check_insn(ctx, ISA_MIPS32R2);
5475 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5476 rn = "SRSConf1";
5477 break;
5478 case 3:
5479 check_insn(ctx, ISA_MIPS32R2);
5480 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5481 rn = "SRSConf2";
5482 break;
5483 case 4:
5484 check_insn(ctx, ISA_MIPS32R2);
5485 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5486 rn = "SRSConf3";
5487 break;
5488 case 5:
5489 check_insn(ctx, ISA_MIPS32R2);
5490 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5491 rn = "SRSConf4";
5492 break;
5493 default:
5494 goto die;
5496 break;
5497 case 7:
5498 switch (sel) {
5499 case 0:
5500 check_insn(ctx, ISA_MIPS32R2);
5501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5502 rn = "HWREna";
5503 break;
5504 default:
5505 goto die;
5507 break;
5508 case 8:
5509 switch (sel) {
5510 case 0:
5511 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5512 rn = "BadVAddr";
5513 break;
5514 default:
5515 goto die;
5517 break;
5518 case 9:
5519 switch (sel) {
5520 case 0:
5521 /* Mark as an IO operation because we read the time. */
5522 if (use_icount)
5523 gen_io_start();
5524 gen_helper_mfc0_count(arg, cpu_env);
5525 if (use_icount) {
5526 gen_io_end();
5528 /* Break the TB to be able to take timer interrupts immediately
5529 after reading count. */
5530 ctx->bstate = BS_STOP;
5531 rn = "Count";
5532 break;
5533 /* 6,7 are implementation dependent */
5534 default:
5535 goto die;
5537 break;
5538 case 10:
5539 switch (sel) {
5540 case 0:
5541 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5542 rn = "EntryHi";
5543 break;
5544 default:
5545 goto die;
5547 break;
5548 case 11:
5549 switch (sel) {
5550 case 0:
5551 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5552 rn = "Compare";
5553 break;
5554 /* 6,7 are implementation dependent */
5555 default:
5556 goto die;
5558 break;
5559 case 12:
5560 switch (sel) {
5561 case 0:
5562 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5563 rn = "Status";
5564 break;
5565 case 1:
5566 check_insn(ctx, ISA_MIPS32R2);
5567 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5568 rn = "IntCtl";
5569 break;
5570 case 2:
5571 check_insn(ctx, ISA_MIPS32R2);
5572 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5573 rn = "SRSCtl";
5574 break;
5575 case 3:
5576 check_insn(ctx, ISA_MIPS32R2);
5577 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5578 rn = "SRSMap";
5579 break;
5580 default:
5581 goto die;
5583 break;
5584 case 13:
5585 switch (sel) {
5586 case 0:
5587 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5588 rn = "Cause";
5589 break;
5590 default:
5591 goto die;
5593 break;
5594 case 14:
5595 switch (sel) {
5596 case 0:
5597 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5598 rn = "EPC";
5599 break;
5600 default:
5601 goto die;
5603 break;
5604 case 15:
5605 switch (sel) {
5606 case 0:
5607 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5608 rn = "PRid";
5609 break;
5610 case 1:
5611 check_insn(ctx, ISA_MIPS32R2);
5612 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5613 rn = "EBase";
5614 break;
5615 default:
5616 goto die;
5618 break;
5619 case 16:
5620 switch (sel) {
5621 case 0:
5622 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5623 rn = "Config";
5624 break;
5625 case 1:
5626 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5627 rn = "Config1";
5628 break;
5629 case 2:
5630 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5631 rn = "Config2";
5632 break;
5633 case 3:
5634 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5635 rn = "Config3";
5636 break;
5637 /* 6,7 are implementation dependent */
5638 case 6:
5639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5640 rn = "Config6";
5641 break;
5642 case 7:
5643 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5644 rn = "Config7";
5645 break;
5646 default:
5647 goto die;
5649 break;
5650 case 17:
5651 switch (sel) {
5652 case 0:
5653 gen_helper_dmfc0_lladdr(arg, cpu_env);
5654 rn = "LLAddr";
5655 break;
5656 default:
5657 goto die;
5659 break;
5660 case 18:
5661 switch (sel) {
5662 case 0 ... 7:
5663 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
5664 rn = "WatchLo";
5665 break;
5666 default:
5667 goto die;
5669 break;
5670 case 19:
5671 switch (sel) {
5672 case 0 ... 7:
5673 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5674 rn = "WatchHi";
5675 break;
5676 default:
5677 goto die;
5679 break;
5680 case 20:
5681 switch (sel) {
5682 case 0:
5683 check_insn(ctx, ISA_MIPS3);
5684 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5685 rn = "XContext";
5686 break;
5687 default:
5688 goto die;
5690 break;
5691 case 21:
5692 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5693 switch (sel) {
5694 case 0:
5695 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5696 rn = "Framemask";
5697 break;
5698 default:
5699 goto die;
5701 break;
5702 case 22:
5703 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5704 rn = "'Diagnostic"; /* implementation dependent */
5705 break;
5706 case 23:
5707 switch (sel) {
5708 case 0:
5709 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5710 rn = "Debug";
5711 break;
5712 case 1:
5713 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
5714 rn = "TraceControl";
5715 // break;
5716 case 2:
5717 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
5718 rn = "TraceControl2";
5719 // break;
5720 case 3:
5721 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
5722 rn = "UserTraceData";
5723 // break;
5724 case 4:
5725 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
5726 rn = "TraceBPC";
5727 // break;
5728 default:
5729 goto die;
5731 break;
5732 case 24:
5733 switch (sel) {
5734 case 0:
5735 /* EJTAG support */
5736 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5737 rn = "DEPC";
5738 break;
5739 default:
5740 goto die;
5742 break;
5743 case 25:
5744 switch (sel) {
5745 case 0:
5746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5747 rn = "Performance0";
5748 break;
5749 case 1:
5750 // gen_helper_dmfc0_performance1(arg);
5751 rn = "Performance1";
5752 // break;
5753 case 2:
5754 // gen_helper_dmfc0_performance2(arg);
5755 rn = "Performance2";
5756 // break;
5757 case 3:
5758 // gen_helper_dmfc0_performance3(arg);
5759 rn = "Performance3";
5760 // break;
5761 case 4:
5762 // gen_helper_dmfc0_performance4(arg);
5763 rn = "Performance4";
5764 // break;
5765 case 5:
5766 // gen_helper_dmfc0_performance5(arg);
5767 rn = "Performance5";
5768 // break;
5769 case 6:
5770 // gen_helper_dmfc0_performance6(arg);
5771 rn = "Performance6";
5772 // break;
5773 case 7:
5774 // gen_helper_dmfc0_performance7(arg);
5775 rn = "Performance7";
5776 // break;
5777 default:
5778 goto die;
5780 break;
5781 case 26:
5782 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5783 rn = "ECC";
5784 break;
5785 case 27:
5786 switch (sel) {
5787 /* ignored */
5788 case 0 ... 3:
5789 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5790 rn = "CacheErr";
5791 break;
5792 default:
5793 goto die;
5795 break;
5796 case 28:
5797 switch (sel) {
5798 case 0:
5799 case 2:
5800 case 4:
5801 case 6:
5802 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
5803 rn = "TagLo";
5804 break;
5805 case 1:
5806 case 3:
5807 case 5:
5808 case 7:
5809 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5810 rn = "DataLo";
5811 break;
5812 default:
5813 goto die;
5815 break;
5816 case 29:
5817 switch (sel) {
5818 case 0:
5819 case 2:
5820 case 4:
5821 case 6:
5822 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5823 rn = "TagHi";
5824 break;
5825 case 1:
5826 case 3:
5827 case 5:
5828 case 7:
5829 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5830 rn = "DataHi";
5831 break;
5832 default:
5833 goto die;
5835 break;
5836 case 30:
5837 switch (sel) {
5838 case 0:
5839 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5840 rn = "ErrorEPC";
5841 break;
5842 default:
5843 goto die;
5845 break;
5846 case 31:
5847 switch (sel) {
5848 case 0:
5849 /* EJTAG support */
5850 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5851 rn = "DESAVE";
5852 break;
5853 default:
5854 goto die;
5856 break;
5857 default:
5858 goto die;
5860 (void)rn; /* avoid a compiler warning */
5861 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5862 return;
5864 die:
5865 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5866 generate_exception(ctx, EXCP_RI);
5869 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5871 const char *rn = "invalid";
5873 if (sel != 0)
5874 check_insn(ctx, ISA_MIPS64);
5876 if (use_icount)
5877 gen_io_start();
5879 switch (reg) {
5880 case 0:
5881 switch (sel) {
5882 case 0:
5883 gen_helper_mtc0_index(cpu_env, arg);
5884 rn = "Index";
5885 break;
5886 case 1:
5887 check_insn(ctx, ASE_MT);
5888 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5889 rn = "MVPControl";
5890 break;
5891 case 2:
5892 check_insn(ctx, ASE_MT);
5893 /* ignored */
5894 rn = "MVPConf0";
5895 break;
5896 case 3:
5897 check_insn(ctx, ASE_MT);
5898 /* ignored */
5899 rn = "MVPConf1";
5900 break;
5901 default:
5902 goto die;
5904 break;
5905 case 1:
5906 switch (sel) {
5907 case 0:
5908 /* ignored */
5909 rn = "Random";
5910 break;
5911 case 1:
5912 check_insn(ctx, ASE_MT);
5913 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5914 rn = "VPEControl";
5915 break;
5916 case 2:
5917 check_insn(ctx, ASE_MT);
5918 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5919 rn = "VPEConf0";
5920 break;
5921 case 3:
5922 check_insn(ctx, ASE_MT);
5923 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5924 rn = "VPEConf1";
5925 break;
5926 case 4:
5927 check_insn(ctx, ASE_MT);
5928 gen_helper_mtc0_yqmask(cpu_env, arg);
5929 rn = "YQMask";
5930 break;
5931 case 5:
5932 check_insn(ctx, ASE_MT);
5933 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5934 rn = "VPESchedule";
5935 break;
5936 case 6:
5937 check_insn(ctx, ASE_MT);
5938 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5939 rn = "VPEScheFBack";
5940 break;
5941 case 7:
5942 check_insn(ctx, ASE_MT);
5943 gen_helper_mtc0_vpeopt(cpu_env, arg);
5944 rn = "VPEOpt";
5945 break;
5946 default:
5947 goto die;
5949 break;
5950 case 2:
5951 switch (sel) {
5952 case 0:
5953 gen_helper_mtc0_entrylo0(cpu_env, arg);
5954 rn = "EntryLo0";
5955 break;
5956 case 1:
5957 check_insn(ctx, ASE_MT);
5958 gen_helper_mtc0_tcstatus(cpu_env, arg);
5959 rn = "TCStatus";
5960 break;
5961 case 2:
5962 check_insn(ctx, ASE_MT);
5963 gen_helper_mtc0_tcbind(cpu_env, arg);
5964 rn = "TCBind";
5965 break;
5966 case 3:
5967 check_insn(ctx, ASE_MT);
5968 gen_helper_mtc0_tcrestart(cpu_env, arg);
5969 rn = "TCRestart";
5970 break;
5971 case 4:
5972 check_insn(ctx, ASE_MT);
5973 gen_helper_mtc0_tchalt(cpu_env, arg);
5974 rn = "TCHalt";
5975 break;
5976 case 5:
5977 check_insn(ctx, ASE_MT);
5978 gen_helper_mtc0_tccontext(cpu_env, arg);
5979 rn = "TCContext";
5980 break;
5981 case 6:
5982 check_insn(ctx, ASE_MT);
5983 gen_helper_mtc0_tcschedule(cpu_env, arg);
5984 rn = "TCSchedule";
5985 break;
5986 case 7:
5987 check_insn(ctx, ASE_MT);
5988 gen_helper_mtc0_tcschefback(cpu_env, arg);
5989 rn = "TCScheFBack";
5990 break;
5991 default:
5992 goto die;
5994 break;
5995 case 3:
5996 switch (sel) {
5997 case 0:
5998 gen_helper_mtc0_entrylo1(cpu_env, arg);
5999 rn = "EntryLo1";
6000 break;
6001 default:
6002 goto die;
6004 break;
6005 case 4:
6006 switch (sel) {
6007 case 0:
6008 gen_helper_mtc0_context(cpu_env, arg);
6009 rn = "Context";
6010 break;
6011 case 1:
6012 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6013 rn = "ContextConfig";
6014 goto die;
6015 // break;
6016 case 2:
6017 if (ctx->ulri) {
6018 tcg_gen_st_tl(arg, cpu_env,
6019 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6020 rn = "UserLocal";
6022 break;
6023 default:
6024 goto die;
6026 break;
6027 case 5:
6028 switch (sel) {
6029 case 0:
6030 gen_helper_mtc0_pagemask(cpu_env, arg);
6031 rn = "PageMask";
6032 break;
6033 case 1:
6034 check_insn(ctx, ISA_MIPS32R2);
6035 gen_helper_mtc0_pagegrain(cpu_env, arg);
6036 rn = "PageGrain";
6037 break;
6038 default:
6039 goto die;
6041 break;
6042 case 6:
6043 switch (sel) {
6044 case 0:
6045 gen_helper_mtc0_wired(cpu_env, arg);
6046 rn = "Wired";
6047 break;
6048 case 1:
6049 check_insn(ctx, ISA_MIPS32R2);
6050 gen_helper_mtc0_srsconf0(cpu_env, arg);
6051 rn = "SRSConf0";
6052 break;
6053 case 2:
6054 check_insn(ctx, ISA_MIPS32R2);
6055 gen_helper_mtc0_srsconf1(cpu_env, arg);
6056 rn = "SRSConf1";
6057 break;
6058 case 3:
6059 check_insn(ctx, ISA_MIPS32R2);
6060 gen_helper_mtc0_srsconf2(cpu_env, arg);
6061 rn = "SRSConf2";
6062 break;
6063 case 4:
6064 check_insn(ctx, ISA_MIPS32R2);
6065 gen_helper_mtc0_srsconf3(cpu_env, arg);
6066 rn = "SRSConf3";
6067 break;
6068 case 5:
6069 check_insn(ctx, ISA_MIPS32R2);
6070 gen_helper_mtc0_srsconf4(cpu_env, arg);
6071 rn = "SRSConf4";
6072 break;
6073 default:
6074 goto die;
6076 break;
6077 case 7:
6078 switch (sel) {
6079 case 0:
6080 check_insn(ctx, ISA_MIPS32R2);
6081 gen_helper_mtc0_hwrena(cpu_env, arg);
6082 ctx->bstate = BS_STOP;
6083 rn = "HWREna";
6084 break;
6085 default:
6086 goto die;
6088 break;
6089 case 8:
6090 /* ignored */
6091 rn = "BadVAddr";
6092 break;
6093 case 9:
6094 switch (sel) {
6095 case 0:
6096 gen_helper_mtc0_count(cpu_env, arg);
6097 rn = "Count";
6098 break;
6099 /* 6,7 are implementation dependent */
6100 default:
6101 goto die;
6103 /* Stop translation as we may have switched the execution mode */
6104 ctx->bstate = BS_STOP;
6105 break;
6106 case 10:
6107 switch (sel) {
6108 case 0:
6109 gen_helper_mtc0_entryhi(cpu_env, arg);
6110 rn = "EntryHi";
6111 break;
6112 default:
6113 goto die;
6115 break;
6116 case 11:
6117 switch (sel) {
6118 case 0:
6119 gen_helper_mtc0_compare(cpu_env, arg);
6120 rn = "Compare";
6121 break;
6122 /* 6,7 are implementation dependent */
6123 default:
6124 goto die;
6126 /* Stop translation as we may have switched the execution mode */
6127 ctx->bstate = BS_STOP;
6128 break;
6129 case 12:
6130 switch (sel) {
6131 case 0:
6132 save_cpu_state(ctx, 1);
6133 gen_helper_mtc0_status(cpu_env, arg);
6134 /* BS_STOP isn't good enough here, hflags may have changed. */
6135 gen_save_pc(ctx->pc + 4);
6136 ctx->bstate = BS_EXCP;
6137 rn = "Status";
6138 break;
6139 case 1:
6140 check_insn(ctx, ISA_MIPS32R2);
6141 gen_helper_mtc0_intctl(cpu_env, arg);
6142 /* Stop translation as we may have switched the execution mode */
6143 ctx->bstate = BS_STOP;
6144 rn = "IntCtl";
6145 break;
6146 case 2:
6147 check_insn(ctx, ISA_MIPS32R2);
6148 gen_helper_mtc0_srsctl(cpu_env, arg);
6149 /* Stop translation as we may have switched the execution mode */
6150 ctx->bstate = BS_STOP;
6151 rn = "SRSCtl";
6152 break;
6153 case 3:
6154 check_insn(ctx, ISA_MIPS32R2);
6155 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6156 /* Stop translation as we may have switched the execution mode */
6157 ctx->bstate = BS_STOP;
6158 rn = "SRSMap";
6159 break;
6160 default:
6161 goto die;
6163 break;
6164 case 13:
6165 switch (sel) {
6166 case 0:
6167 save_cpu_state(ctx, 1);
6168 /* Mark as an IO operation because we may trigger a software
6169 interrupt. */
6170 if (use_icount) {
6171 gen_io_start();
6173 gen_helper_mtc0_cause(cpu_env, arg);
6174 if (use_icount) {
6175 gen_io_end();
6177 /* Stop translation as we may have triggered an intetrupt */
6178 ctx->bstate = BS_STOP;
6179 rn = "Cause";
6180 break;
6181 default:
6182 goto die;
6184 break;
6185 case 14:
6186 switch (sel) {
6187 case 0:
6188 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6189 rn = "EPC";
6190 break;
6191 default:
6192 goto die;
6194 break;
6195 case 15:
6196 switch (sel) {
6197 case 0:
6198 /* ignored */
6199 rn = "PRid";
6200 break;
6201 case 1:
6202 check_insn(ctx, ISA_MIPS32R2);
6203 gen_helper_mtc0_ebase(cpu_env, arg);
6204 rn = "EBase";
6205 break;
6206 default:
6207 goto die;
6209 break;
6210 case 16:
6211 switch (sel) {
6212 case 0:
6213 gen_helper_mtc0_config0(cpu_env, arg);
6214 rn = "Config";
6215 /* Stop translation as we may have switched the execution mode */
6216 ctx->bstate = BS_STOP;
6217 break;
6218 case 1:
6219 /* ignored, read only */
6220 rn = "Config1";
6221 break;
6222 case 2:
6223 gen_helper_mtc0_config2(cpu_env, arg);
6224 rn = "Config2";
6225 /* Stop translation as we may have switched the execution mode */
6226 ctx->bstate = BS_STOP;
6227 break;
6228 case 3:
6229 /* ignored */
6230 rn = "Config3";
6231 break;
6232 /* 6,7 are implementation dependent */
6233 default:
6234 rn = "Invalid config selector";
6235 goto die;
6237 break;
6238 case 17:
6239 switch (sel) {
6240 case 0:
6241 gen_helper_mtc0_lladdr(cpu_env, arg);
6242 rn = "LLAddr";
6243 break;
6244 default:
6245 goto die;
6247 break;
6248 case 18:
6249 switch (sel) {
6250 case 0 ... 7:
6251 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6252 rn = "WatchLo";
6253 break;
6254 default:
6255 goto die;
6257 break;
6258 case 19:
6259 switch (sel) {
6260 case 0 ... 7:
6261 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6262 rn = "WatchHi";
6263 break;
6264 default:
6265 goto die;
6267 break;
6268 case 20:
6269 switch (sel) {
6270 case 0:
6271 check_insn(ctx, ISA_MIPS3);
6272 gen_helper_mtc0_xcontext(cpu_env, arg);
6273 rn = "XContext";
6274 break;
6275 default:
6276 goto die;
6278 break;
6279 case 21:
6280 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6281 switch (sel) {
6282 case 0:
6283 gen_helper_mtc0_framemask(cpu_env, arg);
6284 rn = "Framemask";
6285 break;
6286 default:
6287 goto die;
6289 break;
6290 case 22:
6291 /* ignored */
6292 rn = "Diagnostic"; /* implementation dependent */
6293 break;
6294 case 23:
6295 switch (sel) {
6296 case 0:
6297 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6298 /* BS_STOP isn't good enough here, hflags may have changed. */
6299 gen_save_pc(ctx->pc + 4);
6300 ctx->bstate = BS_EXCP;
6301 rn = "Debug";
6302 break;
6303 case 1:
6304 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6305 /* Stop translation as we may have switched the execution mode */
6306 ctx->bstate = BS_STOP;
6307 rn = "TraceControl";
6308 // break;
6309 case 2:
6310 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6311 /* Stop translation as we may have switched the execution mode */
6312 ctx->bstate = BS_STOP;
6313 rn = "TraceControl2";
6314 // break;
6315 case 3:
6316 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6317 /* Stop translation as we may have switched the execution mode */
6318 ctx->bstate = BS_STOP;
6319 rn = "UserTraceData";
6320 // break;
6321 case 4:
6322 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6323 /* Stop translation as we may have switched the execution mode */
6324 ctx->bstate = BS_STOP;
6325 rn = "TraceBPC";
6326 // break;
6327 default:
6328 goto die;
6330 break;
6331 case 24:
6332 switch (sel) {
6333 case 0:
6334 /* EJTAG support */
6335 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6336 rn = "DEPC";
6337 break;
6338 default:
6339 goto die;
6341 break;
6342 case 25:
6343 switch (sel) {
6344 case 0:
6345 gen_helper_mtc0_performance0(cpu_env, arg);
6346 rn = "Performance0";
6347 break;
6348 case 1:
6349 // gen_helper_mtc0_performance1(cpu_env, arg);
6350 rn = "Performance1";
6351 // break;
6352 case 2:
6353 // gen_helper_mtc0_performance2(cpu_env, arg);
6354 rn = "Performance2";
6355 // break;
6356 case 3:
6357 // gen_helper_mtc0_performance3(cpu_env, arg);
6358 rn = "Performance3";
6359 // break;
6360 case 4:
6361 // gen_helper_mtc0_performance4(cpu_env, arg);
6362 rn = "Performance4";
6363 // break;
6364 case 5:
6365 // gen_helper_mtc0_performance5(cpu_env, arg);
6366 rn = "Performance5";
6367 // break;
6368 case 6:
6369 // gen_helper_mtc0_performance6(cpu_env, arg);
6370 rn = "Performance6";
6371 // break;
6372 case 7:
6373 // gen_helper_mtc0_performance7(cpu_env, arg);
6374 rn = "Performance7";
6375 // break;
6376 default:
6377 goto die;
6379 break;
6380 case 26:
6381 /* ignored */
6382 rn = "ECC";
6383 break;
6384 case 27:
6385 switch (sel) {
6386 case 0 ... 3:
6387 /* ignored */
6388 rn = "CacheErr";
6389 break;
6390 default:
6391 goto die;
6393 break;
6394 case 28:
6395 switch (sel) {
6396 case 0:
6397 case 2:
6398 case 4:
6399 case 6:
6400 gen_helper_mtc0_taglo(cpu_env, arg);
6401 rn = "TagLo";
6402 break;
6403 case 1:
6404 case 3:
6405 case 5:
6406 case 7:
6407 gen_helper_mtc0_datalo(cpu_env, arg);
6408 rn = "DataLo";
6409 break;
6410 default:
6411 goto die;
6413 break;
6414 case 29:
6415 switch (sel) {
6416 case 0:
6417 case 2:
6418 case 4:
6419 case 6:
6420 gen_helper_mtc0_taghi(cpu_env, arg);
6421 rn = "TagHi";
6422 break;
6423 case 1:
6424 case 3:
6425 case 5:
6426 case 7:
6427 gen_helper_mtc0_datahi(cpu_env, arg);
6428 rn = "DataHi";
6429 break;
6430 default:
6431 rn = "invalid sel";
6432 goto die;
6434 break;
6435 case 30:
6436 switch (sel) {
6437 case 0:
6438 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6439 rn = "ErrorEPC";
6440 break;
6441 default:
6442 goto die;
6444 break;
6445 case 31:
6446 switch (sel) {
6447 case 0:
6448 /* EJTAG support */
6449 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6450 rn = "DESAVE";
6451 break;
6452 default:
6453 goto die;
6455 /* Stop translation as we may have switched the execution mode */
6456 ctx->bstate = BS_STOP;
6457 break;
6458 default:
6459 goto die;
6461 (void)rn; /* avoid a compiler warning */
6462 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6463 /* For simplicity assume that all writes can cause interrupts. */
6464 if (use_icount) {
6465 gen_io_end();
6466 ctx->bstate = BS_STOP;
6468 return;
6470 die:
6471 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6472 generate_exception(ctx, EXCP_RI);
6474 #endif /* TARGET_MIPS64 */
6476 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
6477 int u, int sel, int h)
6479 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6480 TCGv t0 = tcg_temp_local_new();
6482 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
6483 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6484 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
6485 tcg_gen_movi_tl(t0, -1);
6486 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6487 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6488 tcg_gen_movi_tl(t0, -1);
6489 else if (u == 0) {
6490 switch (rt) {
6491 case 1:
6492 switch (sel) {
6493 case 1:
6494 gen_helper_mftc0_vpecontrol(t0, cpu_env);
6495 break;
6496 case 2:
6497 gen_helper_mftc0_vpeconf0(t0, cpu_env);
6498 break;
6499 default:
6500 goto die;
6501 break;
6503 break;
6504 case 2:
6505 switch (sel) {
6506 case 1:
6507 gen_helper_mftc0_tcstatus(t0, cpu_env);
6508 break;
6509 case 2:
6510 gen_helper_mftc0_tcbind(t0, cpu_env);
6511 break;
6512 case 3:
6513 gen_helper_mftc0_tcrestart(t0, cpu_env);
6514 break;
6515 case 4:
6516 gen_helper_mftc0_tchalt(t0, cpu_env);
6517 break;
6518 case 5:
6519 gen_helper_mftc0_tccontext(t0, cpu_env);
6520 break;
6521 case 6:
6522 gen_helper_mftc0_tcschedule(t0, cpu_env);
6523 break;
6524 case 7:
6525 gen_helper_mftc0_tcschefback(t0, cpu_env);
6526 break;
6527 default:
6528 gen_mfc0(ctx, t0, rt, sel);
6529 break;
6531 break;
6532 case 10:
6533 switch (sel) {
6534 case 0:
6535 gen_helper_mftc0_entryhi(t0, cpu_env);
6536 break;
6537 default:
6538 gen_mfc0(ctx, t0, rt, sel);
6539 break;
6541 case 12:
6542 switch (sel) {
6543 case 0:
6544 gen_helper_mftc0_status(t0, cpu_env);
6545 break;
6546 default:
6547 gen_mfc0(ctx, t0, rt, sel);
6548 break;
6550 case 13:
6551 switch (sel) {
6552 case 0:
6553 gen_helper_mftc0_cause(t0, cpu_env);
6554 break;
6555 default:
6556 goto die;
6557 break;
6559 break;
6560 case 14:
6561 switch (sel) {
6562 case 0:
6563 gen_helper_mftc0_epc(t0, cpu_env);
6564 break;
6565 default:
6566 goto die;
6567 break;
6569 break;
6570 case 15:
6571 switch (sel) {
6572 case 1:
6573 gen_helper_mftc0_ebase(t0, cpu_env);
6574 break;
6575 default:
6576 goto die;
6577 break;
6579 break;
6580 case 16:
6581 switch (sel) {
6582 case 0 ... 7:
6583 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
6584 break;
6585 default:
6586 goto die;
6587 break;
6589 break;
6590 case 23:
6591 switch (sel) {
6592 case 0:
6593 gen_helper_mftc0_debug(t0, cpu_env);
6594 break;
6595 default:
6596 gen_mfc0(ctx, t0, rt, sel);
6597 break;
6599 break;
6600 default:
6601 gen_mfc0(ctx, t0, rt, sel);
6603 } else switch (sel) {
6604 /* GPR registers. */
6605 case 0:
6606 gen_helper_1e0i(mftgpr, t0, rt);
6607 break;
6608 /* Auxiliary CPU registers */
6609 case 1:
6610 switch (rt) {
6611 case 0:
6612 gen_helper_1e0i(mftlo, t0, 0);
6613 break;
6614 case 1:
6615 gen_helper_1e0i(mfthi, t0, 0);
6616 break;
6617 case 2:
6618 gen_helper_1e0i(mftacx, t0, 0);
6619 break;
6620 case 4:
6621 gen_helper_1e0i(mftlo, t0, 1);
6622 break;
6623 case 5:
6624 gen_helper_1e0i(mfthi, t0, 1);
6625 break;
6626 case 6:
6627 gen_helper_1e0i(mftacx, t0, 1);
6628 break;
6629 case 8:
6630 gen_helper_1e0i(mftlo, t0, 2);
6631 break;
6632 case 9:
6633 gen_helper_1e0i(mfthi, t0, 2);
6634 break;
6635 case 10:
6636 gen_helper_1e0i(mftacx, t0, 2);
6637 break;
6638 case 12:
6639 gen_helper_1e0i(mftlo, t0, 3);
6640 break;
6641 case 13:
6642 gen_helper_1e0i(mfthi, t0, 3);
6643 break;
6644 case 14:
6645 gen_helper_1e0i(mftacx, t0, 3);
6646 break;
6647 case 16:
6648 gen_helper_mftdsp(t0, cpu_env);
6649 break;
6650 default:
6651 goto die;
6653 break;
6654 /* Floating point (COP1). */
6655 case 2:
6656 /* XXX: For now we support only a single FPU context. */
6657 if (h == 0) {
6658 TCGv_i32 fp0 = tcg_temp_new_i32();
6660 gen_load_fpr32(fp0, rt);
6661 tcg_gen_ext_i32_tl(t0, fp0);
6662 tcg_temp_free_i32(fp0);
6663 } else {
6664 TCGv_i32 fp0 = tcg_temp_new_i32();
6666 gen_load_fpr32h(ctx, fp0, rt);
6667 tcg_gen_ext_i32_tl(t0, fp0);
6668 tcg_temp_free_i32(fp0);
6670 break;
6671 case 3:
6672 /* XXX: For now we support only a single FPU context. */
6673 gen_helper_1e0i(cfc1, t0, rt);
6674 break;
6675 /* COP2: Not implemented. */
6676 case 4:
6677 case 5:
6678 /* fall through */
6679 default:
6680 goto die;
6682 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
6683 gen_store_gpr(t0, rd);
6684 tcg_temp_free(t0);
6685 return;
6687 die:
6688 tcg_temp_free(t0);
6689 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
6690 generate_exception(ctx, EXCP_RI);
6693 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
6694 int u, int sel, int h)
6696 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6697 TCGv t0 = tcg_temp_local_new();
6699 gen_load_gpr(t0, rt);
6700 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
6701 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6702 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
6703 /* NOP */ ;
6704 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6705 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6706 /* NOP */ ;
6707 else if (u == 0) {
6708 switch (rd) {
6709 case 1:
6710 switch (sel) {
6711 case 1:
6712 gen_helper_mttc0_vpecontrol(cpu_env, t0);
6713 break;
6714 case 2:
6715 gen_helper_mttc0_vpeconf0(cpu_env, t0);
6716 break;
6717 default:
6718 goto die;
6719 break;
6721 break;
6722 case 2:
6723 switch (sel) {
6724 case 1:
6725 gen_helper_mttc0_tcstatus(cpu_env, t0);
6726 break;
6727 case 2:
6728 gen_helper_mttc0_tcbind(cpu_env, t0);
6729 break;
6730 case 3:
6731 gen_helper_mttc0_tcrestart(cpu_env, t0);
6732 break;
6733 case 4:
6734 gen_helper_mttc0_tchalt(cpu_env, t0);
6735 break;
6736 case 5:
6737 gen_helper_mttc0_tccontext(cpu_env, t0);
6738 break;
6739 case 6:
6740 gen_helper_mttc0_tcschedule(cpu_env, t0);
6741 break;
6742 case 7:
6743 gen_helper_mttc0_tcschefback(cpu_env, t0);
6744 break;
6745 default:
6746 gen_mtc0(ctx, t0, rd, sel);
6747 break;
6749 break;
6750 case 10:
6751 switch (sel) {
6752 case 0:
6753 gen_helper_mttc0_entryhi(cpu_env, t0);
6754 break;
6755 default:
6756 gen_mtc0(ctx, t0, rd, sel);
6757 break;
6759 case 12:
6760 switch (sel) {
6761 case 0:
6762 gen_helper_mttc0_status(cpu_env, t0);
6763 break;
6764 default:
6765 gen_mtc0(ctx, t0, rd, sel);
6766 break;
6768 case 13:
6769 switch (sel) {
6770 case 0:
6771 gen_helper_mttc0_cause(cpu_env, t0);
6772 break;
6773 default:
6774 goto die;
6775 break;
6777 break;
6778 case 15:
6779 switch (sel) {
6780 case 1:
6781 gen_helper_mttc0_ebase(cpu_env, t0);
6782 break;
6783 default:
6784 goto die;
6785 break;
6787 break;
6788 case 23:
6789 switch (sel) {
6790 case 0:
6791 gen_helper_mttc0_debug(cpu_env, t0);
6792 break;
6793 default:
6794 gen_mtc0(ctx, t0, rd, sel);
6795 break;
6797 break;
6798 default:
6799 gen_mtc0(ctx, t0, rd, sel);
6801 } else switch (sel) {
6802 /* GPR registers. */
6803 case 0:
6804 gen_helper_0e1i(mttgpr, t0, rd);
6805 break;
6806 /* Auxiliary CPU registers */
6807 case 1:
6808 switch (rd) {
6809 case 0:
6810 gen_helper_0e1i(mttlo, t0, 0);
6811 break;
6812 case 1:
6813 gen_helper_0e1i(mtthi, t0, 0);
6814 break;
6815 case 2:
6816 gen_helper_0e1i(mttacx, t0, 0);
6817 break;
6818 case 4:
6819 gen_helper_0e1i(mttlo, t0, 1);
6820 break;
6821 case 5:
6822 gen_helper_0e1i(mtthi, t0, 1);
6823 break;
6824 case 6:
6825 gen_helper_0e1i(mttacx, t0, 1);
6826 break;
6827 case 8:
6828 gen_helper_0e1i(mttlo, t0, 2);
6829 break;
6830 case 9:
6831 gen_helper_0e1i(mtthi, t0, 2);
6832 break;
6833 case 10:
6834 gen_helper_0e1i(mttacx, t0, 2);
6835 break;
6836 case 12:
6837 gen_helper_0e1i(mttlo, t0, 3);
6838 break;
6839 case 13:
6840 gen_helper_0e1i(mtthi, t0, 3);
6841 break;
6842 case 14:
6843 gen_helper_0e1i(mttacx, t0, 3);
6844 break;
6845 case 16:
6846 gen_helper_mttdsp(cpu_env, t0);
6847 break;
6848 default:
6849 goto die;
6851 break;
6852 /* Floating point (COP1). */
6853 case 2:
6854 /* XXX: For now we support only a single FPU context. */
6855 if (h == 0) {
6856 TCGv_i32 fp0 = tcg_temp_new_i32();
6858 tcg_gen_trunc_tl_i32(fp0, t0);
6859 gen_store_fpr32(fp0, rd);
6860 tcg_temp_free_i32(fp0);
6861 } else {
6862 TCGv_i32 fp0 = tcg_temp_new_i32();
6864 tcg_gen_trunc_tl_i32(fp0, t0);
6865 gen_store_fpr32h(ctx, fp0, rd);
6866 tcg_temp_free_i32(fp0);
6868 break;
6869 case 3:
6870 /* XXX: For now we support only a single FPU context. */
6872 TCGv_i32 fs_tmp = tcg_const_i32(rd);
6874 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
6875 tcg_temp_free_i32(fs_tmp);
6877 break;
6878 /* COP2: Not implemented. */
6879 case 4:
6880 case 5:
6881 /* fall through */
6882 default:
6883 goto die;
6885 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
6886 tcg_temp_free(t0);
6887 return;
6889 die:
6890 tcg_temp_free(t0);
6891 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
6892 generate_exception(ctx, EXCP_RI);
6895 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6897 const char *opn = "ldst";
6899 check_cp0_enabled(ctx);
6900 switch (opc) {
6901 case OPC_MFC0:
6902 if (rt == 0) {
6903 /* Treat as NOP. */
6904 return;
6906 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6907 opn = "mfc0";
6908 break;
6909 case OPC_MTC0:
6911 TCGv t0 = tcg_temp_new();
6913 gen_load_gpr(t0, rt);
6914 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
6915 tcg_temp_free(t0);
6917 opn = "mtc0";
6918 break;
6919 #if defined(TARGET_MIPS64)
6920 case OPC_DMFC0:
6921 check_insn(ctx, ISA_MIPS3);
6922 if (rt == 0) {
6923 /* Treat as NOP. */
6924 return;
6926 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6927 opn = "dmfc0";
6928 break;
6929 case OPC_DMTC0:
6930 check_insn(ctx, ISA_MIPS3);
6932 TCGv t0 = tcg_temp_new();
6934 gen_load_gpr(t0, rt);
6935 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
6936 tcg_temp_free(t0);
6938 opn = "dmtc0";
6939 break;
6940 #endif
6941 case OPC_MFTR:
6942 check_insn(ctx, ASE_MT);
6943 if (rd == 0) {
6944 /* Treat as NOP. */
6945 return;
6947 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
6948 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6949 opn = "mftr";
6950 break;
6951 case OPC_MTTR:
6952 check_insn(ctx, ASE_MT);
6953 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
6954 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6955 opn = "mttr";
6956 break;
6957 case OPC_TLBWI:
6958 opn = "tlbwi";
6959 if (!env->tlb->helper_tlbwi)
6960 goto die;
6961 gen_helper_tlbwi(cpu_env);
6962 break;
6963 case OPC_TLBWR:
6964 opn = "tlbwr";
6965 if (!env->tlb->helper_tlbwr)
6966 goto die;
6967 gen_helper_tlbwr(cpu_env);
6968 break;
6969 case OPC_TLBP:
6970 opn = "tlbp";
6971 if (!env->tlb->helper_tlbp)
6972 goto die;
6973 gen_helper_tlbp(cpu_env);
6974 break;
6975 case OPC_TLBR:
6976 opn = "tlbr";
6977 if (!env->tlb->helper_tlbr)
6978 goto die;
6979 gen_helper_tlbr(cpu_env);
6980 break;
6981 case OPC_ERET:
6982 opn = "eret";
6983 check_insn(ctx, ISA_MIPS2);
6984 gen_helper_eret(cpu_env);
6985 ctx->bstate = BS_EXCP;
6986 break;
6987 case OPC_DERET:
6988 opn = "deret";
6989 check_insn(ctx, ISA_MIPS32);
6990 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6991 MIPS_INVAL(opn);
6992 generate_exception(ctx, EXCP_RI);
6993 } else {
6994 gen_helper_deret(cpu_env);
6995 ctx->bstate = BS_EXCP;
6997 break;
6998 case OPC_WAIT:
6999 opn = "wait";
7000 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
7001 /* If we get an exception, we want to restart at next instruction */
7002 ctx->pc += 4;
7003 save_cpu_state(ctx, 1);
7004 ctx->pc -= 4;
7005 gen_helper_wait(cpu_env);
7006 ctx->bstate = BS_EXCP;
7007 break;
7008 default:
7009 die:
7010 MIPS_INVAL(opn);
7011 generate_exception(ctx, EXCP_RI);
7012 return;
7014 (void)opn; /* avoid a compiler warning */
7015 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
7017 #endif /* !CONFIG_USER_ONLY */
7019 /* CP1 Branches (before delay slot) */
7020 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7021 int32_t cc, int32_t offset)
7023 target_ulong btarget;
7024 const char *opn = "cp1 cond branch";
7025 TCGv_i32 t0 = tcg_temp_new_i32();
7027 if (cc != 0)
7028 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
7030 btarget = ctx->pc + 4 + offset;
7032 switch (op) {
7033 case OPC_BC1F:
7034 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7035 tcg_gen_not_i32(t0, t0);
7036 tcg_gen_andi_i32(t0, t0, 1);
7037 tcg_gen_extu_i32_tl(bcond, t0);
7038 opn = "bc1f";
7039 goto not_likely;
7040 case OPC_BC1FL:
7041 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7042 tcg_gen_not_i32(t0, t0);
7043 tcg_gen_andi_i32(t0, t0, 1);
7044 tcg_gen_extu_i32_tl(bcond, t0);
7045 opn = "bc1fl";
7046 goto likely;
7047 case OPC_BC1T:
7048 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7049 tcg_gen_andi_i32(t0, t0, 1);
7050 tcg_gen_extu_i32_tl(bcond, t0);
7051 opn = "bc1t";
7052 goto not_likely;
7053 case OPC_BC1TL:
7054 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7055 tcg_gen_andi_i32(t0, t0, 1);
7056 tcg_gen_extu_i32_tl(bcond, t0);
7057 opn = "bc1tl";
7058 likely:
7059 ctx->hflags |= MIPS_HFLAG_BL;
7060 break;
7061 case OPC_BC1FANY2:
7063 TCGv_i32 t1 = tcg_temp_new_i32();
7064 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7065 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7066 tcg_gen_nand_i32(t0, t0, t1);
7067 tcg_temp_free_i32(t1);
7068 tcg_gen_andi_i32(t0, t0, 1);
7069 tcg_gen_extu_i32_tl(bcond, t0);
7071 opn = "bc1any2f";
7072 goto not_likely;
7073 case OPC_BC1TANY2:
7075 TCGv_i32 t1 = tcg_temp_new_i32();
7076 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7077 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7078 tcg_gen_or_i32(t0, t0, t1);
7079 tcg_temp_free_i32(t1);
7080 tcg_gen_andi_i32(t0, t0, 1);
7081 tcg_gen_extu_i32_tl(bcond, t0);
7083 opn = "bc1any2t";
7084 goto not_likely;
7085 case OPC_BC1FANY4:
7087 TCGv_i32 t1 = tcg_temp_new_i32();
7088 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7089 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7090 tcg_gen_and_i32(t0, t0, t1);
7091 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7092 tcg_gen_and_i32(t0, t0, t1);
7093 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7094 tcg_gen_nand_i32(t0, t0, t1);
7095 tcg_temp_free_i32(t1);
7096 tcg_gen_andi_i32(t0, t0, 1);
7097 tcg_gen_extu_i32_tl(bcond, t0);
7099 opn = "bc1any4f";
7100 goto not_likely;
7101 case OPC_BC1TANY4:
7103 TCGv_i32 t1 = tcg_temp_new_i32();
7104 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7105 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7106 tcg_gen_or_i32(t0, t0, t1);
7107 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7108 tcg_gen_or_i32(t0, t0, t1);
7109 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7110 tcg_gen_or_i32(t0, t0, t1);
7111 tcg_temp_free_i32(t1);
7112 tcg_gen_andi_i32(t0, t0, 1);
7113 tcg_gen_extu_i32_tl(bcond, t0);
7115 opn = "bc1any4t";
7116 not_likely:
7117 ctx->hflags |= MIPS_HFLAG_BC;
7118 break;
7119 default:
7120 MIPS_INVAL(opn);
7121 generate_exception (ctx, EXCP_RI);
7122 goto out;
7124 (void)opn; /* avoid a compiler warning */
7125 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
7126 ctx->hflags, btarget);
7127 ctx->btarget = btarget;
7129 out:
7130 tcg_temp_free_i32(t0);
7133 /* Coprocessor 1 (FPU) */
7135 #define FOP(func, fmt) (((fmt) << 21) | (func))
7137 enum fopcode {
7138 OPC_ADD_S = FOP(0, FMT_S),
7139 OPC_SUB_S = FOP(1, FMT_S),
7140 OPC_MUL_S = FOP(2, FMT_S),
7141 OPC_DIV_S = FOP(3, FMT_S),
7142 OPC_SQRT_S = FOP(4, FMT_S),
7143 OPC_ABS_S = FOP(5, FMT_S),
7144 OPC_MOV_S = FOP(6, FMT_S),
7145 OPC_NEG_S = FOP(7, FMT_S),
7146 OPC_ROUND_L_S = FOP(8, FMT_S),
7147 OPC_TRUNC_L_S = FOP(9, FMT_S),
7148 OPC_CEIL_L_S = FOP(10, FMT_S),
7149 OPC_FLOOR_L_S = FOP(11, FMT_S),
7150 OPC_ROUND_W_S = FOP(12, FMT_S),
7151 OPC_TRUNC_W_S = FOP(13, FMT_S),
7152 OPC_CEIL_W_S = FOP(14, FMT_S),
7153 OPC_FLOOR_W_S = FOP(15, FMT_S),
7154 OPC_MOVCF_S = FOP(17, FMT_S),
7155 OPC_MOVZ_S = FOP(18, FMT_S),
7156 OPC_MOVN_S = FOP(19, FMT_S),
7157 OPC_RECIP_S = FOP(21, FMT_S),
7158 OPC_RSQRT_S = FOP(22, FMT_S),
7159 OPC_RECIP2_S = FOP(28, FMT_S),
7160 OPC_RECIP1_S = FOP(29, FMT_S),
7161 OPC_RSQRT1_S = FOP(30, FMT_S),
7162 OPC_RSQRT2_S = FOP(31, FMT_S),
7163 OPC_CVT_D_S = FOP(33, FMT_S),
7164 OPC_CVT_W_S = FOP(36, FMT_S),
7165 OPC_CVT_L_S = FOP(37, FMT_S),
7166 OPC_CVT_PS_S = FOP(38, FMT_S),
7167 OPC_CMP_F_S = FOP (48, FMT_S),
7168 OPC_CMP_UN_S = FOP (49, FMT_S),
7169 OPC_CMP_EQ_S = FOP (50, FMT_S),
7170 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7171 OPC_CMP_OLT_S = FOP (52, FMT_S),
7172 OPC_CMP_ULT_S = FOP (53, FMT_S),
7173 OPC_CMP_OLE_S = FOP (54, FMT_S),
7174 OPC_CMP_ULE_S = FOP (55, FMT_S),
7175 OPC_CMP_SF_S = FOP (56, FMT_S),
7176 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7177 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7178 OPC_CMP_NGL_S = FOP (59, FMT_S),
7179 OPC_CMP_LT_S = FOP (60, FMT_S),
7180 OPC_CMP_NGE_S = FOP (61, FMT_S),
7181 OPC_CMP_LE_S = FOP (62, FMT_S),
7182 OPC_CMP_NGT_S = FOP (63, FMT_S),
7184 OPC_ADD_D = FOP(0, FMT_D),
7185 OPC_SUB_D = FOP(1, FMT_D),
7186 OPC_MUL_D = FOP(2, FMT_D),
7187 OPC_DIV_D = FOP(3, FMT_D),
7188 OPC_SQRT_D = FOP(4, FMT_D),
7189 OPC_ABS_D = FOP(5, FMT_D),
7190 OPC_MOV_D = FOP(6, FMT_D),
7191 OPC_NEG_D = FOP(7, FMT_D),
7192 OPC_ROUND_L_D = FOP(8, FMT_D),
7193 OPC_TRUNC_L_D = FOP(9, FMT_D),
7194 OPC_CEIL_L_D = FOP(10, FMT_D),
7195 OPC_FLOOR_L_D = FOP(11, FMT_D),
7196 OPC_ROUND_W_D = FOP(12, FMT_D),
7197 OPC_TRUNC_W_D = FOP(13, FMT_D),
7198 OPC_CEIL_W_D = FOP(14, FMT_D),
7199 OPC_FLOOR_W_D = FOP(15, FMT_D),
7200 OPC_MOVCF_D = FOP(17, FMT_D),
7201 OPC_MOVZ_D = FOP(18, FMT_D),
7202 OPC_MOVN_D = FOP(19, FMT_D),
7203 OPC_RECIP_D = FOP(21, FMT_D),
7204 OPC_RSQRT_D = FOP(22, FMT_D),
7205 OPC_RECIP2_D = FOP(28, FMT_D),
7206 OPC_RECIP1_D = FOP(29, FMT_D),
7207 OPC_RSQRT1_D = FOP(30, FMT_D),
7208 OPC_RSQRT2_D = FOP(31, FMT_D),
7209 OPC_CVT_S_D = FOP(32, FMT_D),
7210 OPC_CVT_W_D = FOP(36, FMT_D),
7211 OPC_CVT_L_D = FOP(37, FMT_D),
7212 OPC_CMP_F_D = FOP (48, FMT_D),
7213 OPC_CMP_UN_D = FOP (49, FMT_D),
7214 OPC_CMP_EQ_D = FOP (50, FMT_D),
7215 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7216 OPC_CMP_OLT_D = FOP (52, FMT_D),
7217 OPC_CMP_ULT_D = FOP (53, FMT_D),
7218 OPC_CMP_OLE_D = FOP (54, FMT_D),
7219 OPC_CMP_ULE_D = FOP (55, FMT_D),
7220 OPC_CMP_SF_D = FOP (56, FMT_D),
7221 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7222 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7223 OPC_CMP_NGL_D = FOP (59, FMT_D),
7224 OPC_CMP_LT_D = FOP (60, FMT_D),
7225 OPC_CMP_NGE_D = FOP (61, FMT_D),
7226 OPC_CMP_LE_D = FOP (62, FMT_D),
7227 OPC_CMP_NGT_D = FOP (63, FMT_D),
7229 OPC_CVT_S_W = FOP(32, FMT_W),
7230 OPC_CVT_D_W = FOP(33, FMT_W),
7231 OPC_CVT_S_L = FOP(32, FMT_L),
7232 OPC_CVT_D_L = FOP(33, FMT_L),
7233 OPC_CVT_PS_PW = FOP(38, FMT_W),
7235 OPC_ADD_PS = FOP(0, FMT_PS),
7236 OPC_SUB_PS = FOP(1, FMT_PS),
7237 OPC_MUL_PS = FOP(2, FMT_PS),
7238 OPC_DIV_PS = FOP(3, FMT_PS),
7239 OPC_ABS_PS = FOP(5, FMT_PS),
7240 OPC_MOV_PS = FOP(6, FMT_PS),
7241 OPC_NEG_PS = FOP(7, FMT_PS),
7242 OPC_MOVCF_PS = FOP(17, FMT_PS),
7243 OPC_MOVZ_PS = FOP(18, FMT_PS),
7244 OPC_MOVN_PS = FOP(19, FMT_PS),
7245 OPC_ADDR_PS = FOP(24, FMT_PS),
7246 OPC_MULR_PS = FOP(26, FMT_PS),
7247 OPC_RECIP2_PS = FOP(28, FMT_PS),
7248 OPC_RECIP1_PS = FOP(29, FMT_PS),
7249 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7250 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7252 OPC_CVT_S_PU = FOP(32, FMT_PS),
7253 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7254 OPC_CVT_S_PL = FOP(40, FMT_PS),
7255 OPC_PLL_PS = FOP(44, FMT_PS),
7256 OPC_PLU_PS = FOP(45, FMT_PS),
7257 OPC_PUL_PS = FOP(46, FMT_PS),
7258 OPC_PUU_PS = FOP(47, FMT_PS),
7259 OPC_CMP_F_PS = FOP (48, FMT_PS),
7260 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7261 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7262 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7263 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7264 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7265 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7266 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7267 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7268 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7269 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7270 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7271 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7272 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7273 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7274 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7277 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
7279 const char *opn = "cp1 move";
7280 TCGv t0 = tcg_temp_new();
7282 switch (opc) {
7283 case OPC_MFC1:
7285 TCGv_i32 fp0 = tcg_temp_new_i32();
7287 gen_load_fpr32(fp0, fs);
7288 tcg_gen_ext_i32_tl(t0, fp0);
7289 tcg_temp_free_i32(fp0);
7291 gen_store_gpr(t0, rt);
7292 opn = "mfc1";
7293 break;
7294 case OPC_MTC1:
7295 gen_load_gpr(t0, rt);
7297 TCGv_i32 fp0 = tcg_temp_new_i32();
7299 tcg_gen_trunc_tl_i32(fp0, t0);
7300 gen_store_fpr32(fp0, fs);
7301 tcg_temp_free_i32(fp0);
7303 opn = "mtc1";
7304 break;
7305 case OPC_CFC1:
7306 gen_helper_1e0i(cfc1, t0, fs);
7307 gen_store_gpr(t0, rt);
7308 opn = "cfc1";
7309 break;
7310 case OPC_CTC1:
7311 gen_load_gpr(t0, rt);
7313 TCGv_i32 fs_tmp = tcg_const_i32(fs);
7315 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7316 tcg_temp_free_i32(fs_tmp);
7318 opn = "ctc1";
7319 break;
7320 #if defined(TARGET_MIPS64)
7321 case OPC_DMFC1:
7322 gen_load_fpr64(ctx, t0, fs);
7323 gen_store_gpr(t0, rt);
7324 opn = "dmfc1";
7325 break;
7326 case OPC_DMTC1:
7327 gen_load_gpr(t0, rt);
7328 gen_store_fpr64(ctx, t0, fs);
7329 opn = "dmtc1";
7330 break;
7331 #endif
7332 case OPC_MFHC1:
7334 TCGv_i32 fp0 = tcg_temp_new_i32();
7336 gen_load_fpr32h(ctx, fp0, fs);
7337 tcg_gen_ext_i32_tl(t0, fp0);
7338 tcg_temp_free_i32(fp0);
7340 gen_store_gpr(t0, rt);
7341 opn = "mfhc1";
7342 break;
7343 case OPC_MTHC1:
7344 gen_load_gpr(t0, rt);
7346 TCGv_i32 fp0 = tcg_temp_new_i32();
7348 tcg_gen_trunc_tl_i32(fp0, t0);
7349 gen_store_fpr32h(ctx, fp0, fs);
7350 tcg_temp_free_i32(fp0);
7352 opn = "mthc1";
7353 break;
7354 default:
7355 MIPS_INVAL(opn);
7356 generate_exception (ctx, EXCP_RI);
7357 goto out;
7359 (void)opn; /* avoid a compiler warning */
7360 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
7362 out:
7363 tcg_temp_free(t0);
7366 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
7368 int l1;
7369 TCGCond cond;
7370 TCGv_i32 t0;
7372 if (rd == 0) {
7373 /* Treat as NOP. */
7374 return;
7377 if (tf)
7378 cond = TCG_COND_EQ;
7379 else
7380 cond = TCG_COND_NE;
7382 l1 = gen_new_label();
7383 t0 = tcg_temp_new_i32();
7384 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7385 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7386 tcg_temp_free_i32(t0);
7387 if (rs == 0) {
7388 tcg_gen_movi_tl(cpu_gpr[rd], 0);
7389 } else {
7390 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
7392 gen_set_label(l1);
7395 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
7397 int cond;
7398 TCGv_i32 t0 = tcg_temp_new_i32();
7399 int l1 = gen_new_label();
7401 if (tf)
7402 cond = TCG_COND_EQ;
7403 else
7404 cond = TCG_COND_NE;
7406 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7407 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7408 gen_load_fpr32(t0, fs);
7409 gen_store_fpr32(t0, fd);
7410 gen_set_label(l1);
7411 tcg_temp_free_i32(t0);
7414 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
7416 int cond;
7417 TCGv_i32 t0 = tcg_temp_new_i32();
7418 TCGv_i64 fp0;
7419 int l1 = gen_new_label();
7421 if (tf)
7422 cond = TCG_COND_EQ;
7423 else
7424 cond = TCG_COND_NE;
7426 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7427 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7428 tcg_temp_free_i32(t0);
7429 fp0 = tcg_temp_new_i64();
7430 gen_load_fpr64(ctx, fp0, fs);
7431 gen_store_fpr64(ctx, fp0, fd);
7432 tcg_temp_free_i64(fp0);
7433 gen_set_label(l1);
7436 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
7437 int cc, int tf)
7439 int cond;
7440 TCGv_i32 t0 = tcg_temp_new_i32();
7441 int l1 = gen_new_label();
7442 int l2 = gen_new_label();
7444 if (tf)
7445 cond = TCG_COND_EQ;
7446 else
7447 cond = TCG_COND_NE;
7449 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7450 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7451 gen_load_fpr32(t0, fs);
7452 gen_store_fpr32(t0, fd);
7453 gen_set_label(l1);
7455 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
7456 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7457 gen_load_fpr32h(ctx, t0, fs);
7458 gen_store_fpr32h(ctx, t0, fd);
7459 tcg_temp_free_i32(t0);
7460 gen_set_label(l2);
7464 static void gen_farith (DisasContext *ctx, enum fopcode op1,
7465 int ft, int fs, int fd, int cc)
7467 const char *opn = "farith";
7468 const char *condnames[] = {
7469 "c.f",
7470 "c.un",
7471 "c.eq",
7472 "c.ueq",
7473 "c.olt",
7474 "c.ult",
7475 "c.ole",
7476 "c.ule",
7477 "c.sf",
7478 "c.ngle",
7479 "c.seq",
7480 "c.ngl",
7481 "c.lt",
7482 "c.nge",
7483 "c.le",
7484 "c.ngt",
7486 const char *condnames_abs[] = {
7487 "cabs.f",
7488 "cabs.un",
7489 "cabs.eq",
7490 "cabs.ueq",
7491 "cabs.olt",
7492 "cabs.ult",
7493 "cabs.ole",
7494 "cabs.ule",
7495 "cabs.sf",
7496 "cabs.ngle",
7497 "cabs.seq",
7498 "cabs.ngl",
7499 "cabs.lt",
7500 "cabs.nge",
7501 "cabs.le",
7502 "cabs.ngt",
7504 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7505 uint32_t func = ctx->opcode & 0x3f;
7507 switch (op1) {
7508 case OPC_ADD_S:
7510 TCGv_i32 fp0 = tcg_temp_new_i32();
7511 TCGv_i32 fp1 = tcg_temp_new_i32();
7513 gen_load_fpr32(fp0, fs);
7514 gen_load_fpr32(fp1, ft);
7515 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
7516 tcg_temp_free_i32(fp1);
7517 gen_store_fpr32(fp0, fd);
7518 tcg_temp_free_i32(fp0);
7520 opn = "add.s";
7521 optype = BINOP;
7522 break;
7523 case OPC_SUB_S:
7525 TCGv_i32 fp0 = tcg_temp_new_i32();
7526 TCGv_i32 fp1 = tcg_temp_new_i32();
7528 gen_load_fpr32(fp0, fs);
7529 gen_load_fpr32(fp1, ft);
7530 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
7531 tcg_temp_free_i32(fp1);
7532 gen_store_fpr32(fp0, fd);
7533 tcg_temp_free_i32(fp0);
7535 opn = "sub.s";
7536 optype = BINOP;
7537 break;
7538 case OPC_MUL_S:
7540 TCGv_i32 fp0 = tcg_temp_new_i32();
7541 TCGv_i32 fp1 = tcg_temp_new_i32();
7543 gen_load_fpr32(fp0, fs);
7544 gen_load_fpr32(fp1, ft);
7545 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
7546 tcg_temp_free_i32(fp1);
7547 gen_store_fpr32(fp0, fd);
7548 tcg_temp_free_i32(fp0);
7550 opn = "mul.s";
7551 optype = BINOP;
7552 break;
7553 case OPC_DIV_S:
7555 TCGv_i32 fp0 = tcg_temp_new_i32();
7556 TCGv_i32 fp1 = tcg_temp_new_i32();
7558 gen_load_fpr32(fp0, fs);
7559 gen_load_fpr32(fp1, ft);
7560 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
7561 tcg_temp_free_i32(fp1);
7562 gen_store_fpr32(fp0, fd);
7563 tcg_temp_free_i32(fp0);
7565 opn = "div.s";
7566 optype = BINOP;
7567 break;
7568 case OPC_SQRT_S:
7570 TCGv_i32 fp0 = tcg_temp_new_i32();
7572 gen_load_fpr32(fp0, fs);
7573 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7574 gen_store_fpr32(fp0, fd);
7575 tcg_temp_free_i32(fp0);
7577 opn = "sqrt.s";
7578 break;
7579 case OPC_ABS_S:
7581 TCGv_i32 fp0 = tcg_temp_new_i32();
7583 gen_load_fpr32(fp0, fs);
7584 gen_helper_float_abs_s(fp0, fp0);
7585 gen_store_fpr32(fp0, fd);
7586 tcg_temp_free_i32(fp0);
7588 opn = "abs.s";
7589 break;
7590 case OPC_MOV_S:
7592 TCGv_i32 fp0 = tcg_temp_new_i32();
7594 gen_load_fpr32(fp0, fs);
7595 gen_store_fpr32(fp0, fd);
7596 tcg_temp_free_i32(fp0);
7598 opn = "mov.s";
7599 break;
7600 case OPC_NEG_S:
7602 TCGv_i32 fp0 = tcg_temp_new_i32();
7604 gen_load_fpr32(fp0, fs);
7605 gen_helper_float_chs_s(fp0, fp0);
7606 gen_store_fpr32(fp0, fd);
7607 tcg_temp_free_i32(fp0);
7609 opn = "neg.s";
7610 break;
7611 case OPC_ROUND_L_S:
7612 check_cp1_64bitmode(ctx);
7614 TCGv_i32 fp32 = tcg_temp_new_i32();
7615 TCGv_i64 fp64 = tcg_temp_new_i64();
7617 gen_load_fpr32(fp32, fs);
7618 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
7619 tcg_temp_free_i32(fp32);
7620 gen_store_fpr64(ctx, fp64, fd);
7621 tcg_temp_free_i64(fp64);
7623 opn = "round.l.s";
7624 break;
7625 case OPC_TRUNC_L_S:
7626 check_cp1_64bitmode(ctx);
7628 TCGv_i32 fp32 = tcg_temp_new_i32();
7629 TCGv_i64 fp64 = tcg_temp_new_i64();
7631 gen_load_fpr32(fp32, fs);
7632 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
7633 tcg_temp_free_i32(fp32);
7634 gen_store_fpr64(ctx, fp64, fd);
7635 tcg_temp_free_i64(fp64);
7637 opn = "trunc.l.s";
7638 break;
7639 case OPC_CEIL_L_S:
7640 check_cp1_64bitmode(ctx);
7642 TCGv_i32 fp32 = tcg_temp_new_i32();
7643 TCGv_i64 fp64 = tcg_temp_new_i64();
7645 gen_load_fpr32(fp32, fs);
7646 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
7647 tcg_temp_free_i32(fp32);
7648 gen_store_fpr64(ctx, fp64, fd);
7649 tcg_temp_free_i64(fp64);
7651 opn = "ceil.l.s";
7652 break;
7653 case OPC_FLOOR_L_S:
7654 check_cp1_64bitmode(ctx);
7656 TCGv_i32 fp32 = tcg_temp_new_i32();
7657 TCGv_i64 fp64 = tcg_temp_new_i64();
7659 gen_load_fpr32(fp32, fs);
7660 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
7661 tcg_temp_free_i32(fp32);
7662 gen_store_fpr64(ctx, fp64, fd);
7663 tcg_temp_free_i64(fp64);
7665 opn = "floor.l.s";
7666 break;
7667 case OPC_ROUND_W_S:
7669 TCGv_i32 fp0 = tcg_temp_new_i32();
7671 gen_load_fpr32(fp0, fs);
7672 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
7673 gen_store_fpr32(fp0, fd);
7674 tcg_temp_free_i32(fp0);
7676 opn = "round.w.s";
7677 break;
7678 case OPC_TRUNC_W_S:
7680 TCGv_i32 fp0 = tcg_temp_new_i32();
7682 gen_load_fpr32(fp0, fs);
7683 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
7684 gen_store_fpr32(fp0, fd);
7685 tcg_temp_free_i32(fp0);
7687 opn = "trunc.w.s";
7688 break;
7689 case OPC_CEIL_W_S:
7691 TCGv_i32 fp0 = tcg_temp_new_i32();
7693 gen_load_fpr32(fp0, fs);
7694 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
7695 gen_store_fpr32(fp0, fd);
7696 tcg_temp_free_i32(fp0);
7698 opn = "ceil.w.s";
7699 break;
7700 case OPC_FLOOR_W_S:
7702 TCGv_i32 fp0 = tcg_temp_new_i32();
7704 gen_load_fpr32(fp0, fs);
7705 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
7706 gen_store_fpr32(fp0, fd);
7707 tcg_temp_free_i32(fp0);
7709 opn = "floor.w.s";
7710 break;
7711 case OPC_MOVCF_S:
7712 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7713 opn = "movcf.s";
7714 break;
7715 case OPC_MOVZ_S:
7717 int l1 = gen_new_label();
7718 TCGv_i32 fp0;
7720 if (ft != 0) {
7721 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7723 fp0 = tcg_temp_new_i32();
7724 gen_load_fpr32(fp0, fs);
7725 gen_store_fpr32(fp0, fd);
7726 tcg_temp_free_i32(fp0);
7727 gen_set_label(l1);
7729 opn = "movz.s";
7730 break;
7731 case OPC_MOVN_S:
7733 int l1 = gen_new_label();
7734 TCGv_i32 fp0;
7736 if (ft != 0) {
7737 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7738 fp0 = tcg_temp_new_i32();
7739 gen_load_fpr32(fp0, fs);
7740 gen_store_fpr32(fp0, fd);
7741 tcg_temp_free_i32(fp0);
7742 gen_set_label(l1);
7745 opn = "movn.s";
7746 break;
7747 case OPC_RECIP_S:
7748 check_cop1x(ctx);
7750 TCGv_i32 fp0 = tcg_temp_new_i32();
7752 gen_load_fpr32(fp0, fs);
7753 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7754 gen_store_fpr32(fp0, fd);
7755 tcg_temp_free_i32(fp0);
7757 opn = "recip.s";
7758 break;
7759 case OPC_RSQRT_S:
7760 check_cop1x(ctx);
7762 TCGv_i32 fp0 = tcg_temp_new_i32();
7764 gen_load_fpr32(fp0, fs);
7765 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7766 gen_store_fpr32(fp0, fd);
7767 tcg_temp_free_i32(fp0);
7769 opn = "rsqrt.s";
7770 break;
7771 case OPC_RECIP2_S:
7772 check_cp1_64bitmode(ctx);
7774 TCGv_i32 fp0 = tcg_temp_new_i32();
7775 TCGv_i32 fp1 = tcg_temp_new_i32();
7777 gen_load_fpr32(fp0, fs);
7778 gen_load_fpr32(fp1, ft);
7779 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
7780 tcg_temp_free_i32(fp1);
7781 gen_store_fpr32(fp0, fd);
7782 tcg_temp_free_i32(fp0);
7784 opn = "recip2.s";
7785 break;
7786 case OPC_RECIP1_S:
7787 check_cp1_64bitmode(ctx);
7789 TCGv_i32 fp0 = tcg_temp_new_i32();
7791 gen_load_fpr32(fp0, fs);
7792 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7793 gen_store_fpr32(fp0, fd);
7794 tcg_temp_free_i32(fp0);
7796 opn = "recip1.s";
7797 break;
7798 case OPC_RSQRT1_S:
7799 check_cp1_64bitmode(ctx);
7801 TCGv_i32 fp0 = tcg_temp_new_i32();
7803 gen_load_fpr32(fp0, fs);
7804 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7805 gen_store_fpr32(fp0, fd);
7806 tcg_temp_free_i32(fp0);
7808 opn = "rsqrt1.s";
7809 break;
7810 case OPC_RSQRT2_S:
7811 check_cp1_64bitmode(ctx);
7813 TCGv_i32 fp0 = tcg_temp_new_i32();
7814 TCGv_i32 fp1 = tcg_temp_new_i32();
7816 gen_load_fpr32(fp0, fs);
7817 gen_load_fpr32(fp1, ft);
7818 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
7819 tcg_temp_free_i32(fp1);
7820 gen_store_fpr32(fp0, fd);
7821 tcg_temp_free_i32(fp0);
7823 opn = "rsqrt2.s";
7824 break;
7825 case OPC_CVT_D_S:
7826 check_cp1_registers(ctx, fd);
7828 TCGv_i32 fp32 = tcg_temp_new_i32();
7829 TCGv_i64 fp64 = tcg_temp_new_i64();
7831 gen_load_fpr32(fp32, fs);
7832 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
7833 tcg_temp_free_i32(fp32);
7834 gen_store_fpr64(ctx, fp64, fd);
7835 tcg_temp_free_i64(fp64);
7837 opn = "cvt.d.s";
7838 break;
7839 case OPC_CVT_W_S:
7841 TCGv_i32 fp0 = tcg_temp_new_i32();
7843 gen_load_fpr32(fp0, fs);
7844 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
7845 gen_store_fpr32(fp0, fd);
7846 tcg_temp_free_i32(fp0);
7848 opn = "cvt.w.s";
7849 break;
7850 case OPC_CVT_L_S:
7851 check_cp1_64bitmode(ctx);
7853 TCGv_i32 fp32 = tcg_temp_new_i32();
7854 TCGv_i64 fp64 = tcg_temp_new_i64();
7856 gen_load_fpr32(fp32, fs);
7857 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
7858 tcg_temp_free_i32(fp32);
7859 gen_store_fpr64(ctx, fp64, fd);
7860 tcg_temp_free_i64(fp64);
7862 opn = "cvt.l.s";
7863 break;
7864 case OPC_CVT_PS_S:
7865 check_cp1_64bitmode(ctx);
7867 TCGv_i64 fp64 = tcg_temp_new_i64();
7868 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7869 TCGv_i32 fp32_1 = tcg_temp_new_i32();
7871 gen_load_fpr32(fp32_0, fs);
7872 gen_load_fpr32(fp32_1, ft);
7873 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
7874 tcg_temp_free_i32(fp32_1);
7875 tcg_temp_free_i32(fp32_0);
7876 gen_store_fpr64(ctx, fp64, fd);
7877 tcg_temp_free_i64(fp64);
7879 opn = "cvt.ps.s";
7880 break;
7881 case OPC_CMP_F_S:
7882 case OPC_CMP_UN_S:
7883 case OPC_CMP_EQ_S:
7884 case OPC_CMP_UEQ_S:
7885 case OPC_CMP_OLT_S:
7886 case OPC_CMP_ULT_S:
7887 case OPC_CMP_OLE_S:
7888 case OPC_CMP_ULE_S:
7889 case OPC_CMP_SF_S:
7890 case OPC_CMP_NGLE_S:
7891 case OPC_CMP_SEQ_S:
7892 case OPC_CMP_NGL_S:
7893 case OPC_CMP_LT_S:
7894 case OPC_CMP_NGE_S:
7895 case OPC_CMP_LE_S:
7896 case OPC_CMP_NGT_S:
7897 if (ctx->opcode & (1 << 6)) {
7898 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7899 opn = condnames_abs[func-48];
7900 } else {
7901 gen_cmp_s(ctx, func-48, ft, fs, cc);
7902 opn = condnames[func-48];
7904 break;
7905 case OPC_ADD_D:
7906 check_cp1_registers(ctx, fs | ft | fd);
7908 TCGv_i64 fp0 = tcg_temp_new_i64();
7909 TCGv_i64 fp1 = tcg_temp_new_i64();
7911 gen_load_fpr64(ctx, fp0, fs);
7912 gen_load_fpr64(ctx, fp1, ft);
7913 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
7914 tcg_temp_free_i64(fp1);
7915 gen_store_fpr64(ctx, fp0, fd);
7916 tcg_temp_free_i64(fp0);
7918 opn = "add.d";
7919 optype = BINOP;
7920 break;
7921 case OPC_SUB_D:
7922 check_cp1_registers(ctx, fs | ft | fd);
7924 TCGv_i64 fp0 = tcg_temp_new_i64();
7925 TCGv_i64 fp1 = tcg_temp_new_i64();
7927 gen_load_fpr64(ctx, fp0, fs);
7928 gen_load_fpr64(ctx, fp1, ft);
7929 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
7930 tcg_temp_free_i64(fp1);
7931 gen_store_fpr64(ctx, fp0, fd);
7932 tcg_temp_free_i64(fp0);
7934 opn = "sub.d";
7935 optype = BINOP;
7936 break;
7937 case OPC_MUL_D:
7938 check_cp1_registers(ctx, fs | ft | fd);
7940 TCGv_i64 fp0 = tcg_temp_new_i64();
7941 TCGv_i64 fp1 = tcg_temp_new_i64();
7943 gen_load_fpr64(ctx, fp0, fs);
7944 gen_load_fpr64(ctx, fp1, ft);
7945 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
7946 tcg_temp_free_i64(fp1);
7947 gen_store_fpr64(ctx, fp0, fd);
7948 tcg_temp_free_i64(fp0);
7950 opn = "mul.d";
7951 optype = BINOP;
7952 break;
7953 case OPC_DIV_D:
7954 check_cp1_registers(ctx, fs | ft | fd);
7956 TCGv_i64 fp0 = tcg_temp_new_i64();
7957 TCGv_i64 fp1 = tcg_temp_new_i64();
7959 gen_load_fpr64(ctx, fp0, fs);
7960 gen_load_fpr64(ctx, fp1, ft);
7961 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
7962 tcg_temp_free_i64(fp1);
7963 gen_store_fpr64(ctx, fp0, fd);
7964 tcg_temp_free_i64(fp0);
7966 opn = "div.d";
7967 optype = BINOP;
7968 break;
7969 case OPC_SQRT_D:
7970 check_cp1_registers(ctx, fs | fd);
7972 TCGv_i64 fp0 = tcg_temp_new_i64();
7974 gen_load_fpr64(ctx, fp0, fs);
7975 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
7976 gen_store_fpr64(ctx, fp0, fd);
7977 tcg_temp_free_i64(fp0);
7979 opn = "sqrt.d";
7980 break;
7981 case OPC_ABS_D:
7982 check_cp1_registers(ctx, fs | fd);
7984 TCGv_i64 fp0 = tcg_temp_new_i64();
7986 gen_load_fpr64(ctx, fp0, fs);
7987 gen_helper_float_abs_d(fp0, fp0);
7988 gen_store_fpr64(ctx, fp0, fd);
7989 tcg_temp_free_i64(fp0);
7991 opn = "abs.d";
7992 break;
7993 case OPC_MOV_D:
7994 check_cp1_registers(ctx, fs | fd);
7996 TCGv_i64 fp0 = tcg_temp_new_i64();
7998 gen_load_fpr64(ctx, fp0, fs);
7999 gen_store_fpr64(ctx, fp0, fd);
8000 tcg_temp_free_i64(fp0);
8002 opn = "mov.d";
8003 break;
8004 case OPC_NEG_D:
8005 check_cp1_registers(ctx, fs | fd);
8007 TCGv_i64 fp0 = tcg_temp_new_i64();
8009 gen_load_fpr64(ctx, fp0, fs);
8010 gen_helper_float_chs_d(fp0, fp0);
8011 gen_store_fpr64(ctx, fp0, fd);
8012 tcg_temp_free_i64(fp0);
8014 opn = "neg.d";
8015 break;
8016 case OPC_ROUND_L_D:
8017 check_cp1_64bitmode(ctx);
8019 TCGv_i64 fp0 = tcg_temp_new_i64();
8021 gen_load_fpr64(ctx, fp0, fs);
8022 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
8023 gen_store_fpr64(ctx, fp0, fd);
8024 tcg_temp_free_i64(fp0);
8026 opn = "round.l.d";
8027 break;
8028 case OPC_TRUNC_L_D:
8029 check_cp1_64bitmode(ctx);
8031 TCGv_i64 fp0 = tcg_temp_new_i64();
8033 gen_load_fpr64(ctx, fp0, fs);
8034 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
8035 gen_store_fpr64(ctx, fp0, fd);
8036 tcg_temp_free_i64(fp0);
8038 opn = "trunc.l.d";
8039 break;
8040 case OPC_CEIL_L_D:
8041 check_cp1_64bitmode(ctx);
8043 TCGv_i64 fp0 = tcg_temp_new_i64();
8045 gen_load_fpr64(ctx, fp0, fs);
8046 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
8047 gen_store_fpr64(ctx, fp0, fd);
8048 tcg_temp_free_i64(fp0);
8050 opn = "ceil.l.d";
8051 break;
8052 case OPC_FLOOR_L_D:
8053 check_cp1_64bitmode(ctx);
8055 TCGv_i64 fp0 = tcg_temp_new_i64();
8057 gen_load_fpr64(ctx, fp0, fs);
8058 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
8059 gen_store_fpr64(ctx, fp0, fd);
8060 tcg_temp_free_i64(fp0);
8062 opn = "floor.l.d";
8063 break;
8064 case OPC_ROUND_W_D:
8065 check_cp1_registers(ctx, fs);
8067 TCGv_i32 fp32 = tcg_temp_new_i32();
8068 TCGv_i64 fp64 = tcg_temp_new_i64();
8070 gen_load_fpr64(ctx, fp64, fs);
8071 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
8072 tcg_temp_free_i64(fp64);
8073 gen_store_fpr32(fp32, fd);
8074 tcg_temp_free_i32(fp32);
8076 opn = "round.w.d";
8077 break;
8078 case OPC_TRUNC_W_D:
8079 check_cp1_registers(ctx, fs);
8081 TCGv_i32 fp32 = tcg_temp_new_i32();
8082 TCGv_i64 fp64 = tcg_temp_new_i64();
8084 gen_load_fpr64(ctx, fp64, fs);
8085 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
8086 tcg_temp_free_i64(fp64);
8087 gen_store_fpr32(fp32, fd);
8088 tcg_temp_free_i32(fp32);
8090 opn = "trunc.w.d";
8091 break;
8092 case OPC_CEIL_W_D:
8093 check_cp1_registers(ctx, fs);
8095 TCGv_i32 fp32 = tcg_temp_new_i32();
8096 TCGv_i64 fp64 = tcg_temp_new_i64();
8098 gen_load_fpr64(ctx, fp64, fs);
8099 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
8100 tcg_temp_free_i64(fp64);
8101 gen_store_fpr32(fp32, fd);
8102 tcg_temp_free_i32(fp32);
8104 opn = "ceil.w.d";
8105 break;
8106 case OPC_FLOOR_W_D:
8107 check_cp1_registers(ctx, fs);
8109 TCGv_i32 fp32 = tcg_temp_new_i32();
8110 TCGv_i64 fp64 = tcg_temp_new_i64();
8112 gen_load_fpr64(ctx, fp64, fs);
8113 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
8114 tcg_temp_free_i64(fp64);
8115 gen_store_fpr32(fp32, fd);
8116 tcg_temp_free_i32(fp32);
8118 opn = "floor.w.d";
8119 break;
8120 case OPC_MOVCF_D:
8121 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8122 opn = "movcf.d";
8123 break;
8124 case OPC_MOVZ_D:
8126 int l1 = gen_new_label();
8127 TCGv_i64 fp0;
8129 if (ft != 0) {
8130 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8132 fp0 = tcg_temp_new_i64();
8133 gen_load_fpr64(ctx, fp0, fs);
8134 gen_store_fpr64(ctx, fp0, fd);
8135 tcg_temp_free_i64(fp0);
8136 gen_set_label(l1);
8138 opn = "movz.d";
8139 break;
8140 case OPC_MOVN_D:
8142 int l1 = gen_new_label();
8143 TCGv_i64 fp0;
8145 if (ft != 0) {
8146 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8147 fp0 = tcg_temp_new_i64();
8148 gen_load_fpr64(ctx, fp0, fs);
8149 gen_store_fpr64(ctx, fp0, fd);
8150 tcg_temp_free_i64(fp0);
8151 gen_set_label(l1);
8154 opn = "movn.d";
8155 break;
8156 case OPC_RECIP_D:
8157 check_cp1_64bitmode(ctx);
8159 TCGv_i64 fp0 = tcg_temp_new_i64();
8161 gen_load_fpr64(ctx, fp0, fs);
8162 gen_helper_float_recip_d(fp0, cpu_env, fp0);
8163 gen_store_fpr64(ctx, fp0, fd);
8164 tcg_temp_free_i64(fp0);
8166 opn = "recip.d";
8167 break;
8168 case OPC_RSQRT_D:
8169 check_cp1_64bitmode(ctx);
8171 TCGv_i64 fp0 = tcg_temp_new_i64();
8173 gen_load_fpr64(ctx, fp0, fs);
8174 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
8175 gen_store_fpr64(ctx, fp0, fd);
8176 tcg_temp_free_i64(fp0);
8178 opn = "rsqrt.d";
8179 break;
8180 case OPC_RECIP2_D:
8181 check_cp1_64bitmode(ctx);
8183 TCGv_i64 fp0 = tcg_temp_new_i64();
8184 TCGv_i64 fp1 = tcg_temp_new_i64();
8186 gen_load_fpr64(ctx, fp0, fs);
8187 gen_load_fpr64(ctx, fp1, ft);
8188 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
8189 tcg_temp_free_i64(fp1);
8190 gen_store_fpr64(ctx, fp0, fd);
8191 tcg_temp_free_i64(fp0);
8193 opn = "recip2.d";
8194 break;
8195 case OPC_RECIP1_D:
8196 check_cp1_64bitmode(ctx);
8198 TCGv_i64 fp0 = tcg_temp_new_i64();
8200 gen_load_fpr64(ctx, fp0, fs);
8201 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
8202 gen_store_fpr64(ctx, fp0, fd);
8203 tcg_temp_free_i64(fp0);
8205 opn = "recip1.d";
8206 break;
8207 case OPC_RSQRT1_D:
8208 check_cp1_64bitmode(ctx);
8210 TCGv_i64 fp0 = tcg_temp_new_i64();
8212 gen_load_fpr64(ctx, fp0, fs);
8213 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
8214 gen_store_fpr64(ctx, fp0, fd);
8215 tcg_temp_free_i64(fp0);
8217 opn = "rsqrt1.d";
8218 break;
8219 case OPC_RSQRT2_D:
8220 check_cp1_64bitmode(ctx);
8222 TCGv_i64 fp0 = tcg_temp_new_i64();
8223 TCGv_i64 fp1 = tcg_temp_new_i64();
8225 gen_load_fpr64(ctx, fp0, fs);
8226 gen_load_fpr64(ctx, fp1, ft);
8227 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
8228 tcg_temp_free_i64(fp1);
8229 gen_store_fpr64(ctx, fp0, fd);
8230 tcg_temp_free_i64(fp0);
8232 opn = "rsqrt2.d";
8233 break;
8234 case OPC_CMP_F_D:
8235 case OPC_CMP_UN_D:
8236 case OPC_CMP_EQ_D:
8237 case OPC_CMP_UEQ_D:
8238 case OPC_CMP_OLT_D:
8239 case OPC_CMP_ULT_D:
8240 case OPC_CMP_OLE_D:
8241 case OPC_CMP_ULE_D:
8242 case OPC_CMP_SF_D:
8243 case OPC_CMP_NGLE_D:
8244 case OPC_CMP_SEQ_D:
8245 case OPC_CMP_NGL_D:
8246 case OPC_CMP_LT_D:
8247 case OPC_CMP_NGE_D:
8248 case OPC_CMP_LE_D:
8249 case OPC_CMP_NGT_D:
8250 if (ctx->opcode & (1 << 6)) {
8251 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8252 opn = condnames_abs[func-48];
8253 } else {
8254 gen_cmp_d(ctx, func-48, ft, fs, cc);
8255 opn = condnames[func-48];
8257 break;
8258 case OPC_CVT_S_D:
8259 check_cp1_registers(ctx, fs);
8261 TCGv_i32 fp32 = tcg_temp_new_i32();
8262 TCGv_i64 fp64 = tcg_temp_new_i64();
8264 gen_load_fpr64(ctx, fp64, fs);
8265 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
8266 tcg_temp_free_i64(fp64);
8267 gen_store_fpr32(fp32, fd);
8268 tcg_temp_free_i32(fp32);
8270 opn = "cvt.s.d";
8271 break;
8272 case OPC_CVT_W_D:
8273 check_cp1_registers(ctx, fs);
8275 TCGv_i32 fp32 = tcg_temp_new_i32();
8276 TCGv_i64 fp64 = tcg_temp_new_i64();
8278 gen_load_fpr64(ctx, fp64, fs);
8279 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
8280 tcg_temp_free_i64(fp64);
8281 gen_store_fpr32(fp32, fd);
8282 tcg_temp_free_i32(fp32);
8284 opn = "cvt.w.d";
8285 break;
8286 case OPC_CVT_L_D:
8287 check_cp1_64bitmode(ctx);
8289 TCGv_i64 fp0 = tcg_temp_new_i64();
8291 gen_load_fpr64(ctx, fp0, fs);
8292 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
8293 gen_store_fpr64(ctx, fp0, fd);
8294 tcg_temp_free_i64(fp0);
8296 opn = "cvt.l.d";
8297 break;
8298 case OPC_CVT_S_W:
8300 TCGv_i32 fp0 = tcg_temp_new_i32();
8302 gen_load_fpr32(fp0, fs);
8303 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
8304 gen_store_fpr32(fp0, fd);
8305 tcg_temp_free_i32(fp0);
8307 opn = "cvt.s.w";
8308 break;
8309 case OPC_CVT_D_W:
8310 check_cp1_registers(ctx, fd);
8312 TCGv_i32 fp32 = tcg_temp_new_i32();
8313 TCGv_i64 fp64 = tcg_temp_new_i64();
8315 gen_load_fpr32(fp32, fs);
8316 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
8317 tcg_temp_free_i32(fp32);
8318 gen_store_fpr64(ctx, fp64, fd);
8319 tcg_temp_free_i64(fp64);
8321 opn = "cvt.d.w";
8322 break;
8323 case OPC_CVT_S_L:
8324 check_cp1_64bitmode(ctx);
8326 TCGv_i32 fp32 = tcg_temp_new_i32();
8327 TCGv_i64 fp64 = tcg_temp_new_i64();
8329 gen_load_fpr64(ctx, fp64, fs);
8330 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
8331 tcg_temp_free_i64(fp64);
8332 gen_store_fpr32(fp32, fd);
8333 tcg_temp_free_i32(fp32);
8335 opn = "cvt.s.l";
8336 break;
8337 case OPC_CVT_D_L:
8338 check_cp1_64bitmode(ctx);
8340 TCGv_i64 fp0 = tcg_temp_new_i64();
8342 gen_load_fpr64(ctx, fp0, fs);
8343 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
8344 gen_store_fpr64(ctx, fp0, fd);
8345 tcg_temp_free_i64(fp0);
8347 opn = "cvt.d.l";
8348 break;
8349 case OPC_CVT_PS_PW:
8350 check_cp1_64bitmode(ctx);
8352 TCGv_i64 fp0 = tcg_temp_new_i64();
8354 gen_load_fpr64(ctx, fp0, fs);
8355 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
8356 gen_store_fpr64(ctx, fp0, fd);
8357 tcg_temp_free_i64(fp0);
8359 opn = "cvt.ps.pw";
8360 break;
8361 case OPC_ADD_PS:
8362 check_cp1_64bitmode(ctx);
8364 TCGv_i64 fp0 = tcg_temp_new_i64();
8365 TCGv_i64 fp1 = tcg_temp_new_i64();
8367 gen_load_fpr64(ctx, fp0, fs);
8368 gen_load_fpr64(ctx, fp1, ft);
8369 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
8370 tcg_temp_free_i64(fp1);
8371 gen_store_fpr64(ctx, fp0, fd);
8372 tcg_temp_free_i64(fp0);
8374 opn = "add.ps";
8375 break;
8376 case OPC_SUB_PS:
8377 check_cp1_64bitmode(ctx);
8379 TCGv_i64 fp0 = tcg_temp_new_i64();
8380 TCGv_i64 fp1 = tcg_temp_new_i64();
8382 gen_load_fpr64(ctx, fp0, fs);
8383 gen_load_fpr64(ctx, fp1, ft);
8384 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
8385 tcg_temp_free_i64(fp1);
8386 gen_store_fpr64(ctx, fp0, fd);
8387 tcg_temp_free_i64(fp0);
8389 opn = "sub.ps";
8390 break;
8391 case OPC_MUL_PS:
8392 check_cp1_64bitmode(ctx);
8394 TCGv_i64 fp0 = tcg_temp_new_i64();
8395 TCGv_i64 fp1 = tcg_temp_new_i64();
8397 gen_load_fpr64(ctx, fp0, fs);
8398 gen_load_fpr64(ctx, fp1, ft);
8399 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
8400 tcg_temp_free_i64(fp1);
8401 gen_store_fpr64(ctx, fp0, fd);
8402 tcg_temp_free_i64(fp0);
8404 opn = "mul.ps";
8405 break;
8406 case OPC_ABS_PS:
8407 check_cp1_64bitmode(ctx);
8409 TCGv_i64 fp0 = tcg_temp_new_i64();
8411 gen_load_fpr64(ctx, fp0, fs);
8412 gen_helper_float_abs_ps(fp0, fp0);
8413 gen_store_fpr64(ctx, fp0, fd);
8414 tcg_temp_free_i64(fp0);
8416 opn = "abs.ps";
8417 break;
8418 case OPC_MOV_PS:
8419 check_cp1_64bitmode(ctx);
8421 TCGv_i64 fp0 = tcg_temp_new_i64();
8423 gen_load_fpr64(ctx, fp0, fs);
8424 gen_store_fpr64(ctx, fp0, fd);
8425 tcg_temp_free_i64(fp0);
8427 opn = "mov.ps";
8428 break;
8429 case OPC_NEG_PS:
8430 check_cp1_64bitmode(ctx);
8432 TCGv_i64 fp0 = tcg_temp_new_i64();
8434 gen_load_fpr64(ctx, fp0, fs);
8435 gen_helper_float_chs_ps(fp0, fp0);
8436 gen_store_fpr64(ctx, fp0, fd);
8437 tcg_temp_free_i64(fp0);
8439 opn = "neg.ps";
8440 break;
8441 case OPC_MOVCF_PS:
8442 check_cp1_64bitmode(ctx);
8443 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8444 opn = "movcf.ps";
8445 break;
8446 case OPC_MOVZ_PS:
8447 check_cp1_64bitmode(ctx);
8449 int l1 = gen_new_label();
8450 TCGv_i64 fp0;
8452 if (ft != 0)
8453 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8454 fp0 = tcg_temp_new_i64();
8455 gen_load_fpr64(ctx, fp0, fs);
8456 gen_store_fpr64(ctx, fp0, fd);
8457 tcg_temp_free_i64(fp0);
8458 gen_set_label(l1);
8460 opn = "movz.ps";
8461 break;
8462 case OPC_MOVN_PS:
8463 check_cp1_64bitmode(ctx);
8465 int l1 = gen_new_label();
8466 TCGv_i64 fp0;
8468 if (ft != 0) {
8469 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8470 fp0 = tcg_temp_new_i64();
8471 gen_load_fpr64(ctx, fp0, fs);
8472 gen_store_fpr64(ctx, fp0, fd);
8473 tcg_temp_free_i64(fp0);
8474 gen_set_label(l1);
8477 opn = "movn.ps";
8478 break;
8479 case OPC_ADDR_PS:
8480 check_cp1_64bitmode(ctx);
8482 TCGv_i64 fp0 = tcg_temp_new_i64();
8483 TCGv_i64 fp1 = tcg_temp_new_i64();
8485 gen_load_fpr64(ctx, fp0, ft);
8486 gen_load_fpr64(ctx, fp1, fs);
8487 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
8488 tcg_temp_free_i64(fp1);
8489 gen_store_fpr64(ctx, fp0, fd);
8490 tcg_temp_free_i64(fp0);
8492 opn = "addr.ps";
8493 break;
8494 case OPC_MULR_PS:
8495 check_cp1_64bitmode(ctx);
8497 TCGv_i64 fp0 = tcg_temp_new_i64();
8498 TCGv_i64 fp1 = tcg_temp_new_i64();
8500 gen_load_fpr64(ctx, fp0, ft);
8501 gen_load_fpr64(ctx, fp1, fs);
8502 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
8503 tcg_temp_free_i64(fp1);
8504 gen_store_fpr64(ctx, fp0, fd);
8505 tcg_temp_free_i64(fp0);
8507 opn = "mulr.ps";
8508 break;
8509 case OPC_RECIP2_PS:
8510 check_cp1_64bitmode(ctx);
8512 TCGv_i64 fp0 = tcg_temp_new_i64();
8513 TCGv_i64 fp1 = tcg_temp_new_i64();
8515 gen_load_fpr64(ctx, fp0, fs);
8516 gen_load_fpr64(ctx, fp1, ft);
8517 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
8518 tcg_temp_free_i64(fp1);
8519 gen_store_fpr64(ctx, fp0, fd);
8520 tcg_temp_free_i64(fp0);
8522 opn = "recip2.ps";
8523 break;
8524 case OPC_RECIP1_PS:
8525 check_cp1_64bitmode(ctx);
8527 TCGv_i64 fp0 = tcg_temp_new_i64();
8529 gen_load_fpr64(ctx, fp0, fs);
8530 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
8531 gen_store_fpr64(ctx, fp0, fd);
8532 tcg_temp_free_i64(fp0);
8534 opn = "recip1.ps";
8535 break;
8536 case OPC_RSQRT1_PS:
8537 check_cp1_64bitmode(ctx);
8539 TCGv_i64 fp0 = tcg_temp_new_i64();
8541 gen_load_fpr64(ctx, fp0, fs);
8542 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
8543 gen_store_fpr64(ctx, fp0, fd);
8544 tcg_temp_free_i64(fp0);
8546 opn = "rsqrt1.ps";
8547 break;
8548 case OPC_RSQRT2_PS:
8549 check_cp1_64bitmode(ctx);
8551 TCGv_i64 fp0 = tcg_temp_new_i64();
8552 TCGv_i64 fp1 = tcg_temp_new_i64();
8554 gen_load_fpr64(ctx, fp0, fs);
8555 gen_load_fpr64(ctx, fp1, ft);
8556 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
8557 tcg_temp_free_i64(fp1);
8558 gen_store_fpr64(ctx, fp0, fd);
8559 tcg_temp_free_i64(fp0);
8561 opn = "rsqrt2.ps";
8562 break;
8563 case OPC_CVT_S_PU:
8564 check_cp1_64bitmode(ctx);
8566 TCGv_i32 fp0 = tcg_temp_new_i32();
8568 gen_load_fpr32h(ctx, fp0, fs);
8569 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
8570 gen_store_fpr32(fp0, fd);
8571 tcg_temp_free_i32(fp0);
8573 opn = "cvt.s.pu";
8574 break;
8575 case OPC_CVT_PW_PS:
8576 check_cp1_64bitmode(ctx);
8578 TCGv_i64 fp0 = tcg_temp_new_i64();
8580 gen_load_fpr64(ctx, fp0, fs);
8581 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
8582 gen_store_fpr64(ctx, fp0, fd);
8583 tcg_temp_free_i64(fp0);
8585 opn = "cvt.pw.ps";
8586 break;
8587 case OPC_CVT_S_PL:
8588 check_cp1_64bitmode(ctx);
8590 TCGv_i32 fp0 = tcg_temp_new_i32();
8592 gen_load_fpr32(fp0, fs);
8593 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
8594 gen_store_fpr32(fp0, fd);
8595 tcg_temp_free_i32(fp0);
8597 opn = "cvt.s.pl";
8598 break;
8599 case OPC_PLL_PS:
8600 check_cp1_64bitmode(ctx);
8602 TCGv_i32 fp0 = tcg_temp_new_i32();
8603 TCGv_i32 fp1 = tcg_temp_new_i32();
8605 gen_load_fpr32(fp0, fs);
8606 gen_load_fpr32(fp1, ft);
8607 gen_store_fpr32h(ctx, fp0, fd);
8608 gen_store_fpr32(fp1, fd);
8609 tcg_temp_free_i32(fp0);
8610 tcg_temp_free_i32(fp1);
8612 opn = "pll.ps";
8613 break;
8614 case OPC_PLU_PS:
8615 check_cp1_64bitmode(ctx);
8617 TCGv_i32 fp0 = tcg_temp_new_i32();
8618 TCGv_i32 fp1 = tcg_temp_new_i32();
8620 gen_load_fpr32(fp0, fs);
8621 gen_load_fpr32h(ctx, fp1, ft);
8622 gen_store_fpr32(fp1, fd);
8623 gen_store_fpr32h(ctx, fp0, fd);
8624 tcg_temp_free_i32(fp0);
8625 tcg_temp_free_i32(fp1);
8627 opn = "plu.ps";
8628 break;
8629 case OPC_PUL_PS:
8630 check_cp1_64bitmode(ctx);
8632 TCGv_i32 fp0 = tcg_temp_new_i32();
8633 TCGv_i32 fp1 = tcg_temp_new_i32();
8635 gen_load_fpr32h(ctx, fp0, fs);
8636 gen_load_fpr32(fp1, ft);
8637 gen_store_fpr32(fp1, fd);
8638 gen_store_fpr32h(ctx, fp0, fd);
8639 tcg_temp_free_i32(fp0);
8640 tcg_temp_free_i32(fp1);
8642 opn = "pul.ps";
8643 break;
8644 case OPC_PUU_PS:
8645 check_cp1_64bitmode(ctx);
8647 TCGv_i32 fp0 = tcg_temp_new_i32();
8648 TCGv_i32 fp1 = tcg_temp_new_i32();
8650 gen_load_fpr32h(ctx, fp0, fs);
8651 gen_load_fpr32h(ctx, fp1, ft);
8652 gen_store_fpr32(fp1, fd);
8653 gen_store_fpr32h(ctx, fp0, fd);
8654 tcg_temp_free_i32(fp0);
8655 tcg_temp_free_i32(fp1);
8657 opn = "puu.ps";
8658 break;
8659 case OPC_CMP_F_PS:
8660 case OPC_CMP_UN_PS:
8661 case OPC_CMP_EQ_PS:
8662 case OPC_CMP_UEQ_PS:
8663 case OPC_CMP_OLT_PS:
8664 case OPC_CMP_ULT_PS:
8665 case OPC_CMP_OLE_PS:
8666 case OPC_CMP_ULE_PS:
8667 case OPC_CMP_SF_PS:
8668 case OPC_CMP_NGLE_PS:
8669 case OPC_CMP_SEQ_PS:
8670 case OPC_CMP_NGL_PS:
8671 case OPC_CMP_LT_PS:
8672 case OPC_CMP_NGE_PS:
8673 case OPC_CMP_LE_PS:
8674 case OPC_CMP_NGT_PS:
8675 if (ctx->opcode & (1 << 6)) {
8676 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8677 opn = condnames_abs[func-48];
8678 } else {
8679 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8680 opn = condnames[func-48];
8682 break;
8683 default:
8684 MIPS_INVAL(opn);
8685 generate_exception (ctx, EXCP_RI);
8686 return;
8688 (void)opn; /* avoid a compiler warning */
8689 switch (optype) {
8690 case BINOP:
8691 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
8692 break;
8693 case CMPOP:
8694 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8695 break;
8696 default:
8697 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
8698 break;
8702 /* Coprocessor 3 (FPU) */
8703 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8704 int fd, int fs, int base, int index)
8706 const char *opn = "extended float load/store";
8707 int store = 0;
8708 TCGv t0 = tcg_temp_new();
8710 if (base == 0) {
8711 gen_load_gpr(t0, index);
8712 } else if (index == 0) {
8713 gen_load_gpr(t0, base);
8714 } else {
8715 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
8717 /* Don't do NOP if destination is zero: we must perform the actual
8718 memory access. */
8719 switch (opc) {
8720 case OPC_LWXC1:
8721 check_cop1x(ctx);
8723 TCGv_i32 fp0 = tcg_temp_new_i32();
8725 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
8726 tcg_gen_trunc_tl_i32(fp0, t0);
8727 gen_store_fpr32(fp0, fd);
8728 tcg_temp_free_i32(fp0);
8730 opn = "lwxc1";
8731 break;
8732 case OPC_LDXC1:
8733 check_cop1x(ctx);
8734 check_cp1_registers(ctx, fd);
8736 TCGv_i64 fp0 = tcg_temp_new_i64();
8737 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8738 gen_store_fpr64(ctx, fp0, fd);
8739 tcg_temp_free_i64(fp0);
8741 opn = "ldxc1";
8742 break;
8743 case OPC_LUXC1:
8744 check_cp1_64bitmode(ctx);
8745 tcg_gen_andi_tl(t0, t0, ~0x7);
8747 TCGv_i64 fp0 = tcg_temp_new_i64();
8749 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8750 gen_store_fpr64(ctx, fp0, fd);
8751 tcg_temp_free_i64(fp0);
8753 opn = "luxc1";
8754 break;
8755 case OPC_SWXC1:
8756 check_cop1x(ctx);
8758 TCGv_i32 fp0 = tcg_temp_new_i32();
8759 gen_load_fpr32(fp0, fs);
8760 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
8761 tcg_temp_free_i32(fp0);
8763 opn = "swxc1";
8764 store = 1;
8765 break;
8766 case OPC_SDXC1:
8767 check_cop1x(ctx);
8768 check_cp1_registers(ctx, fs);
8770 TCGv_i64 fp0 = tcg_temp_new_i64();
8771 gen_load_fpr64(ctx, fp0, fs);
8772 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8773 tcg_temp_free_i64(fp0);
8775 opn = "sdxc1";
8776 store = 1;
8777 break;
8778 case OPC_SUXC1:
8779 check_cp1_64bitmode(ctx);
8780 tcg_gen_andi_tl(t0, t0, ~0x7);
8782 TCGv_i64 fp0 = tcg_temp_new_i64();
8783 gen_load_fpr64(ctx, fp0, fs);
8784 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8785 tcg_temp_free_i64(fp0);
8787 opn = "suxc1";
8788 store = 1;
8789 break;
8791 tcg_temp_free(t0);
8792 (void)opn; (void)store; /* avoid compiler warnings */
8793 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8794 regnames[index], regnames[base]);
8797 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8798 int fd, int fr, int fs, int ft)
8800 const char *opn = "flt3_arith";
8802 switch (opc) {
8803 case OPC_ALNV_PS:
8804 check_cp1_64bitmode(ctx);
8806 TCGv t0 = tcg_temp_local_new();
8807 TCGv_i32 fp = tcg_temp_new_i32();
8808 TCGv_i32 fph = tcg_temp_new_i32();
8809 int l1 = gen_new_label();
8810 int l2 = gen_new_label();
8812 gen_load_gpr(t0, fr);
8813 tcg_gen_andi_tl(t0, t0, 0x7);
8815 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
8816 gen_load_fpr32(fp, fs);
8817 gen_load_fpr32h(ctx, fph, fs);
8818 gen_store_fpr32(fp, fd);
8819 gen_store_fpr32h(ctx, fph, fd);
8820 tcg_gen_br(l2);
8821 gen_set_label(l1);
8822 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8823 tcg_temp_free(t0);
8824 #ifdef TARGET_WORDS_BIGENDIAN
8825 gen_load_fpr32(fp, fs);
8826 gen_load_fpr32h(ctx, fph, ft);
8827 gen_store_fpr32h(ctx, fp, fd);
8828 gen_store_fpr32(fph, fd);
8829 #else
8830 gen_load_fpr32h(ctx, fph, fs);
8831 gen_load_fpr32(fp, ft);
8832 gen_store_fpr32(fph, fd);
8833 gen_store_fpr32h(ctx, fp, fd);
8834 #endif
8835 gen_set_label(l2);
8836 tcg_temp_free_i32(fp);
8837 tcg_temp_free_i32(fph);
8839 opn = "alnv.ps";
8840 break;
8841 case OPC_MADD_S:
8842 check_cop1x(ctx);
8844 TCGv_i32 fp0 = tcg_temp_new_i32();
8845 TCGv_i32 fp1 = tcg_temp_new_i32();
8846 TCGv_i32 fp2 = tcg_temp_new_i32();
8848 gen_load_fpr32(fp0, fs);
8849 gen_load_fpr32(fp1, ft);
8850 gen_load_fpr32(fp2, fr);
8851 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
8852 tcg_temp_free_i32(fp0);
8853 tcg_temp_free_i32(fp1);
8854 gen_store_fpr32(fp2, fd);
8855 tcg_temp_free_i32(fp2);
8857 opn = "madd.s";
8858 break;
8859 case OPC_MADD_D:
8860 check_cop1x(ctx);
8861 check_cp1_registers(ctx, fd | fs | ft | fr);
8863 TCGv_i64 fp0 = tcg_temp_new_i64();
8864 TCGv_i64 fp1 = tcg_temp_new_i64();
8865 TCGv_i64 fp2 = tcg_temp_new_i64();
8867 gen_load_fpr64(ctx, fp0, fs);
8868 gen_load_fpr64(ctx, fp1, ft);
8869 gen_load_fpr64(ctx, fp2, fr);
8870 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
8871 tcg_temp_free_i64(fp0);
8872 tcg_temp_free_i64(fp1);
8873 gen_store_fpr64(ctx, fp2, fd);
8874 tcg_temp_free_i64(fp2);
8876 opn = "madd.d";
8877 break;
8878 case OPC_MADD_PS:
8879 check_cp1_64bitmode(ctx);
8881 TCGv_i64 fp0 = tcg_temp_new_i64();
8882 TCGv_i64 fp1 = tcg_temp_new_i64();
8883 TCGv_i64 fp2 = tcg_temp_new_i64();
8885 gen_load_fpr64(ctx, fp0, fs);
8886 gen_load_fpr64(ctx, fp1, ft);
8887 gen_load_fpr64(ctx, fp2, fr);
8888 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
8889 tcg_temp_free_i64(fp0);
8890 tcg_temp_free_i64(fp1);
8891 gen_store_fpr64(ctx, fp2, fd);
8892 tcg_temp_free_i64(fp2);
8894 opn = "madd.ps";
8895 break;
8896 case OPC_MSUB_S:
8897 check_cop1x(ctx);
8899 TCGv_i32 fp0 = tcg_temp_new_i32();
8900 TCGv_i32 fp1 = tcg_temp_new_i32();
8901 TCGv_i32 fp2 = tcg_temp_new_i32();
8903 gen_load_fpr32(fp0, fs);
8904 gen_load_fpr32(fp1, ft);
8905 gen_load_fpr32(fp2, fr);
8906 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
8907 tcg_temp_free_i32(fp0);
8908 tcg_temp_free_i32(fp1);
8909 gen_store_fpr32(fp2, fd);
8910 tcg_temp_free_i32(fp2);
8912 opn = "msub.s";
8913 break;
8914 case OPC_MSUB_D:
8915 check_cop1x(ctx);
8916 check_cp1_registers(ctx, fd | fs | ft | fr);
8918 TCGv_i64 fp0 = tcg_temp_new_i64();
8919 TCGv_i64 fp1 = tcg_temp_new_i64();
8920 TCGv_i64 fp2 = tcg_temp_new_i64();
8922 gen_load_fpr64(ctx, fp0, fs);
8923 gen_load_fpr64(ctx, fp1, ft);
8924 gen_load_fpr64(ctx, fp2, fr);
8925 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
8926 tcg_temp_free_i64(fp0);
8927 tcg_temp_free_i64(fp1);
8928 gen_store_fpr64(ctx, fp2, fd);
8929 tcg_temp_free_i64(fp2);
8931 opn = "msub.d";
8932 break;
8933 case OPC_MSUB_PS:
8934 check_cp1_64bitmode(ctx);
8936 TCGv_i64 fp0 = tcg_temp_new_i64();
8937 TCGv_i64 fp1 = tcg_temp_new_i64();
8938 TCGv_i64 fp2 = tcg_temp_new_i64();
8940 gen_load_fpr64(ctx, fp0, fs);
8941 gen_load_fpr64(ctx, fp1, ft);
8942 gen_load_fpr64(ctx, fp2, fr);
8943 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
8944 tcg_temp_free_i64(fp0);
8945 tcg_temp_free_i64(fp1);
8946 gen_store_fpr64(ctx, fp2, fd);
8947 tcg_temp_free_i64(fp2);
8949 opn = "msub.ps";
8950 break;
8951 case OPC_NMADD_S:
8952 check_cop1x(ctx);
8954 TCGv_i32 fp0 = tcg_temp_new_i32();
8955 TCGv_i32 fp1 = tcg_temp_new_i32();
8956 TCGv_i32 fp2 = tcg_temp_new_i32();
8958 gen_load_fpr32(fp0, fs);
8959 gen_load_fpr32(fp1, ft);
8960 gen_load_fpr32(fp2, fr);
8961 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
8962 tcg_temp_free_i32(fp0);
8963 tcg_temp_free_i32(fp1);
8964 gen_store_fpr32(fp2, fd);
8965 tcg_temp_free_i32(fp2);
8967 opn = "nmadd.s";
8968 break;
8969 case OPC_NMADD_D:
8970 check_cop1x(ctx);
8971 check_cp1_registers(ctx, fd | fs | ft | fr);
8973 TCGv_i64 fp0 = tcg_temp_new_i64();
8974 TCGv_i64 fp1 = tcg_temp_new_i64();
8975 TCGv_i64 fp2 = tcg_temp_new_i64();
8977 gen_load_fpr64(ctx, fp0, fs);
8978 gen_load_fpr64(ctx, fp1, ft);
8979 gen_load_fpr64(ctx, fp2, fr);
8980 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
8981 tcg_temp_free_i64(fp0);
8982 tcg_temp_free_i64(fp1);
8983 gen_store_fpr64(ctx, fp2, fd);
8984 tcg_temp_free_i64(fp2);
8986 opn = "nmadd.d";
8987 break;
8988 case OPC_NMADD_PS:
8989 check_cp1_64bitmode(ctx);
8991 TCGv_i64 fp0 = tcg_temp_new_i64();
8992 TCGv_i64 fp1 = tcg_temp_new_i64();
8993 TCGv_i64 fp2 = tcg_temp_new_i64();
8995 gen_load_fpr64(ctx, fp0, fs);
8996 gen_load_fpr64(ctx, fp1, ft);
8997 gen_load_fpr64(ctx, fp2, fr);
8998 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
8999 tcg_temp_free_i64(fp0);
9000 tcg_temp_free_i64(fp1);
9001 gen_store_fpr64(ctx, fp2, fd);
9002 tcg_temp_free_i64(fp2);
9004 opn = "nmadd.ps";
9005 break;
9006 case OPC_NMSUB_S:
9007 check_cop1x(ctx);
9009 TCGv_i32 fp0 = tcg_temp_new_i32();
9010 TCGv_i32 fp1 = tcg_temp_new_i32();
9011 TCGv_i32 fp2 = tcg_temp_new_i32();
9013 gen_load_fpr32(fp0, fs);
9014 gen_load_fpr32(fp1, ft);
9015 gen_load_fpr32(fp2, fr);
9016 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
9017 tcg_temp_free_i32(fp0);
9018 tcg_temp_free_i32(fp1);
9019 gen_store_fpr32(fp2, fd);
9020 tcg_temp_free_i32(fp2);
9022 opn = "nmsub.s";
9023 break;
9024 case OPC_NMSUB_D:
9025 check_cop1x(ctx);
9026 check_cp1_registers(ctx, fd | fs | ft | fr);
9028 TCGv_i64 fp0 = tcg_temp_new_i64();
9029 TCGv_i64 fp1 = tcg_temp_new_i64();
9030 TCGv_i64 fp2 = tcg_temp_new_i64();
9032 gen_load_fpr64(ctx, fp0, fs);
9033 gen_load_fpr64(ctx, fp1, ft);
9034 gen_load_fpr64(ctx, fp2, fr);
9035 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
9036 tcg_temp_free_i64(fp0);
9037 tcg_temp_free_i64(fp1);
9038 gen_store_fpr64(ctx, fp2, fd);
9039 tcg_temp_free_i64(fp2);
9041 opn = "nmsub.d";
9042 break;
9043 case OPC_NMSUB_PS:
9044 check_cp1_64bitmode(ctx);
9046 TCGv_i64 fp0 = tcg_temp_new_i64();
9047 TCGv_i64 fp1 = tcg_temp_new_i64();
9048 TCGv_i64 fp2 = tcg_temp_new_i64();
9050 gen_load_fpr64(ctx, fp0, fs);
9051 gen_load_fpr64(ctx, fp1, ft);
9052 gen_load_fpr64(ctx, fp2, fr);
9053 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
9054 tcg_temp_free_i64(fp0);
9055 tcg_temp_free_i64(fp1);
9056 gen_store_fpr64(ctx, fp2, fd);
9057 tcg_temp_free_i64(fp2);
9059 opn = "nmsub.ps";
9060 break;
9061 default:
9062 MIPS_INVAL(opn);
9063 generate_exception (ctx, EXCP_RI);
9064 return;
9066 (void)opn; /* avoid a compiler warning */
9067 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
9068 fregnames[fs], fregnames[ft]);
9071 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
9073 TCGv t0;
9075 #if !defined(CONFIG_USER_ONLY)
9076 /* The Linux kernel will emulate rdhwr if it's not supported natively.
9077 Therefore only check the ISA in system mode. */
9078 check_insn(ctx, ISA_MIPS32R2);
9079 #endif
9080 t0 = tcg_temp_new();
9082 switch (rd) {
9083 case 0:
9084 save_cpu_state(ctx, 1);
9085 gen_helper_rdhwr_cpunum(t0, cpu_env);
9086 gen_store_gpr(t0, rt);
9087 break;
9088 case 1:
9089 save_cpu_state(ctx, 1);
9090 gen_helper_rdhwr_synci_step(t0, cpu_env);
9091 gen_store_gpr(t0, rt);
9092 break;
9093 case 2:
9094 save_cpu_state(ctx, 1);
9095 gen_helper_rdhwr_cc(t0, cpu_env);
9096 gen_store_gpr(t0, rt);
9097 break;
9098 case 3:
9099 save_cpu_state(ctx, 1);
9100 gen_helper_rdhwr_ccres(t0, cpu_env);
9101 gen_store_gpr(t0, rt);
9102 break;
9103 case 29:
9104 #if defined(CONFIG_USER_ONLY)
9105 tcg_gen_ld_tl(t0, cpu_env,
9106 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9107 gen_store_gpr(t0, rt);
9108 break;
9109 #else
9110 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
9111 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
9112 tcg_gen_ld_tl(t0, cpu_env,
9113 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9114 gen_store_gpr(t0, rt);
9115 } else {
9116 generate_exception(ctx, EXCP_RI);
9118 break;
9119 #endif
9120 default: /* Invalid */
9121 MIPS_INVAL("rdhwr");
9122 generate_exception(ctx, EXCP_RI);
9123 break;
9125 tcg_temp_free(t0);
9128 static void handle_delay_slot(DisasContext *ctx, int insn_bytes)
9130 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9131 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
9132 /* Branches completion */
9133 ctx->hflags &= ~MIPS_HFLAG_BMASK;
9134 ctx->bstate = BS_BRANCH;
9135 save_cpu_state(ctx, 0);
9136 /* FIXME: Need to clear can_do_io. */
9137 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
9138 case MIPS_HFLAG_B:
9139 /* unconditional branch */
9140 MIPS_DEBUG("unconditional branch");
9141 if (proc_hflags & MIPS_HFLAG_BX) {
9142 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
9144 gen_goto_tb(ctx, 0, ctx->btarget);
9145 break;
9146 case MIPS_HFLAG_BL:
9147 /* blikely taken case */
9148 MIPS_DEBUG("blikely branch taken");
9149 gen_goto_tb(ctx, 0, ctx->btarget);
9150 break;
9151 case MIPS_HFLAG_BC:
9152 /* Conditional branch */
9153 MIPS_DEBUG("conditional branch");
9155 int l1 = gen_new_label();
9157 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
9158 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
9159 gen_set_label(l1);
9160 gen_goto_tb(ctx, 0, ctx->btarget);
9162 break;
9163 case MIPS_HFLAG_BR:
9164 /* unconditional branch to register */
9165 MIPS_DEBUG("branch to register");
9166 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
9167 TCGv t0 = tcg_temp_new();
9168 TCGv_i32 t1 = tcg_temp_new_i32();
9170 tcg_gen_andi_tl(t0, btarget, 0x1);
9171 tcg_gen_trunc_tl_i32(t1, t0);
9172 tcg_temp_free(t0);
9173 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
9174 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
9175 tcg_gen_or_i32(hflags, hflags, t1);
9176 tcg_temp_free_i32(t1);
9178 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
9179 } else {
9180 tcg_gen_mov_tl(cpu_PC, btarget);
9182 if (ctx->singlestep_enabled) {
9183 save_cpu_state(ctx, 0);
9184 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
9186 tcg_gen_exit_tb(0);
9187 break;
9188 default:
9189 MIPS_DEBUG("unknown branch");
9190 break;
9195 /* ISA extensions (ASEs) */
9196 /* MIPS16 extension to MIPS32 */
9198 /* MIPS16 major opcodes */
9199 enum {
9200 M16_OPC_ADDIUSP = 0x00,
9201 M16_OPC_ADDIUPC = 0x01,
9202 M16_OPC_B = 0x02,
9203 M16_OPC_JAL = 0x03,
9204 M16_OPC_BEQZ = 0x04,
9205 M16_OPC_BNEQZ = 0x05,
9206 M16_OPC_SHIFT = 0x06,
9207 M16_OPC_LD = 0x07,
9208 M16_OPC_RRIA = 0x08,
9209 M16_OPC_ADDIU8 = 0x09,
9210 M16_OPC_SLTI = 0x0a,
9211 M16_OPC_SLTIU = 0x0b,
9212 M16_OPC_I8 = 0x0c,
9213 M16_OPC_LI = 0x0d,
9214 M16_OPC_CMPI = 0x0e,
9215 M16_OPC_SD = 0x0f,
9216 M16_OPC_LB = 0x10,
9217 M16_OPC_LH = 0x11,
9218 M16_OPC_LWSP = 0x12,
9219 M16_OPC_LW = 0x13,
9220 M16_OPC_LBU = 0x14,
9221 M16_OPC_LHU = 0x15,
9222 M16_OPC_LWPC = 0x16,
9223 M16_OPC_LWU = 0x17,
9224 M16_OPC_SB = 0x18,
9225 M16_OPC_SH = 0x19,
9226 M16_OPC_SWSP = 0x1a,
9227 M16_OPC_SW = 0x1b,
9228 M16_OPC_RRR = 0x1c,
9229 M16_OPC_RR = 0x1d,
9230 M16_OPC_EXTEND = 0x1e,
9231 M16_OPC_I64 = 0x1f
9234 /* I8 funct field */
9235 enum {
9236 I8_BTEQZ = 0x0,
9237 I8_BTNEZ = 0x1,
9238 I8_SWRASP = 0x2,
9239 I8_ADJSP = 0x3,
9240 I8_SVRS = 0x4,
9241 I8_MOV32R = 0x5,
9242 I8_MOVR32 = 0x7
9245 /* RRR f field */
9246 enum {
9247 RRR_DADDU = 0x0,
9248 RRR_ADDU = 0x1,
9249 RRR_DSUBU = 0x2,
9250 RRR_SUBU = 0x3
9253 /* RR funct field */
9254 enum {
9255 RR_JR = 0x00,
9256 RR_SDBBP = 0x01,
9257 RR_SLT = 0x02,
9258 RR_SLTU = 0x03,
9259 RR_SLLV = 0x04,
9260 RR_BREAK = 0x05,
9261 RR_SRLV = 0x06,
9262 RR_SRAV = 0x07,
9263 RR_DSRL = 0x08,
9264 RR_CMP = 0x0a,
9265 RR_NEG = 0x0b,
9266 RR_AND = 0x0c,
9267 RR_OR = 0x0d,
9268 RR_XOR = 0x0e,
9269 RR_NOT = 0x0f,
9270 RR_MFHI = 0x10,
9271 RR_CNVT = 0x11,
9272 RR_MFLO = 0x12,
9273 RR_DSRA = 0x13,
9274 RR_DSLLV = 0x14,
9275 RR_DSRLV = 0x16,
9276 RR_DSRAV = 0x17,
9277 RR_MULT = 0x18,
9278 RR_MULTU = 0x19,
9279 RR_DIV = 0x1a,
9280 RR_DIVU = 0x1b,
9281 RR_DMULT = 0x1c,
9282 RR_DMULTU = 0x1d,
9283 RR_DDIV = 0x1e,
9284 RR_DDIVU = 0x1f
9287 /* I64 funct field */
9288 enum {
9289 I64_LDSP = 0x0,
9290 I64_SDSP = 0x1,
9291 I64_SDRASP = 0x2,
9292 I64_DADJSP = 0x3,
9293 I64_LDPC = 0x4,
9294 I64_DADDIU5 = 0x5,
9295 I64_DADDIUPC = 0x6,
9296 I64_DADDIUSP = 0x7
9299 /* RR ry field for CNVT */
9300 enum {
9301 RR_RY_CNVT_ZEB = 0x0,
9302 RR_RY_CNVT_ZEH = 0x1,
9303 RR_RY_CNVT_ZEW = 0x2,
9304 RR_RY_CNVT_SEB = 0x4,
9305 RR_RY_CNVT_SEH = 0x5,
9306 RR_RY_CNVT_SEW = 0x6,
9309 static int xlat (int r)
9311 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9313 return map[r];
9316 static void gen_mips16_save (DisasContext *ctx,
9317 int xsregs, int aregs,
9318 int do_ra, int do_s0, int do_s1,
9319 int framesize)
9321 TCGv t0 = tcg_temp_new();
9322 TCGv t1 = tcg_temp_new();
9323 int args, astatic;
9325 switch (aregs) {
9326 case 0:
9327 case 1:
9328 case 2:
9329 case 3:
9330 case 11:
9331 args = 0;
9332 break;
9333 case 4:
9334 case 5:
9335 case 6:
9336 case 7:
9337 args = 1;
9338 break;
9339 case 8:
9340 case 9:
9341 case 10:
9342 args = 2;
9343 break;
9344 case 12:
9345 case 13:
9346 args = 3;
9347 break;
9348 case 14:
9349 args = 4;
9350 break;
9351 default:
9352 generate_exception(ctx, EXCP_RI);
9353 return;
9356 switch (args) {
9357 case 4:
9358 gen_base_offset_addr(ctx, t0, 29, 12);
9359 gen_load_gpr(t1, 7);
9360 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9361 /* Fall through */
9362 case 3:
9363 gen_base_offset_addr(ctx, t0, 29, 8);
9364 gen_load_gpr(t1, 6);
9365 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9366 /* Fall through */
9367 case 2:
9368 gen_base_offset_addr(ctx, t0, 29, 4);
9369 gen_load_gpr(t1, 5);
9370 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9371 /* Fall through */
9372 case 1:
9373 gen_base_offset_addr(ctx, t0, 29, 0);
9374 gen_load_gpr(t1, 4);
9375 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9378 gen_load_gpr(t0, 29);
9380 #define DECR_AND_STORE(reg) do { \
9381 tcg_gen_subi_tl(t0, t0, 4); \
9382 gen_load_gpr(t1, reg); \
9383 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
9384 } while (0)
9386 if (do_ra) {
9387 DECR_AND_STORE(31);
9390 switch (xsregs) {
9391 case 7:
9392 DECR_AND_STORE(30);
9393 /* Fall through */
9394 case 6:
9395 DECR_AND_STORE(23);
9396 /* Fall through */
9397 case 5:
9398 DECR_AND_STORE(22);
9399 /* Fall through */
9400 case 4:
9401 DECR_AND_STORE(21);
9402 /* Fall through */
9403 case 3:
9404 DECR_AND_STORE(20);
9405 /* Fall through */
9406 case 2:
9407 DECR_AND_STORE(19);
9408 /* Fall through */
9409 case 1:
9410 DECR_AND_STORE(18);
9413 if (do_s1) {
9414 DECR_AND_STORE(17);
9416 if (do_s0) {
9417 DECR_AND_STORE(16);
9420 switch (aregs) {
9421 case 0:
9422 case 4:
9423 case 8:
9424 case 12:
9425 case 14:
9426 astatic = 0;
9427 break;
9428 case 1:
9429 case 5:
9430 case 9:
9431 case 13:
9432 astatic = 1;
9433 break;
9434 case 2:
9435 case 6:
9436 case 10:
9437 astatic = 2;
9438 break;
9439 case 3:
9440 case 7:
9441 astatic = 3;
9442 break;
9443 case 11:
9444 astatic = 4;
9445 break;
9446 default:
9447 generate_exception(ctx, EXCP_RI);
9448 return;
9451 if (astatic > 0) {
9452 DECR_AND_STORE(7);
9453 if (astatic > 1) {
9454 DECR_AND_STORE(6);
9455 if (astatic > 2) {
9456 DECR_AND_STORE(5);
9457 if (astatic > 3) {
9458 DECR_AND_STORE(4);
9463 #undef DECR_AND_STORE
9465 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9466 tcg_temp_free(t0);
9467 tcg_temp_free(t1);
9470 static void gen_mips16_restore (DisasContext *ctx,
9471 int xsregs, int aregs,
9472 int do_ra, int do_s0, int do_s1,
9473 int framesize)
9475 int astatic;
9476 TCGv t0 = tcg_temp_new();
9477 TCGv t1 = tcg_temp_new();
9479 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
9481 #define DECR_AND_LOAD(reg) do { \
9482 tcg_gen_subi_tl(t0, t0, 4); \
9483 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
9484 gen_store_gpr(t1, reg); \
9485 } while (0)
9487 if (do_ra) {
9488 DECR_AND_LOAD(31);
9491 switch (xsregs) {
9492 case 7:
9493 DECR_AND_LOAD(30);
9494 /* Fall through */
9495 case 6:
9496 DECR_AND_LOAD(23);
9497 /* Fall through */
9498 case 5:
9499 DECR_AND_LOAD(22);
9500 /* Fall through */
9501 case 4:
9502 DECR_AND_LOAD(21);
9503 /* Fall through */
9504 case 3:
9505 DECR_AND_LOAD(20);
9506 /* Fall through */
9507 case 2:
9508 DECR_AND_LOAD(19);
9509 /* Fall through */
9510 case 1:
9511 DECR_AND_LOAD(18);
9514 if (do_s1) {
9515 DECR_AND_LOAD(17);
9517 if (do_s0) {
9518 DECR_AND_LOAD(16);
9521 switch (aregs) {
9522 case 0:
9523 case 4:
9524 case 8:
9525 case 12:
9526 case 14:
9527 astatic = 0;
9528 break;
9529 case 1:
9530 case 5:
9531 case 9:
9532 case 13:
9533 astatic = 1;
9534 break;
9535 case 2:
9536 case 6:
9537 case 10:
9538 astatic = 2;
9539 break;
9540 case 3:
9541 case 7:
9542 astatic = 3;
9543 break;
9544 case 11:
9545 astatic = 4;
9546 break;
9547 default:
9548 generate_exception(ctx, EXCP_RI);
9549 return;
9552 if (astatic > 0) {
9553 DECR_AND_LOAD(7);
9554 if (astatic > 1) {
9555 DECR_AND_LOAD(6);
9556 if (astatic > 2) {
9557 DECR_AND_LOAD(5);
9558 if (astatic > 3) {
9559 DECR_AND_LOAD(4);
9564 #undef DECR_AND_LOAD
9566 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9567 tcg_temp_free(t0);
9568 tcg_temp_free(t1);
9571 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9572 int is_64_bit, int extended)
9574 TCGv t0;
9576 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9577 generate_exception(ctx, EXCP_RI);
9578 return;
9581 t0 = tcg_temp_new();
9583 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9584 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9585 if (!is_64_bit) {
9586 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9589 tcg_temp_free(t0);
9592 #if defined(TARGET_MIPS64)
9593 static void decode_i64_mips16 (DisasContext *ctx,
9594 int ry, int funct, int16_t offset,
9595 int extended)
9597 switch (funct) {
9598 case I64_LDSP:
9599 check_mips_64(ctx);
9600 offset = extended ? offset : offset << 3;
9601 gen_ld(ctx, OPC_LD, ry, 29, offset);
9602 break;
9603 case I64_SDSP:
9604 check_mips_64(ctx);
9605 offset = extended ? offset : offset << 3;
9606 gen_st(ctx, OPC_SD, ry, 29, offset);
9607 break;
9608 case I64_SDRASP:
9609 check_mips_64(ctx);
9610 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
9611 gen_st(ctx, OPC_SD, 31, 29, offset);
9612 break;
9613 case I64_DADJSP:
9614 check_mips_64(ctx);
9615 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
9616 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
9617 break;
9618 case I64_LDPC:
9619 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9620 generate_exception(ctx, EXCP_RI);
9621 } else {
9622 offset = extended ? offset : offset << 3;
9623 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
9625 break;
9626 case I64_DADDIU5:
9627 check_mips_64(ctx);
9628 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
9629 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
9630 break;
9631 case I64_DADDIUPC:
9632 check_mips_64(ctx);
9633 offset = extended ? offset : offset << 2;
9634 gen_addiupc(ctx, ry, offset, 1, extended);
9635 break;
9636 case I64_DADDIUSP:
9637 check_mips_64(ctx);
9638 offset = extended ? offset : offset << 2;
9639 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
9640 break;
9643 #endif
9645 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
9647 int extend = cpu_lduw_code(env, ctx->pc + 2);
9648 int op, rx, ry, funct, sa;
9649 int16_t imm, offset;
9651 ctx->opcode = (ctx->opcode << 16) | extend;
9652 op = (ctx->opcode >> 11) & 0x1f;
9653 sa = (ctx->opcode >> 22) & 0x1f;
9654 funct = (ctx->opcode >> 8) & 0x7;
9655 rx = xlat((ctx->opcode >> 8) & 0x7);
9656 ry = xlat((ctx->opcode >> 5) & 0x7);
9657 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9658 | ((ctx->opcode >> 21) & 0x3f) << 5
9659 | (ctx->opcode & 0x1f));
9661 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9662 counterparts. */
9663 switch (op) {
9664 case M16_OPC_ADDIUSP:
9665 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
9666 break;
9667 case M16_OPC_ADDIUPC:
9668 gen_addiupc(ctx, rx, imm, 0, 1);
9669 break;
9670 case M16_OPC_B:
9671 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9672 /* No delay slot, so just process as a normal instruction */
9673 break;
9674 case M16_OPC_BEQZ:
9675 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9676 /* No delay slot, so just process as a normal instruction */
9677 break;
9678 case M16_OPC_BNEQZ:
9679 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9680 /* No delay slot, so just process as a normal instruction */
9681 break;
9682 case M16_OPC_SHIFT:
9683 switch (ctx->opcode & 0x3) {
9684 case 0x0:
9685 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
9686 break;
9687 case 0x1:
9688 #if defined(TARGET_MIPS64)
9689 check_mips_64(ctx);
9690 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
9691 #else
9692 generate_exception(ctx, EXCP_RI);
9693 #endif
9694 break;
9695 case 0x2:
9696 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
9697 break;
9698 case 0x3:
9699 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
9700 break;
9702 break;
9703 #if defined(TARGET_MIPS64)
9704 case M16_OPC_LD:
9705 check_mips_64(ctx);
9706 gen_ld(ctx, OPC_LD, ry, rx, offset);
9707 break;
9708 #endif
9709 case M16_OPC_RRIA:
9710 imm = ctx->opcode & 0xf;
9711 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9712 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9713 imm = (int16_t) (imm << 1) >> 1;
9714 if ((ctx->opcode >> 4) & 0x1) {
9715 #if defined(TARGET_MIPS64)
9716 check_mips_64(ctx);
9717 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
9718 #else
9719 generate_exception(ctx, EXCP_RI);
9720 #endif
9721 } else {
9722 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
9724 break;
9725 case M16_OPC_ADDIU8:
9726 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
9727 break;
9728 case M16_OPC_SLTI:
9729 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
9730 break;
9731 case M16_OPC_SLTIU:
9732 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
9733 break;
9734 case M16_OPC_I8:
9735 switch (funct) {
9736 case I8_BTEQZ:
9737 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9738 break;
9739 case I8_BTNEZ:
9740 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9741 break;
9742 case I8_SWRASP:
9743 gen_st(ctx, OPC_SW, 31, 29, imm);
9744 break;
9745 case I8_ADJSP:
9746 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
9747 break;
9748 case I8_SVRS:
9750 int xsregs = (ctx->opcode >> 24) & 0x7;
9751 int aregs = (ctx->opcode >> 16) & 0xf;
9752 int do_ra = (ctx->opcode >> 6) & 0x1;
9753 int do_s0 = (ctx->opcode >> 5) & 0x1;
9754 int do_s1 = (ctx->opcode >> 4) & 0x1;
9755 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9756 | (ctx->opcode & 0xf)) << 3;
9758 if (ctx->opcode & (1 << 7)) {
9759 gen_mips16_save(ctx, xsregs, aregs,
9760 do_ra, do_s0, do_s1,
9761 framesize);
9762 } else {
9763 gen_mips16_restore(ctx, xsregs, aregs,
9764 do_ra, do_s0, do_s1,
9765 framesize);
9768 break;
9769 default:
9770 generate_exception(ctx, EXCP_RI);
9771 break;
9773 break;
9774 case M16_OPC_LI:
9775 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9776 break;
9777 case M16_OPC_CMPI:
9778 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9779 break;
9780 #if defined(TARGET_MIPS64)
9781 case M16_OPC_SD:
9782 gen_st(ctx, OPC_SD, ry, rx, offset);
9783 break;
9784 #endif
9785 case M16_OPC_LB:
9786 gen_ld(ctx, OPC_LB, ry, rx, offset);
9787 break;
9788 case M16_OPC_LH:
9789 gen_ld(ctx, OPC_LH, ry, rx, offset);
9790 break;
9791 case M16_OPC_LWSP:
9792 gen_ld(ctx, OPC_LW, rx, 29, offset);
9793 break;
9794 case M16_OPC_LW:
9795 gen_ld(ctx, OPC_LW, ry, rx, offset);
9796 break;
9797 case M16_OPC_LBU:
9798 gen_ld(ctx, OPC_LBU, ry, rx, offset);
9799 break;
9800 case M16_OPC_LHU:
9801 gen_ld(ctx, OPC_LHU, ry, rx, offset);
9802 break;
9803 case M16_OPC_LWPC:
9804 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
9805 break;
9806 #if defined(TARGET_MIPS64)
9807 case M16_OPC_LWU:
9808 gen_ld(ctx, OPC_LWU, ry, rx, offset);
9809 break;
9810 #endif
9811 case M16_OPC_SB:
9812 gen_st(ctx, OPC_SB, ry, rx, offset);
9813 break;
9814 case M16_OPC_SH:
9815 gen_st(ctx, OPC_SH, ry, rx, offset);
9816 break;
9817 case M16_OPC_SWSP:
9818 gen_st(ctx, OPC_SW, rx, 29, offset);
9819 break;
9820 case M16_OPC_SW:
9821 gen_st(ctx, OPC_SW, ry, rx, offset);
9822 break;
9823 #if defined(TARGET_MIPS64)
9824 case M16_OPC_I64:
9825 decode_i64_mips16(ctx, ry, funct, offset, 1);
9826 break;
9827 #endif
9828 default:
9829 generate_exception(ctx, EXCP_RI);
9830 break;
9833 return 4;
9836 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
9838 int rx, ry;
9839 int sa;
9840 int op, cnvt_op, op1, offset;
9841 int funct;
9842 int n_bytes;
9844 op = (ctx->opcode >> 11) & 0x1f;
9845 sa = (ctx->opcode >> 2) & 0x7;
9846 sa = sa == 0 ? 8 : sa;
9847 rx = xlat((ctx->opcode >> 8) & 0x7);
9848 cnvt_op = (ctx->opcode >> 5) & 0x7;
9849 ry = xlat((ctx->opcode >> 5) & 0x7);
9850 op1 = offset = ctx->opcode & 0x1f;
9852 n_bytes = 2;
9854 switch (op) {
9855 case M16_OPC_ADDIUSP:
9857 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9859 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
9861 break;
9862 case M16_OPC_ADDIUPC:
9863 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9864 break;
9865 case M16_OPC_B:
9866 offset = (ctx->opcode & 0x7ff) << 1;
9867 offset = (int16_t)(offset << 4) >> 4;
9868 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9869 /* No delay slot, so just process as a normal instruction */
9870 break;
9871 case M16_OPC_JAL:
9872 offset = cpu_lduw_code(env, ctx->pc + 2);
9873 offset = (((ctx->opcode & 0x1f) << 21)
9874 | ((ctx->opcode >> 5) & 0x1f) << 16
9875 | offset) << 2;
9876 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
9877 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9878 n_bytes = 4;
9879 break;
9880 case M16_OPC_BEQZ:
9881 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9882 /* No delay slot, so just process as a normal instruction */
9883 break;
9884 case M16_OPC_BNEQZ:
9885 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9886 /* No delay slot, so just process as a normal instruction */
9887 break;
9888 case M16_OPC_SHIFT:
9889 switch (ctx->opcode & 0x3) {
9890 case 0x0:
9891 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
9892 break;
9893 case 0x1:
9894 #if defined(TARGET_MIPS64)
9895 check_mips_64(ctx);
9896 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
9897 #else
9898 generate_exception(ctx, EXCP_RI);
9899 #endif
9900 break;
9901 case 0x2:
9902 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
9903 break;
9904 case 0x3:
9905 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
9906 break;
9908 break;
9909 #if defined(TARGET_MIPS64)
9910 case M16_OPC_LD:
9911 check_mips_64(ctx);
9912 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
9913 break;
9914 #endif
9915 case M16_OPC_RRIA:
9917 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9919 if ((ctx->opcode >> 4) & 1) {
9920 #if defined(TARGET_MIPS64)
9921 check_mips_64(ctx);
9922 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
9923 #else
9924 generate_exception(ctx, EXCP_RI);
9925 #endif
9926 } else {
9927 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
9930 break;
9931 case M16_OPC_ADDIU8:
9933 int16_t imm = (int8_t) ctx->opcode;
9935 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
9937 break;
9938 case M16_OPC_SLTI:
9940 int16_t imm = (uint8_t) ctx->opcode;
9941 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
9943 break;
9944 case M16_OPC_SLTIU:
9946 int16_t imm = (uint8_t) ctx->opcode;
9947 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
9949 break;
9950 case M16_OPC_I8:
9952 int reg32;
9954 funct = (ctx->opcode >> 8) & 0x7;
9955 switch (funct) {
9956 case I8_BTEQZ:
9957 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9958 ((int8_t)ctx->opcode) << 1);
9959 break;
9960 case I8_BTNEZ:
9961 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9962 ((int8_t)ctx->opcode) << 1);
9963 break;
9964 case I8_SWRASP:
9965 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
9966 break;
9967 case I8_ADJSP:
9968 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
9969 ((int8_t)ctx->opcode) << 3);
9970 break;
9971 case I8_SVRS:
9973 int do_ra = ctx->opcode & (1 << 6);
9974 int do_s0 = ctx->opcode & (1 << 5);
9975 int do_s1 = ctx->opcode & (1 << 4);
9976 int framesize = ctx->opcode & 0xf;
9978 if (framesize == 0) {
9979 framesize = 128;
9980 } else {
9981 framesize = framesize << 3;
9984 if (ctx->opcode & (1 << 7)) {
9985 gen_mips16_save(ctx, 0, 0,
9986 do_ra, do_s0, do_s1, framesize);
9987 } else {
9988 gen_mips16_restore(ctx, 0, 0,
9989 do_ra, do_s0, do_s1, framesize);
9992 break;
9993 case I8_MOV32R:
9995 int rz = xlat(ctx->opcode & 0x7);
9997 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9998 ((ctx->opcode >> 5) & 0x7);
9999 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
10001 break;
10002 case I8_MOVR32:
10003 reg32 = ctx->opcode & 0x1f;
10004 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
10005 break;
10006 default:
10007 generate_exception(ctx, EXCP_RI);
10008 break;
10011 break;
10012 case M16_OPC_LI:
10014 int16_t imm = (uint8_t) ctx->opcode;
10016 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
10018 break;
10019 case M16_OPC_CMPI:
10021 int16_t imm = (uint8_t) ctx->opcode;
10022 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
10024 break;
10025 #if defined(TARGET_MIPS64)
10026 case M16_OPC_SD:
10027 check_mips_64(ctx);
10028 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
10029 break;
10030 #endif
10031 case M16_OPC_LB:
10032 gen_ld(ctx, OPC_LB, ry, rx, offset);
10033 break;
10034 case M16_OPC_LH:
10035 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
10036 break;
10037 case M16_OPC_LWSP:
10038 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
10039 break;
10040 case M16_OPC_LW:
10041 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
10042 break;
10043 case M16_OPC_LBU:
10044 gen_ld(ctx, OPC_LBU, ry, rx, offset);
10045 break;
10046 case M16_OPC_LHU:
10047 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
10048 break;
10049 case M16_OPC_LWPC:
10050 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
10051 break;
10052 #if defined (TARGET_MIPS64)
10053 case M16_OPC_LWU:
10054 check_mips_64(ctx);
10055 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
10056 break;
10057 #endif
10058 case M16_OPC_SB:
10059 gen_st(ctx, OPC_SB, ry, rx, offset);
10060 break;
10061 case M16_OPC_SH:
10062 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
10063 break;
10064 case M16_OPC_SWSP:
10065 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
10066 break;
10067 case M16_OPC_SW:
10068 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
10069 break;
10070 case M16_OPC_RRR:
10072 int rz = xlat((ctx->opcode >> 2) & 0x7);
10073 int mips32_op;
10075 switch (ctx->opcode & 0x3) {
10076 case RRR_ADDU:
10077 mips32_op = OPC_ADDU;
10078 break;
10079 case RRR_SUBU:
10080 mips32_op = OPC_SUBU;
10081 break;
10082 #if defined(TARGET_MIPS64)
10083 case RRR_DADDU:
10084 mips32_op = OPC_DADDU;
10085 check_mips_64(ctx);
10086 break;
10087 case RRR_DSUBU:
10088 mips32_op = OPC_DSUBU;
10089 check_mips_64(ctx);
10090 break;
10091 #endif
10092 default:
10093 generate_exception(ctx, EXCP_RI);
10094 goto done;
10097 gen_arith(ctx, mips32_op, rz, rx, ry);
10098 done:
10101 break;
10102 case M16_OPC_RR:
10103 switch (op1) {
10104 case RR_JR:
10106 int nd = (ctx->opcode >> 7) & 0x1;
10107 int link = (ctx->opcode >> 6) & 0x1;
10108 int ra = (ctx->opcode >> 5) & 0x1;
10110 if (link) {
10111 op = nd ? OPC_JALRC : OPC_JALRS;
10112 } else {
10113 op = OPC_JR;
10116 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
10118 break;
10119 case RR_SDBBP:
10120 /* XXX: not clear which exception should be raised
10121 * when in debug mode...
10123 check_insn(ctx, ISA_MIPS32);
10124 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10125 generate_exception(ctx, EXCP_DBp);
10126 } else {
10127 generate_exception(ctx, EXCP_DBp);
10129 break;
10130 case RR_SLT:
10131 gen_slt(ctx, OPC_SLT, 24, rx, ry);
10132 break;
10133 case RR_SLTU:
10134 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
10135 break;
10136 case RR_BREAK:
10137 generate_exception(ctx, EXCP_BREAK);
10138 break;
10139 case RR_SLLV:
10140 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
10141 break;
10142 case RR_SRLV:
10143 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
10144 break;
10145 case RR_SRAV:
10146 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
10147 break;
10148 #if defined (TARGET_MIPS64)
10149 case RR_DSRL:
10150 check_mips_64(ctx);
10151 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
10152 break;
10153 #endif
10154 case RR_CMP:
10155 gen_logic(ctx, OPC_XOR, 24, rx, ry);
10156 break;
10157 case RR_NEG:
10158 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
10159 break;
10160 case RR_AND:
10161 gen_logic(ctx, OPC_AND, rx, rx, ry);
10162 break;
10163 case RR_OR:
10164 gen_logic(ctx, OPC_OR, rx, rx, ry);
10165 break;
10166 case RR_XOR:
10167 gen_logic(ctx, OPC_XOR, rx, rx, ry);
10168 break;
10169 case RR_NOT:
10170 gen_logic(ctx, OPC_NOR, rx, ry, 0);
10171 break;
10172 case RR_MFHI:
10173 gen_HILO(ctx, OPC_MFHI, 0, rx);
10174 break;
10175 case RR_CNVT:
10176 switch (cnvt_op) {
10177 case RR_RY_CNVT_ZEB:
10178 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10179 break;
10180 case RR_RY_CNVT_ZEH:
10181 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10182 break;
10183 case RR_RY_CNVT_SEB:
10184 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10185 break;
10186 case RR_RY_CNVT_SEH:
10187 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10188 break;
10189 #if defined (TARGET_MIPS64)
10190 case RR_RY_CNVT_ZEW:
10191 check_mips_64(ctx);
10192 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10193 break;
10194 case RR_RY_CNVT_SEW:
10195 check_mips_64(ctx);
10196 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10197 break;
10198 #endif
10199 default:
10200 generate_exception(ctx, EXCP_RI);
10201 break;
10203 break;
10204 case RR_MFLO:
10205 gen_HILO(ctx, OPC_MFLO, 0, rx);
10206 break;
10207 #if defined (TARGET_MIPS64)
10208 case RR_DSRA:
10209 check_mips_64(ctx);
10210 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
10211 break;
10212 case RR_DSLLV:
10213 check_mips_64(ctx);
10214 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
10215 break;
10216 case RR_DSRLV:
10217 check_mips_64(ctx);
10218 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
10219 break;
10220 case RR_DSRAV:
10221 check_mips_64(ctx);
10222 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
10223 break;
10224 #endif
10225 case RR_MULT:
10226 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
10227 break;
10228 case RR_MULTU:
10229 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
10230 break;
10231 case RR_DIV:
10232 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
10233 break;
10234 case RR_DIVU:
10235 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
10236 break;
10237 #if defined (TARGET_MIPS64)
10238 case RR_DMULT:
10239 check_mips_64(ctx);
10240 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
10241 break;
10242 case RR_DMULTU:
10243 check_mips_64(ctx);
10244 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
10245 break;
10246 case RR_DDIV:
10247 check_mips_64(ctx);
10248 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
10249 break;
10250 case RR_DDIVU:
10251 check_mips_64(ctx);
10252 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
10253 break;
10254 #endif
10255 default:
10256 generate_exception(ctx, EXCP_RI);
10257 break;
10259 break;
10260 case M16_OPC_EXTEND:
10261 decode_extended_mips16_opc(env, ctx);
10262 n_bytes = 4;
10263 break;
10264 #if defined(TARGET_MIPS64)
10265 case M16_OPC_I64:
10266 funct = (ctx->opcode >> 8) & 0x7;
10267 decode_i64_mips16(ctx, ry, funct, offset, 0);
10268 break;
10269 #endif
10270 default:
10271 generate_exception(ctx, EXCP_RI);
10272 break;
10275 return n_bytes;
10278 /* microMIPS extension to MIPS32/MIPS64 */
10281 * microMIPS32/microMIPS64 major opcodes
10283 * 1. MIPS Architecture for Programmers Volume II-B:
10284 * The microMIPS32 Instruction Set (Revision 3.05)
10286 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
10288 * 2. MIPS Architecture For Programmers Volume II-A:
10289 * The MIPS64 Instruction Set (Revision 3.51)
10292 enum {
10293 POOL32A = 0x00,
10294 POOL16A = 0x01,
10295 LBU16 = 0x02,
10296 MOVE16 = 0x03,
10297 ADDI32 = 0x04,
10298 LBU32 = 0x05,
10299 SB32 = 0x06,
10300 LB32 = 0x07,
10302 POOL32B = 0x08,
10303 POOL16B = 0x09,
10304 LHU16 = 0x0a,
10305 ANDI16 = 0x0b,
10306 ADDIU32 = 0x0c,
10307 LHU32 = 0x0d,
10308 SH32 = 0x0e,
10309 LH32 = 0x0f,
10311 POOL32I = 0x10,
10312 POOL16C = 0x11,
10313 LWSP16 = 0x12,
10314 POOL16D = 0x13,
10315 ORI32 = 0x14,
10316 POOL32F = 0x15,
10317 POOL32S = 0x16, /* MIPS64 */
10318 DADDIU32 = 0x17, /* MIPS64 */
10320 /* 0x1f is reserved */
10321 POOL32C = 0x18,
10322 LWGP16 = 0x19,
10323 LW16 = 0x1a,
10324 POOL16E = 0x1b,
10325 XORI32 = 0x1c,
10326 JALS32 = 0x1d,
10327 ADDIUPC = 0x1e,
10329 /* 0x20 is reserved */
10330 RES_20 = 0x20,
10331 POOL16F = 0x21,
10332 SB16 = 0x22,
10333 BEQZ16 = 0x23,
10334 SLTI32 = 0x24,
10335 BEQ32 = 0x25,
10336 SWC132 = 0x26,
10337 LWC132 = 0x27,
10339 /* 0x28 and 0x29 are reserved */
10340 RES_28 = 0x28,
10341 RES_29 = 0x29,
10342 SH16 = 0x2a,
10343 BNEZ16 = 0x2b,
10344 SLTIU32 = 0x2c,
10345 BNE32 = 0x2d,
10346 SDC132 = 0x2e,
10347 LDC132 = 0x2f,
10349 /* 0x30 and 0x31 are reserved */
10350 RES_30 = 0x30,
10351 RES_31 = 0x31,
10352 SWSP16 = 0x32,
10353 B16 = 0x33,
10354 ANDI32 = 0x34,
10355 J32 = 0x35,
10356 SD32 = 0x36, /* MIPS64 */
10357 LD32 = 0x37, /* MIPS64 */
10359 /* 0x38 and 0x39 are reserved */
10360 RES_38 = 0x38,
10361 RES_39 = 0x39,
10362 SW16 = 0x3a,
10363 LI16 = 0x3b,
10364 JALX32 = 0x3c,
10365 JAL32 = 0x3d,
10366 SW32 = 0x3e,
10367 LW32 = 0x3f
10370 /* POOL32A encoding of minor opcode field */
10372 enum {
10373 /* These opcodes are distinguished only by bits 9..6; those bits are
10374 * what are recorded below. */
10375 SLL32 = 0x0,
10376 SRL32 = 0x1,
10377 SRA = 0x2,
10378 ROTR = 0x3,
10380 SLLV = 0x0,
10381 SRLV = 0x1,
10382 SRAV = 0x2,
10383 ROTRV = 0x3,
10384 ADD = 0x4,
10385 ADDU32 = 0x5,
10386 SUB = 0x6,
10387 SUBU32 = 0x7,
10388 MUL = 0x8,
10389 AND = 0x9,
10390 OR32 = 0xa,
10391 NOR = 0xb,
10392 XOR32 = 0xc,
10393 SLT = 0xd,
10394 SLTU = 0xe,
10396 MOVN = 0x0,
10397 MOVZ = 0x1,
10398 LWXS = 0x4,
10400 /* The following can be distinguished by their lower 6 bits. */
10401 INS = 0x0c,
10402 EXT = 0x2c,
10403 POOL32AXF = 0x3c
10406 /* POOL32AXF encoding of minor opcode field extension */
10409 * 1. MIPS Architecture for Programmers Volume II-B:
10410 * The microMIPS32 Instruction Set (Revision 3.05)
10412 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
10414 * 2. MIPS Architecture for Programmers VolumeIV-e:
10415 * The MIPS DSP Application-Specific Extension
10416 * to the microMIPS32 Architecture (Revision 2.34)
10418 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
10421 enum {
10422 /* bits 11..6 */
10423 TEQ = 0x00,
10424 TGE = 0x08,
10425 TGEU = 0x10,
10426 TLT = 0x20,
10427 TLTU = 0x28,
10428 TNE = 0x30,
10430 MFC0 = 0x03,
10431 MTC0 = 0x0b,
10433 /* begin of microMIPS32 DSP */
10435 /* bits 13..12 for 0x01 */
10436 MFHI_ACC = 0x0,
10437 MFLO_ACC = 0x1,
10438 MTHI_ACC = 0x2,
10439 MTLO_ACC = 0x3,
10441 /* bits 13..12 for 0x2a */
10442 MADD_ACC = 0x0,
10443 MADDU_ACC = 0x1,
10444 MSUB_ACC = 0x2,
10445 MSUBU_ACC = 0x3,
10447 /* bits 13..12 for 0x32 */
10448 MULT_ACC = 0x0,
10449 MULTU_ACC = 0x1,
10451 /* end of microMIPS32 DSP */
10453 /* bits 15..12 for 0x2c */
10454 SEB = 0x2,
10455 SEH = 0x3,
10456 CLO = 0x4,
10457 CLZ = 0x5,
10458 RDHWR = 0x6,
10459 WSBH = 0x7,
10460 MULT = 0x8,
10461 MULTU = 0x9,
10462 DIV = 0xa,
10463 DIVU = 0xb,
10464 MADD = 0xc,
10465 MADDU = 0xd,
10466 MSUB = 0xe,
10467 MSUBU = 0xf,
10469 /* bits 15..12 for 0x34 */
10470 MFC2 = 0x4,
10471 MTC2 = 0x5,
10472 MFHC2 = 0x8,
10473 MTHC2 = 0x9,
10474 CFC2 = 0xc,
10475 CTC2 = 0xd,
10477 /* bits 15..12 for 0x3c */
10478 JALR = 0x0,
10479 JR = 0x0, /* alias */
10480 JALR_HB = 0x1,
10481 JALRS = 0x4,
10482 JALRS_HB = 0x5,
10484 /* bits 15..12 for 0x05 */
10485 RDPGPR = 0xe,
10486 WRPGPR = 0xf,
10488 /* bits 15..12 for 0x0d */
10489 TLBP = 0x0,
10490 TLBR = 0x1,
10491 TLBWI = 0x2,
10492 TLBWR = 0x3,
10493 WAIT = 0x9,
10494 IRET = 0xd,
10495 DERET = 0xe,
10496 ERET = 0xf,
10498 /* bits 15..12 for 0x15 */
10499 DMT = 0x0,
10500 DVPE = 0x1,
10501 EMT = 0x2,
10502 EVPE = 0x3,
10504 /* bits 15..12 for 0x1d */
10505 DI = 0x4,
10506 EI = 0x5,
10508 /* bits 15..12 for 0x2d */
10509 SYNC = 0x6,
10510 SYSCALL = 0x8,
10511 SDBBP = 0xd,
10513 /* bits 15..12 for 0x35 */
10514 MFHI32 = 0x0,
10515 MFLO32 = 0x1,
10516 MTHI32 = 0x2,
10517 MTLO32 = 0x3,
10520 /* POOL32B encoding of minor opcode field (bits 15..12) */
10522 enum {
10523 LWC2 = 0x0,
10524 LWP = 0x1,
10525 LDP = 0x4,
10526 LWM32 = 0x5,
10527 CACHE = 0x6,
10528 LDM = 0x7,
10529 SWC2 = 0x8,
10530 SWP = 0x9,
10531 SDP = 0xc,
10532 SWM32 = 0xd,
10533 SDM = 0xf
10536 /* POOL32C encoding of minor opcode field (bits 15..12) */
10538 enum {
10539 LWL = 0x0,
10540 SWL = 0x8,
10541 LWR = 0x1,
10542 SWR = 0x9,
10543 PREF = 0x2,
10544 /* 0xa is reserved */
10545 LL = 0x3,
10546 SC = 0xb,
10547 LDL = 0x4,
10548 SDL = 0xc,
10549 LDR = 0x5,
10550 SDR = 0xd,
10551 /* 0x6 is reserved */
10552 LWU = 0xe,
10553 LLD = 0x7,
10554 SCD = 0xf
10557 /* POOL32F encoding of minor opcode field (bits 5..0) */
10559 enum {
10560 /* These are the bit 7..6 values */
10561 ADD_FMT = 0x0,
10562 MOVN_FMT = 0x0,
10564 SUB_FMT = 0x1,
10565 MOVZ_FMT = 0x1,
10567 MUL_FMT = 0x2,
10569 DIV_FMT = 0x3,
10571 /* These are the bit 8..6 values */
10572 RSQRT2_FMT = 0x0,
10573 MOVF_FMT = 0x0,
10575 LWXC1 = 0x1,
10576 MOVT_FMT = 0x1,
10578 PLL_PS = 0x2,
10579 SWXC1 = 0x2,
10581 PLU_PS = 0x3,
10582 LDXC1 = 0x3,
10584 PUL_PS = 0x4,
10585 SDXC1 = 0x4,
10586 RECIP2_FMT = 0x4,
10588 PUU_PS = 0x5,
10589 LUXC1 = 0x5,
10591 CVT_PS_S = 0x6,
10592 SUXC1 = 0x6,
10593 ADDR_PS = 0x6,
10594 PREFX = 0x6,
10596 MULR_PS = 0x7,
10598 MADD_S = 0x01,
10599 MADD_D = 0x09,
10600 MADD_PS = 0x11,
10601 ALNV_PS = 0x19,
10602 MSUB_S = 0x21,
10603 MSUB_D = 0x29,
10604 MSUB_PS = 0x31,
10606 NMADD_S = 0x02,
10607 NMADD_D = 0x0a,
10608 NMADD_PS = 0x12,
10609 NMSUB_S = 0x22,
10610 NMSUB_D = 0x2a,
10611 NMSUB_PS = 0x32,
10613 POOL32FXF = 0x3b,
10615 CABS_COND_FMT = 0x1c, /* MIPS3D */
10616 C_COND_FMT = 0x3c
10619 /* POOL32Fxf encoding of minor opcode extension field */
10621 enum {
10622 CVT_L = 0x04,
10623 RSQRT_FMT = 0x08,
10624 FLOOR_L = 0x0c,
10625 CVT_PW_PS = 0x1c,
10626 CVT_W = 0x24,
10627 SQRT_FMT = 0x28,
10628 FLOOR_W = 0x2c,
10629 CVT_PS_PW = 0x3c,
10630 CFC1 = 0x40,
10631 RECIP_FMT = 0x48,
10632 CEIL_L = 0x4c,
10633 CTC1 = 0x60,
10634 CEIL_W = 0x6c,
10635 MFC1 = 0x80,
10636 CVT_S_PL = 0x84,
10637 TRUNC_L = 0x8c,
10638 MTC1 = 0xa0,
10639 CVT_S_PU = 0xa4,
10640 TRUNC_W = 0xac,
10641 MFHC1 = 0xc0,
10642 ROUND_L = 0xcc,
10643 MTHC1 = 0xe0,
10644 ROUND_W = 0xec,
10646 MOV_FMT = 0x01,
10647 MOVF = 0x05,
10648 ABS_FMT = 0x0d,
10649 RSQRT1_FMT = 0x1d,
10650 MOVT = 0x25,
10651 NEG_FMT = 0x2d,
10652 CVT_D = 0x4d,
10653 RECIP1_FMT = 0x5d,
10654 CVT_S = 0x6d
10657 /* POOL32I encoding of minor opcode field (bits 25..21) */
10659 enum {
10660 BLTZ = 0x00,
10661 BLTZAL = 0x01,
10662 BGEZ = 0x02,
10663 BGEZAL = 0x03,
10664 BLEZ = 0x04,
10665 BNEZC = 0x05,
10666 BGTZ = 0x06,
10667 BEQZC = 0x07,
10668 TLTI = 0x08,
10669 TGEI = 0x09,
10670 TLTIU = 0x0a,
10671 TGEIU = 0x0b,
10672 TNEI = 0x0c,
10673 LUI = 0x0d,
10674 TEQI = 0x0e,
10675 SYNCI = 0x10,
10676 BLTZALS = 0x11,
10677 BGEZALS = 0x13,
10678 BC2F = 0x14,
10679 BC2T = 0x15,
10680 BPOSGE64 = 0x1a,
10681 BPOSGE32 = 0x1b,
10682 /* These overlap and are distinguished by bit16 of the instruction */
10683 BC1F = 0x1c,
10684 BC1T = 0x1d,
10685 BC1ANY2F = 0x1c,
10686 BC1ANY2T = 0x1d,
10687 BC1ANY4F = 0x1e,
10688 BC1ANY4T = 0x1f
10691 /* POOL16A encoding of minor opcode field */
10693 enum {
10694 ADDU16 = 0x0,
10695 SUBU16 = 0x1
10698 /* POOL16B encoding of minor opcode field */
10700 enum {
10701 SLL16 = 0x0,
10702 SRL16 = 0x1
10705 /* POOL16C encoding of minor opcode field */
10707 enum {
10708 NOT16 = 0x00,
10709 XOR16 = 0x04,
10710 AND16 = 0x08,
10711 OR16 = 0x0c,
10712 LWM16 = 0x10,
10713 SWM16 = 0x14,
10714 JR16 = 0x18,
10715 JRC16 = 0x1a,
10716 JALR16 = 0x1c,
10717 JALR16S = 0x1e,
10718 MFHI16 = 0x20,
10719 MFLO16 = 0x24,
10720 BREAK16 = 0x28,
10721 SDBBP16 = 0x2c,
10722 JRADDIUSP = 0x30
10725 /* POOL16D encoding of minor opcode field */
10727 enum {
10728 ADDIUS5 = 0x0,
10729 ADDIUSP = 0x1
10732 /* POOL16E encoding of minor opcode field */
10734 enum {
10735 ADDIUR2 = 0x0,
10736 ADDIUR1SP = 0x1
10739 static int mmreg (int r)
10741 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10743 return map[r];
10746 /* Used for 16-bit store instructions. */
10747 static int mmreg2 (int r)
10749 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10751 return map[r];
10754 #define uMIPS_RD(op) ((op >> 7) & 0x7)
10755 #define uMIPS_RS(op) ((op >> 4) & 0x7)
10756 #define uMIPS_RS2(op) uMIPS_RS(op)
10757 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
10758 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10759 #define uMIPS_RS5(op) (op & 0x1f)
10761 /* Signed immediate */
10762 #define SIMM(op, start, width) \
10763 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10764 << (32-width)) \
10765 >> (32-width))
10766 /* Zero-extended immediate */
10767 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10769 static void gen_addiur1sp(DisasContext *ctx)
10771 int rd = mmreg(uMIPS_RD(ctx->opcode));
10773 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
10776 static void gen_addiur2(DisasContext *ctx)
10778 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10779 int rd = mmreg(uMIPS_RD(ctx->opcode));
10780 int rs = mmreg(uMIPS_RS(ctx->opcode));
10782 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
10785 static void gen_addiusp(DisasContext *ctx)
10787 int encoded = ZIMM(ctx->opcode, 1, 9);
10788 int decoded;
10790 if (encoded <= 1) {
10791 decoded = 256 + encoded;
10792 } else if (encoded <= 255) {
10793 decoded = encoded;
10794 } else if (encoded <= 509) {
10795 decoded = encoded - 512;
10796 } else {
10797 decoded = encoded - 768;
10800 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
10803 static void gen_addius5(DisasContext *ctx)
10805 int imm = SIMM(ctx->opcode, 1, 4);
10806 int rd = (ctx->opcode >> 5) & 0x1f;
10808 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
10811 static void gen_andi16(DisasContext *ctx)
10813 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10814 31, 32, 63, 64, 255, 32768, 65535 };
10815 int rd = mmreg(uMIPS_RD(ctx->opcode));
10816 int rs = mmreg(uMIPS_RS(ctx->opcode));
10817 int encoded = ZIMM(ctx->opcode, 0, 4);
10819 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
10822 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10823 int base, int16_t offset)
10825 const char *opn = "ldst_multiple";
10826 TCGv t0, t1;
10827 TCGv_i32 t2;
10829 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10830 generate_exception(ctx, EXCP_RI);
10831 return;
10834 t0 = tcg_temp_new();
10836 gen_base_offset_addr(ctx, t0, base, offset);
10838 t1 = tcg_const_tl(reglist);
10839 t2 = tcg_const_i32(ctx->mem_idx);
10841 save_cpu_state(ctx, 1);
10842 switch (opc) {
10843 case LWM32:
10844 gen_helper_lwm(cpu_env, t0, t1, t2);
10845 opn = "lwm";
10846 break;
10847 case SWM32:
10848 gen_helper_swm(cpu_env, t0, t1, t2);
10849 opn = "swm";
10850 break;
10851 #ifdef TARGET_MIPS64
10852 case LDM:
10853 gen_helper_ldm(cpu_env, t0, t1, t2);
10854 opn = "ldm";
10855 break;
10856 case SDM:
10857 gen_helper_sdm(cpu_env, t0, t1, t2);
10858 opn = "sdm";
10859 break;
10860 #endif
10862 (void)opn;
10863 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10864 tcg_temp_free(t0);
10865 tcg_temp_free(t1);
10866 tcg_temp_free_i32(t2);
10870 static void gen_pool16c_insn(DisasContext *ctx)
10872 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10873 int rs = mmreg(ctx->opcode & 0x7);
10874 int opc;
10876 switch (((ctx->opcode) >> 4) & 0x3f) {
10877 case NOT16 + 0:
10878 case NOT16 + 1:
10879 case NOT16 + 2:
10880 case NOT16 + 3:
10881 gen_logic(ctx, OPC_NOR, rd, rs, 0);
10882 break;
10883 case XOR16 + 0:
10884 case XOR16 + 1:
10885 case XOR16 + 2:
10886 case XOR16 + 3:
10887 gen_logic(ctx, OPC_XOR, rd, rd, rs);
10888 break;
10889 case AND16 + 0:
10890 case AND16 + 1:
10891 case AND16 + 2:
10892 case AND16 + 3:
10893 gen_logic(ctx, OPC_AND, rd, rd, rs);
10894 break;
10895 case OR16 + 0:
10896 case OR16 + 1:
10897 case OR16 + 2:
10898 case OR16 + 3:
10899 gen_logic(ctx, OPC_OR, rd, rd, rs);
10900 break;
10901 case LWM16 + 0:
10902 case LWM16 + 1:
10903 case LWM16 + 2:
10904 case LWM16 + 3:
10906 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10907 int offset = ZIMM(ctx->opcode, 0, 4);
10909 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10910 29, offset << 2);
10912 break;
10913 case SWM16 + 0:
10914 case SWM16 + 1:
10915 case SWM16 + 2:
10916 case SWM16 + 3:
10918 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10919 int offset = ZIMM(ctx->opcode, 0, 4);
10921 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10922 29, offset << 2);
10924 break;
10925 case JR16 + 0:
10926 case JR16 + 1:
10928 int reg = ctx->opcode & 0x1f;
10930 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10932 break;
10933 case JRC16 + 0:
10934 case JRC16 + 1:
10936 int reg = ctx->opcode & 0x1f;
10938 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10939 /* Let normal delay slot handling in our caller take us
10940 to the branch target. */
10942 break;
10943 case JALR16 + 0:
10944 case JALR16 + 1:
10945 opc = OPC_JALR;
10946 goto do_jalr;
10947 case JALR16S + 0:
10948 case JALR16S + 1:
10949 opc = OPC_JALRS;
10950 do_jalr:
10952 int reg = ctx->opcode & 0x1f;
10954 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10956 break;
10957 case MFHI16 + 0:
10958 case MFHI16 + 1:
10959 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
10960 break;
10961 case MFLO16 + 0:
10962 case MFLO16 + 1:
10963 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
10964 break;
10965 case BREAK16:
10966 generate_exception(ctx, EXCP_BREAK);
10967 break;
10968 case SDBBP16:
10969 /* XXX: not clear which exception should be raised
10970 * when in debug mode...
10972 check_insn(ctx, ISA_MIPS32);
10973 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10974 generate_exception(ctx, EXCP_DBp);
10975 } else {
10976 generate_exception(ctx, EXCP_DBp);
10978 break;
10979 case JRADDIUSP + 0:
10980 case JRADDIUSP + 1:
10982 int imm = ZIMM(ctx->opcode, 0, 5);
10984 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
10985 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
10986 /* Let normal delay slot handling in our caller take us
10987 to the branch target. */
10989 break;
10990 default:
10991 generate_exception(ctx, EXCP_RI);
10992 break;
10996 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10998 TCGv t0 = tcg_temp_new();
10999 TCGv t1 = tcg_temp_new();
11001 gen_load_gpr(t0, base);
11003 if (index != 0) {
11004 gen_load_gpr(t1, index);
11005 tcg_gen_shli_tl(t1, t1, 2);
11006 gen_op_addr_add(ctx, t0, t1, t0);
11009 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11010 gen_store_gpr(t1, rd);
11012 tcg_temp_free(t0);
11013 tcg_temp_free(t1);
11016 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
11017 int base, int16_t offset)
11019 const char *opn = "ldst_pair";
11020 TCGv t0, t1;
11022 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
11023 generate_exception(ctx, EXCP_RI);
11024 return;
11027 t0 = tcg_temp_new();
11028 t1 = tcg_temp_new();
11030 gen_base_offset_addr(ctx, t0, base, offset);
11032 switch (opc) {
11033 case LWP:
11034 if (rd == base) {
11035 generate_exception(ctx, EXCP_RI);
11036 return;
11038 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11039 gen_store_gpr(t1, rd);
11040 tcg_gen_movi_tl(t1, 4);
11041 gen_op_addr_add(ctx, t0, t0, t1);
11042 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11043 gen_store_gpr(t1, rd+1);
11044 opn = "lwp";
11045 break;
11046 case SWP:
11047 gen_load_gpr(t1, rd);
11048 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11049 tcg_gen_movi_tl(t1, 4);
11050 gen_op_addr_add(ctx, t0, t0, t1);
11051 gen_load_gpr(t1, rd+1);
11052 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11053 opn = "swp";
11054 break;
11055 #ifdef TARGET_MIPS64
11056 case LDP:
11057 if (rd == base) {
11058 generate_exception(ctx, EXCP_RI);
11059 return;
11061 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11062 gen_store_gpr(t1, rd);
11063 tcg_gen_movi_tl(t1, 8);
11064 gen_op_addr_add(ctx, t0, t0, t1);
11065 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11066 gen_store_gpr(t1, rd+1);
11067 opn = "ldp";
11068 break;
11069 case SDP:
11070 gen_load_gpr(t1, rd);
11071 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11072 tcg_gen_movi_tl(t1, 8);
11073 gen_op_addr_add(ctx, t0, t0, t1);
11074 gen_load_gpr(t1, rd+1);
11075 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11076 opn = "sdp";
11077 break;
11078 #endif
11080 (void)opn; /* avoid a compiler warning */
11081 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
11082 tcg_temp_free(t0);
11083 tcg_temp_free(t1);
11086 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
11088 int extension = (ctx->opcode >> 6) & 0x3f;
11089 int minor = (ctx->opcode >> 12) & 0xf;
11090 uint32_t mips32_op;
11092 switch (extension) {
11093 case TEQ:
11094 mips32_op = OPC_TEQ;
11095 goto do_trap;
11096 case TGE:
11097 mips32_op = OPC_TGE;
11098 goto do_trap;
11099 case TGEU:
11100 mips32_op = OPC_TGEU;
11101 goto do_trap;
11102 case TLT:
11103 mips32_op = OPC_TLT;
11104 goto do_trap;
11105 case TLTU:
11106 mips32_op = OPC_TLTU;
11107 goto do_trap;
11108 case TNE:
11109 mips32_op = OPC_TNE;
11110 do_trap:
11111 gen_trap(ctx, mips32_op, rs, rt, -1);
11112 break;
11113 #ifndef CONFIG_USER_ONLY
11114 case MFC0:
11115 case MFC0 + 32:
11116 check_cp0_enabled(ctx);
11117 if (rt == 0) {
11118 /* Treat as NOP. */
11119 break;
11121 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
11122 break;
11123 case MTC0:
11124 case MTC0 + 32:
11125 check_cp0_enabled(ctx);
11127 TCGv t0 = tcg_temp_new();
11129 gen_load_gpr(t0, rt);
11130 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
11131 tcg_temp_free(t0);
11133 break;
11134 #endif
11135 case 0x2a:
11136 switch (minor & 3) {
11137 case MADD_ACC:
11138 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
11139 break;
11140 case MADDU_ACC:
11141 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
11142 break;
11143 case MSUB_ACC:
11144 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
11145 break;
11146 case MSUBU_ACC:
11147 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
11148 break;
11149 default:
11150 goto pool32axf_invalid;
11152 break;
11153 case 0x32:
11154 switch (minor & 3) {
11155 case MULT_ACC:
11156 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
11157 break;
11158 case MULTU_ACC:
11159 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
11160 break;
11161 default:
11162 goto pool32axf_invalid;
11164 break;
11165 case 0x2c:
11166 switch (minor) {
11167 case SEB:
11168 gen_bshfl(ctx, OPC_SEB, rs, rt);
11169 break;
11170 case SEH:
11171 gen_bshfl(ctx, OPC_SEH, rs, rt);
11172 break;
11173 case CLO:
11174 mips32_op = OPC_CLO;
11175 goto do_cl;
11176 case CLZ:
11177 mips32_op = OPC_CLZ;
11178 do_cl:
11179 check_insn(ctx, ISA_MIPS32);
11180 gen_cl(ctx, mips32_op, rt, rs);
11181 break;
11182 case RDHWR:
11183 gen_rdhwr(ctx, rt, rs);
11184 break;
11185 case WSBH:
11186 gen_bshfl(ctx, OPC_WSBH, rs, rt);
11187 break;
11188 case MULT:
11189 mips32_op = OPC_MULT;
11190 goto do_mul;
11191 case MULTU:
11192 mips32_op = OPC_MULTU;
11193 goto do_mul;
11194 case DIV:
11195 mips32_op = OPC_DIV;
11196 goto do_div;
11197 case DIVU:
11198 mips32_op = OPC_DIVU;
11199 goto do_div;
11200 do_div:
11201 check_insn(ctx, ISA_MIPS32);
11202 gen_muldiv(ctx, mips32_op, 0, rs, rt);
11203 break;
11204 case MADD:
11205 mips32_op = OPC_MADD;
11206 goto do_mul;
11207 case MADDU:
11208 mips32_op = OPC_MADDU;
11209 goto do_mul;
11210 case MSUB:
11211 mips32_op = OPC_MSUB;
11212 goto do_mul;
11213 case MSUBU:
11214 mips32_op = OPC_MSUBU;
11215 do_mul:
11216 check_insn(ctx, ISA_MIPS32);
11217 gen_muldiv(ctx, mips32_op, 0, rs, rt);
11218 break;
11219 default:
11220 goto pool32axf_invalid;
11222 break;
11223 case 0x34:
11224 switch (minor) {
11225 case MFC2:
11226 case MTC2:
11227 case MFHC2:
11228 case MTHC2:
11229 case CFC2:
11230 case CTC2:
11231 generate_exception_err(ctx, EXCP_CpU, 2);
11232 break;
11233 default:
11234 goto pool32axf_invalid;
11236 break;
11237 case 0x3c:
11238 switch (minor) {
11239 case JALR:
11240 case JALR_HB:
11241 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
11242 break;
11243 case JALRS:
11244 case JALRS_HB:
11245 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
11246 break;
11247 default:
11248 goto pool32axf_invalid;
11250 break;
11251 case 0x05:
11252 switch (minor) {
11253 case RDPGPR:
11254 check_cp0_enabled(ctx);
11255 check_insn(ctx, ISA_MIPS32R2);
11256 gen_load_srsgpr(rt, rs);
11257 break;
11258 case WRPGPR:
11259 check_cp0_enabled(ctx);
11260 check_insn(ctx, ISA_MIPS32R2);
11261 gen_store_srsgpr(rt, rs);
11262 break;
11263 default:
11264 goto pool32axf_invalid;
11266 break;
11267 #ifndef CONFIG_USER_ONLY
11268 case 0x0d:
11269 switch (minor) {
11270 case TLBP:
11271 mips32_op = OPC_TLBP;
11272 goto do_cp0;
11273 case TLBR:
11274 mips32_op = OPC_TLBR;
11275 goto do_cp0;
11276 case TLBWI:
11277 mips32_op = OPC_TLBWI;
11278 goto do_cp0;
11279 case TLBWR:
11280 mips32_op = OPC_TLBWR;
11281 goto do_cp0;
11282 case WAIT:
11283 mips32_op = OPC_WAIT;
11284 goto do_cp0;
11285 case DERET:
11286 mips32_op = OPC_DERET;
11287 goto do_cp0;
11288 case ERET:
11289 mips32_op = OPC_ERET;
11290 do_cp0:
11291 gen_cp0(env, ctx, mips32_op, rt, rs);
11292 break;
11293 default:
11294 goto pool32axf_invalid;
11296 break;
11297 case 0x1d:
11298 switch (minor) {
11299 case DI:
11300 check_cp0_enabled(ctx);
11302 TCGv t0 = tcg_temp_new();
11304 save_cpu_state(ctx, 1);
11305 gen_helper_di(t0, cpu_env);
11306 gen_store_gpr(t0, rs);
11307 /* Stop translation as we may have switched the execution mode */
11308 ctx->bstate = BS_STOP;
11309 tcg_temp_free(t0);
11311 break;
11312 case EI:
11313 check_cp0_enabled(ctx);
11315 TCGv t0 = tcg_temp_new();
11317 save_cpu_state(ctx, 1);
11318 gen_helper_ei(t0, cpu_env);
11319 gen_store_gpr(t0, rs);
11320 /* Stop translation as we may have switched the execution mode */
11321 ctx->bstate = BS_STOP;
11322 tcg_temp_free(t0);
11324 break;
11325 default:
11326 goto pool32axf_invalid;
11328 break;
11329 #endif
11330 case 0x2d:
11331 switch (minor) {
11332 case SYNC:
11333 /* NOP */
11334 break;
11335 case SYSCALL:
11336 generate_exception(ctx, EXCP_SYSCALL);
11337 ctx->bstate = BS_STOP;
11338 break;
11339 case SDBBP:
11340 check_insn(ctx, ISA_MIPS32);
11341 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11342 generate_exception(ctx, EXCP_DBp);
11343 } else {
11344 generate_exception(ctx, EXCP_DBp);
11346 break;
11347 default:
11348 goto pool32axf_invalid;
11350 break;
11351 case 0x01:
11352 switch (minor & 3) {
11353 case MFHI_ACC:
11354 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
11355 break;
11356 case MFLO_ACC:
11357 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
11358 break;
11359 case MTHI_ACC:
11360 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
11361 break;
11362 case MTLO_ACC:
11363 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
11364 break;
11365 default:
11366 goto pool32axf_invalid;
11368 break;
11369 case 0x35:
11370 switch (minor) {
11371 case MFHI32:
11372 gen_HILO(ctx, OPC_MFHI, 0, rs);
11373 break;
11374 case MFLO32:
11375 gen_HILO(ctx, OPC_MFLO, 0, rs);
11376 break;
11377 case MTHI32:
11378 gen_HILO(ctx, OPC_MTHI, 0, rs);
11379 break;
11380 case MTLO32:
11381 gen_HILO(ctx, OPC_MTLO, 0, rs);
11382 break;
11383 default:
11384 goto pool32axf_invalid;
11386 break;
11387 default:
11388 pool32axf_invalid:
11389 MIPS_INVAL("pool32axf");
11390 generate_exception(ctx, EXCP_RI);
11391 break;
11395 /* Values for microMIPS fmt field. Variable-width, depending on which
11396 formats the instruction supports. */
11398 enum {
11399 FMT_SD_S = 0,
11400 FMT_SD_D = 1,
11402 FMT_SDPS_S = 0,
11403 FMT_SDPS_D = 1,
11404 FMT_SDPS_PS = 2,
11406 FMT_SWL_S = 0,
11407 FMT_SWL_W = 1,
11408 FMT_SWL_L = 2,
11410 FMT_DWL_D = 0,
11411 FMT_DWL_W = 1,
11412 FMT_DWL_L = 2
11415 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
11417 int extension = (ctx->opcode >> 6) & 0x3ff;
11418 uint32_t mips32_op;
11420 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
11421 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
11422 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
11424 switch (extension) {
11425 case FLOAT_1BIT_FMT(CFC1, 0):
11426 mips32_op = OPC_CFC1;
11427 goto do_cp1;
11428 case FLOAT_1BIT_FMT(CTC1, 0):
11429 mips32_op = OPC_CTC1;
11430 goto do_cp1;
11431 case FLOAT_1BIT_FMT(MFC1, 0):
11432 mips32_op = OPC_MFC1;
11433 goto do_cp1;
11434 case FLOAT_1BIT_FMT(MTC1, 0):
11435 mips32_op = OPC_MTC1;
11436 goto do_cp1;
11437 case FLOAT_1BIT_FMT(MFHC1, 0):
11438 mips32_op = OPC_MFHC1;
11439 goto do_cp1;
11440 case FLOAT_1BIT_FMT(MTHC1, 0):
11441 mips32_op = OPC_MTHC1;
11442 do_cp1:
11443 gen_cp1(ctx, mips32_op, rt, rs);
11444 break;
11446 /* Reciprocal square root */
11447 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
11448 mips32_op = OPC_RSQRT_S;
11449 goto do_unaryfp;
11450 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
11451 mips32_op = OPC_RSQRT_D;
11452 goto do_unaryfp;
11454 /* Square root */
11455 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
11456 mips32_op = OPC_SQRT_S;
11457 goto do_unaryfp;
11458 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
11459 mips32_op = OPC_SQRT_D;
11460 goto do_unaryfp;
11462 /* Reciprocal */
11463 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
11464 mips32_op = OPC_RECIP_S;
11465 goto do_unaryfp;
11466 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
11467 mips32_op = OPC_RECIP_D;
11468 goto do_unaryfp;
11470 /* Floor */
11471 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
11472 mips32_op = OPC_FLOOR_L_S;
11473 goto do_unaryfp;
11474 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
11475 mips32_op = OPC_FLOOR_L_D;
11476 goto do_unaryfp;
11477 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
11478 mips32_op = OPC_FLOOR_W_S;
11479 goto do_unaryfp;
11480 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
11481 mips32_op = OPC_FLOOR_W_D;
11482 goto do_unaryfp;
11484 /* Ceiling */
11485 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
11486 mips32_op = OPC_CEIL_L_S;
11487 goto do_unaryfp;
11488 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
11489 mips32_op = OPC_CEIL_L_D;
11490 goto do_unaryfp;
11491 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
11492 mips32_op = OPC_CEIL_W_S;
11493 goto do_unaryfp;
11494 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
11495 mips32_op = OPC_CEIL_W_D;
11496 goto do_unaryfp;
11498 /* Truncation */
11499 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
11500 mips32_op = OPC_TRUNC_L_S;
11501 goto do_unaryfp;
11502 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
11503 mips32_op = OPC_TRUNC_L_D;
11504 goto do_unaryfp;
11505 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
11506 mips32_op = OPC_TRUNC_W_S;
11507 goto do_unaryfp;
11508 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
11509 mips32_op = OPC_TRUNC_W_D;
11510 goto do_unaryfp;
11512 /* Round */
11513 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
11514 mips32_op = OPC_ROUND_L_S;
11515 goto do_unaryfp;
11516 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
11517 mips32_op = OPC_ROUND_L_D;
11518 goto do_unaryfp;
11519 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
11520 mips32_op = OPC_ROUND_W_S;
11521 goto do_unaryfp;
11522 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
11523 mips32_op = OPC_ROUND_W_D;
11524 goto do_unaryfp;
11526 /* Integer to floating-point conversion */
11527 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
11528 mips32_op = OPC_CVT_L_S;
11529 goto do_unaryfp;
11530 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
11531 mips32_op = OPC_CVT_L_D;
11532 goto do_unaryfp;
11533 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
11534 mips32_op = OPC_CVT_W_S;
11535 goto do_unaryfp;
11536 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
11537 mips32_op = OPC_CVT_W_D;
11538 goto do_unaryfp;
11540 /* Paired-foo conversions */
11541 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
11542 mips32_op = OPC_CVT_S_PL;
11543 goto do_unaryfp;
11544 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
11545 mips32_op = OPC_CVT_S_PU;
11546 goto do_unaryfp;
11547 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
11548 mips32_op = OPC_CVT_PW_PS;
11549 goto do_unaryfp;
11550 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
11551 mips32_op = OPC_CVT_PS_PW;
11552 goto do_unaryfp;
11554 /* Floating-point moves */
11555 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
11556 mips32_op = OPC_MOV_S;
11557 goto do_unaryfp;
11558 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
11559 mips32_op = OPC_MOV_D;
11560 goto do_unaryfp;
11561 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
11562 mips32_op = OPC_MOV_PS;
11563 goto do_unaryfp;
11565 /* Absolute value */
11566 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
11567 mips32_op = OPC_ABS_S;
11568 goto do_unaryfp;
11569 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
11570 mips32_op = OPC_ABS_D;
11571 goto do_unaryfp;
11572 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
11573 mips32_op = OPC_ABS_PS;
11574 goto do_unaryfp;
11576 /* Negation */
11577 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
11578 mips32_op = OPC_NEG_S;
11579 goto do_unaryfp;
11580 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
11581 mips32_op = OPC_NEG_D;
11582 goto do_unaryfp;
11583 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
11584 mips32_op = OPC_NEG_PS;
11585 goto do_unaryfp;
11587 /* Reciprocal square root step */
11588 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
11589 mips32_op = OPC_RSQRT1_S;
11590 goto do_unaryfp;
11591 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
11592 mips32_op = OPC_RSQRT1_D;
11593 goto do_unaryfp;
11594 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
11595 mips32_op = OPC_RSQRT1_PS;
11596 goto do_unaryfp;
11598 /* Reciprocal step */
11599 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
11600 mips32_op = OPC_RECIP1_S;
11601 goto do_unaryfp;
11602 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
11603 mips32_op = OPC_RECIP1_S;
11604 goto do_unaryfp;
11605 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
11606 mips32_op = OPC_RECIP1_PS;
11607 goto do_unaryfp;
11609 /* Conversions from double */
11610 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
11611 mips32_op = OPC_CVT_D_S;
11612 goto do_unaryfp;
11613 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
11614 mips32_op = OPC_CVT_D_W;
11615 goto do_unaryfp;
11616 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
11617 mips32_op = OPC_CVT_D_L;
11618 goto do_unaryfp;
11620 /* Conversions from single */
11621 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
11622 mips32_op = OPC_CVT_S_D;
11623 goto do_unaryfp;
11624 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
11625 mips32_op = OPC_CVT_S_W;
11626 goto do_unaryfp;
11627 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
11628 mips32_op = OPC_CVT_S_L;
11629 do_unaryfp:
11630 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
11631 break;
11633 /* Conditional moves on floating-point codes */
11634 case COND_FLOAT_MOV(MOVT, 0):
11635 case COND_FLOAT_MOV(MOVT, 1):
11636 case COND_FLOAT_MOV(MOVT, 2):
11637 case COND_FLOAT_MOV(MOVT, 3):
11638 case COND_FLOAT_MOV(MOVT, 4):
11639 case COND_FLOAT_MOV(MOVT, 5):
11640 case COND_FLOAT_MOV(MOVT, 6):
11641 case COND_FLOAT_MOV(MOVT, 7):
11642 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11643 break;
11644 case COND_FLOAT_MOV(MOVF, 0):
11645 case COND_FLOAT_MOV(MOVF, 1):
11646 case COND_FLOAT_MOV(MOVF, 2):
11647 case COND_FLOAT_MOV(MOVF, 3):
11648 case COND_FLOAT_MOV(MOVF, 4):
11649 case COND_FLOAT_MOV(MOVF, 5):
11650 case COND_FLOAT_MOV(MOVF, 6):
11651 case COND_FLOAT_MOV(MOVF, 7):
11652 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11653 break;
11654 default:
11655 MIPS_INVAL("pool32fxf");
11656 generate_exception(ctx, EXCP_RI);
11657 break;
11661 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
11662 uint16_t insn_hw1)
11664 int32_t offset;
11665 uint16_t insn;
11666 int rt, rs, rd, rr;
11667 int16_t imm;
11668 uint32_t op, minor, mips32_op;
11669 uint32_t cond, fmt, cc;
11671 insn = cpu_lduw_code(env, ctx->pc + 2);
11672 ctx->opcode = (ctx->opcode << 16) | insn;
11674 rt = (ctx->opcode >> 21) & 0x1f;
11675 rs = (ctx->opcode >> 16) & 0x1f;
11676 rd = (ctx->opcode >> 11) & 0x1f;
11677 rr = (ctx->opcode >> 6) & 0x1f;
11678 imm = (int16_t) ctx->opcode;
11680 op = (ctx->opcode >> 26) & 0x3f;
11681 switch (op) {
11682 case POOL32A:
11683 minor = ctx->opcode & 0x3f;
11684 switch (minor) {
11685 case 0x00:
11686 minor = (ctx->opcode >> 6) & 0xf;
11687 switch (minor) {
11688 case SLL32:
11689 mips32_op = OPC_SLL;
11690 goto do_shifti;
11691 case SRA:
11692 mips32_op = OPC_SRA;
11693 goto do_shifti;
11694 case SRL32:
11695 mips32_op = OPC_SRL;
11696 goto do_shifti;
11697 case ROTR:
11698 mips32_op = OPC_ROTR;
11699 do_shifti:
11700 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
11701 break;
11702 default:
11703 goto pool32a_invalid;
11705 break;
11706 case 0x10:
11707 minor = (ctx->opcode >> 6) & 0xf;
11708 switch (minor) {
11709 /* Arithmetic */
11710 case ADD:
11711 mips32_op = OPC_ADD;
11712 goto do_arith;
11713 case ADDU32:
11714 mips32_op = OPC_ADDU;
11715 goto do_arith;
11716 case SUB:
11717 mips32_op = OPC_SUB;
11718 goto do_arith;
11719 case SUBU32:
11720 mips32_op = OPC_SUBU;
11721 goto do_arith;
11722 case MUL:
11723 mips32_op = OPC_MUL;
11724 do_arith:
11725 gen_arith(ctx, mips32_op, rd, rs, rt);
11726 break;
11727 /* Shifts */
11728 case SLLV:
11729 mips32_op = OPC_SLLV;
11730 goto do_shift;
11731 case SRLV:
11732 mips32_op = OPC_SRLV;
11733 goto do_shift;
11734 case SRAV:
11735 mips32_op = OPC_SRAV;
11736 goto do_shift;
11737 case ROTRV:
11738 mips32_op = OPC_ROTRV;
11739 do_shift:
11740 gen_shift(ctx, mips32_op, rd, rs, rt);
11741 break;
11742 /* Logical operations */
11743 case AND:
11744 mips32_op = OPC_AND;
11745 goto do_logic;
11746 case OR32:
11747 mips32_op = OPC_OR;
11748 goto do_logic;
11749 case NOR:
11750 mips32_op = OPC_NOR;
11751 goto do_logic;
11752 case XOR32:
11753 mips32_op = OPC_XOR;
11754 do_logic:
11755 gen_logic(ctx, mips32_op, rd, rs, rt);
11756 break;
11757 /* Set less than */
11758 case SLT:
11759 mips32_op = OPC_SLT;
11760 goto do_slt;
11761 case SLTU:
11762 mips32_op = OPC_SLTU;
11763 do_slt:
11764 gen_slt(ctx, mips32_op, rd, rs, rt);
11765 break;
11766 default:
11767 goto pool32a_invalid;
11769 break;
11770 case 0x18:
11771 minor = (ctx->opcode >> 6) & 0xf;
11772 switch (minor) {
11773 /* Conditional moves */
11774 case MOVN:
11775 mips32_op = OPC_MOVN;
11776 goto do_cmov;
11777 case MOVZ:
11778 mips32_op = OPC_MOVZ;
11779 do_cmov:
11780 gen_cond_move(ctx, mips32_op, rd, rs, rt);
11781 break;
11782 case LWXS:
11783 gen_ldxs(ctx, rs, rt, rd);
11784 break;
11785 default:
11786 goto pool32a_invalid;
11788 break;
11789 case INS:
11790 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11791 return;
11792 case EXT:
11793 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11794 return;
11795 case POOL32AXF:
11796 gen_pool32axf(env, ctx, rt, rs);
11797 break;
11798 case 0x07:
11799 generate_exception(ctx, EXCP_BREAK);
11800 break;
11801 default:
11802 pool32a_invalid:
11803 MIPS_INVAL("pool32a");
11804 generate_exception(ctx, EXCP_RI);
11805 break;
11807 break;
11808 case POOL32B:
11809 minor = (ctx->opcode >> 12) & 0xf;
11810 switch (minor) {
11811 case CACHE:
11812 check_cp0_enabled(ctx);
11813 /* Treat as no-op. */
11814 break;
11815 case LWC2:
11816 case SWC2:
11817 /* COP2: Not implemented. */
11818 generate_exception_err(ctx, EXCP_CpU, 2);
11819 break;
11820 case LWP:
11821 case SWP:
11822 #ifdef TARGET_MIPS64
11823 case LDP:
11824 case SDP:
11825 #endif
11826 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11827 break;
11828 case LWM32:
11829 case SWM32:
11830 #ifdef TARGET_MIPS64
11831 case LDM:
11832 case SDM:
11833 #endif
11834 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11835 break;
11836 default:
11837 MIPS_INVAL("pool32b");
11838 generate_exception(ctx, EXCP_RI);
11839 break;
11841 break;
11842 case POOL32F:
11843 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
11844 minor = ctx->opcode & 0x3f;
11845 check_cp1_enabled(ctx);
11846 switch (minor) {
11847 case ALNV_PS:
11848 mips32_op = OPC_ALNV_PS;
11849 goto do_madd;
11850 case MADD_S:
11851 mips32_op = OPC_MADD_S;
11852 goto do_madd;
11853 case MADD_D:
11854 mips32_op = OPC_MADD_D;
11855 goto do_madd;
11856 case MADD_PS:
11857 mips32_op = OPC_MADD_PS;
11858 goto do_madd;
11859 case MSUB_S:
11860 mips32_op = OPC_MSUB_S;
11861 goto do_madd;
11862 case MSUB_D:
11863 mips32_op = OPC_MSUB_D;
11864 goto do_madd;
11865 case MSUB_PS:
11866 mips32_op = OPC_MSUB_PS;
11867 goto do_madd;
11868 case NMADD_S:
11869 mips32_op = OPC_NMADD_S;
11870 goto do_madd;
11871 case NMADD_D:
11872 mips32_op = OPC_NMADD_D;
11873 goto do_madd;
11874 case NMADD_PS:
11875 mips32_op = OPC_NMADD_PS;
11876 goto do_madd;
11877 case NMSUB_S:
11878 mips32_op = OPC_NMSUB_S;
11879 goto do_madd;
11880 case NMSUB_D:
11881 mips32_op = OPC_NMSUB_D;
11882 goto do_madd;
11883 case NMSUB_PS:
11884 mips32_op = OPC_NMSUB_PS;
11885 do_madd:
11886 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11887 break;
11888 case CABS_COND_FMT:
11889 cond = (ctx->opcode >> 6) & 0xf;
11890 cc = (ctx->opcode >> 13) & 0x7;
11891 fmt = (ctx->opcode >> 10) & 0x3;
11892 switch (fmt) {
11893 case 0x0:
11894 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11895 break;
11896 case 0x1:
11897 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11898 break;
11899 case 0x2:
11900 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11901 break;
11902 default:
11903 goto pool32f_invalid;
11905 break;
11906 case C_COND_FMT:
11907 cond = (ctx->opcode >> 6) & 0xf;
11908 cc = (ctx->opcode >> 13) & 0x7;
11909 fmt = (ctx->opcode >> 10) & 0x3;
11910 switch (fmt) {
11911 case 0x0:
11912 gen_cmp_s(ctx, cond, rt, rs, cc);
11913 break;
11914 case 0x1:
11915 gen_cmp_d(ctx, cond, rt, rs, cc);
11916 break;
11917 case 0x2:
11918 gen_cmp_ps(ctx, cond, rt, rs, cc);
11919 break;
11920 default:
11921 goto pool32f_invalid;
11923 break;
11924 case POOL32FXF:
11925 gen_pool32fxf(ctx, rt, rs);
11926 break;
11927 case 0x00:
11928 /* PLL foo */
11929 switch ((ctx->opcode >> 6) & 0x7) {
11930 case PLL_PS:
11931 mips32_op = OPC_PLL_PS;
11932 goto do_ps;
11933 case PLU_PS:
11934 mips32_op = OPC_PLU_PS;
11935 goto do_ps;
11936 case PUL_PS:
11937 mips32_op = OPC_PUL_PS;
11938 goto do_ps;
11939 case PUU_PS:
11940 mips32_op = OPC_PUU_PS;
11941 goto do_ps;
11942 case CVT_PS_S:
11943 mips32_op = OPC_CVT_PS_S;
11944 do_ps:
11945 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11946 break;
11947 default:
11948 goto pool32f_invalid;
11950 break;
11951 case 0x08:
11952 /* [LS][WDU]XC1 */
11953 switch ((ctx->opcode >> 6) & 0x7) {
11954 case LWXC1:
11955 mips32_op = OPC_LWXC1;
11956 goto do_ldst_cp1;
11957 case SWXC1:
11958 mips32_op = OPC_SWXC1;
11959 goto do_ldst_cp1;
11960 case LDXC1:
11961 mips32_op = OPC_LDXC1;
11962 goto do_ldst_cp1;
11963 case SDXC1:
11964 mips32_op = OPC_SDXC1;
11965 goto do_ldst_cp1;
11966 case LUXC1:
11967 mips32_op = OPC_LUXC1;
11968 goto do_ldst_cp1;
11969 case SUXC1:
11970 mips32_op = OPC_SUXC1;
11971 do_ldst_cp1:
11972 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11973 break;
11974 default:
11975 goto pool32f_invalid;
11977 break;
11978 case 0x18:
11979 /* 3D insns */
11980 fmt = (ctx->opcode >> 9) & 0x3;
11981 switch ((ctx->opcode >> 6) & 0x7) {
11982 case RSQRT2_FMT:
11983 switch (fmt) {
11984 case FMT_SDPS_S:
11985 mips32_op = OPC_RSQRT2_S;
11986 goto do_3d;
11987 case FMT_SDPS_D:
11988 mips32_op = OPC_RSQRT2_D;
11989 goto do_3d;
11990 case FMT_SDPS_PS:
11991 mips32_op = OPC_RSQRT2_PS;
11992 goto do_3d;
11993 default:
11994 goto pool32f_invalid;
11996 break;
11997 case RECIP2_FMT:
11998 switch (fmt) {
11999 case FMT_SDPS_S:
12000 mips32_op = OPC_RECIP2_S;
12001 goto do_3d;
12002 case FMT_SDPS_D:
12003 mips32_op = OPC_RECIP2_D;
12004 goto do_3d;
12005 case FMT_SDPS_PS:
12006 mips32_op = OPC_RECIP2_PS;
12007 goto do_3d;
12008 default:
12009 goto pool32f_invalid;
12011 break;
12012 case ADDR_PS:
12013 mips32_op = OPC_ADDR_PS;
12014 goto do_3d;
12015 case MULR_PS:
12016 mips32_op = OPC_MULR_PS;
12017 do_3d:
12018 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12019 break;
12020 default:
12021 goto pool32f_invalid;
12023 break;
12024 case 0x20:
12025 /* MOV[FT].fmt and PREFX */
12026 cc = (ctx->opcode >> 13) & 0x7;
12027 fmt = (ctx->opcode >> 9) & 0x3;
12028 switch ((ctx->opcode >> 6) & 0x7) {
12029 case MOVF_FMT:
12030 switch (fmt) {
12031 case FMT_SDPS_S:
12032 gen_movcf_s(rs, rt, cc, 0);
12033 break;
12034 case FMT_SDPS_D:
12035 gen_movcf_d(ctx, rs, rt, cc, 0);
12036 break;
12037 case FMT_SDPS_PS:
12038 gen_movcf_ps(ctx, rs, rt, cc, 0);
12039 break;
12040 default:
12041 goto pool32f_invalid;
12043 break;
12044 case MOVT_FMT:
12045 switch (fmt) {
12046 case FMT_SDPS_S:
12047 gen_movcf_s(rs, rt, cc, 1);
12048 break;
12049 case FMT_SDPS_D:
12050 gen_movcf_d(ctx, rs, rt, cc, 1);
12051 break;
12052 case FMT_SDPS_PS:
12053 gen_movcf_ps(ctx, rs, rt, cc, 1);
12054 break;
12055 default:
12056 goto pool32f_invalid;
12058 break;
12059 case PREFX:
12060 break;
12061 default:
12062 goto pool32f_invalid;
12064 break;
12065 #define FINSN_3ARG_SDPS(prfx) \
12066 switch ((ctx->opcode >> 8) & 0x3) { \
12067 case FMT_SDPS_S: \
12068 mips32_op = OPC_##prfx##_S; \
12069 goto do_fpop; \
12070 case FMT_SDPS_D: \
12071 mips32_op = OPC_##prfx##_D; \
12072 goto do_fpop; \
12073 case FMT_SDPS_PS: \
12074 mips32_op = OPC_##prfx##_PS; \
12075 goto do_fpop; \
12076 default: \
12077 goto pool32f_invalid; \
12079 case 0x30:
12080 /* regular FP ops */
12081 switch ((ctx->opcode >> 6) & 0x3) {
12082 case ADD_FMT:
12083 FINSN_3ARG_SDPS(ADD);
12084 break;
12085 case SUB_FMT:
12086 FINSN_3ARG_SDPS(SUB);
12087 break;
12088 case MUL_FMT:
12089 FINSN_3ARG_SDPS(MUL);
12090 break;
12091 case DIV_FMT:
12092 fmt = (ctx->opcode >> 8) & 0x3;
12093 if (fmt == 1) {
12094 mips32_op = OPC_DIV_D;
12095 } else if (fmt == 0) {
12096 mips32_op = OPC_DIV_S;
12097 } else {
12098 goto pool32f_invalid;
12100 goto do_fpop;
12101 default:
12102 goto pool32f_invalid;
12104 break;
12105 case 0x38:
12106 /* cmovs */
12107 switch ((ctx->opcode >> 6) & 0x3) {
12108 case MOVN_FMT:
12109 FINSN_3ARG_SDPS(MOVN);
12110 break;
12111 case MOVZ_FMT:
12112 FINSN_3ARG_SDPS(MOVZ);
12113 break;
12114 default:
12115 goto pool32f_invalid;
12117 break;
12118 do_fpop:
12119 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12120 break;
12121 default:
12122 pool32f_invalid:
12123 MIPS_INVAL("pool32f");
12124 generate_exception(ctx, EXCP_RI);
12125 break;
12127 } else {
12128 generate_exception_err(ctx, EXCP_CpU, 1);
12130 break;
12131 case POOL32I:
12132 minor = (ctx->opcode >> 21) & 0x1f;
12133 switch (minor) {
12134 case BLTZ:
12135 mips32_op = OPC_BLTZ;
12136 goto do_branch;
12137 case BLTZAL:
12138 mips32_op = OPC_BLTZAL;
12139 goto do_branch;
12140 case BLTZALS:
12141 mips32_op = OPC_BLTZALS;
12142 goto do_branch;
12143 case BGEZ:
12144 mips32_op = OPC_BGEZ;
12145 goto do_branch;
12146 case BGEZAL:
12147 mips32_op = OPC_BGEZAL;
12148 goto do_branch;
12149 case BGEZALS:
12150 mips32_op = OPC_BGEZALS;
12151 goto do_branch;
12152 case BLEZ:
12153 mips32_op = OPC_BLEZ;
12154 goto do_branch;
12155 case BGTZ:
12156 mips32_op = OPC_BGTZ;
12157 do_branch:
12158 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
12159 break;
12161 /* Traps */
12162 case TLTI:
12163 mips32_op = OPC_TLTI;
12164 goto do_trapi;
12165 case TGEI:
12166 mips32_op = OPC_TGEI;
12167 goto do_trapi;
12168 case TLTIU:
12169 mips32_op = OPC_TLTIU;
12170 goto do_trapi;
12171 case TGEIU:
12172 mips32_op = OPC_TGEIU;
12173 goto do_trapi;
12174 case TNEI:
12175 mips32_op = OPC_TNEI;
12176 goto do_trapi;
12177 case TEQI:
12178 mips32_op = OPC_TEQI;
12179 do_trapi:
12180 gen_trap(ctx, mips32_op, rs, -1, imm);
12181 break;
12183 case BNEZC:
12184 case BEQZC:
12185 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
12186 4, rs, 0, imm << 1);
12187 /* Compact branches don't have a delay slot, so just let
12188 the normal delay slot handling take us to the branch
12189 target. */
12190 break;
12191 case LUI:
12192 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
12193 break;
12194 case SYNCI:
12195 break;
12196 case BC2F:
12197 case BC2T:
12198 /* COP2: Not implemented. */
12199 generate_exception_err(ctx, EXCP_CpU, 2);
12200 break;
12201 case BC1F:
12202 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
12203 goto do_cp1branch;
12204 case BC1T:
12205 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
12206 goto do_cp1branch;
12207 case BC1ANY4F:
12208 mips32_op = OPC_BC1FANY4;
12209 goto do_cp1mips3d;
12210 case BC1ANY4T:
12211 mips32_op = OPC_BC1TANY4;
12212 do_cp1mips3d:
12213 check_cop1x(ctx);
12214 check_insn(ctx, ASE_MIPS3D);
12215 /* Fall through */
12216 do_cp1branch:
12217 gen_compute_branch1(ctx, mips32_op,
12218 (ctx->opcode >> 18) & 0x7, imm << 1);
12219 break;
12220 case BPOSGE64:
12221 case BPOSGE32:
12222 /* MIPS DSP: not implemented */
12223 /* Fall through */
12224 default:
12225 MIPS_INVAL("pool32i");
12226 generate_exception(ctx, EXCP_RI);
12227 break;
12229 break;
12230 case POOL32C:
12231 minor = (ctx->opcode >> 12) & 0xf;
12232 switch (minor) {
12233 case LWL:
12234 mips32_op = OPC_LWL;
12235 goto do_ld_lr;
12236 case SWL:
12237 mips32_op = OPC_SWL;
12238 goto do_st_lr;
12239 case LWR:
12240 mips32_op = OPC_LWR;
12241 goto do_ld_lr;
12242 case SWR:
12243 mips32_op = OPC_SWR;
12244 goto do_st_lr;
12245 #if defined(TARGET_MIPS64)
12246 case LDL:
12247 mips32_op = OPC_LDL;
12248 goto do_ld_lr;
12249 case SDL:
12250 mips32_op = OPC_SDL;
12251 goto do_st_lr;
12252 case LDR:
12253 mips32_op = OPC_LDR;
12254 goto do_ld_lr;
12255 case SDR:
12256 mips32_op = OPC_SDR;
12257 goto do_st_lr;
12258 case LWU:
12259 mips32_op = OPC_LWU;
12260 goto do_ld_lr;
12261 case LLD:
12262 mips32_op = OPC_LLD;
12263 goto do_ld_lr;
12264 #endif
12265 case LL:
12266 mips32_op = OPC_LL;
12267 goto do_ld_lr;
12268 do_ld_lr:
12269 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
12270 break;
12271 do_st_lr:
12272 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
12273 break;
12274 case SC:
12275 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
12276 break;
12277 #if defined(TARGET_MIPS64)
12278 case SCD:
12279 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
12280 break;
12281 #endif
12282 case PREF:
12283 /* Treat as no-op */
12284 break;
12285 default:
12286 MIPS_INVAL("pool32c");
12287 generate_exception(ctx, EXCP_RI);
12288 break;
12290 break;
12291 case ADDI32:
12292 mips32_op = OPC_ADDI;
12293 goto do_addi;
12294 case ADDIU32:
12295 mips32_op = OPC_ADDIU;
12296 do_addi:
12297 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
12298 break;
12300 /* Logical operations */
12301 case ORI32:
12302 mips32_op = OPC_ORI;
12303 goto do_logici;
12304 case XORI32:
12305 mips32_op = OPC_XORI;
12306 goto do_logici;
12307 case ANDI32:
12308 mips32_op = OPC_ANDI;
12309 do_logici:
12310 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
12311 break;
12313 /* Set less than immediate */
12314 case SLTI32:
12315 mips32_op = OPC_SLTI;
12316 goto do_slti;
12317 case SLTIU32:
12318 mips32_op = OPC_SLTIU;
12319 do_slti:
12320 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
12321 break;
12322 case JALX32:
12323 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12324 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
12325 break;
12326 case JALS32:
12327 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
12328 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
12329 break;
12330 case BEQ32:
12331 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
12332 break;
12333 case BNE32:
12334 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
12335 break;
12336 case J32:
12337 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
12338 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12339 break;
12340 case JAL32:
12341 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
12342 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12343 break;
12344 /* Floating point (COP1) */
12345 case LWC132:
12346 mips32_op = OPC_LWC1;
12347 goto do_cop1;
12348 case LDC132:
12349 mips32_op = OPC_LDC1;
12350 goto do_cop1;
12351 case SWC132:
12352 mips32_op = OPC_SWC1;
12353 goto do_cop1;
12354 case SDC132:
12355 mips32_op = OPC_SDC1;
12356 do_cop1:
12357 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
12358 break;
12359 case ADDIUPC:
12361 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
12362 int offset = SIMM(ctx->opcode, 0, 23) << 2;
12364 gen_addiupc(ctx, reg, offset, 0, 0);
12366 break;
12367 /* Loads and stores */
12368 case LB32:
12369 mips32_op = OPC_LB;
12370 goto do_ld;
12371 case LBU32:
12372 mips32_op = OPC_LBU;
12373 goto do_ld;
12374 case LH32:
12375 mips32_op = OPC_LH;
12376 goto do_ld;
12377 case LHU32:
12378 mips32_op = OPC_LHU;
12379 goto do_ld;
12380 case LW32:
12381 mips32_op = OPC_LW;
12382 goto do_ld;
12383 #ifdef TARGET_MIPS64
12384 case LD32:
12385 mips32_op = OPC_LD;
12386 goto do_ld;
12387 case SD32:
12388 mips32_op = OPC_SD;
12389 goto do_st;
12390 #endif
12391 case SB32:
12392 mips32_op = OPC_SB;
12393 goto do_st;
12394 case SH32:
12395 mips32_op = OPC_SH;
12396 goto do_st;
12397 case SW32:
12398 mips32_op = OPC_SW;
12399 goto do_st;
12400 do_ld:
12401 gen_ld(ctx, mips32_op, rt, rs, imm);
12402 break;
12403 do_st:
12404 gen_st(ctx, mips32_op, rt, rs, imm);
12405 break;
12406 default:
12407 generate_exception(ctx, EXCP_RI);
12408 break;
12412 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
12414 uint32_t op;
12416 /* make sure instructions are on a halfword boundary */
12417 if (ctx->pc & 0x1) {
12418 env->CP0_BadVAddr = ctx->pc;
12419 generate_exception(ctx, EXCP_AdEL);
12420 ctx->bstate = BS_STOP;
12421 return 2;
12424 op = (ctx->opcode >> 10) & 0x3f;
12425 /* Enforce properly-sized instructions in a delay slot */
12426 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12427 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
12429 switch (op) {
12430 case POOL32A:
12431 case POOL32B:
12432 case POOL32I:
12433 case POOL32C:
12434 case ADDI32:
12435 case ADDIU32:
12436 case ORI32:
12437 case XORI32:
12438 case SLTI32:
12439 case SLTIU32:
12440 case ANDI32:
12441 case JALX32:
12442 case LBU32:
12443 case LHU32:
12444 case POOL32F:
12445 case JALS32:
12446 case BEQ32:
12447 case BNE32:
12448 case J32:
12449 case JAL32:
12450 case SB32:
12451 case SH32:
12452 case POOL32S:
12453 case ADDIUPC:
12454 case SWC132:
12455 case SDC132:
12456 case SD32:
12457 case SW32:
12458 case LB32:
12459 case LH32:
12460 case DADDIU32:
12461 case LWC132:
12462 case LDC132:
12463 case LD32:
12464 case LW32:
12465 if (bits & MIPS_HFLAG_BDS16) {
12466 generate_exception(ctx, EXCP_RI);
12467 /* Just stop translation; the user is confused. */
12468 ctx->bstate = BS_STOP;
12469 return 2;
12471 break;
12472 case POOL16A:
12473 case POOL16B:
12474 case POOL16C:
12475 case LWGP16:
12476 case POOL16F:
12477 case LBU16:
12478 case LHU16:
12479 case LWSP16:
12480 case LW16:
12481 case SB16:
12482 case SH16:
12483 case SWSP16:
12484 case SW16:
12485 case MOVE16:
12486 case ANDI16:
12487 case POOL16D:
12488 case POOL16E:
12489 case BEQZ16:
12490 case BNEZ16:
12491 case B16:
12492 case LI16:
12493 if (bits & MIPS_HFLAG_BDS32) {
12494 generate_exception(ctx, EXCP_RI);
12495 /* Just stop translation; the user is confused. */
12496 ctx->bstate = BS_STOP;
12497 return 2;
12499 break;
12500 default:
12501 break;
12504 switch (op) {
12505 case POOL16A:
12507 int rd = mmreg(uMIPS_RD(ctx->opcode));
12508 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
12509 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
12510 uint32_t opc = 0;
12512 switch (ctx->opcode & 0x1) {
12513 case ADDU16:
12514 opc = OPC_ADDU;
12515 break;
12516 case SUBU16:
12517 opc = OPC_SUBU;
12518 break;
12521 gen_arith(ctx, opc, rd, rs1, rs2);
12523 break;
12524 case POOL16B:
12526 int rd = mmreg(uMIPS_RD(ctx->opcode));
12527 int rs = mmreg(uMIPS_RS(ctx->opcode));
12528 int amount = (ctx->opcode >> 1) & 0x7;
12529 uint32_t opc = 0;
12530 amount = amount == 0 ? 8 : amount;
12532 switch (ctx->opcode & 0x1) {
12533 case SLL16:
12534 opc = OPC_SLL;
12535 break;
12536 case SRL16:
12537 opc = OPC_SRL;
12538 break;
12541 gen_shift_imm(ctx, opc, rd, rs, amount);
12543 break;
12544 case POOL16C:
12545 gen_pool16c_insn(ctx);
12546 break;
12547 case LWGP16:
12549 int rd = mmreg(uMIPS_RD(ctx->opcode));
12550 int rb = 28; /* GP */
12551 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
12553 gen_ld(ctx, OPC_LW, rd, rb, offset);
12555 break;
12556 case POOL16F:
12557 if (ctx->opcode & 1) {
12558 generate_exception(ctx, EXCP_RI);
12559 } else {
12560 /* MOVEP */
12561 int enc_dest = uMIPS_RD(ctx->opcode);
12562 int enc_rt = uMIPS_RS2(ctx->opcode);
12563 int enc_rs = uMIPS_RS1(ctx->opcode);
12564 int rd, rs, re, rt;
12565 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12566 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12567 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12569 rd = rd_enc[enc_dest];
12570 re = re_enc[enc_dest];
12571 rs = rs_rt_enc[enc_rs];
12572 rt = rs_rt_enc[enc_rt];
12574 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
12575 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
12577 break;
12578 case LBU16:
12580 int rd = mmreg(uMIPS_RD(ctx->opcode));
12581 int rb = mmreg(uMIPS_RS(ctx->opcode));
12582 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12583 offset = (offset == 0xf ? -1 : offset);
12585 gen_ld(ctx, OPC_LBU, rd, rb, offset);
12587 break;
12588 case LHU16:
12590 int rd = mmreg(uMIPS_RD(ctx->opcode));
12591 int rb = mmreg(uMIPS_RS(ctx->opcode));
12592 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12594 gen_ld(ctx, OPC_LHU, rd, rb, offset);
12596 break;
12597 case LWSP16:
12599 int rd = (ctx->opcode >> 5) & 0x1f;
12600 int rb = 29; /* SP */
12601 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12603 gen_ld(ctx, OPC_LW, rd, rb, offset);
12605 break;
12606 case LW16:
12608 int rd = mmreg(uMIPS_RD(ctx->opcode));
12609 int rb = mmreg(uMIPS_RS(ctx->opcode));
12610 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12612 gen_ld(ctx, OPC_LW, rd, rb, offset);
12614 break;
12615 case SB16:
12617 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12618 int rb = mmreg(uMIPS_RS(ctx->opcode));
12619 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12621 gen_st(ctx, OPC_SB, rd, rb, offset);
12623 break;
12624 case SH16:
12626 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12627 int rb = mmreg(uMIPS_RS(ctx->opcode));
12628 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12630 gen_st(ctx, OPC_SH, rd, rb, offset);
12632 break;
12633 case SWSP16:
12635 int rd = (ctx->opcode >> 5) & 0x1f;
12636 int rb = 29; /* SP */
12637 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12639 gen_st(ctx, OPC_SW, rd, rb, offset);
12641 break;
12642 case SW16:
12644 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12645 int rb = mmreg(uMIPS_RS(ctx->opcode));
12646 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12648 gen_st(ctx, OPC_SW, rd, rb, offset);
12650 break;
12651 case MOVE16:
12653 int rd = uMIPS_RD5(ctx->opcode);
12654 int rs = uMIPS_RS5(ctx->opcode);
12656 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
12658 break;
12659 case ANDI16:
12660 gen_andi16(ctx);
12661 break;
12662 case POOL16D:
12663 switch (ctx->opcode & 0x1) {
12664 case ADDIUS5:
12665 gen_addius5(ctx);
12666 break;
12667 case ADDIUSP:
12668 gen_addiusp(ctx);
12669 break;
12671 break;
12672 case POOL16E:
12673 switch (ctx->opcode & 0x1) {
12674 case ADDIUR2:
12675 gen_addiur2(ctx);
12676 break;
12677 case ADDIUR1SP:
12678 gen_addiur1sp(ctx);
12679 break;
12681 break;
12682 case B16:
12683 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12684 SIMM(ctx->opcode, 0, 10) << 1);
12685 break;
12686 case BNEZ16:
12687 case BEQZ16:
12688 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12689 mmreg(uMIPS_RD(ctx->opcode)),
12690 0, SIMM(ctx->opcode, 0, 7) << 1);
12691 break;
12692 case LI16:
12694 int reg = mmreg(uMIPS_RD(ctx->opcode));
12695 int imm = ZIMM(ctx->opcode, 0, 7);
12697 imm = (imm == 0x7f ? -1 : imm);
12698 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12700 break;
12701 case RES_20:
12702 case RES_28:
12703 case RES_29:
12704 case RES_30:
12705 case RES_31:
12706 case RES_38:
12707 case RES_39:
12708 generate_exception(ctx, EXCP_RI);
12709 break;
12710 default:
12711 decode_micromips32_opc (env, ctx, op);
12712 return 4;
12715 return 2;
12718 /* SmartMIPS extension to MIPS32 */
12720 #if defined(TARGET_MIPS64)
12722 /* MDMX extension to MIPS64 */
12724 #endif
12726 /* MIPSDSP functions. */
12727 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
12728 int rd, int base, int offset)
12730 const char *opn = "ldx";
12731 TCGv t0;
12733 check_dsp(ctx);
12734 t0 = tcg_temp_new();
12736 if (base == 0) {
12737 gen_load_gpr(t0, offset);
12738 } else if (offset == 0) {
12739 gen_load_gpr(t0, base);
12740 } else {
12741 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12744 switch (opc) {
12745 case OPC_LBUX:
12746 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
12747 gen_store_gpr(t0, rd);
12748 opn = "lbux";
12749 break;
12750 case OPC_LHX:
12751 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
12752 gen_store_gpr(t0, rd);
12753 opn = "lhx";
12754 break;
12755 case OPC_LWX:
12756 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12757 gen_store_gpr(t0, rd);
12758 opn = "lwx";
12759 break;
12760 #if defined(TARGET_MIPS64)
12761 case OPC_LDX:
12762 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
12763 gen_store_gpr(t0, rd);
12764 opn = "ldx";
12765 break;
12766 #endif
12768 (void)opn; /* avoid a compiler warning */
12769 MIPS_DEBUG("%s %s, %s(%s)", opn,
12770 regnames[rd], regnames[offset], regnames[base]);
12771 tcg_temp_free(t0);
12774 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12775 int ret, int v1, int v2)
12777 const char *opn = "mipsdsp arith";
12778 TCGv v1_t;
12779 TCGv v2_t;
12781 if (ret == 0) {
12782 /* Treat as NOP. */
12783 MIPS_DEBUG("NOP");
12784 return;
12787 v1_t = tcg_temp_new();
12788 v2_t = tcg_temp_new();
12790 gen_load_gpr(v1_t, v1);
12791 gen_load_gpr(v2_t, v2);
12793 switch (op1) {
12794 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12795 case OPC_MULT_G_2E:
12796 check_dspr2(ctx);
12797 switch (op2) {
12798 case OPC_ADDUH_QB:
12799 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12800 break;
12801 case OPC_ADDUH_R_QB:
12802 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12803 break;
12804 case OPC_ADDQH_PH:
12805 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12806 break;
12807 case OPC_ADDQH_R_PH:
12808 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12809 break;
12810 case OPC_ADDQH_W:
12811 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12812 break;
12813 case OPC_ADDQH_R_W:
12814 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12815 break;
12816 case OPC_SUBUH_QB:
12817 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12818 break;
12819 case OPC_SUBUH_R_QB:
12820 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12821 break;
12822 case OPC_SUBQH_PH:
12823 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12824 break;
12825 case OPC_SUBQH_R_PH:
12826 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12827 break;
12828 case OPC_SUBQH_W:
12829 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12830 break;
12831 case OPC_SUBQH_R_W:
12832 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12833 break;
12835 break;
12836 case OPC_ABSQ_S_PH_DSP:
12837 switch (op2) {
12838 case OPC_ABSQ_S_QB:
12839 check_dspr2(ctx);
12840 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12841 break;
12842 case OPC_ABSQ_S_PH:
12843 check_dsp(ctx);
12844 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12845 break;
12846 case OPC_ABSQ_S_W:
12847 check_dsp(ctx);
12848 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12849 break;
12850 case OPC_PRECEQ_W_PHL:
12851 check_dsp(ctx);
12852 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12853 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12854 break;
12855 case OPC_PRECEQ_W_PHR:
12856 check_dsp(ctx);
12857 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12858 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12859 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12860 break;
12861 case OPC_PRECEQU_PH_QBL:
12862 check_dsp(ctx);
12863 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12864 break;
12865 case OPC_PRECEQU_PH_QBR:
12866 check_dsp(ctx);
12867 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12868 break;
12869 case OPC_PRECEQU_PH_QBLA:
12870 check_dsp(ctx);
12871 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12872 break;
12873 case OPC_PRECEQU_PH_QBRA:
12874 check_dsp(ctx);
12875 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12876 break;
12877 case OPC_PRECEU_PH_QBL:
12878 check_dsp(ctx);
12879 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12880 break;
12881 case OPC_PRECEU_PH_QBR:
12882 check_dsp(ctx);
12883 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12884 break;
12885 case OPC_PRECEU_PH_QBLA:
12886 check_dsp(ctx);
12887 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12888 break;
12889 case OPC_PRECEU_PH_QBRA:
12890 check_dsp(ctx);
12891 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12892 break;
12894 break;
12895 case OPC_ADDU_QB_DSP:
12896 switch (op2) {
12897 case OPC_ADDQ_PH:
12898 check_dsp(ctx);
12899 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12900 break;
12901 case OPC_ADDQ_S_PH:
12902 check_dsp(ctx);
12903 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12904 break;
12905 case OPC_ADDQ_S_W:
12906 check_dsp(ctx);
12907 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12908 break;
12909 case OPC_ADDU_QB:
12910 check_dsp(ctx);
12911 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12912 break;
12913 case OPC_ADDU_S_QB:
12914 check_dsp(ctx);
12915 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12916 break;
12917 case OPC_ADDU_PH:
12918 check_dspr2(ctx);
12919 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12920 break;
12921 case OPC_ADDU_S_PH:
12922 check_dspr2(ctx);
12923 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12924 break;
12925 case OPC_SUBQ_PH:
12926 check_dsp(ctx);
12927 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12928 break;
12929 case OPC_SUBQ_S_PH:
12930 check_dsp(ctx);
12931 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12932 break;
12933 case OPC_SUBQ_S_W:
12934 check_dsp(ctx);
12935 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12936 break;
12937 case OPC_SUBU_QB:
12938 check_dsp(ctx);
12939 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12940 break;
12941 case OPC_SUBU_S_QB:
12942 check_dsp(ctx);
12943 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12944 break;
12945 case OPC_SUBU_PH:
12946 check_dspr2(ctx);
12947 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12948 break;
12949 case OPC_SUBU_S_PH:
12950 check_dspr2(ctx);
12951 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12952 break;
12953 case OPC_ADDSC:
12954 check_dsp(ctx);
12955 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12956 break;
12957 case OPC_ADDWC:
12958 check_dsp(ctx);
12959 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12960 break;
12961 case OPC_MODSUB:
12962 check_dsp(ctx);
12963 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12964 break;
12965 case OPC_RADDU_W_QB:
12966 check_dsp(ctx);
12967 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12968 break;
12970 break;
12971 case OPC_CMPU_EQ_QB_DSP:
12972 switch (op2) {
12973 case OPC_PRECR_QB_PH:
12974 check_dspr2(ctx);
12975 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12976 break;
12977 case OPC_PRECRQ_QB_PH:
12978 check_dsp(ctx);
12979 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12980 break;
12981 case OPC_PRECR_SRA_PH_W:
12982 check_dspr2(ctx);
12984 TCGv_i32 sa_t = tcg_const_i32(v2);
12985 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12986 cpu_gpr[ret]);
12987 tcg_temp_free_i32(sa_t);
12988 break;
12990 case OPC_PRECR_SRA_R_PH_W:
12991 check_dspr2(ctx);
12993 TCGv_i32 sa_t = tcg_const_i32(v2);
12994 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12995 cpu_gpr[ret]);
12996 tcg_temp_free_i32(sa_t);
12997 break;
12999 case OPC_PRECRQ_PH_W:
13000 check_dsp(ctx);
13001 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
13002 break;
13003 case OPC_PRECRQ_RS_PH_W:
13004 check_dsp(ctx);
13005 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13006 break;
13007 case OPC_PRECRQU_S_QB_PH:
13008 check_dsp(ctx);
13009 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13010 break;
13012 break;
13013 #ifdef TARGET_MIPS64
13014 case OPC_ABSQ_S_QH_DSP:
13015 switch (op2) {
13016 case OPC_PRECEQ_L_PWL:
13017 check_dsp(ctx);
13018 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
13019 break;
13020 case OPC_PRECEQ_L_PWR:
13021 check_dsp(ctx);
13022 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
13023 break;
13024 case OPC_PRECEQ_PW_QHL:
13025 check_dsp(ctx);
13026 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
13027 break;
13028 case OPC_PRECEQ_PW_QHR:
13029 check_dsp(ctx);
13030 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
13031 break;
13032 case OPC_PRECEQ_PW_QHLA:
13033 check_dsp(ctx);
13034 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
13035 break;
13036 case OPC_PRECEQ_PW_QHRA:
13037 check_dsp(ctx);
13038 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
13039 break;
13040 case OPC_PRECEQU_QH_OBL:
13041 check_dsp(ctx);
13042 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
13043 break;
13044 case OPC_PRECEQU_QH_OBR:
13045 check_dsp(ctx);
13046 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
13047 break;
13048 case OPC_PRECEQU_QH_OBLA:
13049 check_dsp(ctx);
13050 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
13051 break;
13052 case OPC_PRECEQU_QH_OBRA:
13053 check_dsp(ctx);
13054 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
13055 break;
13056 case OPC_PRECEU_QH_OBL:
13057 check_dsp(ctx);
13058 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
13059 break;
13060 case OPC_PRECEU_QH_OBR:
13061 check_dsp(ctx);
13062 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
13063 break;
13064 case OPC_PRECEU_QH_OBLA:
13065 check_dsp(ctx);
13066 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
13067 break;
13068 case OPC_PRECEU_QH_OBRA:
13069 check_dsp(ctx);
13070 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
13071 break;
13072 case OPC_ABSQ_S_OB:
13073 check_dspr2(ctx);
13074 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
13075 break;
13076 case OPC_ABSQ_S_PW:
13077 check_dsp(ctx);
13078 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
13079 break;
13080 case OPC_ABSQ_S_QH:
13081 check_dsp(ctx);
13082 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
13083 break;
13085 break;
13086 case OPC_ADDU_OB_DSP:
13087 switch (op2) {
13088 case OPC_RADDU_L_OB:
13089 check_dsp(ctx);
13090 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
13091 break;
13092 case OPC_SUBQ_PW:
13093 check_dsp(ctx);
13094 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13095 break;
13096 case OPC_SUBQ_S_PW:
13097 check_dsp(ctx);
13098 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13099 break;
13100 case OPC_SUBQ_QH:
13101 check_dsp(ctx);
13102 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13103 break;
13104 case OPC_SUBQ_S_QH:
13105 check_dsp(ctx);
13106 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13107 break;
13108 case OPC_SUBU_OB:
13109 check_dsp(ctx);
13110 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13111 break;
13112 case OPC_SUBU_S_OB:
13113 check_dsp(ctx);
13114 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13115 break;
13116 case OPC_SUBU_QH:
13117 check_dspr2(ctx);
13118 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13119 break;
13120 case OPC_SUBU_S_QH:
13121 check_dspr2(ctx);
13122 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13123 break;
13124 case OPC_SUBUH_OB:
13125 check_dspr2(ctx);
13126 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
13127 break;
13128 case OPC_SUBUH_R_OB:
13129 check_dspr2(ctx);
13130 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13131 break;
13132 case OPC_ADDQ_PW:
13133 check_dsp(ctx);
13134 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13135 break;
13136 case OPC_ADDQ_S_PW:
13137 check_dsp(ctx);
13138 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13139 break;
13140 case OPC_ADDQ_QH:
13141 check_dsp(ctx);
13142 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13143 break;
13144 case OPC_ADDQ_S_QH:
13145 check_dsp(ctx);
13146 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13147 break;
13148 case OPC_ADDU_OB:
13149 check_dsp(ctx);
13150 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13151 break;
13152 case OPC_ADDU_S_OB:
13153 check_dsp(ctx);
13154 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13155 break;
13156 case OPC_ADDU_QH:
13157 check_dspr2(ctx);
13158 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13159 break;
13160 case OPC_ADDU_S_QH:
13161 check_dspr2(ctx);
13162 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13163 break;
13164 case OPC_ADDUH_OB:
13165 check_dspr2(ctx);
13166 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
13167 break;
13168 case OPC_ADDUH_R_OB:
13169 check_dspr2(ctx);
13170 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13171 break;
13173 break;
13174 case OPC_CMPU_EQ_OB_DSP:
13175 switch (op2) {
13176 case OPC_PRECR_OB_QH:
13177 check_dspr2(ctx);
13178 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13179 break;
13180 case OPC_PRECR_SRA_QH_PW:
13181 check_dspr2(ctx);
13183 TCGv_i32 ret_t = tcg_const_i32(ret);
13184 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
13185 tcg_temp_free_i32(ret_t);
13186 break;
13188 case OPC_PRECR_SRA_R_QH_PW:
13189 check_dspr2(ctx);
13191 TCGv_i32 sa_v = tcg_const_i32(ret);
13192 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
13193 tcg_temp_free_i32(sa_v);
13194 break;
13196 case OPC_PRECRQ_OB_QH:
13197 check_dsp(ctx);
13198 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13199 break;
13200 case OPC_PRECRQ_PW_L:
13201 check_dsp(ctx);
13202 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
13203 break;
13204 case OPC_PRECRQ_QH_PW:
13205 check_dsp(ctx);
13206 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
13207 break;
13208 case OPC_PRECRQ_RS_QH_PW:
13209 check_dsp(ctx);
13210 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13211 break;
13212 case OPC_PRECRQU_S_OB_QH:
13213 check_dsp(ctx);
13214 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13215 break;
13217 break;
13218 #endif
13221 tcg_temp_free(v1_t);
13222 tcg_temp_free(v2_t);
13224 (void)opn; /* avoid a compiler warning */
13225 MIPS_DEBUG("%s", opn);
13228 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
13229 int ret, int v1, int v2)
13231 uint32_t op2;
13232 const char *opn = "mipsdsp shift";
13233 TCGv t0;
13234 TCGv v1_t;
13235 TCGv v2_t;
13237 if (ret == 0) {
13238 /* Treat as NOP. */
13239 MIPS_DEBUG("NOP");
13240 return;
13243 t0 = tcg_temp_new();
13244 v1_t = tcg_temp_new();
13245 v2_t = tcg_temp_new();
13247 tcg_gen_movi_tl(t0, v1);
13248 gen_load_gpr(v1_t, v1);
13249 gen_load_gpr(v2_t, v2);
13251 switch (opc) {
13252 case OPC_SHLL_QB_DSP:
13254 op2 = MASK_SHLL_QB(ctx->opcode);
13255 switch (op2) {
13256 case OPC_SHLL_QB:
13257 check_dsp(ctx);
13258 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
13259 break;
13260 case OPC_SHLLV_QB:
13261 check_dsp(ctx);
13262 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13263 break;
13264 case OPC_SHLL_PH:
13265 check_dsp(ctx);
13266 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13267 break;
13268 case OPC_SHLLV_PH:
13269 check_dsp(ctx);
13270 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13271 break;
13272 case OPC_SHLL_S_PH:
13273 check_dsp(ctx);
13274 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13275 break;
13276 case OPC_SHLLV_S_PH:
13277 check_dsp(ctx);
13278 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13279 break;
13280 case OPC_SHLL_S_W:
13281 check_dsp(ctx);
13282 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
13283 break;
13284 case OPC_SHLLV_S_W:
13285 check_dsp(ctx);
13286 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13287 break;
13288 case OPC_SHRL_QB:
13289 check_dsp(ctx);
13290 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
13291 break;
13292 case OPC_SHRLV_QB:
13293 check_dsp(ctx);
13294 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
13295 break;
13296 case OPC_SHRL_PH:
13297 check_dspr2(ctx);
13298 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
13299 break;
13300 case OPC_SHRLV_PH:
13301 check_dspr2(ctx);
13302 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
13303 break;
13304 case OPC_SHRA_QB:
13305 check_dspr2(ctx);
13306 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
13307 break;
13308 case OPC_SHRA_R_QB:
13309 check_dspr2(ctx);
13310 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
13311 break;
13312 case OPC_SHRAV_QB:
13313 check_dspr2(ctx);
13314 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
13315 break;
13316 case OPC_SHRAV_R_QB:
13317 check_dspr2(ctx);
13318 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
13319 break;
13320 case OPC_SHRA_PH:
13321 check_dsp(ctx);
13322 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
13323 break;
13324 case OPC_SHRA_R_PH:
13325 check_dsp(ctx);
13326 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
13327 break;
13328 case OPC_SHRAV_PH:
13329 check_dsp(ctx);
13330 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
13331 break;
13332 case OPC_SHRAV_R_PH:
13333 check_dsp(ctx);
13334 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
13335 break;
13336 case OPC_SHRA_R_W:
13337 check_dsp(ctx);
13338 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
13339 break;
13340 case OPC_SHRAV_R_W:
13341 check_dsp(ctx);
13342 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
13343 break;
13344 default: /* Invalid */
13345 MIPS_INVAL("MASK SHLL.QB");
13346 generate_exception(ctx, EXCP_RI);
13347 break;
13349 break;
13351 #ifdef TARGET_MIPS64
13352 case OPC_SHLL_OB_DSP:
13353 op2 = MASK_SHLL_OB(ctx->opcode);
13354 switch (op2) {
13355 case OPC_SHLL_PW:
13356 check_dsp(ctx);
13357 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13358 break;
13359 case OPC_SHLLV_PW:
13360 check_dsp(ctx);
13361 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13362 break;
13363 case OPC_SHLL_S_PW:
13364 check_dsp(ctx);
13365 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13366 break;
13367 case OPC_SHLLV_S_PW:
13368 check_dsp(ctx);
13369 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13370 break;
13371 case OPC_SHLL_OB:
13372 check_dsp(ctx);
13373 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
13374 break;
13375 case OPC_SHLLV_OB:
13376 check_dsp(ctx);
13377 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13378 break;
13379 case OPC_SHLL_QH:
13380 check_dsp(ctx);
13381 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13382 break;
13383 case OPC_SHLLV_QH:
13384 check_dsp(ctx);
13385 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13386 break;
13387 case OPC_SHLL_S_QH:
13388 check_dsp(ctx);
13389 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13390 break;
13391 case OPC_SHLLV_S_QH:
13392 check_dsp(ctx);
13393 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13394 break;
13395 case OPC_SHRA_OB:
13396 check_dspr2(ctx);
13397 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
13398 break;
13399 case OPC_SHRAV_OB:
13400 check_dspr2(ctx);
13401 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
13402 break;
13403 case OPC_SHRA_R_OB:
13404 check_dspr2(ctx);
13405 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
13406 break;
13407 case OPC_SHRAV_R_OB:
13408 check_dspr2(ctx);
13409 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
13410 break;
13411 case OPC_SHRA_PW:
13412 check_dsp(ctx);
13413 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
13414 break;
13415 case OPC_SHRAV_PW:
13416 check_dsp(ctx);
13417 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
13418 break;
13419 case OPC_SHRA_R_PW:
13420 check_dsp(ctx);
13421 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
13422 break;
13423 case OPC_SHRAV_R_PW:
13424 check_dsp(ctx);
13425 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
13426 break;
13427 case OPC_SHRA_QH:
13428 check_dsp(ctx);
13429 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
13430 break;
13431 case OPC_SHRAV_QH:
13432 check_dsp(ctx);
13433 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
13434 break;
13435 case OPC_SHRA_R_QH:
13436 check_dsp(ctx);
13437 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
13438 break;
13439 case OPC_SHRAV_R_QH:
13440 check_dsp(ctx);
13441 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
13442 break;
13443 case OPC_SHRL_OB:
13444 check_dsp(ctx);
13445 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
13446 break;
13447 case OPC_SHRLV_OB:
13448 check_dsp(ctx);
13449 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
13450 break;
13451 case OPC_SHRL_QH:
13452 check_dspr2(ctx);
13453 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
13454 break;
13455 case OPC_SHRLV_QH:
13456 check_dspr2(ctx);
13457 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
13458 break;
13459 default: /* Invalid */
13460 MIPS_INVAL("MASK SHLL.OB");
13461 generate_exception(ctx, EXCP_RI);
13462 break;
13464 break;
13465 #endif
13468 tcg_temp_free(t0);
13469 tcg_temp_free(v1_t);
13470 tcg_temp_free(v2_t);
13471 (void)opn; /* avoid a compiler warning */
13472 MIPS_DEBUG("%s", opn);
13475 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
13476 int ret, int v1, int v2, int check_ret)
13478 const char *opn = "mipsdsp multiply";
13479 TCGv_i32 t0;
13480 TCGv v1_t;
13481 TCGv v2_t;
13483 if ((ret == 0) && (check_ret == 1)) {
13484 /* Treat as NOP. */
13485 MIPS_DEBUG("NOP");
13486 return;
13489 t0 = tcg_temp_new_i32();
13490 v1_t = tcg_temp_new();
13491 v2_t = tcg_temp_new();
13493 tcg_gen_movi_i32(t0, ret);
13494 gen_load_gpr(v1_t, v1);
13495 gen_load_gpr(v2_t, v2);
13497 switch (op1) {
13498 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13499 * the same mask and op1. */
13500 case OPC_MULT_G_2E:
13501 check_dspr2(ctx);
13502 switch (op2) {
13503 case OPC_MUL_PH:
13504 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13505 break;
13506 case OPC_MUL_S_PH:
13507 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13508 break;
13509 case OPC_MULQ_S_W:
13510 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13511 break;
13512 case OPC_MULQ_RS_W:
13513 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13514 break;
13516 break;
13517 case OPC_DPA_W_PH_DSP:
13518 switch (op2) {
13519 case OPC_DPAU_H_QBL:
13520 check_dsp(ctx);
13521 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
13522 break;
13523 case OPC_DPAU_H_QBR:
13524 check_dsp(ctx);
13525 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
13526 break;
13527 case OPC_DPSU_H_QBL:
13528 check_dsp(ctx);
13529 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
13530 break;
13531 case OPC_DPSU_H_QBR:
13532 check_dsp(ctx);
13533 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
13534 break;
13535 case OPC_DPA_W_PH:
13536 check_dspr2(ctx);
13537 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
13538 break;
13539 case OPC_DPAX_W_PH:
13540 check_dspr2(ctx);
13541 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
13542 break;
13543 case OPC_DPAQ_S_W_PH:
13544 check_dsp(ctx);
13545 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13546 break;
13547 case OPC_DPAQX_S_W_PH:
13548 check_dspr2(ctx);
13549 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13550 break;
13551 case OPC_DPAQX_SA_W_PH:
13552 check_dspr2(ctx);
13553 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13554 break;
13555 case OPC_DPS_W_PH:
13556 check_dspr2(ctx);
13557 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
13558 break;
13559 case OPC_DPSX_W_PH:
13560 check_dspr2(ctx);
13561 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
13562 break;
13563 case OPC_DPSQ_S_W_PH:
13564 check_dsp(ctx);
13565 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13566 break;
13567 case OPC_DPSQX_S_W_PH:
13568 check_dspr2(ctx);
13569 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13570 break;
13571 case OPC_DPSQX_SA_W_PH:
13572 check_dspr2(ctx);
13573 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13574 break;
13575 case OPC_MULSAQ_S_W_PH:
13576 check_dsp(ctx);
13577 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13578 break;
13579 case OPC_DPAQ_SA_L_W:
13580 check_dsp(ctx);
13581 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13582 break;
13583 case OPC_DPSQ_SA_L_W:
13584 check_dsp(ctx);
13585 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13586 break;
13587 case OPC_MAQ_S_W_PHL:
13588 check_dsp(ctx);
13589 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
13590 break;
13591 case OPC_MAQ_S_W_PHR:
13592 check_dsp(ctx);
13593 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
13594 break;
13595 case OPC_MAQ_SA_W_PHL:
13596 check_dsp(ctx);
13597 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
13598 break;
13599 case OPC_MAQ_SA_W_PHR:
13600 check_dsp(ctx);
13601 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
13602 break;
13603 case OPC_MULSA_W_PH:
13604 check_dspr2(ctx);
13605 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
13606 break;
13608 break;
13609 #ifdef TARGET_MIPS64
13610 case OPC_DPAQ_W_QH_DSP:
13612 int ac = ret & 0x03;
13613 tcg_gen_movi_i32(t0, ac);
13615 switch (op2) {
13616 case OPC_DMADD:
13617 check_dsp(ctx);
13618 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
13619 break;
13620 case OPC_DMADDU:
13621 check_dsp(ctx);
13622 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
13623 break;
13624 case OPC_DMSUB:
13625 check_dsp(ctx);
13626 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
13627 break;
13628 case OPC_DMSUBU:
13629 check_dsp(ctx);
13630 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
13631 break;
13632 case OPC_DPA_W_QH:
13633 check_dspr2(ctx);
13634 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
13635 break;
13636 case OPC_DPAQ_S_W_QH:
13637 check_dsp(ctx);
13638 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13639 break;
13640 case OPC_DPAQ_SA_L_PW:
13641 check_dsp(ctx);
13642 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13643 break;
13644 case OPC_DPAU_H_OBL:
13645 check_dsp(ctx);
13646 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
13647 break;
13648 case OPC_DPAU_H_OBR:
13649 check_dsp(ctx);
13650 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
13651 break;
13652 case OPC_DPS_W_QH:
13653 check_dspr2(ctx);
13654 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
13655 break;
13656 case OPC_DPSQ_S_W_QH:
13657 check_dsp(ctx);
13658 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13659 break;
13660 case OPC_DPSQ_SA_L_PW:
13661 check_dsp(ctx);
13662 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13663 break;
13664 case OPC_DPSU_H_OBL:
13665 check_dsp(ctx);
13666 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
13667 break;
13668 case OPC_DPSU_H_OBR:
13669 check_dsp(ctx);
13670 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
13671 break;
13672 case OPC_MAQ_S_L_PWL:
13673 check_dsp(ctx);
13674 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
13675 break;
13676 case OPC_MAQ_S_L_PWR:
13677 check_dsp(ctx);
13678 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
13679 break;
13680 case OPC_MAQ_S_W_QHLL:
13681 check_dsp(ctx);
13682 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
13683 break;
13684 case OPC_MAQ_SA_W_QHLL:
13685 check_dsp(ctx);
13686 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
13687 break;
13688 case OPC_MAQ_S_W_QHLR:
13689 check_dsp(ctx);
13690 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
13691 break;
13692 case OPC_MAQ_SA_W_QHLR:
13693 check_dsp(ctx);
13694 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
13695 break;
13696 case OPC_MAQ_S_W_QHRL:
13697 check_dsp(ctx);
13698 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
13699 break;
13700 case OPC_MAQ_SA_W_QHRL:
13701 check_dsp(ctx);
13702 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
13703 break;
13704 case OPC_MAQ_S_W_QHRR:
13705 check_dsp(ctx);
13706 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
13707 break;
13708 case OPC_MAQ_SA_W_QHRR:
13709 check_dsp(ctx);
13710 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
13711 break;
13712 case OPC_MULSAQ_S_L_PW:
13713 check_dsp(ctx);
13714 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
13715 break;
13716 case OPC_MULSAQ_S_W_QH:
13717 check_dsp(ctx);
13718 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13719 break;
13722 break;
13723 #endif
13724 case OPC_ADDU_QB_DSP:
13725 switch (op2) {
13726 case OPC_MULEU_S_PH_QBL:
13727 check_dsp(ctx);
13728 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13729 break;
13730 case OPC_MULEU_S_PH_QBR:
13731 check_dsp(ctx);
13732 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13733 break;
13734 case OPC_MULQ_RS_PH:
13735 check_dsp(ctx);
13736 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13737 break;
13738 case OPC_MULEQ_S_W_PHL:
13739 check_dsp(ctx);
13740 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13741 break;
13742 case OPC_MULEQ_S_W_PHR:
13743 check_dsp(ctx);
13744 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13745 break;
13746 case OPC_MULQ_S_PH:
13747 check_dspr2(ctx);
13748 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13749 break;
13751 break;
13752 #ifdef TARGET_MIPS64
13753 case OPC_ADDU_OB_DSP:
13754 switch (op2) {
13755 case OPC_MULEQ_S_PW_QHL:
13756 check_dsp(ctx);
13757 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13758 break;
13759 case OPC_MULEQ_S_PW_QHR:
13760 check_dsp(ctx);
13761 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13762 break;
13763 case OPC_MULEU_S_QH_OBL:
13764 check_dsp(ctx);
13765 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13766 break;
13767 case OPC_MULEU_S_QH_OBR:
13768 check_dsp(ctx);
13769 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13770 break;
13771 case OPC_MULQ_RS_QH:
13772 check_dsp(ctx);
13773 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13774 break;
13776 break;
13777 #endif
13780 tcg_temp_free_i32(t0);
13781 tcg_temp_free(v1_t);
13782 tcg_temp_free(v2_t);
13784 (void)opn; /* avoid a compiler warning */
13785 MIPS_DEBUG("%s", opn);
13789 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
13790 int ret, int val)
13792 const char *opn = "mipsdsp Bit/ Manipulation";
13793 int16_t imm;
13794 TCGv t0;
13795 TCGv val_t;
13797 if (ret == 0) {
13798 /* Treat as NOP. */
13799 MIPS_DEBUG("NOP");
13800 return;
13803 t0 = tcg_temp_new();
13804 val_t = tcg_temp_new();
13805 gen_load_gpr(val_t, val);
13807 switch (op1) {
13808 case OPC_ABSQ_S_PH_DSP:
13809 switch (op2) {
13810 case OPC_BITREV:
13811 check_dsp(ctx);
13812 gen_helper_bitrev(cpu_gpr[ret], val_t);
13813 break;
13814 case OPC_REPL_QB:
13815 check_dsp(ctx);
13817 target_long result;
13818 imm = (ctx->opcode >> 16) & 0xFF;
13819 result = (uint32_t)imm << 24 |
13820 (uint32_t)imm << 16 |
13821 (uint32_t)imm << 8 |
13822 (uint32_t)imm;
13823 result = (int32_t)result;
13824 tcg_gen_movi_tl(cpu_gpr[ret], result);
13826 break;
13827 case OPC_REPLV_QB:
13828 check_dsp(ctx);
13829 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13830 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13831 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13832 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13833 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13834 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13835 break;
13836 case OPC_REPL_PH:
13837 check_dsp(ctx);
13839 imm = (ctx->opcode >> 16) & 0x03FF;
13840 imm = (int16_t)(imm << 6) >> 6;
13841 tcg_gen_movi_tl(cpu_gpr[ret], \
13842 (target_long)((int32_t)imm << 16 | \
13843 (uint16_t)imm));
13845 break;
13846 case OPC_REPLV_PH:
13847 check_dsp(ctx);
13848 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13849 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13850 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13851 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13852 break;
13854 break;
13855 #ifdef TARGET_MIPS64
13856 case OPC_ABSQ_S_QH_DSP:
13857 switch (op2) {
13858 case OPC_REPL_OB:
13859 check_dsp(ctx);
13861 target_long temp;
13863 imm = (ctx->opcode >> 16) & 0xFF;
13864 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
13865 temp = (temp << 16) | temp;
13866 temp = (temp << 32) | temp;
13867 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13868 break;
13870 case OPC_REPL_PW:
13871 check_dsp(ctx);
13873 target_long temp;
13875 imm = (ctx->opcode >> 16) & 0x03FF;
13876 imm = (int16_t)(imm << 6) >> 6;
13877 temp = ((target_long)imm << 32) \
13878 | ((target_long)imm & 0xFFFFFFFF);
13879 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13880 break;
13882 case OPC_REPL_QH:
13883 check_dsp(ctx);
13885 target_long temp;
13887 imm = (ctx->opcode >> 16) & 0x03FF;
13888 imm = (int16_t)(imm << 6) >> 6;
13890 temp = ((uint64_t)(uint16_t)imm << 48) |
13891 ((uint64_t)(uint16_t)imm << 32) |
13892 ((uint64_t)(uint16_t)imm << 16) |
13893 (uint64_t)(uint16_t)imm;
13894 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13895 break;
13897 case OPC_REPLV_OB:
13898 check_dsp(ctx);
13899 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13900 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13901 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13902 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13903 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13904 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13905 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13906 break;
13907 case OPC_REPLV_PW:
13908 check_dsp(ctx);
13909 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
13910 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13911 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13912 break;
13913 case OPC_REPLV_QH:
13914 check_dsp(ctx);
13915 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13916 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13917 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13918 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13919 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13920 break;
13922 break;
13923 #endif
13925 tcg_temp_free(t0);
13926 tcg_temp_free(val_t);
13928 (void)opn; /* avoid a compiler warning */
13929 MIPS_DEBUG("%s", opn);
13932 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
13933 uint32_t op1, uint32_t op2,
13934 int ret, int v1, int v2, int check_ret)
13936 const char *opn = "mipsdsp add compare pick";
13937 TCGv t1;
13938 TCGv v1_t;
13939 TCGv v2_t;
13941 if ((ret == 0) && (check_ret == 1)) {
13942 /* Treat as NOP. */
13943 MIPS_DEBUG("NOP");
13944 return;
13947 t1 = tcg_temp_new();
13948 v1_t = tcg_temp_new();
13949 v2_t = tcg_temp_new();
13951 gen_load_gpr(v1_t, v1);
13952 gen_load_gpr(v2_t, v2);
13954 switch (op1) {
13955 case OPC_CMPU_EQ_QB_DSP:
13956 switch (op2) {
13957 case OPC_CMPU_EQ_QB:
13958 check_dsp(ctx);
13959 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
13960 break;
13961 case OPC_CMPU_LT_QB:
13962 check_dsp(ctx);
13963 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
13964 break;
13965 case OPC_CMPU_LE_QB:
13966 check_dsp(ctx);
13967 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
13968 break;
13969 case OPC_CMPGU_EQ_QB:
13970 check_dsp(ctx);
13971 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
13972 break;
13973 case OPC_CMPGU_LT_QB:
13974 check_dsp(ctx);
13975 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
13976 break;
13977 case OPC_CMPGU_LE_QB:
13978 check_dsp(ctx);
13979 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
13980 break;
13981 case OPC_CMPGDU_EQ_QB:
13982 check_dspr2(ctx);
13983 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
13984 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13985 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13986 tcg_gen_shli_tl(t1, t1, 24);
13987 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13988 break;
13989 case OPC_CMPGDU_LT_QB:
13990 check_dspr2(ctx);
13991 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
13992 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13993 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13994 tcg_gen_shli_tl(t1, t1, 24);
13995 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13996 break;
13997 case OPC_CMPGDU_LE_QB:
13998 check_dspr2(ctx);
13999 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
14000 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14001 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14002 tcg_gen_shli_tl(t1, t1, 24);
14003 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14004 break;
14005 case OPC_CMP_EQ_PH:
14006 check_dsp(ctx);
14007 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
14008 break;
14009 case OPC_CMP_LT_PH:
14010 check_dsp(ctx);
14011 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
14012 break;
14013 case OPC_CMP_LE_PH:
14014 check_dsp(ctx);
14015 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
14016 break;
14017 case OPC_PICK_QB:
14018 check_dsp(ctx);
14019 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14020 break;
14021 case OPC_PICK_PH:
14022 check_dsp(ctx);
14023 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14024 break;
14025 case OPC_PACKRL_PH:
14026 check_dsp(ctx);
14027 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
14028 break;
14030 break;
14031 #ifdef TARGET_MIPS64
14032 case OPC_CMPU_EQ_OB_DSP:
14033 switch (op2) {
14034 case OPC_CMP_EQ_PW:
14035 check_dsp(ctx);
14036 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
14037 break;
14038 case OPC_CMP_LT_PW:
14039 check_dsp(ctx);
14040 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
14041 break;
14042 case OPC_CMP_LE_PW:
14043 check_dsp(ctx);
14044 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
14045 break;
14046 case OPC_CMP_EQ_QH:
14047 check_dsp(ctx);
14048 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
14049 break;
14050 case OPC_CMP_LT_QH:
14051 check_dsp(ctx);
14052 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
14053 break;
14054 case OPC_CMP_LE_QH:
14055 check_dsp(ctx);
14056 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
14057 break;
14058 case OPC_CMPGDU_EQ_OB:
14059 check_dspr2(ctx);
14060 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14061 break;
14062 case OPC_CMPGDU_LT_OB:
14063 check_dspr2(ctx);
14064 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14065 break;
14066 case OPC_CMPGDU_LE_OB:
14067 check_dspr2(ctx);
14068 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14069 break;
14070 case OPC_CMPGU_EQ_OB:
14071 check_dsp(ctx);
14072 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
14073 break;
14074 case OPC_CMPGU_LT_OB:
14075 check_dsp(ctx);
14076 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
14077 break;
14078 case OPC_CMPGU_LE_OB:
14079 check_dsp(ctx);
14080 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
14081 break;
14082 case OPC_CMPU_EQ_OB:
14083 check_dsp(ctx);
14084 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
14085 break;
14086 case OPC_CMPU_LT_OB:
14087 check_dsp(ctx);
14088 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
14089 break;
14090 case OPC_CMPU_LE_OB:
14091 check_dsp(ctx);
14092 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
14093 break;
14094 case OPC_PACKRL_PW:
14095 check_dsp(ctx);
14096 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
14097 break;
14098 case OPC_PICK_OB:
14099 check_dsp(ctx);
14100 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14101 break;
14102 case OPC_PICK_PW:
14103 check_dsp(ctx);
14104 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14105 break;
14106 case OPC_PICK_QH:
14107 check_dsp(ctx);
14108 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14109 break;
14111 break;
14112 #endif
14115 tcg_temp_free(t1);
14116 tcg_temp_free(v1_t);
14117 tcg_temp_free(v2_t);
14119 (void)opn; /* avoid a compiler warning */
14120 MIPS_DEBUG("%s", opn);
14123 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
14124 uint32_t op1, int rt, int rs, int sa)
14126 const char *opn = "mipsdsp append/dappend";
14127 TCGv t0;
14129 check_dspr2(ctx);
14131 if (rt == 0) {
14132 /* Treat as NOP. */
14133 MIPS_DEBUG("NOP");
14134 return;
14137 t0 = tcg_temp_new();
14138 gen_load_gpr(t0, rs);
14140 switch (op1) {
14141 case OPC_APPEND_DSP:
14142 switch (MASK_APPEND(ctx->opcode)) {
14143 case OPC_APPEND:
14144 if (sa != 0) {
14145 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
14147 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14148 break;
14149 case OPC_PREPEND:
14150 if (sa != 0) {
14151 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
14152 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14153 tcg_gen_shli_tl(t0, t0, 32 - sa);
14154 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14156 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14157 break;
14158 case OPC_BALIGN:
14159 sa &= 3;
14160 if (sa != 0 && sa != 2) {
14161 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14162 tcg_gen_ext32u_tl(t0, t0);
14163 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
14164 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14166 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14167 break;
14168 default: /* Invalid */
14169 MIPS_INVAL("MASK APPEND");
14170 generate_exception(ctx, EXCP_RI);
14171 break;
14173 break;
14174 #ifdef TARGET_MIPS64
14175 case OPC_DAPPEND_DSP:
14176 switch (MASK_DAPPEND(ctx->opcode)) {
14177 case OPC_DAPPEND:
14178 if (sa != 0) {
14179 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
14181 break;
14182 case OPC_PREPENDD:
14183 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
14184 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
14185 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
14186 break;
14187 case OPC_PREPENDW:
14188 if (sa != 0) {
14189 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14190 tcg_gen_shli_tl(t0, t0, 64 - sa);
14191 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14193 break;
14194 case OPC_DBALIGN:
14195 sa &= 7;
14196 if (sa != 0 && sa != 2 && sa != 4) {
14197 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14198 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
14199 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14201 break;
14202 default: /* Invalid */
14203 MIPS_INVAL("MASK DAPPEND");
14204 generate_exception(ctx, EXCP_RI);
14205 break;
14207 break;
14208 #endif
14210 tcg_temp_free(t0);
14211 (void)opn; /* avoid a compiler warning */
14212 MIPS_DEBUG("%s", opn);
14215 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
14216 int ret, int v1, int v2, int check_ret)
14219 const char *opn = "mipsdsp accumulator";
14220 TCGv t0;
14221 TCGv t1;
14222 TCGv v1_t;
14223 TCGv v2_t;
14224 int16_t imm;
14226 if ((ret == 0) && (check_ret == 1)) {
14227 /* Treat as NOP. */
14228 MIPS_DEBUG("NOP");
14229 return;
14232 t0 = tcg_temp_new();
14233 t1 = tcg_temp_new();
14234 v1_t = tcg_temp_new();
14235 v2_t = tcg_temp_new();
14237 gen_load_gpr(v1_t, v1);
14238 gen_load_gpr(v2_t, v2);
14240 switch (op1) {
14241 case OPC_EXTR_W_DSP:
14242 check_dsp(ctx);
14243 switch (op2) {
14244 case OPC_EXTR_W:
14245 tcg_gen_movi_tl(t0, v2);
14246 tcg_gen_movi_tl(t1, v1);
14247 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
14248 break;
14249 case OPC_EXTR_R_W:
14250 tcg_gen_movi_tl(t0, v2);
14251 tcg_gen_movi_tl(t1, v1);
14252 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14253 break;
14254 case OPC_EXTR_RS_W:
14255 tcg_gen_movi_tl(t0, v2);
14256 tcg_gen_movi_tl(t1, v1);
14257 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14258 break;
14259 case OPC_EXTR_S_H:
14260 tcg_gen_movi_tl(t0, v2);
14261 tcg_gen_movi_tl(t1, v1);
14262 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14263 break;
14264 case OPC_EXTRV_S_H:
14265 tcg_gen_movi_tl(t0, v2);
14266 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
14267 break;
14268 case OPC_EXTRV_W:
14269 tcg_gen_movi_tl(t0, v2);
14270 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14271 break;
14272 case OPC_EXTRV_R_W:
14273 tcg_gen_movi_tl(t0, v2);
14274 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14275 break;
14276 case OPC_EXTRV_RS_W:
14277 tcg_gen_movi_tl(t0, v2);
14278 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14279 break;
14280 case OPC_EXTP:
14281 tcg_gen_movi_tl(t0, v2);
14282 tcg_gen_movi_tl(t1, v1);
14283 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
14284 break;
14285 case OPC_EXTPV:
14286 tcg_gen_movi_tl(t0, v2);
14287 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
14288 break;
14289 case OPC_EXTPDP:
14290 tcg_gen_movi_tl(t0, v2);
14291 tcg_gen_movi_tl(t1, v1);
14292 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
14293 break;
14294 case OPC_EXTPDPV:
14295 tcg_gen_movi_tl(t0, v2);
14296 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14297 break;
14298 case OPC_SHILO:
14299 imm = (ctx->opcode >> 20) & 0x3F;
14300 tcg_gen_movi_tl(t0, ret);
14301 tcg_gen_movi_tl(t1, imm);
14302 gen_helper_shilo(t0, t1, cpu_env);
14303 break;
14304 case OPC_SHILOV:
14305 tcg_gen_movi_tl(t0, ret);
14306 gen_helper_shilo(t0, v1_t, cpu_env);
14307 break;
14308 case OPC_MTHLIP:
14309 tcg_gen_movi_tl(t0, ret);
14310 gen_helper_mthlip(t0, v1_t, cpu_env);
14311 break;
14312 case OPC_WRDSP:
14313 imm = (ctx->opcode >> 11) & 0x3FF;
14314 tcg_gen_movi_tl(t0, imm);
14315 gen_helper_wrdsp(v1_t, t0, cpu_env);
14316 break;
14317 case OPC_RDDSP:
14318 imm = (ctx->opcode >> 16) & 0x03FF;
14319 tcg_gen_movi_tl(t0, imm);
14320 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
14321 break;
14323 break;
14324 #ifdef TARGET_MIPS64
14325 case OPC_DEXTR_W_DSP:
14326 check_dsp(ctx);
14327 switch (op2) {
14328 case OPC_DMTHLIP:
14329 tcg_gen_movi_tl(t0, ret);
14330 gen_helper_dmthlip(v1_t, t0, cpu_env);
14331 break;
14332 case OPC_DSHILO:
14334 int shift = (ctx->opcode >> 19) & 0x7F;
14335 int ac = (ctx->opcode >> 11) & 0x03;
14336 tcg_gen_movi_tl(t0, shift);
14337 tcg_gen_movi_tl(t1, ac);
14338 gen_helper_dshilo(t0, t1, cpu_env);
14339 break;
14341 case OPC_DSHILOV:
14343 int ac = (ctx->opcode >> 11) & 0x03;
14344 tcg_gen_movi_tl(t0, ac);
14345 gen_helper_dshilo(v1_t, t0, cpu_env);
14346 break;
14348 case OPC_DEXTP:
14349 tcg_gen_movi_tl(t0, v2);
14350 tcg_gen_movi_tl(t1, v1);
14352 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
14353 break;
14354 case OPC_DEXTPV:
14355 tcg_gen_movi_tl(t0, v2);
14356 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
14357 break;
14358 case OPC_DEXTPDP:
14359 tcg_gen_movi_tl(t0, v2);
14360 tcg_gen_movi_tl(t1, v1);
14361 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
14362 break;
14363 case OPC_DEXTPDPV:
14364 tcg_gen_movi_tl(t0, v2);
14365 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14366 break;
14367 case OPC_DEXTR_L:
14368 tcg_gen_movi_tl(t0, v2);
14369 tcg_gen_movi_tl(t1, v1);
14370 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
14371 break;
14372 case OPC_DEXTR_R_L:
14373 tcg_gen_movi_tl(t0, v2);
14374 tcg_gen_movi_tl(t1, v1);
14375 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
14376 break;
14377 case OPC_DEXTR_RS_L:
14378 tcg_gen_movi_tl(t0, v2);
14379 tcg_gen_movi_tl(t1, v1);
14380 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
14381 break;
14382 case OPC_DEXTR_W:
14383 tcg_gen_movi_tl(t0, v2);
14384 tcg_gen_movi_tl(t1, v1);
14385 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
14386 break;
14387 case OPC_DEXTR_R_W:
14388 tcg_gen_movi_tl(t0, v2);
14389 tcg_gen_movi_tl(t1, v1);
14390 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14391 break;
14392 case OPC_DEXTR_RS_W:
14393 tcg_gen_movi_tl(t0, v2);
14394 tcg_gen_movi_tl(t1, v1);
14395 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14396 break;
14397 case OPC_DEXTR_S_H:
14398 tcg_gen_movi_tl(t0, v2);
14399 tcg_gen_movi_tl(t1, v1);
14400 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14401 break;
14402 case OPC_DEXTRV_S_H:
14403 tcg_gen_movi_tl(t0, v2);
14404 tcg_gen_movi_tl(t1, v1);
14405 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14406 break;
14407 case OPC_DEXTRV_L:
14408 tcg_gen_movi_tl(t0, v2);
14409 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14410 break;
14411 case OPC_DEXTRV_R_L:
14412 tcg_gen_movi_tl(t0, v2);
14413 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14414 break;
14415 case OPC_DEXTRV_RS_L:
14416 tcg_gen_movi_tl(t0, v2);
14417 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14418 break;
14419 case OPC_DEXTRV_W:
14420 tcg_gen_movi_tl(t0, v2);
14421 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14422 break;
14423 case OPC_DEXTRV_R_W:
14424 tcg_gen_movi_tl(t0, v2);
14425 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14426 break;
14427 case OPC_DEXTRV_RS_W:
14428 tcg_gen_movi_tl(t0, v2);
14429 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14430 break;
14432 break;
14433 #endif
14436 tcg_temp_free(t0);
14437 tcg_temp_free(t1);
14438 tcg_temp_free(v1_t);
14439 tcg_temp_free(v2_t);
14441 (void)opn; /* avoid a compiler warning */
14442 MIPS_DEBUG("%s", opn);
14445 /* End MIPSDSP functions. */
14447 static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
14449 int32_t offset;
14450 int rs, rt, rd, sa;
14451 uint32_t op, op1, op2;
14452 int16_t imm;
14454 /* make sure instructions are on a word boundary */
14455 if (ctx->pc & 0x3) {
14456 env->CP0_BadVAddr = ctx->pc;
14457 generate_exception(ctx, EXCP_AdEL);
14458 return;
14461 /* Handle blikely not taken case */
14462 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
14463 int l1 = gen_new_label();
14465 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
14466 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
14467 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
14468 gen_goto_tb(ctx, 1, ctx->pc + 4);
14469 gen_set_label(l1);
14472 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
14473 tcg_gen_debug_insn_start(ctx->pc);
14476 op = MASK_OP_MAJOR(ctx->opcode);
14477 rs = (ctx->opcode >> 21) & 0x1f;
14478 rt = (ctx->opcode >> 16) & 0x1f;
14479 rd = (ctx->opcode >> 11) & 0x1f;
14480 sa = (ctx->opcode >> 6) & 0x1f;
14481 imm = (int16_t)ctx->opcode;
14482 switch (op) {
14483 case OPC_SPECIAL:
14484 op1 = MASK_SPECIAL(ctx->opcode);
14485 switch (op1) {
14486 case OPC_SLL: /* Shift with immediate */
14487 case OPC_SRA:
14488 gen_shift_imm(ctx, op1, rd, rt, sa);
14489 break;
14490 case OPC_SRL:
14491 switch ((ctx->opcode >> 21) & 0x1f) {
14492 case 1:
14493 /* rotr is decoded as srl on non-R2 CPUs */
14494 if (ctx->insn_flags & ISA_MIPS32R2) {
14495 op1 = OPC_ROTR;
14497 /* Fallthrough */
14498 case 0:
14499 gen_shift_imm(ctx, op1, rd, rt, sa);
14500 break;
14501 default:
14502 generate_exception(ctx, EXCP_RI);
14503 break;
14505 break;
14506 case OPC_MOVN: /* Conditional move */
14507 case OPC_MOVZ:
14508 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
14509 INSN_LOONGSON2E | INSN_LOONGSON2F);
14510 gen_cond_move(ctx, op1, rd, rs, rt);
14511 break;
14512 case OPC_ADD ... OPC_SUBU:
14513 gen_arith(ctx, op1, rd, rs, rt);
14514 break;
14515 case OPC_SLLV: /* Shifts */
14516 case OPC_SRAV:
14517 gen_shift(ctx, op1, rd, rs, rt);
14518 break;
14519 case OPC_SRLV:
14520 switch ((ctx->opcode >> 6) & 0x1f) {
14521 case 1:
14522 /* rotrv is decoded as srlv on non-R2 CPUs */
14523 if (ctx->insn_flags & ISA_MIPS32R2) {
14524 op1 = OPC_ROTRV;
14526 /* Fallthrough */
14527 case 0:
14528 gen_shift(ctx, op1, rd, rs, rt);
14529 break;
14530 default:
14531 generate_exception(ctx, EXCP_RI);
14532 break;
14534 break;
14535 case OPC_SLT: /* Set on less than */
14536 case OPC_SLTU:
14537 gen_slt(ctx, op1, rd, rs, rt);
14538 break;
14539 case OPC_AND: /* Logic*/
14540 case OPC_OR:
14541 case OPC_NOR:
14542 case OPC_XOR:
14543 gen_logic(ctx, op1, rd, rs, rt);
14544 break;
14545 case OPC_MULT:
14546 case OPC_MULTU:
14547 if (sa) {
14548 check_insn(ctx, INSN_VR54XX);
14549 op1 = MASK_MUL_VR54XX(ctx->opcode);
14550 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
14551 } else {
14552 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14554 break;
14555 case OPC_DIV:
14556 case OPC_DIVU:
14557 gen_muldiv(ctx, op1, 0, rs, rt);
14558 break;
14559 case OPC_JR ... OPC_JALR:
14560 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
14561 break;
14562 case OPC_TGE ... OPC_TEQ: /* Traps */
14563 case OPC_TNE:
14564 gen_trap(ctx, op1, rs, rt, -1);
14565 break;
14566 case OPC_MFHI: /* Move from HI/LO */
14567 case OPC_MFLO:
14568 gen_HILO(ctx, op1, rs & 3, rd);
14569 break;
14570 case OPC_MTHI:
14571 case OPC_MTLO: /* Move to HI/LO */
14572 gen_HILO(ctx, op1, rd & 3, rs);
14573 break;
14574 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
14575 #ifdef MIPS_STRICT_STANDARD
14576 MIPS_INVAL("PMON / selsl");
14577 generate_exception(ctx, EXCP_RI);
14578 #else
14579 gen_helper_0e0i(pmon, sa);
14580 #endif
14581 break;
14582 case OPC_SYSCALL:
14583 generate_exception(ctx, EXCP_SYSCALL);
14584 ctx->bstate = BS_STOP;
14585 break;
14586 case OPC_BREAK:
14587 generate_exception(ctx, EXCP_BREAK);
14588 break;
14589 case OPC_SPIM:
14590 #ifdef MIPS_STRICT_STANDARD
14591 MIPS_INVAL("SPIM");
14592 generate_exception(ctx, EXCP_RI);
14593 #else
14594 /* Implemented as RI exception for now. */
14595 MIPS_INVAL("spim (unofficial)");
14596 generate_exception(ctx, EXCP_RI);
14597 #endif
14598 break;
14599 case OPC_SYNC:
14600 /* Treat as NOP. */
14601 break;
14603 case OPC_MOVCI:
14604 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
14605 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14606 check_cp1_enabled(ctx);
14607 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
14608 (ctx->opcode >> 16) & 1);
14609 } else {
14610 generate_exception_err(ctx, EXCP_CpU, 1);
14612 break;
14614 #if defined(TARGET_MIPS64)
14615 /* MIPS64 specific opcodes */
14616 case OPC_DSLL:
14617 case OPC_DSRA:
14618 case OPC_DSLL32:
14619 case OPC_DSRA32:
14620 check_insn(ctx, ISA_MIPS3);
14621 check_mips_64(ctx);
14622 gen_shift_imm(ctx, op1, rd, rt, sa);
14623 break;
14624 case OPC_DSRL:
14625 switch ((ctx->opcode >> 21) & 0x1f) {
14626 case 1:
14627 /* drotr is decoded as dsrl on non-R2 CPUs */
14628 if (ctx->insn_flags & ISA_MIPS32R2) {
14629 op1 = OPC_DROTR;
14631 /* Fallthrough */
14632 case 0:
14633 check_insn(ctx, ISA_MIPS3);
14634 check_mips_64(ctx);
14635 gen_shift_imm(ctx, op1, rd, rt, sa);
14636 break;
14637 default:
14638 generate_exception(ctx, EXCP_RI);
14639 break;
14641 break;
14642 case OPC_DSRL32:
14643 switch ((ctx->opcode >> 21) & 0x1f) {
14644 case 1:
14645 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
14646 if (ctx->insn_flags & ISA_MIPS32R2) {
14647 op1 = OPC_DROTR32;
14649 /* Fallthrough */
14650 case 0:
14651 check_insn(ctx, ISA_MIPS3);
14652 check_mips_64(ctx);
14653 gen_shift_imm(ctx, op1, rd, rt, sa);
14654 break;
14655 default:
14656 generate_exception(ctx, EXCP_RI);
14657 break;
14659 break;
14660 case OPC_DADD ... OPC_DSUBU:
14661 check_insn(ctx, ISA_MIPS3);
14662 check_mips_64(ctx);
14663 gen_arith(ctx, op1, rd, rs, rt);
14664 break;
14665 case OPC_DSLLV:
14666 case OPC_DSRAV:
14667 check_insn(ctx, ISA_MIPS3);
14668 check_mips_64(ctx);
14669 gen_shift(ctx, op1, rd, rs, rt);
14670 break;
14671 case OPC_DSRLV:
14672 switch ((ctx->opcode >> 6) & 0x1f) {
14673 case 1:
14674 /* drotrv is decoded as dsrlv on non-R2 CPUs */
14675 if (ctx->insn_flags & ISA_MIPS32R2) {
14676 op1 = OPC_DROTRV;
14678 /* Fallthrough */
14679 case 0:
14680 check_insn(ctx, ISA_MIPS3);
14681 check_mips_64(ctx);
14682 gen_shift(ctx, op1, rd, rs, rt);
14683 break;
14684 default:
14685 generate_exception(ctx, EXCP_RI);
14686 break;
14688 break;
14689 case OPC_DMULT ... OPC_DDIVU:
14690 check_insn(ctx, ISA_MIPS3);
14691 check_mips_64(ctx);
14692 gen_muldiv(ctx, op1, 0, rs, rt);
14693 break;
14694 #endif
14695 default: /* Invalid */
14696 MIPS_INVAL("special");
14697 generate_exception(ctx, EXCP_RI);
14698 break;
14700 break;
14701 case OPC_SPECIAL2:
14702 op1 = MASK_SPECIAL2(ctx->opcode);
14703 switch (op1) {
14704 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
14705 case OPC_MSUB ... OPC_MSUBU:
14706 check_insn(ctx, ISA_MIPS32);
14707 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14708 break;
14709 case OPC_MUL:
14710 gen_arith(ctx, op1, rd, rs, rt);
14711 break;
14712 case OPC_CLO:
14713 case OPC_CLZ:
14714 check_insn(ctx, ISA_MIPS32);
14715 gen_cl(ctx, op1, rd, rs);
14716 break;
14717 case OPC_SDBBP:
14718 /* XXX: not clear which exception should be raised
14719 * when in debug mode...
14721 check_insn(ctx, ISA_MIPS32);
14722 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
14723 generate_exception(ctx, EXCP_DBp);
14724 } else {
14725 generate_exception(ctx, EXCP_DBp);
14727 /* Treat as NOP. */
14728 break;
14729 case OPC_DIV_G_2F:
14730 case OPC_DIVU_G_2F:
14731 case OPC_MULT_G_2F:
14732 case OPC_MULTU_G_2F:
14733 case OPC_MOD_G_2F:
14734 case OPC_MODU_G_2F:
14735 check_insn(ctx, INSN_LOONGSON2F);
14736 gen_loongson_integer(ctx, op1, rd, rs, rt);
14737 break;
14738 #if defined(TARGET_MIPS64)
14739 case OPC_DCLO:
14740 case OPC_DCLZ:
14741 check_insn(ctx, ISA_MIPS64);
14742 check_mips_64(ctx);
14743 gen_cl(ctx, op1, rd, rs);
14744 break;
14745 case OPC_DMULT_G_2F:
14746 case OPC_DMULTU_G_2F:
14747 case OPC_DDIV_G_2F:
14748 case OPC_DDIVU_G_2F:
14749 case OPC_DMOD_G_2F:
14750 case OPC_DMODU_G_2F:
14751 check_insn(ctx, INSN_LOONGSON2F);
14752 gen_loongson_integer(ctx, op1, rd, rs, rt);
14753 break;
14754 #endif
14755 default: /* Invalid */
14756 MIPS_INVAL("special2");
14757 generate_exception(ctx, EXCP_RI);
14758 break;
14760 break;
14761 case OPC_SPECIAL3:
14762 op1 = MASK_SPECIAL3(ctx->opcode);
14763 switch (op1) {
14764 case OPC_EXT:
14765 case OPC_INS:
14766 check_insn(ctx, ISA_MIPS32R2);
14767 gen_bitops(ctx, op1, rt, rs, sa, rd);
14768 break;
14769 case OPC_BSHFL:
14770 check_insn(ctx, ISA_MIPS32R2);
14771 op2 = MASK_BSHFL(ctx->opcode);
14772 gen_bshfl(ctx, op2, rt, rd);
14773 break;
14774 case OPC_RDHWR:
14775 gen_rdhwr(ctx, rt, rd);
14776 break;
14777 case OPC_FORK:
14778 check_insn(ctx, ASE_MT);
14780 TCGv t0 = tcg_temp_new();
14781 TCGv t1 = tcg_temp_new();
14783 gen_load_gpr(t0, rt);
14784 gen_load_gpr(t1, rs);
14785 gen_helper_fork(t0, t1);
14786 tcg_temp_free(t0);
14787 tcg_temp_free(t1);
14789 break;
14790 case OPC_YIELD:
14791 check_insn(ctx, ASE_MT);
14793 TCGv t0 = tcg_temp_new();
14795 save_cpu_state(ctx, 1);
14796 gen_load_gpr(t0, rs);
14797 gen_helper_yield(t0, cpu_env, t0);
14798 gen_store_gpr(t0, rd);
14799 tcg_temp_free(t0);
14801 break;
14802 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
14803 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
14804 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
14805 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14806 * the same mask and op1. */
14807 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
14808 op2 = MASK_ADDUH_QB(ctx->opcode);
14809 switch (op2) {
14810 case OPC_ADDUH_QB:
14811 case OPC_ADDUH_R_QB:
14812 case OPC_ADDQH_PH:
14813 case OPC_ADDQH_R_PH:
14814 case OPC_ADDQH_W:
14815 case OPC_ADDQH_R_W:
14816 case OPC_SUBUH_QB:
14817 case OPC_SUBUH_R_QB:
14818 case OPC_SUBQH_PH:
14819 case OPC_SUBQH_R_PH:
14820 case OPC_SUBQH_W:
14821 case OPC_SUBQH_R_W:
14822 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14823 break;
14824 case OPC_MUL_PH:
14825 case OPC_MUL_S_PH:
14826 case OPC_MULQ_S_W:
14827 case OPC_MULQ_RS_W:
14828 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14829 break;
14830 default:
14831 MIPS_INVAL("MASK ADDUH.QB");
14832 generate_exception(ctx, EXCP_RI);
14833 break;
14835 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
14836 gen_loongson_integer(ctx, op1, rd, rs, rt);
14837 } else {
14838 generate_exception(ctx, EXCP_RI);
14840 break;
14841 case OPC_LX_DSP:
14842 op2 = MASK_LX(ctx->opcode);
14843 switch (op2) {
14844 #if defined(TARGET_MIPS64)
14845 case OPC_LDX:
14846 #endif
14847 case OPC_LBUX:
14848 case OPC_LHX:
14849 case OPC_LWX:
14850 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
14851 break;
14852 default: /* Invalid */
14853 MIPS_INVAL("MASK LX");
14854 generate_exception(ctx, EXCP_RI);
14855 break;
14857 break;
14858 case OPC_ABSQ_S_PH_DSP:
14859 op2 = MASK_ABSQ_S_PH(ctx->opcode);
14860 switch (op2) {
14861 case OPC_ABSQ_S_QB:
14862 case OPC_ABSQ_S_PH:
14863 case OPC_ABSQ_S_W:
14864 case OPC_PRECEQ_W_PHL:
14865 case OPC_PRECEQ_W_PHR:
14866 case OPC_PRECEQU_PH_QBL:
14867 case OPC_PRECEQU_PH_QBR:
14868 case OPC_PRECEQU_PH_QBLA:
14869 case OPC_PRECEQU_PH_QBRA:
14870 case OPC_PRECEU_PH_QBL:
14871 case OPC_PRECEU_PH_QBR:
14872 case OPC_PRECEU_PH_QBLA:
14873 case OPC_PRECEU_PH_QBRA:
14874 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14875 break;
14876 case OPC_BITREV:
14877 case OPC_REPL_QB:
14878 case OPC_REPLV_QB:
14879 case OPC_REPL_PH:
14880 case OPC_REPLV_PH:
14881 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
14882 break;
14883 default:
14884 MIPS_INVAL("MASK ABSQ_S.PH");
14885 generate_exception(ctx, EXCP_RI);
14886 break;
14888 break;
14889 case OPC_ADDU_QB_DSP:
14890 op2 = MASK_ADDU_QB(ctx->opcode);
14891 switch (op2) {
14892 case OPC_ADDQ_PH:
14893 case OPC_ADDQ_S_PH:
14894 case OPC_ADDQ_S_W:
14895 case OPC_ADDU_QB:
14896 case OPC_ADDU_S_QB:
14897 case OPC_ADDU_PH:
14898 case OPC_ADDU_S_PH:
14899 case OPC_SUBQ_PH:
14900 case OPC_SUBQ_S_PH:
14901 case OPC_SUBQ_S_W:
14902 case OPC_SUBU_QB:
14903 case OPC_SUBU_S_QB:
14904 case OPC_SUBU_PH:
14905 case OPC_SUBU_S_PH:
14906 case OPC_ADDSC:
14907 case OPC_ADDWC:
14908 case OPC_MODSUB:
14909 case OPC_RADDU_W_QB:
14910 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14911 break;
14912 case OPC_MULEU_S_PH_QBL:
14913 case OPC_MULEU_S_PH_QBR:
14914 case OPC_MULQ_RS_PH:
14915 case OPC_MULEQ_S_W_PHL:
14916 case OPC_MULEQ_S_W_PHR:
14917 case OPC_MULQ_S_PH:
14918 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14919 break;
14920 default: /* Invalid */
14921 MIPS_INVAL("MASK ADDU.QB");
14922 generate_exception(ctx, EXCP_RI);
14923 break;
14926 break;
14927 case OPC_CMPU_EQ_QB_DSP:
14928 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14929 switch (op2) {
14930 case OPC_PRECR_SRA_PH_W:
14931 case OPC_PRECR_SRA_R_PH_W:
14932 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14933 break;
14934 case OPC_PRECR_QB_PH:
14935 case OPC_PRECRQ_QB_PH:
14936 case OPC_PRECRQ_PH_W:
14937 case OPC_PRECRQ_RS_PH_W:
14938 case OPC_PRECRQU_S_QB_PH:
14939 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14940 break;
14941 case OPC_CMPU_EQ_QB:
14942 case OPC_CMPU_LT_QB:
14943 case OPC_CMPU_LE_QB:
14944 case OPC_CMP_EQ_PH:
14945 case OPC_CMP_LT_PH:
14946 case OPC_CMP_LE_PH:
14947 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
14948 break;
14949 case OPC_CMPGU_EQ_QB:
14950 case OPC_CMPGU_LT_QB:
14951 case OPC_CMPGU_LE_QB:
14952 case OPC_CMPGDU_EQ_QB:
14953 case OPC_CMPGDU_LT_QB:
14954 case OPC_CMPGDU_LE_QB:
14955 case OPC_PICK_QB:
14956 case OPC_PICK_PH:
14957 case OPC_PACKRL_PH:
14958 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14959 break;
14960 default: /* Invalid */
14961 MIPS_INVAL("MASK CMPU.EQ.QB");
14962 generate_exception(ctx, EXCP_RI);
14963 break;
14965 break;
14966 case OPC_SHLL_QB_DSP:
14967 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14968 break;
14969 case OPC_DPA_W_PH_DSP:
14970 op2 = MASK_DPA_W_PH(ctx->opcode);
14971 switch (op2) {
14972 case OPC_DPAU_H_QBL:
14973 case OPC_DPAU_H_QBR:
14974 case OPC_DPSU_H_QBL:
14975 case OPC_DPSU_H_QBR:
14976 case OPC_DPA_W_PH:
14977 case OPC_DPAX_W_PH:
14978 case OPC_DPAQ_S_W_PH:
14979 case OPC_DPAQX_S_W_PH:
14980 case OPC_DPAQX_SA_W_PH:
14981 case OPC_DPS_W_PH:
14982 case OPC_DPSX_W_PH:
14983 case OPC_DPSQ_S_W_PH:
14984 case OPC_DPSQX_S_W_PH:
14985 case OPC_DPSQX_SA_W_PH:
14986 case OPC_MULSAQ_S_W_PH:
14987 case OPC_DPAQ_SA_L_W:
14988 case OPC_DPSQ_SA_L_W:
14989 case OPC_MAQ_S_W_PHL:
14990 case OPC_MAQ_S_W_PHR:
14991 case OPC_MAQ_SA_W_PHL:
14992 case OPC_MAQ_SA_W_PHR:
14993 case OPC_MULSA_W_PH:
14994 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14995 break;
14996 default: /* Invalid */
14997 MIPS_INVAL("MASK DPAW.PH");
14998 generate_exception(ctx, EXCP_RI);
14999 break;
15001 break;
15002 case OPC_INSV_DSP:
15003 op2 = MASK_INSV(ctx->opcode);
15004 switch (op2) {
15005 case OPC_INSV:
15006 check_dsp(ctx);
15008 TCGv t0, t1;
15010 if (rt == 0) {
15011 MIPS_DEBUG("NOP");
15012 break;
15015 t0 = tcg_temp_new();
15016 t1 = tcg_temp_new();
15018 gen_load_gpr(t0, rt);
15019 gen_load_gpr(t1, rs);
15021 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
15023 tcg_temp_free(t0);
15024 tcg_temp_free(t1);
15025 break;
15027 default: /* Invalid */
15028 MIPS_INVAL("MASK INSV");
15029 generate_exception(ctx, EXCP_RI);
15030 break;
15032 break;
15033 case OPC_APPEND_DSP:
15034 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
15035 break;
15036 case OPC_EXTR_W_DSP:
15037 op2 = MASK_EXTR_W(ctx->opcode);
15038 switch (op2) {
15039 case OPC_EXTR_W:
15040 case OPC_EXTR_R_W:
15041 case OPC_EXTR_RS_W:
15042 case OPC_EXTR_S_H:
15043 case OPC_EXTRV_S_H:
15044 case OPC_EXTRV_W:
15045 case OPC_EXTRV_R_W:
15046 case OPC_EXTRV_RS_W:
15047 case OPC_EXTP:
15048 case OPC_EXTPV:
15049 case OPC_EXTPDP:
15050 case OPC_EXTPDPV:
15051 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
15052 break;
15053 case OPC_RDDSP:
15054 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
15055 break;
15056 case OPC_SHILO:
15057 case OPC_SHILOV:
15058 case OPC_MTHLIP:
15059 case OPC_WRDSP:
15060 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
15061 break;
15062 default: /* Invalid */
15063 MIPS_INVAL("MASK EXTR.W");
15064 generate_exception(ctx, EXCP_RI);
15065 break;
15067 break;
15068 #if defined(TARGET_MIPS64)
15069 case OPC_DEXTM ... OPC_DEXT:
15070 case OPC_DINSM ... OPC_DINS:
15071 check_insn(ctx, ISA_MIPS64R2);
15072 check_mips_64(ctx);
15073 gen_bitops(ctx, op1, rt, rs, sa, rd);
15074 break;
15075 case OPC_DBSHFL:
15076 check_insn(ctx, ISA_MIPS64R2);
15077 check_mips_64(ctx);
15078 op2 = MASK_DBSHFL(ctx->opcode);
15079 gen_bshfl(ctx, op2, rt, rd);
15080 break;
15081 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
15082 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
15083 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
15084 check_insn(ctx, INSN_LOONGSON2E);
15085 gen_loongson_integer(ctx, op1, rd, rs, rt);
15086 break;
15087 case OPC_ABSQ_S_QH_DSP:
15088 op2 = MASK_ABSQ_S_QH(ctx->opcode);
15089 switch (op2) {
15090 case OPC_PRECEQ_L_PWL:
15091 case OPC_PRECEQ_L_PWR:
15092 case OPC_PRECEQ_PW_QHL:
15093 case OPC_PRECEQ_PW_QHR:
15094 case OPC_PRECEQ_PW_QHLA:
15095 case OPC_PRECEQ_PW_QHRA:
15096 case OPC_PRECEQU_QH_OBL:
15097 case OPC_PRECEQU_QH_OBR:
15098 case OPC_PRECEQU_QH_OBLA:
15099 case OPC_PRECEQU_QH_OBRA:
15100 case OPC_PRECEU_QH_OBL:
15101 case OPC_PRECEU_QH_OBR:
15102 case OPC_PRECEU_QH_OBLA:
15103 case OPC_PRECEU_QH_OBRA:
15104 case OPC_ABSQ_S_OB:
15105 case OPC_ABSQ_S_PW:
15106 case OPC_ABSQ_S_QH:
15107 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15108 break;
15109 case OPC_REPL_OB:
15110 case OPC_REPL_PW:
15111 case OPC_REPL_QH:
15112 case OPC_REPLV_OB:
15113 case OPC_REPLV_PW:
15114 case OPC_REPLV_QH:
15115 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
15116 break;
15117 default: /* Invalid */
15118 MIPS_INVAL("MASK ABSQ_S.QH");
15119 generate_exception(ctx, EXCP_RI);
15120 break;
15122 break;
15123 case OPC_ADDU_OB_DSP:
15124 op2 = MASK_ADDU_OB(ctx->opcode);
15125 switch (op2) {
15126 case OPC_RADDU_L_OB:
15127 case OPC_SUBQ_PW:
15128 case OPC_SUBQ_S_PW:
15129 case OPC_SUBQ_QH:
15130 case OPC_SUBQ_S_QH:
15131 case OPC_SUBU_OB:
15132 case OPC_SUBU_S_OB:
15133 case OPC_SUBU_QH:
15134 case OPC_SUBU_S_QH:
15135 case OPC_SUBUH_OB:
15136 case OPC_SUBUH_R_OB:
15137 case OPC_ADDQ_PW:
15138 case OPC_ADDQ_S_PW:
15139 case OPC_ADDQ_QH:
15140 case OPC_ADDQ_S_QH:
15141 case OPC_ADDU_OB:
15142 case OPC_ADDU_S_OB:
15143 case OPC_ADDU_QH:
15144 case OPC_ADDU_S_QH:
15145 case OPC_ADDUH_OB:
15146 case OPC_ADDUH_R_OB:
15147 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15148 break;
15149 case OPC_MULEQ_S_PW_QHL:
15150 case OPC_MULEQ_S_PW_QHR:
15151 case OPC_MULEU_S_QH_OBL:
15152 case OPC_MULEU_S_QH_OBR:
15153 case OPC_MULQ_RS_QH:
15154 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
15155 break;
15156 default: /* Invalid */
15157 MIPS_INVAL("MASK ADDU.OB");
15158 generate_exception(ctx, EXCP_RI);
15159 break;
15161 break;
15162 case OPC_CMPU_EQ_OB_DSP:
15163 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
15164 switch (op2) {
15165 case OPC_PRECR_SRA_QH_PW:
15166 case OPC_PRECR_SRA_R_QH_PW:
15167 /* Return value is rt. */
15168 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
15169 break;
15170 case OPC_PRECR_OB_QH:
15171 case OPC_PRECRQ_OB_QH:
15172 case OPC_PRECRQ_PW_L:
15173 case OPC_PRECRQ_QH_PW:
15174 case OPC_PRECRQ_RS_QH_PW:
15175 case OPC_PRECRQU_S_OB_QH:
15176 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15177 break;
15178 case OPC_CMPU_EQ_OB:
15179 case OPC_CMPU_LT_OB:
15180 case OPC_CMPU_LE_OB:
15181 case OPC_CMP_EQ_QH:
15182 case OPC_CMP_LT_QH:
15183 case OPC_CMP_LE_QH:
15184 case OPC_CMP_EQ_PW:
15185 case OPC_CMP_LT_PW:
15186 case OPC_CMP_LE_PW:
15187 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
15188 break;
15189 case OPC_CMPGDU_EQ_OB:
15190 case OPC_CMPGDU_LT_OB:
15191 case OPC_CMPGDU_LE_OB:
15192 case OPC_CMPGU_EQ_OB:
15193 case OPC_CMPGU_LT_OB:
15194 case OPC_CMPGU_LE_OB:
15195 case OPC_PACKRL_PW:
15196 case OPC_PICK_OB:
15197 case OPC_PICK_PW:
15198 case OPC_PICK_QH:
15199 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
15200 break;
15201 default: /* Invalid */
15202 MIPS_INVAL("MASK CMPU_EQ.OB");
15203 generate_exception(ctx, EXCP_RI);
15204 break;
15206 break;
15207 case OPC_DAPPEND_DSP:
15208 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
15209 break;
15210 case OPC_DEXTR_W_DSP:
15211 op2 = MASK_DEXTR_W(ctx->opcode);
15212 switch (op2) {
15213 case OPC_DEXTP:
15214 case OPC_DEXTPDP:
15215 case OPC_DEXTPDPV:
15216 case OPC_DEXTPV:
15217 case OPC_DEXTR_L:
15218 case OPC_DEXTR_R_L:
15219 case OPC_DEXTR_RS_L:
15220 case OPC_DEXTR_W:
15221 case OPC_DEXTR_R_W:
15222 case OPC_DEXTR_RS_W:
15223 case OPC_DEXTR_S_H:
15224 case OPC_DEXTRV_L:
15225 case OPC_DEXTRV_R_L:
15226 case OPC_DEXTRV_RS_L:
15227 case OPC_DEXTRV_S_H:
15228 case OPC_DEXTRV_W:
15229 case OPC_DEXTRV_R_W:
15230 case OPC_DEXTRV_RS_W:
15231 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
15232 break;
15233 case OPC_DMTHLIP:
15234 case OPC_DSHILO:
15235 case OPC_DSHILOV:
15236 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
15237 break;
15238 default: /* Invalid */
15239 MIPS_INVAL("MASK EXTR.W");
15240 generate_exception(ctx, EXCP_RI);
15241 break;
15243 break;
15244 case OPC_DPAQ_W_QH_DSP:
15245 op2 = MASK_DPAQ_W_QH(ctx->opcode);
15246 switch (op2) {
15247 case OPC_DPAU_H_OBL:
15248 case OPC_DPAU_H_OBR:
15249 case OPC_DPSU_H_OBL:
15250 case OPC_DPSU_H_OBR:
15251 case OPC_DPA_W_QH:
15252 case OPC_DPAQ_S_W_QH:
15253 case OPC_DPS_W_QH:
15254 case OPC_DPSQ_S_W_QH:
15255 case OPC_MULSAQ_S_W_QH:
15256 case OPC_DPAQ_SA_L_PW:
15257 case OPC_DPSQ_SA_L_PW:
15258 case OPC_MULSAQ_S_L_PW:
15259 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15260 break;
15261 case OPC_MAQ_S_W_QHLL:
15262 case OPC_MAQ_S_W_QHLR:
15263 case OPC_MAQ_S_W_QHRL:
15264 case OPC_MAQ_S_W_QHRR:
15265 case OPC_MAQ_SA_W_QHLL:
15266 case OPC_MAQ_SA_W_QHLR:
15267 case OPC_MAQ_SA_W_QHRL:
15268 case OPC_MAQ_SA_W_QHRR:
15269 case OPC_MAQ_S_L_PWL:
15270 case OPC_MAQ_S_L_PWR:
15271 case OPC_DMADD:
15272 case OPC_DMADDU:
15273 case OPC_DMSUB:
15274 case OPC_DMSUBU:
15275 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15276 break;
15277 default: /* Invalid */
15278 MIPS_INVAL("MASK DPAQ.W.QH");
15279 generate_exception(ctx, EXCP_RI);
15280 break;
15282 break;
15283 case OPC_DINSV_DSP:
15284 op2 = MASK_INSV(ctx->opcode);
15285 switch (op2) {
15286 case OPC_DINSV:
15288 TCGv t0, t1;
15290 if (rt == 0) {
15291 MIPS_DEBUG("NOP");
15292 break;
15294 check_dsp(ctx);
15296 t0 = tcg_temp_new();
15297 t1 = tcg_temp_new();
15299 gen_load_gpr(t0, rt);
15300 gen_load_gpr(t1, rs);
15302 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
15304 tcg_temp_free(t0);
15305 tcg_temp_free(t1);
15306 break;
15308 default: /* Invalid */
15309 MIPS_INVAL("MASK DINSV");
15310 generate_exception(ctx, EXCP_RI);
15311 break;
15313 break;
15314 case OPC_SHLL_OB_DSP:
15315 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
15316 break;
15317 #endif
15318 default: /* Invalid */
15319 MIPS_INVAL("special3");
15320 generate_exception(ctx, EXCP_RI);
15321 break;
15323 break;
15324 case OPC_REGIMM:
15325 op1 = MASK_REGIMM(ctx->opcode);
15326 switch (op1) {
15327 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
15328 case OPC_BLTZAL ... OPC_BGEZALL:
15329 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
15330 break;
15331 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
15332 case OPC_TNEI:
15333 gen_trap(ctx, op1, rs, -1, imm);
15334 break;
15335 case OPC_SYNCI:
15336 check_insn(ctx, ISA_MIPS32R2);
15337 /* Treat as NOP. */
15338 break;
15339 case OPC_BPOSGE32: /* MIPS DSP branch */
15340 #if defined(TARGET_MIPS64)
15341 case OPC_BPOSGE64:
15342 #endif
15343 check_dsp(ctx);
15344 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
15345 break;
15346 default: /* Invalid */
15347 MIPS_INVAL("regimm");
15348 generate_exception(ctx, EXCP_RI);
15349 break;
15351 break;
15352 case OPC_CP0:
15353 check_cp0_enabled(ctx);
15354 op1 = MASK_CP0(ctx->opcode);
15355 switch (op1) {
15356 case OPC_MFC0:
15357 case OPC_MTC0:
15358 case OPC_MFTR:
15359 case OPC_MTTR:
15360 #if defined(TARGET_MIPS64)
15361 case OPC_DMFC0:
15362 case OPC_DMTC0:
15363 #endif
15364 #ifndef CONFIG_USER_ONLY
15365 gen_cp0(env, ctx, op1, rt, rd);
15366 #endif /* !CONFIG_USER_ONLY */
15367 break;
15368 case OPC_C0_FIRST ... OPC_C0_LAST:
15369 #ifndef CONFIG_USER_ONLY
15370 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
15371 #endif /* !CONFIG_USER_ONLY */
15372 break;
15373 case OPC_MFMC0:
15374 #ifndef CONFIG_USER_ONLY
15376 TCGv t0 = tcg_temp_new();
15378 op2 = MASK_MFMC0(ctx->opcode);
15379 switch (op2) {
15380 case OPC_DMT:
15381 check_insn(ctx, ASE_MT);
15382 gen_helper_dmt(t0);
15383 gen_store_gpr(t0, rt);
15384 break;
15385 case OPC_EMT:
15386 check_insn(ctx, ASE_MT);
15387 gen_helper_emt(t0);
15388 gen_store_gpr(t0, rt);
15389 break;
15390 case OPC_DVPE:
15391 check_insn(ctx, ASE_MT);
15392 gen_helper_dvpe(t0, cpu_env);
15393 gen_store_gpr(t0, rt);
15394 break;
15395 case OPC_EVPE:
15396 check_insn(ctx, ASE_MT);
15397 gen_helper_evpe(t0, cpu_env);
15398 gen_store_gpr(t0, rt);
15399 break;
15400 case OPC_DI:
15401 check_insn(ctx, ISA_MIPS32R2);
15402 save_cpu_state(ctx, 1);
15403 gen_helper_di(t0, cpu_env);
15404 gen_store_gpr(t0, rt);
15405 /* Stop translation as we may have switched the execution mode */
15406 ctx->bstate = BS_STOP;
15407 break;
15408 case OPC_EI:
15409 check_insn(ctx, ISA_MIPS32R2);
15410 save_cpu_state(ctx, 1);
15411 gen_helper_ei(t0, cpu_env);
15412 gen_store_gpr(t0, rt);
15413 /* Stop translation as we may have switched the execution mode */
15414 ctx->bstate = BS_STOP;
15415 break;
15416 default: /* Invalid */
15417 MIPS_INVAL("mfmc0");
15418 generate_exception(ctx, EXCP_RI);
15419 break;
15421 tcg_temp_free(t0);
15423 #endif /* !CONFIG_USER_ONLY */
15424 break;
15425 case OPC_RDPGPR:
15426 check_insn(ctx, ISA_MIPS32R2);
15427 gen_load_srsgpr(rt, rd);
15428 break;
15429 case OPC_WRPGPR:
15430 check_insn(ctx, ISA_MIPS32R2);
15431 gen_store_srsgpr(rt, rd);
15432 break;
15433 default:
15434 MIPS_INVAL("cp0");
15435 generate_exception(ctx, EXCP_RI);
15436 break;
15438 break;
15439 case OPC_ADDI: /* Arithmetic with immediate opcode */
15440 case OPC_ADDIU:
15441 gen_arith_imm(ctx, op, rt, rs, imm);
15442 break;
15443 case OPC_SLTI: /* Set on less than with immediate opcode */
15444 case OPC_SLTIU:
15445 gen_slt_imm(ctx, op, rt, rs, imm);
15446 break;
15447 case OPC_ANDI: /* Arithmetic with immediate opcode */
15448 case OPC_LUI:
15449 case OPC_ORI:
15450 case OPC_XORI:
15451 gen_logic_imm(ctx, op, rt, rs, imm);
15452 break;
15453 case OPC_J ... OPC_JAL: /* Jump */
15454 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15455 gen_compute_branch(ctx, op, 4, rs, rt, offset);
15456 break;
15457 case OPC_BEQ ... OPC_BGTZ: /* Branch */
15458 case OPC_BEQL ... OPC_BGTZL:
15459 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
15460 break;
15461 case OPC_LB ... OPC_LWR: /* Load and stores */
15462 case OPC_LL:
15463 gen_ld(ctx, op, rt, rs, imm);
15464 break;
15465 case OPC_SB ... OPC_SW:
15466 case OPC_SWR:
15467 gen_st(ctx, op, rt, rs, imm);
15468 break;
15469 case OPC_SC:
15470 gen_st_cond(ctx, op, rt, rs, imm);
15471 break;
15472 case OPC_CACHE:
15473 check_cp0_enabled(ctx);
15474 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
15475 /* Treat as NOP. */
15476 break;
15477 case OPC_PREF:
15478 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
15479 /* Treat as NOP. */
15480 break;
15482 /* Floating point (COP1). */
15483 case OPC_LWC1:
15484 case OPC_LDC1:
15485 case OPC_SWC1:
15486 case OPC_SDC1:
15487 gen_cop1_ldst(ctx, op, rt, rs, imm);
15488 break;
15490 case OPC_CP1:
15491 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15492 check_cp1_enabled(ctx);
15493 op1 = MASK_CP1(ctx->opcode);
15494 switch (op1) {
15495 case OPC_MFHC1:
15496 case OPC_MTHC1:
15497 check_insn(ctx, ISA_MIPS32R2);
15498 case OPC_MFC1:
15499 case OPC_CFC1:
15500 case OPC_MTC1:
15501 case OPC_CTC1:
15502 gen_cp1(ctx, op1, rt, rd);
15503 break;
15504 #if defined(TARGET_MIPS64)
15505 case OPC_DMFC1:
15506 case OPC_DMTC1:
15507 check_insn(ctx, ISA_MIPS3);
15508 gen_cp1(ctx, op1, rt, rd);
15509 break;
15510 #endif
15511 case OPC_BC1ANY2:
15512 case OPC_BC1ANY4:
15513 check_cop1x(ctx);
15514 check_insn(ctx, ASE_MIPS3D);
15515 /* fall through */
15516 case OPC_BC1:
15517 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
15518 (rt >> 2) & 0x7, imm << 2);
15519 break;
15520 case OPC_S_FMT:
15521 case OPC_D_FMT:
15522 case OPC_W_FMT:
15523 case OPC_L_FMT:
15524 case OPC_PS_FMT:
15525 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15526 (imm >> 8) & 0x7);
15527 break;
15528 default:
15529 MIPS_INVAL("cp1");
15530 generate_exception (ctx, EXCP_RI);
15531 break;
15533 } else {
15534 generate_exception_err(ctx, EXCP_CpU, 1);
15536 break;
15538 /* COP2. */
15539 case OPC_LWC2:
15540 case OPC_LDC2:
15541 case OPC_SWC2:
15542 case OPC_SDC2:
15543 /* COP2: Not implemented. */
15544 generate_exception_err(ctx, EXCP_CpU, 2);
15545 break;
15546 case OPC_CP2:
15547 check_insn(ctx, INSN_LOONGSON2F);
15548 /* Note that these instructions use different fields. */
15549 gen_loongson_multimedia(ctx, sa, rd, rt);
15550 break;
15552 case OPC_CP3:
15553 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15554 check_cp1_enabled(ctx);
15555 op1 = MASK_CP3(ctx->opcode);
15556 switch (op1) {
15557 case OPC_LWXC1:
15558 case OPC_LDXC1:
15559 case OPC_LUXC1:
15560 case OPC_SWXC1:
15561 case OPC_SDXC1:
15562 case OPC_SUXC1:
15563 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
15564 break;
15565 case OPC_PREFX:
15566 /* Treat as NOP. */
15567 break;
15568 case OPC_ALNV_PS:
15569 case OPC_MADD_S:
15570 case OPC_MADD_D:
15571 case OPC_MADD_PS:
15572 case OPC_MSUB_S:
15573 case OPC_MSUB_D:
15574 case OPC_MSUB_PS:
15575 case OPC_NMADD_S:
15576 case OPC_NMADD_D:
15577 case OPC_NMADD_PS:
15578 case OPC_NMSUB_S:
15579 case OPC_NMSUB_D:
15580 case OPC_NMSUB_PS:
15581 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
15582 break;
15583 default:
15584 MIPS_INVAL("cp3");
15585 generate_exception (ctx, EXCP_RI);
15586 break;
15588 } else {
15589 generate_exception_err(ctx, EXCP_CpU, 1);
15591 break;
15593 #if defined(TARGET_MIPS64)
15594 /* MIPS64 opcodes */
15595 case OPC_LWU:
15596 case OPC_LDL ... OPC_LDR:
15597 case OPC_LLD:
15598 case OPC_LD:
15599 check_insn(ctx, ISA_MIPS3);
15600 check_mips_64(ctx);
15601 gen_ld(ctx, op, rt, rs, imm);
15602 break;
15603 case OPC_SDL ... OPC_SDR:
15604 case OPC_SD:
15605 check_insn(ctx, ISA_MIPS3);
15606 check_mips_64(ctx);
15607 gen_st(ctx, op, rt, rs, imm);
15608 break;
15609 case OPC_SCD:
15610 check_insn(ctx, ISA_MIPS3);
15611 check_mips_64(ctx);
15612 gen_st_cond(ctx, op, rt, rs, imm);
15613 break;
15614 case OPC_DADDI:
15615 case OPC_DADDIU:
15616 check_insn(ctx, ISA_MIPS3);
15617 check_mips_64(ctx);
15618 gen_arith_imm(ctx, op, rt, rs, imm);
15619 break;
15620 #endif
15621 case OPC_JALX:
15622 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
15623 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15624 gen_compute_branch(ctx, op, 4, rs, rt, offset);
15625 break;
15626 case OPC_MDMX:
15627 check_insn(ctx, ASE_MDMX);
15628 /* MDMX: Not implemented. */
15629 default: /* Invalid */
15630 MIPS_INVAL("major opcode");
15631 generate_exception(ctx, EXCP_RI);
15632 break;
15636 static inline void
15637 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
15638 bool search_pc)
15640 CPUState *cs = CPU(cpu);
15641 CPUMIPSState *env = &cpu->env;
15642 DisasContext ctx;
15643 target_ulong pc_start;
15644 uint16_t *gen_opc_end;
15645 CPUBreakpoint *bp;
15646 int j, lj = -1;
15647 int num_insns;
15648 int max_insns;
15649 int insn_bytes;
15650 int is_delay;
15652 if (search_pc)
15653 qemu_log("search pc %d\n", search_pc);
15655 pc_start = tb->pc;
15656 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
15657 ctx.pc = pc_start;
15658 ctx.saved_pc = -1;
15659 ctx.singlestep_enabled = cs->singlestep_enabled;
15660 ctx.insn_flags = env->insn_flags;
15661 ctx.CP0_Config1 = env->CP0_Config1;
15662 ctx.tb = tb;
15663 ctx.bstate = BS_NONE;
15664 /* Restore delay slot state from the tb context. */
15665 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
15666 ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
15667 restore_cpu_state(env, &ctx);
15668 #ifdef CONFIG_USER_ONLY
15669 ctx.mem_idx = MIPS_HFLAG_UM;
15670 #else
15671 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
15672 #endif
15673 num_insns = 0;
15674 max_insns = tb->cflags & CF_COUNT_MASK;
15675 if (max_insns == 0)
15676 max_insns = CF_COUNT_MASK;
15677 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
15678 gen_tb_start();
15679 while (ctx.bstate == BS_NONE) {
15680 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
15681 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
15682 if (bp->pc == ctx.pc) {
15683 save_cpu_state(&ctx, 1);
15684 ctx.bstate = BS_BRANCH;
15685 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
15686 /* Include the breakpoint location or the tb won't
15687 * be flushed when it must be. */
15688 ctx.pc += 4;
15689 goto done_generating;
15694 if (search_pc) {
15695 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
15696 if (lj < j) {
15697 lj++;
15698 while (lj < j)
15699 tcg_ctx.gen_opc_instr_start[lj++] = 0;
15701 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
15702 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
15703 gen_opc_btarget[lj] = ctx.btarget;
15704 tcg_ctx.gen_opc_instr_start[lj] = 1;
15705 tcg_ctx.gen_opc_icount[lj] = num_insns;
15707 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
15708 gen_io_start();
15710 is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
15711 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
15712 ctx.opcode = cpu_ldl_code(env, ctx.pc);
15713 insn_bytes = 4;
15714 decode_opc(env, &ctx);
15715 } else if (ctx.insn_flags & ASE_MICROMIPS) {
15716 ctx.opcode = cpu_lduw_code(env, ctx.pc);
15717 insn_bytes = decode_micromips_opc(env, &ctx);
15718 } else if (ctx.insn_flags & ASE_MIPS16) {
15719 ctx.opcode = cpu_lduw_code(env, ctx.pc);
15720 insn_bytes = decode_mips16_opc(env, &ctx);
15721 } else {
15722 generate_exception(&ctx, EXCP_RI);
15723 ctx.bstate = BS_STOP;
15724 break;
15726 if (is_delay) {
15727 handle_delay_slot(&ctx, insn_bytes);
15729 ctx.pc += insn_bytes;
15731 num_insns++;
15733 /* Execute a branch and its delay slot as a single instruction.
15734 This is what GDB expects and is consistent with what the
15735 hardware does (e.g. if a delay slot instruction faults, the
15736 reported PC is the PC of the branch). */
15737 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
15738 break;
15741 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
15742 break;
15744 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
15745 break;
15748 if (num_insns >= max_insns)
15749 break;
15751 if (singlestep)
15752 break;
15754 if (tb->cflags & CF_LAST_IO) {
15755 gen_io_end();
15757 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
15758 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
15759 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
15760 } else {
15761 switch (ctx.bstate) {
15762 case BS_STOP:
15763 gen_goto_tb(&ctx, 0, ctx.pc);
15764 break;
15765 case BS_NONE:
15766 save_cpu_state(&ctx, 0);
15767 gen_goto_tb(&ctx, 0, ctx.pc);
15768 break;
15769 case BS_EXCP:
15770 tcg_gen_exit_tb(0);
15771 break;
15772 case BS_BRANCH:
15773 default:
15774 break;
15777 done_generating:
15778 gen_tb_end(tb, num_insns);
15779 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
15780 if (search_pc) {
15781 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
15782 lj++;
15783 while (lj <= j)
15784 tcg_ctx.gen_opc_instr_start[lj++] = 0;
15785 } else {
15786 tb->size = ctx.pc - pc_start;
15787 tb->icount = num_insns;
15789 #ifdef DEBUG_DISAS
15790 LOG_DISAS("\n");
15791 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
15792 qemu_log("IN: %s\n", lookup_symbol(pc_start));
15793 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
15794 qemu_log("\n");
15796 #endif
15799 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
15801 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
15804 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
15806 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
15809 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
15810 int flags)
15812 int i;
15813 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
15815 #define printfpr(fp) \
15816 do { \
15817 if (is_fpu64) \
15818 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15819 " fd:%13g fs:%13g psu: %13g\n", \
15820 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
15821 (double)(fp)->fd, \
15822 (double)(fp)->fs[FP_ENDIAN_IDX], \
15823 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
15824 else { \
15825 fpr_t tmp; \
15826 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
15827 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
15828 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15829 " fd:%13g fs:%13g psu:%13g\n", \
15830 tmp.w[FP_ENDIAN_IDX], tmp.d, \
15831 (double)tmp.fd, \
15832 (double)tmp.fs[FP_ENDIAN_IDX], \
15833 (double)tmp.fs[!FP_ENDIAN_IDX]); \
15835 } while(0)
15838 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
15839 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
15840 get_float_exception_flags(&env->active_fpu.fp_status));
15841 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
15842 fpu_fprintf(f, "%3s: ", fregnames[i]);
15843 printfpr(&env->active_fpu.fpr[i]);
15846 #undef printfpr
15849 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
15850 /* Debug help: The architecture requires 32bit code to maintain proper
15851 sign-extended values on 64bit machines. */
15853 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
15855 static void
15856 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
15857 fprintf_function cpu_fprintf,
15858 int flags)
15860 int i;
15862 if (!SIGN_EXT_P(env->active_tc.PC))
15863 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
15864 if (!SIGN_EXT_P(env->active_tc.HI[0]))
15865 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
15866 if (!SIGN_EXT_P(env->active_tc.LO[0]))
15867 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
15868 if (!SIGN_EXT_P(env->btarget))
15869 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
15871 for (i = 0; i < 32; i++) {
15872 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
15873 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
15876 if (!SIGN_EXT_P(env->CP0_EPC))
15877 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
15878 if (!SIGN_EXT_P(env->lladdr))
15879 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
15881 #endif
15883 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
15884 int flags)
15886 MIPSCPU *cpu = MIPS_CPU(cs);
15887 CPUMIPSState *env = &cpu->env;
15888 int i;
15890 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
15891 " LO=0x" TARGET_FMT_lx " ds %04x "
15892 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
15893 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
15894 env->hflags, env->btarget, env->bcond);
15895 for (i = 0; i < 32; i++) {
15896 if ((i & 3) == 0)
15897 cpu_fprintf(f, "GPR%02d:", i);
15898 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
15899 if ((i & 3) == 3)
15900 cpu_fprintf(f, "\n");
15903 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
15904 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
15905 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
15906 env->CP0_Config0, env->CP0_Config1, env->lladdr);
15907 if (env->hflags & MIPS_HFLAG_FPU)
15908 fpu_dump_state(env, f, cpu_fprintf, flags);
15909 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
15910 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
15911 #endif
15914 void mips_tcg_init(void)
15916 int i;
15917 static int inited;
15919 /* Initialize various static tables. */
15920 if (inited)
15921 return;
15923 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
15924 TCGV_UNUSED(cpu_gpr[0]);
15925 for (i = 1; i < 32; i++)
15926 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
15927 offsetof(CPUMIPSState, active_tc.gpr[i]),
15928 regnames[i]);
15930 for (i = 0; i < 32; i++) {
15931 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
15932 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
15935 cpu_PC = tcg_global_mem_new(TCG_AREG0,
15936 offsetof(CPUMIPSState, active_tc.PC), "PC");
15937 for (i = 0; i < MIPS_DSP_ACC; i++) {
15938 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
15939 offsetof(CPUMIPSState, active_tc.HI[i]),
15940 regnames_HI[i]);
15941 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
15942 offsetof(CPUMIPSState, active_tc.LO[i]),
15943 regnames_LO[i]);
15944 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
15945 offsetof(CPUMIPSState, active_tc.ACX[i]),
15946 regnames_ACX[i]);
15948 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
15949 offsetof(CPUMIPSState, active_tc.DSPControl),
15950 "DSPControl");
15951 bcond = tcg_global_mem_new(TCG_AREG0,
15952 offsetof(CPUMIPSState, bcond), "bcond");
15953 btarget = tcg_global_mem_new(TCG_AREG0,
15954 offsetof(CPUMIPSState, btarget), "btarget");
15955 hflags = tcg_global_mem_new_i32(TCG_AREG0,
15956 offsetof(CPUMIPSState, hflags), "hflags");
15958 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
15959 offsetof(CPUMIPSState, active_fpu.fcr0),
15960 "fcr0");
15961 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
15962 offsetof(CPUMIPSState, active_fpu.fcr31),
15963 "fcr31");
15965 inited = 1;
15968 #include "translate_init.c"
15970 MIPSCPU *cpu_mips_init(const char *cpu_model)
15972 MIPSCPU *cpu;
15973 CPUMIPSState *env;
15974 const mips_def_t *def;
15976 def = cpu_mips_find_by_name(cpu_model);
15977 if (!def)
15978 return NULL;
15979 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
15980 env = &cpu->env;
15981 env->cpu_model = def;
15983 #ifndef CONFIG_USER_ONLY
15984 mmu_init(env, def);
15985 #endif
15986 fpu_init(env, def);
15987 mvp_init(env, def);
15989 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
15991 return cpu;
15994 void cpu_state_reset(CPUMIPSState *env)
15996 MIPSCPU *cpu = mips_env_get_cpu(env);
15997 CPUState *cs = CPU(cpu);
15999 /* Reset registers to their default values */
16000 env->CP0_PRid = env->cpu_model->CP0_PRid;
16001 env->CP0_Config0 = env->cpu_model->CP0_Config0;
16002 #ifdef TARGET_WORDS_BIGENDIAN
16003 env->CP0_Config0 |= (1 << CP0C0_BE);
16004 #endif
16005 env->CP0_Config1 = env->cpu_model->CP0_Config1;
16006 env->CP0_Config2 = env->cpu_model->CP0_Config2;
16007 env->CP0_Config3 = env->cpu_model->CP0_Config3;
16008 env->CP0_Config4 = env->cpu_model->CP0_Config4;
16009 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
16010 env->CP0_Config5 = env->cpu_model->CP0_Config5;
16011 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
16012 env->CP0_Config6 = env->cpu_model->CP0_Config6;
16013 env->CP0_Config7 = env->cpu_model->CP0_Config7;
16014 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
16015 << env->cpu_model->CP0_LLAddr_shift;
16016 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
16017 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
16018 env->CCRes = env->cpu_model->CCRes;
16019 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
16020 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
16021 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
16022 env->current_tc = 0;
16023 env->SEGBITS = env->cpu_model->SEGBITS;
16024 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
16025 #if defined(TARGET_MIPS64)
16026 if (env->cpu_model->insn_flags & ISA_MIPS3) {
16027 env->SEGMask |= 3ULL << 62;
16029 #endif
16030 env->PABITS = env->cpu_model->PABITS;
16031 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
16032 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
16033 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
16034 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
16035 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
16036 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
16037 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
16038 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
16039 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
16040 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
16041 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
16042 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
16043 env->insn_flags = env->cpu_model->insn_flags;
16045 #if defined(CONFIG_USER_ONLY)
16046 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
16047 # ifdef TARGET_MIPS64
16048 /* Enable 64-bit register mode. */
16049 env->CP0_Status |= (1 << CP0St_PX);
16050 # endif
16051 # ifdef TARGET_ABI_MIPSN64
16052 /* Enable 64-bit address mode. */
16053 env->CP0_Status |= (1 << CP0St_UX);
16054 # endif
16055 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
16056 hardware registers. */
16057 env->CP0_HWREna |= 0x0000000F;
16058 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16059 env->CP0_Status |= (1 << CP0St_CU1);
16061 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
16062 env->CP0_Status |= (1 << CP0St_MX);
16064 # if defined(TARGET_MIPS64)
16065 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
16066 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
16067 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
16068 env->CP0_Status |= (1 << CP0St_FR);
16070 # endif
16071 #else
16072 if (env->hflags & MIPS_HFLAG_BMASK) {
16073 /* If the exception was raised from a delay slot,
16074 come back to the jump. */
16075 env->CP0_ErrorEPC = env->active_tc.PC - 4;
16076 } else {
16077 env->CP0_ErrorEPC = env->active_tc.PC;
16079 env->active_tc.PC = (int32_t)0xBFC00000;
16080 env->CP0_Random = env->tlb->nb_tlb - 1;
16081 env->tlb->tlb_in_use = env->tlb->nb_tlb;
16082 env->CP0_Wired = 0;
16083 env->CP0_EBase = (cs->cpu_index & 0x3FF);
16084 if (kvm_enabled()) {
16085 env->CP0_EBase |= 0x40000000;
16086 } else {
16087 env->CP0_EBase |= 0x80000000;
16089 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
16090 /* vectored interrupts not implemented, timer on int 7,
16091 no performance counters. */
16092 env->CP0_IntCtl = 0xe0000000;
16094 int i;
16096 for (i = 0; i < 7; i++) {
16097 env->CP0_WatchLo[i] = 0;
16098 env->CP0_WatchHi[i] = 0x80000000;
16100 env->CP0_WatchLo[7] = 0;
16101 env->CP0_WatchHi[7] = 0;
16103 /* Count register increments in debug mode, EJTAG version 1 */
16104 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
16106 cpu_mips_store_count(env, 1);
16108 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
16109 int i;
16111 /* Only TC0 on VPE 0 starts as active. */
16112 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
16113 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
16114 env->tcs[i].CP0_TCHalt = 1;
16116 env->active_tc.CP0_TCHalt = 1;
16117 cs->halted = 1;
16119 if (cs->cpu_index == 0) {
16120 /* VPE0 starts up enabled. */
16121 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
16122 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
16124 /* TC0 starts up unhalted. */
16125 cs->halted = 0;
16126 env->active_tc.CP0_TCHalt = 0;
16127 env->tcs[0].CP0_TCHalt = 0;
16128 /* With thread 0 active. */
16129 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
16130 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
16133 #endif
16134 compute_hflags(env);
16135 cs->exception_index = EXCP_NONE;
16138 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
16140 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
16141 env->hflags &= ~MIPS_HFLAG_BMASK;
16142 env->hflags |= gen_opc_hflags[pc_pos];
16143 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
16144 case MIPS_HFLAG_BR:
16145 break;
16146 case MIPS_HFLAG_BC:
16147 case MIPS_HFLAG_BL:
16148 case MIPS_HFLAG_B:
16149 env->btarget = gen_opc_btarget[pc_pos];
16150 break;