tests: vmstate static checker: add substructure for usb-kbd for hid section
[qemu/ar7.git] / target-mips / translate.c
blob2f91959ed7b1cb081c5f70927ea139d3d0f8da1a
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"
32 #define MIPS_DEBUG_DISAS 0
33 //#define MIPS_DEBUG_SIGN_EXTENSIONS
35 /* MIPS major opcodes */
36 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
38 enum {
39 /* indirect opcode tables */
40 OPC_SPECIAL = (0x00 << 26),
41 OPC_REGIMM = (0x01 << 26),
42 OPC_CP0 = (0x10 << 26),
43 OPC_CP1 = (0x11 << 26),
44 OPC_CP2 = (0x12 << 26),
45 OPC_CP3 = (0x13 << 26),
46 OPC_SPECIAL2 = (0x1C << 26),
47 OPC_SPECIAL3 = (0x1F << 26),
48 /* arithmetic with immediate */
49 OPC_ADDI = (0x08 << 26),
50 OPC_ADDIU = (0x09 << 26),
51 OPC_SLTI = (0x0A << 26),
52 OPC_SLTIU = (0x0B << 26),
53 /* logic with immediate */
54 OPC_ANDI = (0x0C << 26),
55 OPC_ORI = (0x0D << 26),
56 OPC_XORI = (0x0E << 26),
57 OPC_LUI = (0x0F << 26),
58 /* arithmetic with immediate */
59 OPC_DADDI = (0x18 << 26),
60 OPC_DADDIU = (0x19 << 26),
61 /* Jump and branches */
62 OPC_J = (0x02 << 26),
63 OPC_JAL = (0x03 << 26),
64 OPC_JALS = OPC_JAL | 0x5,
65 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
66 OPC_BEQL = (0x14 << 26),
67 OPC_BNE = (0x05 << 26),
68 OPC_BNEL = (0x15 << 26),
69 OPC_BLEZ = (0x06 << 26),
70 OPC_BLEZL = (0x16 << 26),
71 OPC_BGTZ = (0x07 << 26),
72 OPC_BGTZL = (0x17 << 26),
73 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
74 OPC_JALXS = OPC_JALX | 0x5,
75 /* Load and stores */
76 OPC_LDL = (0x1A << 26),
77 OPC_LDR = (0x1B << 26),
78 OPC_LB = (0x20 << 26),
79 OPC_LH = (0x21 << 26),
80 OPC_LWL = (0x22 << 26),
81 OPC_LW = (0x23 << 26),
82 OPC_LWPC = OPC_LW | 0x5,
83 OPC_LBU = (0x24 << 26),
84 OPC_LHU = (0x25 << 26),
85 OPC_LWR = (0x26 << 26),
86 OPC_LWU = (0x27 << 26),
87 OPC_SB = (0x28 << 26),
88 OPC_SH = (0x29 << 26),
89 OPC_SWL = (0x2A << 26),
90 OPC_SW = (0x2B << 26),
91 OPC_SDL = (0x2C << 26),
92 OPC_SDR = (0x2D << 26),
93 OPC_SWR = (0x2E << 26),
94 OPC_LL = (0x30 << 26),
95 OPC_LLD = (0x34 << 26),
96 OPC_LD = (0x37 << 26),
97 OPC_LDPC = OPC_LD | 0x5,
98 OPC_SC = (0x38 << 26),
99 OPC_SCD = (0x3C << 26),
100 OPC_SD = (0x3F << 26),
101 /* Floating point load/store */
102 OPC_LWC1 = (0x31 << 26),
103 OPC_LWC2 = (0x32 << 26),
104 OPC_LDC1 = (0x35 << 26),
105 OPC_LDC2 = (0x36 << 26),
106 OPC_SWC1 = (0x39 << 26),
107 OPC_SWC2 = (0x3A << 26),
108 OPC_SDC1 = (0x3D << 26),
109 OPC_SDC2 = (0x3E << 26),
110 /* MDMX ASE specific */
111 OPC_MDMX = (0x1E << 26),
112 /* Cache and prefetch */
113 OPC_CACHE = (0x2F << 26),
114 OPC_PREF = (0x33 << 26),
115 /* Reserved major opcode */
116 OPC_MAJOR3B_RESERVED = (0x3B << 26),
119 /* MIPS special opcodes */
120 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
122 enum {
123 /* Shifts */
124 OPC_SLL = 0x00 | OPC_SPECIAL,
125 /* NOP is SLL r0, r0, 0 */
126 /* SSNOP is SLL r0, r0, 1 */
127 /* EHB is SLL r0, r0, 3 */
128 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
129 OPC_ROTR = OPC_SRL | (1 << 21),
130 OPC_SRA = 0x03 | OPC_SPECIAL,
131 OPC_SLLV = 0x04 | OPC_SPECIAL,
132 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
133 OPC_ROTRV = OPC_SRLV | (1 << 6),
134 OPC_SRAV = 0x07 | OPC_SPECIAL,
135 OPC_DSLLV = 0x14 | OPC_SPECIAL,
136 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
137 OPC_DROTRV = OPC_DSRLV | (1 << 6),
138 OPC_DSRAV = 0x17 | OPC_SPECIAL,
139 OPC_DSLL = 0x38 | OPC_SPECIAL,
140 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
141 OPC_DROTR = OPC_DSRL | (1 << 21),
142 OPC_DSRA = 0x3B | OPC_SPECIAL,
143 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
144 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
145 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
146 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
147 /* Multiplication / division */
148 OPC_MULT = 0x18 | OPC_SPECIAL,
149 OPC_MULTU = 0x19 | OPC_SPECIAL,
150 OPC_DIV = 0x1A | OPC_SPECIAL,
151 OPC_DIVU = 0x1B | OPC_SPECIAL,
152 OPC_DMULT = 0x1C | OPC_SPECIAL,
153 OPC_DMULTU = 0x1D | OPC_SPECIAL,
154 OPC_DDIV = 0x1E | OPC_SPECIAL,
155 OPC_DDIVU = 0x1F | OPC_SPECIAL,
156 /* 2 registers arithmetic / logic */
157 OPC_ADD = 0x20 | OPC_SPECIAL,
158 OPC_ADDU = 0x21 | OPC_SPECIAL,
159 OPC_SUB = 0x22 | OPC_SPECIAL,
160 OPC_SUBU = 0x23 | OPC_SPECIAL,
161 OPC_AND = 0x24 | OPC_SPECIAL,
162 OPC_OR = 0x25 | OPC_SPECIAL,
163 OPC_XOR = 0x26 | OPC_SPECIAL,
164 OPC_NOR = 0x27 | OPC_SPECIAL,
165 OPC_SLT = 0x2A | OPC_SPECIAL,
166 OPC_SLTU = 0x2B | OPC_SPECIAL,
167 OPC_DADD = 0x2C | OPC_SPECIAL,
168 OPC_DADDU = 0x2D | OPC_SPECIAL,
169 OPC_DSUB = 0x2E | OPC_SPECIAL,
170 OPC_DSUBU = 0x2F | OPC_SPECIAL,
171 /* Jumps */
172 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
173 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
174 OPC_JALRC = OPC_JALR | (0x5 << 6),
175 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
176 /* Traps */
177 OPC_TGE = 0x30 | OPC_SPECIAL,
178 OPC_TGEU = 0x31 | OPC_SPECIAL,
179 OPC_TLT = 0x32 | OPC_SPECIAL,
180 OPC_TLTU = 0x33 | OPC_SPECIAL,
181 OPC_TEQ = 0x34 | OPC_SPECIAL,
182 OPC_TNE = 0x36 | OPC_SPECIAL,
183 /* HI / LO registers load & stores */
184 OPC_MFHI = 0x10 | OPC_SPECIAL,
185 OPC_MTHI = 0x11 | OPC_SPECIAL,
186 OPC_MFLO = 0x12 | OPC_SPECIAL,
187 OPC_MTLO = 0x13 | OPC_SPECIAL,
188 /* Conditional moves */
189 OPC_MOVZ = 0x0A | OPC_SPECIAL,
190 OPC_MOVN = 0x0B | OPC_SPECIAL,
192 OPC_MOVCI = 0x01 | OPC_SPECIAL,
194 /* Special */
195 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
196 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
197 OPC_BREAK = 0x0D | OPC_SPECIAL,
198 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
199 OPC_SYNC = 0x0F | OPC_SPECIAL,
201 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
202 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
203 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
204 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
205 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
206 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
207 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
210 /* Multiplication variants of the vr54xx. */
211 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
213 enum {
214 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
215 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
216 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
217 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
218 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
219 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
220 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
221 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
222 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
223 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
224 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
225 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
226 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
227 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
230 /* REGIMM (rt field) opcodes */
231 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
233 enum {
234 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
235 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
236 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
237 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
238 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
239 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
240 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
241 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
242 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
243 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
244 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
245 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
246 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
247 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
248 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
249 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
250 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
253 /* Special2 opcodes */
254 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
256 enum {
257 /* Multiply & xxx operations */
258 OPC_MADD = 0x00 | OPC_SPECIAL2,
259 OPC_MADDU = 0x01 | OPC_SPECIAL2,
260 OPC_MUL = 0x02 | OPC_SPECIAL2,
261 OPC_MSUB = 0x04 | OPC_SPECIAL2,
262 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
263 /* Loongson 2F */
264 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
265 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
266 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
267 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
268 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
269 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
270 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
271 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
272 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
273 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
274 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
275 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
276 /* Misc */
277 OPC_CLZ = 0x20 | OPC_SPECIAL2,
278 OPC_CLO = 0x21 | OPC_SPECIAL2,
279 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
280 OPC_DCLO = 0x25 | OPC_SPECIAL2,
281 /* Special */
282 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
285 /* Special3 opcodes */
286 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
288 enum {
289 OPC_EXT = 0x00 | OPC_SPECIAL3,
290 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
291 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
292 OPC_DEXT = 0x03 | OPC_SPECIAL3,
293 OPC_INS = 0x04 | OPC_SPECIAL3,
294 OPC_DINSM = 0x05 | OPC_SPECIAL3,
295 OPC_DINSU = 0x06 | OPC_SPECIAL3,
296 OPC_DINS = 0x07 | OPC_SPECIAL3,
297 OPC_FORK = 0x08 | OPC_SPECIAL3,
298 OPC_YIELD = 0x09 | OPC_SPECIAL3,
299 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
300 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
301 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
303 /* Loongson 2E */
304 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
305 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
306 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
307 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
308 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
309 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
310 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
311 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
312 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
313 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
314 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
315 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
317 /* MIPS DSP Load */
318 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
319 /* MIPS DSP Arithmetic */
320 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
321 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
322 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
323 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
324 /* OPC_ADDUH_QB_DSP is same as OPC_MULT_G_2E. */
325 /* OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3, */
326 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
327 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
328 /* MIPS DSP GPR-Based Shift Sub-class */
329 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
330 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
331 /* MIPS DSP Multiply Sub-class insns */
332 /* OPC_MUL_PH_DSP is same as OPC_ADDUH_QB_DSP. */
333 /* OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3, */
334 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
335 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
336 /* DSP Bit/Manipulation Sub-class */
337 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
338 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
339 /* MIPS DSP Append Sub-class */
340 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
341 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
342 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
343 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
344 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
347 /* BSHFL opcodes */
348 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
350 enum {
351 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
352 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
353 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
356 /* DBSHFL opcodes */
357 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
359 enum {
360 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
361 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
364 /* MIPS DSP REGIMM opcodes */
365 enum {
366 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
367 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
370 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
371 /* MIPS DSP Load */
372 enum {
373 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
374 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
375 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
376 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
379 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
380 enum {
381 /* MIPS DSP Arithmetic Sub-class */
382 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
383 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
384 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
385 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
386 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
387 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
388 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
389 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
390 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
391 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
392 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
393 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
394 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
395 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
396 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
397 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
398 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
399 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
400 /* MIPS DSP Multiply Sub-class insns */
401 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
402 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
403 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
404 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
405 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
406 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
409 #define OPC_ADDUH_QB_DSP OPC_MULT_G_2E
410 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
411 enum {
412 /* MIPS DSP Arithmetic Sub-class */
413 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
414 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
415 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
416 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
417 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
418 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
419 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
420 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
421 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
422 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
423 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
424 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
425 /* MIPS DSP Multiply Sub-class insns */
426 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
427 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
428 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
429 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
432 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
433 enum {
434 /* MIPS DSP Arithmetic Sub-class */
435 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
436 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
437 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
438 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
439 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
440 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
441 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
442 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
443 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
444 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
445 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
446 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
447 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
448 /* DSP Bit/Manipulation Sub-class */
449 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
450 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
451 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
452 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
453 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
456 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
457 enum {
458 /* MIPS DSP Arithmetic Sub-class */
459 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
460 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
461 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
462 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
463 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
464 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
465 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
466 /* DSP Compare-Pick Sub-class */
467 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
468 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
469 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
470 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
471 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
472 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
473 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
474 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
475 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
476 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
477 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
478 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
479 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
480 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
481 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
484 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
485 enum {
486 /* MIPS DSP GPR-Based Shift Sub-class */
487 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
488 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
489 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
490 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
491 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
492 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
493 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
494 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
495 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
496 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
497 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
498 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
499 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
500 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
501 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
502 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
503 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
504 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
505 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
506 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
507 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
508 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
511 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
512 enum {
513 /* MIPS DSP Multiply Sub-class insns */
514 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
515 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
516 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
517 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
518 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
519 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
520 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
521 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
522 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
523 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
524 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
525 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
526 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
527 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
528 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
529 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
530 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
531 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
532 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
533 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
534 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
535 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
538 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
539 enum {
540 /* DSP Bit/Manipulation Sub-class */
541 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
544 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
545 enum {
546 /* MIPS DSP Append Sub-class */
547 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
548 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
549 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
552 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553 enum {
554 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
555 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
556 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
557 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
558 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
559 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
560 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
561 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
562 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
563 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
564 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
565 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
566 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
567 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
568 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
569 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
570 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
571 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
574 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
575 enum {
576 /* MIPS DSP Arithmetic Sub-class */
577 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
578 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
579 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
580 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
581 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
582 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
583 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
584 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
585 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
586 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
587 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
588 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
589 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
590 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
591 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
592 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
593 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
594 /* DSP Bit/Manipulation Sub-class */
595 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
596 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
597 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
598 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
599 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
600 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
603 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
604 enum {
605 /* MIPS DSP Multiply Sub-class insns */
606 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
607 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
608 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
609 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
610 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
611 /* MIPS DSP Arithmetic Sub-class */
612 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
613 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
614 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
615 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
616 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
617 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
618 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
619 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
620 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
621 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
622 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
623 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
624 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
625 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
626 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
627 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
628 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
629 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
630 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
631 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
632 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
635 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
636 enum {
637 /* DSP Compare-Pick Sub-class */
638 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
639 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
640 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
641 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
642 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
643 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
644 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
645 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
646 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
647 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
648 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
649 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
650 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
651 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
652 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
653 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
654 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
655 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
656 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
657 /* MIPS DSP Arithmetic Sub-class */
658 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
659 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
660 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
661 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
662 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
663 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
664 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
665 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
668 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
669 enum {
670 /* DSP Append Sub-class */
671 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
672 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
673 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
674 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
677 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
678 enum {
679 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
680 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
681 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
682 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
683 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
684 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
685 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
686 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
687 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
688 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
689 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
690 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
691 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
692 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
693 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
694 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
695 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
696 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
697 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
698 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
699 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
700 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
703 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
704 enum {
705 /* DSP Bit/Manipulation Sub-class */
706 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
709 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
710 enum {
711 /* MIPS DSP Multiply Sub-class insns */
712 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
713 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
714 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
715 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
716 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
717 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
718 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
719 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
720 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
721 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
722 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
723 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
724 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
725 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
726 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
727 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
728 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
729 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
730 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
731 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
732 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
733 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
734 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
735 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
736 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
737 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
740 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
741 enum {
742 /* MIPS DSP GPR-Based Shift Sub-class */
743 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
744 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
745 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
746 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
747 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
748 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
749 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
750 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
751 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
752 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
753 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
754 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
755 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
756 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
757 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
758 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
759 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
760 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
761 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
762 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
763 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
764 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
765 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
766 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
767 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
768 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
771 /* Coprocessor 0 (rs field) */
772 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
774 enum {
775 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
776 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
777 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
778 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
779 OPC_MFTR = (0x08 << 21) | OPC_CP0,
780 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
781 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
782 OPC_MTTR = (0x0C << 21) | OPC_CP0,
783 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
784 OPC_C0 = (0x10 << 21) | OPC_CP0,
785 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
786 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
789 /* MFMC0 opcodes */
790 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
792 enum {
793 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
794 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
795 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
796 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
797 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
798 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
801 /* Coprocessor 0 (with rs == C0) */
802 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
804 enum {
805 OPC_TLBR = 0x01 | OPC_C0,
806 OPC_TLBWI = 0x02 | OPC_C0,
807 OPC_TLBWR = 0x06 | OPC_C0,
808 OPC_TLBP = 0x08 | OPC_C0,
809 OPC_RFE = 0x10 | OPC_C0,
810 OPC_ERET = 0x18 | OPC_C0,
811 OPC_DERET = 0x1F | OPC_C0,
812 OPC_WAIT = 0x20 | OPC_C0,
815 /* Coprocessor 1 (rs field) */
816 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
818 /* Values for the fmt field in FP instructions */
819 enum {
820 /* 0 - 15 are reserved */
821 FMT_S = 16, /* single fp */
822 FMT_D = 17, /* double fp */
823 FMT_E = 18, /* extended fp */
824 FMT_Q = 19, /* quad fp */
825 FMT_W = 20, /* 32-bit fixed */
826 FMT_L = 21, /* 64-bit fixed */
827 FMT_PS = 22, /* paired single fp */
828 /* 23 - 31 are reserved */
831 enum {
832 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
833 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
834 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
835 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
836 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
837 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
838 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
839 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
840 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
841 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
842 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
843 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
844 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
845 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
846 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
847 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
848 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
849 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
852 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
853 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
855 enum {
856 OPC_BC1F = (0x00 << 16) | OPC_BC1,
857 OPC_BC1T = (0x01 << 16) | OPC_BC1,
858 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
859 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
862 enum {
863 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
864 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
867 enum {
868 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
869 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
872 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
874 enum {
875 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
876 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
877 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
878 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
879 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
880 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
881 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
882 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
883 OPC_BC2 = (0x08 << 21) | OPC_CP2,
886 #define MASK_LMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
888 enum {
889 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
890 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
891 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
892 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
893 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
894 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
895 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
896 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
898 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
899 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
900 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
901 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
902 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
903 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
904 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
905 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
907 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
908 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
909 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
910 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
911 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
912 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
913 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
914 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
916 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
917 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
918 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
919 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
920 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
921 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
922 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
923 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
925 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
926 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
927 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
928 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
929 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
930 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
932 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
933 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
934 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
935 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
936 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
937 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
939 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
940 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
941 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
942 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
943 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
944 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
946 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
947 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
948 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
949 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
950 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
951 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
953 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
954 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
955 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
956 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
957 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
958 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
960 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
961 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
962 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
963 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
964 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
965 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
967 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
968 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
969 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
970 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
971 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
972 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
974 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
975 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
976 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
977 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
978 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
979 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
983 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
985 enum {
986 OPC_LWXC1 = 0x00 | OPC_CP3,
987 OPC_LDXC1 = 0x01 | OPC_CP3,
988 OPC_LUXC1 = 0x05 | OPC_CP3,
989 OPC_SWXC1 = 0x08 | OPC_CP3,
990 OPC_SDXC1 = 0x09 | OPC_CP3,
991 OPC_SUXC1 = 0x0D | OPC_CP3,
992 OPC_PREFX = 0x0F | OPC_CP3,
993 OPC_ALNV_PS = 0x1E | OPC_CP3,
994 OPC_MADD_S = 0x20 | OPC_CP3,
995 OPC_MADD_D = 0x21 | OPC_CP3,
996 OPC_MADD_PS = 0x26 | OPC_CP3,
997 OPC_MSUB_S = 0x28 | OPC_CP3,
998 OPC_MSUB_D = 0x29 | OPC_CP3,
999 OPC_MSUB_PS = 0x2E | OPC_CP3,
1000 OPC_NMADD_S = 0x30 | OPC_CP3,
1001 OPC_NMADD_D = 0x31 | OPC_CP3,
1002 OPC_NMADD_PS= 0x36 | OPC_CP3,
1003 OPC_NMSUB_S = 0x38 | OPC_CP3,
1004 OPC_NMSUB_D = 0x39 | OPC_CP3,
1005 OPC_NMSUB_PS= 0x3E | OPC_CP3,
1008 /* global register indices */
1009 static TCGv_ptr cpu_env;
1010 static TCGv cpu_gpr[32], cpu_PC;
1011 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
1012 static TCGv cpu_dspctrl, btarget, bcond;
1013 static TCGv_i32 hflags;
1014 static TCGv_i32 fpu_fcr0, fpu_fcr31;
1015 static TCGv_i64 fpu_f64[32];
1017 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
1018 static target_ulong gen_opc_btarget[OPC_BUF_SIZE];
1020 #include "exec/gen-icount.h"
1022 #define gen_helper_0e0i(name, arg) do { \
1023 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
1024 gen_helper_##name(cpu_env, helper_tmp); \
1025 tcg_temp_free_i32(helper_tmp); \
1026 } while(0)
1028 #define gen_helper_0e1i(name, arg1, arg2) do { \
1029 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1030 gen_helper_##name(cpu_env, arg1, helper_tmp); \
1031 tcg_temp_free_i32(helper_tmp); \
1032 } while(0)
1034 #define gen_helper_1e0i(name, ret, arg1) do { \
1035 TCGv_i32 helper_tmp = tcg_const_i32(arg1); \
1036 gen_helper_##name(ret, cpu_env, helper_tmp); \
1037 tcg_temp_free_i32(helper_tmp); \
1038 } while(0)
1040 #define gen_helper_1e1i(name, ret, arg1, arg2) do { \
1041 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
1042 gen_helper_##name(ret, cpu_env, arg1, helper_tmp); \
1043 tcg_temp_free_i32(helper_tmp); \
1044 } while(0)
1046 #define gen_helper_0e2i(name, arg1, arg2, arg3) do { \
1047 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1048 gen_helper_##name(cpu_env, arg1, arg2, helper_tmp); \
1049 tcg_temp_free_i32(helper_tmp); \
1050 } while(0)
1052 #define gen_helper_1e2i(name, ret, arg1, arg2, arg3) do { \
1053 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
1054 gen_helper_##name(ret, cpu_env, arg1, arg2, helper_tmp); \
1055 tcg_temp_free_i32(helper_tmp); \
1056 } while(0)
1058 #define gen_helper_0e3i(name, arg1, arg2, arg3, arg4) do { \
1059 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
1060 gen_helper_##name(cpu_env, arg1, arg2, arg3, helper_tmp); \
1061 tcg_temp_free_i32(helper_tmp); \
1062 } while(0)
1064 typedef struct DisasContext {
1065 struct TranslationBlock *tb;
1066 target_ulong pc, saved_pc;
1067 uint32_t opcode;
1068 int singlestep_enabled;
1069 int insn_flags;
1070 int32_t CP0_Config1;
1071 /* Routine used to access memory */
1072 int mem_idx;
1073 uint32_t hflags, saved_hflags;
1074 int bstate;
1075 target_ulong btarget;
1076 bool ulri;
1077 } DisasContext;
1079 enum {
1080 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
1081 * exception condition */
1082 BS_STOP = 1, /* We want to stop translation for any reason */
1083 BS_BRANCH = 2, /* We reached a branch condition */
1084 BS_EXCP = 3, /* We reached an exception condition */
1087 static const char * const regnames[] = {
1088 "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
1089 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
1090 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
1091 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra",
1094 static const char * const regnames_HI[] = {
1095 "HI0", "HI1", "HI2", "HI3",
1098 static const char * const regnames_LO[] = {
1099 "LO0", "LO1", "LO2", "LO3",
1102 static const char * const regnames_ACX[] = {
1103 "ACX0", "ACX1", "ACX2", "ACX3",
1106 static const char * const fregnames[] = {
1107 "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
1108 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
1109 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
1110 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
1113 #define MIPS_DEBUG(fmt, ...) \
1114 do { \
1115 if (MIPS_DEBUG_DISAS) { \
1116 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
1117 TARGET_FMT_lx ": %08x " fmt "\n", \
1118 ctx->pc, ctx->opcode , ## __VA_ARGS__); \
1120 } while (0)
1122 #define LOG_DISAS(...) \
1123 do { \
1124 if (MIPS_DEBUG_DISAS) { \
1125 qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__); \
1127 } while (0)
1129 #define MIPS_INVAL(op) \
1130 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
1131 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F))
1133 /* General purpose registers moves. */
1134 static inline void gen_load_gpr (TCGv t, int reg)
1136 if (reg == 0)
1137 tcg_gen_movi_tl(t, 0);
1138 else
1139 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1142 static inline void gen_store_gpr (TCGv t, int reg)
1144 if (reg != 0)
1145 tcg_gen_mov_tl(cpu_gpr[reg], t);
1148 /* Moves to/from ACX register. */
1149 static inline void gen_load_ACX (TCGv t, int reg)
1151 tcg_gen_mov_tl(t, cpu_ACX[reg]);
1154 static inline void gen_store_ACX (TCGv t, int reg)
1156 tcg_gen_mov_tl(cpu_ACX[reg], t);
1159 /* Moves to/from shadow registers. */
1160 static inline void gen_load_srsgpr (int from, int to)
1162 TCGv t0 = tcg_temp_new();
1164 if (from == 0)
1165 tcg_gen_movi_tl(t0, 0);
1166 else {
1167 TCGv_i32 t2 = tcg_temp_new_i32();
1168 TCGv_ptr addr = tcg_temp_new_ptr();
1170 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1171 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1172 tcg_gen_andi_i32(t2, t2, 0xf);
1173 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1174 tcg_gen_ext_i32_ptr(addr, t2);
1175 tcg_gen_add_ptr(addr, cpu_env, addr);
1177 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1178 tcg_temp_free_ptr(addr);
1179 tcg_temp_free_i32(t2);
1181 gen_store_gpr(t0, to);
1182 tcg_temp_free(t0);
1185 static inline void gen_store_srsgpr (int from, int to)
1187 if (to != 0) {
1188 TCGv t0 = tcg_temp_new();
1189 TCGv_i32 t2 = tcg_temp_new_i32();
1190 TCGv_ptr addr = tcg_temp_new_ptr();
1192 gen_load_gpr(t0, from);
1193 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1194 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1195 tcg_gen_andi_i32(t2, t2, 0xf);
1196 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1197 tcg_gen_ext_i32_ptr(addr, t2);
1198 tcg_gen_add_ptr(addr, cpu_env, addr);
1200 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1201 tcg_temp_free_ptr(addr);
1202 tcg_temp_free_i32(t2);
1203 tcg_temp_free(t0);
1207 /* Floating point register moves. */
1208 static void gen_load_fpr32(TCGv_i32 t, int reg)
1210 tcg_gen_trunc_i64_i32(t, fpu_f64[reg]);
1213 static void gen_store_fpr32(TCGv_i32 t, int reg)
1215 TCGv_i64 t64 = tcg_temp_new_i64();
1216 tcg_gen_extu_i32_i64(t64, t);
1217 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1218 tcg_temp_free_i64(t64);
1221 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1223 if (ctx->hflags & MIPS_HFLAG_F64) {
1224 TCGv_i64 t64 = tcg_temp_new_i64();
1225 tcg_gen_shri_i64(t64, fpu_f64[reg], 32);
1226 tcg_gen_trunc_i64_i32(t, t64);
1227 tcg_temp_free_i64(t64);
1228 } else {
1229 gen_load_fpr32(t, reg | 1);
1233 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1235 if (ctx->hflags & MIPS_HFLAG_F64) {
1236 TCGv_i64 t64 = tcg_temp_new_i64();
1237 tcg_gen_extu_i32_i64(t64, t);
1238 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1239 tcg_temp_free_i64(t64);
1240 } else {
1241 gen_store_fpr32(t, reg | 1);
1245 static void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1247 if (ctx->hflags & MIPS_HFLAG_F64) {
1248 tcg_gen_mov_i64(t, fpu_f64[reg]);
1249 } else {
1250 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1254 static void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1256 if (ctx->hflags & MIPS_HFLAG_F64) {
1257 tcg_gen_mov_i64(fpu_f64[reg], t);
1258 } else {
1259 TCGv_i64 t0;
1260 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1261 t0 = tcg_temp_new_i64();
1262 tcg_gen_shri_i64(t0, t, 32);
1263 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1264 tcg_temp_free_i64(t0);
1268 static inline int get_fp_bit (int cc)
1270 if (cc)
1271 return 24 + cc;
1272 else
1273 return 23;
1276 /* Tests */
1277 static inline void gen_save_pc(target_ulong pc)
1279 tcg_gen_movi_tl(cpu_PC, pc);
1282 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
1284 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1285 if (do_save_pc && ctx->pc != ctx->saved_pc) {
1286 gen_save_pc(ctx->pc);
1287 ctx->saved_pc = ctx->pc;
1289 if (ctx->hflags != ctx->saved_hflags) {
1290 tcg_gen_movi_i32(hflags, ctx->hflags);
1291 ctx->saved_hflags = ctx->hflags;
1292 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1293 case MIPS_HFLAG_BR:
1294 break;
1295 case MIPS_HFLAG_BC:
1296 case MIPS_HFLAG_BL:
1297 case MIPS_HFLAG_B:
1298 tcg_gen_movi_tl(btarget, ctx->btarget);
1299 break;
1304 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
1306 ctx->saved_hflags = ctx->hflags;
1307 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1308 case MIPS_HFLAG_BR:
1309 break;
1310 case MIPS_HFLAG_BC:
1311 case MIPS_HFLAG_BL:
1312 case MIPS_HFLAG_B:
1313 ctx->btarget = env->btarget;
1314 break;
1318 static inline void
1319 generate_exception_err (DisasContext *ctx, int excp, int err)
1321 TCGv_i32 texcp = tcg_const_i32(excp);
1322 TCGv_i32 terr = tcg_const_i32(err);
1323 save_cpu_state(ctx, 1);
1324 gen_helper_raise_exception_err(cpu_env, texcp, terr);
1325 tcg_temp_free_i32(terr);
1326 tcg_temp_free_i32(texcp);
1329 static inline void
1330 generate_exception (DisasContext *ctx, int excp)
1332 save_cpu_state(ctx, 1);
1333 gen_helper_0e0i(raise_exception, excp);
1336 /* Addresses computation */
1337 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1339 tcg_gen_add_tl(ret, arg0, arg1);
1341 #if defined(TARGET_MIPS64)
1342 /* For compatibility with 32-bit code, data reference in user mode
1343 with Status_UX = 0 should be casted to 32-bit and sign extended.
1344 See the MIPS64 PRA manual, section 4.10. */
1345 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
1346 !(ctx->hflags & MIPS_HFLAG_UX)) {
1347 tcg_gen_ext32s_i64(ret, ret);
1349 #endif
1352 static inline void check_cp0_enabled(DisasContext *ctx)
1354 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
1355 generate_exception_err(ctx, EXCP_CpU, 0);
1358 static inline void check_cp1_enabled(DisasContext *ctx)
1360 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
1361 generate_exception_err(ctx, EXCP_CpU, 1);
1364 /* Verify that the processor is running with COP1X instructions enabled.
1365 This is associated with the nabla symbol in the MIPS32 and MIPS64
1366 opcode tables. */
1368 static inline void check_cop1x(DisasContext *ctx)
1370 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
1371 generate_exception(ctx, EXCP_RI);
1374 /* Verify that the processor is running with 64-bit floating-point
1375 operations enabled. */
1377 static inline void check_cp1_64bitmode(DisasContext *ctx)
1379 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
1380 generate_exception(ctx, EXCP_RI);
1384 * Verify if floating point register is valid; an operation is not defined
1385 * if bit 0 of any register specification is set and the FR bit in the
1386 * Status register equals zero, since the register numbers specify an
1387 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1388 * in the Status register equals one, both even and odd register numbers
1389 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1391 * Multiple 64 bit wide registers can be checked by calling
1392 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1394 static inline void check_cp1_registers(DisasContext *ctx, int regs)
1396 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
1397 generate_exception(ctx, EXCP_RI);
1400 /* Verify that the processor is running with DSP instructions enabled.
1401 This is enabled by CP0 Status register MX(24) bit.
1404 static inline void check_dsp(DisasContext *ctx)
1406 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1407 if (ctx->insn_flags & ASE_DSP) {
1408 generate_exception(ctx, EXCP_DSPDIS);
1409 } else {
1410 generate_exception(ctx, EXCP_RI);
1415 static inline void check_dspr2(DisasContext *ctx)
1417 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSPR2))) {
1418 if (ctx->insn_flags & ASE_DSP) {
1419 generate_exception(ctx, EXCP_DSPDIS);
1420 } else {
1421 generate_exception(ctx, EXCP_RI);
1426 /* This code generates a "reserved instruction" exception if the
1427 CPU does not support the instruction set corresponding to flags. */
1428 static inline void check_insn(DisasContext *ctx, int flags)
1430 if (unlikely(!(ctx->insn_flags & flags))) {
1431 generate_exception(ctx, EXCP_RI);
1435 /* This code generates a "reserved instruction" exception if 64-bit
1436 instructions are not enabled. */
1437 static inline void check_mips_64(DisasContext *ctx)
1439 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
1440 generate_exception(ctx, EXCP_RI);
1443 /* Define small wrappers for gen_load_fpr* so that we have a uniform
1444 calling interface for 32 and 64-bit FPRs. No sense in changing
1445 all callers for gen_load_fpr32 when we need the CTX parameter for
1446 this one use. */
1447 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
1448 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1449 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1450 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1451 int ft, int fs, int cc) \
1453 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
1454 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
1455 switch (ifmt) { \
1456 case FMT_PS: \
1457 check_cp1_64bitmode(ctx); \
1458 break; \
1459 case FMT_D: \
1460 if (abs) { \
1461 check_cop1x(ctx); \
1463 check_cp1_registers(ctx, fs | ft); \
1464 break; \
1465 case FMT_S: \
1466 if (abs) { \
1467 check_cop1x(ctx); \
1469 break; \
1471 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
1472 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
1473 switch (n) { \
1474 case 0: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
1475 case 1: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
1476 case 2: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
1477 case 3: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
1478 case 4: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
1479 case 5: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
1480 case 6: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
1481 case 7: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
1482 case 8: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
1483 case 9: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
1484 case 10: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
1485 case 11: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
1486 case 12: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
1487 case 13: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
1488 case 14: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
1489 case 15: gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
1490 default: abort(); \
1492 tcg_temp_free_i##bits (fp0); \
1493 tcg_temp_free_i##bits (fp1); \
1496 FOP_CONDS(, 0, d, FMT_D, 64)
1497 FOP_CONDS(abs, 1, d, FMT_D, 64)
1498 FOP_CONDS(, 0, s, FMT_S, 32)
1499 FOP_CONDS(abs, 1, s, FMT_S, 32)
1500 FOP_CONDS(, 0, ps, FMT_PS, 64)
1501 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1502 #undef FOP_CONDS
1503 #undef gen_ldcmp_fpr32
1504 #undef gen_ldcmp_fpr64
1506 /* load/store instructions. */
1507 #ifdef CONFIG_USER_ONLY
1508 #define OP_LD_ATOMIC(insn,fname) \
1509 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1511 TCGv t0 = tcg_temp_new(); \
1512 tcg_gen_mov_tl(t0, arg1); \
1513 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
1514 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1515 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
1516 tcg_temp_free(t0); \
1518 #else
1519 #define OP_LD_ATOMIC(insn,fname) \
1520 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
1522 gen_helper_1e1i(insn, ret, arg1, ctx->mem_idx); \
1524 #endif
1525 OP_LD_ATOMIC(ll,ld32s);
1526 #if defined(TARGET_MIPS64)
1527 OP_LD_ATOMIC(lld,ld64);
1528 #endif
1529 #undef OP_LD_ATOMIC
1531 #ifdef CONFIG_USER_ONLY
1532 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1533 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1535 TCGv t0 = tcg_temp_new(); \
1536 int l1 = gen_new_label(); \
1537 int l2 = gen_new_label(); \
1539 tcg_gen_andi_tl(t0, arg2, almask); \
1540 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
1541 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
1542 generate_exception(ctx, EXCP_AdES); \
1543 gen_set_label(l1); \
1544 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
1545 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
1546 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
1547 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
1548 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
1549 gen_helper_0e0i(raise_exception, EXCP_SC); \
1550 gen_set_label(l2); \
1551 tcg_gen_movi_tl(t0, 0); \
1552 gen_store_gpr(t0, rt); \
1553 tcg_temp_free(t0); \
1555 #else
1556 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
1557 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
1559 TCGv t0 = tcg_temp_new(); \
1560 gen_helper_1e2i(insn, t0, arg1, arg2, ctx->mem_idx); \
1561 gen_store_gpr(t0, rt); \
1562 tcg_temp_free(t0); \
1564 #endif
1565 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
1566 #if defined(TARGET_MIPS64)
1567 OP_ST_ATOMIC(scd,st64,ld64,0x7);
1568 #endif
1569 #undef OP_ST_ATOMIC
1571 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1572 int base, int16_t offset)
1574 if (base == 0) {
1575 tcg_gen_movi_tl(addr, offset);
1576 } else if (offset == 0) {
1577 gen_load_gpr(addr, base);
1578 } else {
1579 tcg_gen_movi_tl(addr, offset);
1580 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1584 static target_ulong pc_relative_pc (DisasContext *ctx)
1586 target_ulong pc = ctx->pc;
1588 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1589 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1591 pc -= branch_bytes;
1594 pc &= ~(target_ulong)3;
1595 return pc;
1598 /* Load */
1599 static void gen_ld(DisasContext *ctx, uint32_t opc,
1600 int rt, int base, int16_t offset)
1602 const char *opn = "ld";
1603 TCGv t0, t1, t2;
1605 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1606 /* Loongson CPU uses a load to zero register for prefetch.
1607 We emulate it as a NOP. On other CPU we must perform the
1608 actual memory access. */
1609 MIPS_DEBUG("NOP");
1610 return;
1613 t0 = tcg_temp_new();
1614 gen_base_offset_addr(ctx, t0, base, offset);
1616 switch (opc) {
1617 #if defined(TARGET_MIPS64)
1618 case OPC_LWU:
1619 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1620 gen_store_gpr(t0, rt);
1621 opn = "lwu";
1622 break;
1623 case OPC_LD:
1624 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1625 gen_store_gpr(t0, rt);
1626 opn = "ld";
1627 break;
1628 case OPC_LLD:
1629 save_cpu_state(ctx, 1);
1630 op_ld_lld(t0, t0, ctx);
1631 gen_store_gpr(t0, rt);
1632 opn = "lld";
1633 break;
1634 case OPC_LDL:
1635 t1 = tcg_temp_new();
1636 tcg_gen_andi_tl(t1, t0, 7);
1637 #ifndef TARGET_WORDS_BIGENDIAN
1638 tcg_gen_xori_tl(t1, t1, 7);
1639 #endif
1640 tcg_gen_shli_tl(t1, t1, 3);
1641 tcg_gen_andi_tl(t0, t0, ~7);
1642 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1643 tcg_gen_shl_tl(t0, t0, t1);
1644 tcg_gen_xori_tl(t1, t1, 63);
1645 t2 = tcg_const_tl(0x7fffffffffffffffull);
1646 tcg_gen_shr_tl(t2, t2, t1);
1647 gen_load_gpr(t1, rt);
1648 tcg_gen_and_tl(t1, t1, t2);
1649 tcg_temp_free(t2);
1650 tcg_gen_or_tl(t0, t0, t1);
1651 tcg_temp_free(t1);
1652 gen_store_gpr(t0, rt);
1653 opn = "ldl";
1654 break;
1655 case OPC_LDR:
1656 t1 = tcg_temp_new();
1657 tcg_gen_andi_tl(t1, t0, 7);
1658 #ifdef TARGET_WORDS_BIGENDIAN
1659 tcg_gen_xori_tl(t1, t1, 7);
1660 #endif
1661 tcg_gen_shli_tl(t1, t1, 3);
1662 tcg_gen_andi_tl(t0, t0, ~7);
1663 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1664 tcg_gen_shr_tl(t0, t0, t1);
1665 tcg_gen_xori_tl(t1, t1, 63);
1666 t2 = tcg_const_tl(0xfffffffffffffffeull);
1667 tcg_gen_shl_tl(t2, t2, t1);
1668 gen_load_gpr(t1, rt);
1669 tcg_gen_and_tl(t1, t1, t2);
1670 tcg_temp_free(t2);
1671 tcg_gen_or_tl(t0, t0, t1);
1672 tcg_temp_free(t1);
1673 gen_store_gpr(t0, rt);
1674 opn = "ldr";
1675 break;
1676 case OPC_LDPC:
1677 t1 = tcg_const_tl(pc_relative_pc(ctx));
1678 gen_op_addr_add(ctx, t0, t0, t1);
1679 tcg_temp_free(t1);
1680 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
1681 gen_store_gpr(t0, rt);
1682 opn = "ldpc";
1683 break;
1684 #endif
1685 case OPC_LWPC:
1686 t1 = tcg_const_tl(pc_relative_pc(ctx));
1687 gen_op_addr_add(ctx, t0, t0, t1);
1688 tcg_temp_free(t1);
1689 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1690 gen_store_gpr(t0, rt);
1691 opn = "lwpc";
1692 break;
1693 case OPC_LW:
1694 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
1695 gen_store_gpr(t0, rt);
1696 opn = "lw";
1697 break;
1698 case OPC_LH:
1699 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
1700 gen_store_gpr(t0, rt);
1701 opn = "lh";
1702 break;
1703 case OPC_LHU:
1704 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUW);
1705 gen_store_gpr(t0, rt);
1706 opn = "lhu";
1707 break;
1708 case OPC_LB:
1709 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
1710 gen_store_gpr(t0, rt);
1711 opn = "lb";
1712 break;
1713 case OPC_LBU:
1714 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
1715 gen_store_gpr(t0, rt);
1716 opn = "lbu";
1717 break;
1718 case OPC_LWL:
1719 t1 = tcg_temp_new();
1720 tcg_gen_andi_tl(t1, t0, 3);
1721 #ifndef TARGET_WORDS_BIGENDIAN
1722 tcg_gen_xori_tl(t1, t1, 3);
1723 #endif
1724 tcg_gen_shli_tl(t1, t1, 3);
1725 tcg_gen_andi_tl(t0, t0, ~3);
1726 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1727 tcg_gen_shl_tl(t0, t0, t1);
1728 tcg_gen_xori_tl(t1, t1, 31);
1729 t2 = tcg_const_tl(0x7fffffffull);
1730 tcg_gen_shr_tl(t2, t2, t1);
1731 gen_load_gpr(t1, rt);
1732 tcg_gen_and_tl(t1, t1, t2);
1733 tcg_temp_free(t2);
1734 tcg_gen_or_tl(t0, t0, t1);
1735 tcg_temp_free(t1);
1736 tcg_gen_ext32s_tl(t0, t0);
1737 gen_store_gpr(t0, rt);
1738 opn = "lwl";
1739 break;
1740 case OPC_LWR:
1741 t1 = tcg_temp_new();
1742 tcg_gen_andi_tl(t1, t0, 3);
1743 #ifdef TARGET_WORDS_BIGENDIAN
1744 tcg_gen_xori_tl(t1, t1, 3);
1745 #endif
1746 tcg_gen_shli_tl(t1, t1, 3);
1747 tcg_gen_andi_tl(t0, t0, ~3);
1748 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEUL);
1749 tcg_gen_shr_tl(t0, t0, t1);
1750 tcg_gen_xori_tl(t1, t1, 31);
1751 t2 = tcg_const_tl(0xfffffffeull);
1752 tcg_gen_shl_tl(t2, t2, t1);
1753 gen_load_gpr(t1, rt);
1754 tcg_gen_and_tl(t1, t1, t2);
1755 tcg_temp_free(t2);
1756 tcg_gen_or_tl(t0, t0, t1);
1757 tcg_temp_free(t1);
1758 tcg_gen_ext32s_tl(t0, t0);
1759 gen_store_gpr(t0, rt);
1760 opn = "lwr";
1761 break;
1762 case OPC_LL:
1763 save_cpu_state(ctx, 1);
1764 op_ld_ll(t0, t0, ctx);
1765 gen_store_gpr(t0, rt);
1766 opn = "ll";
1767 break;
1769 (void)opn; /* avoid a compiler warning */
1770 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1771 tcg_temp_free(t0);
1774 /* Store */
1775 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1776 int base, int16_t offset)
1778 const char *opn = "st";
1779 TCGv t0 = tcg_temp_new();
1780 TCGv t1 = tcg_temp_new();
1782 gen_base_offset_addr(ctx, t0, base, offset);
1783 gen_load_gpr(t1, rt);
1784 switch (opc) {
1785 #if defined(TARGET_MIPS64)
1786 case OPC_SD:
1787 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
1788 opn = "sd";
1789 break;
1790 case OPC_SDL:
1791 save_cpu_state(ctx, 1);
1792 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
1793 opn = "sdl";
1794 break;
1795 case OPC_SDR:
1796 save_cpu_state(ctx, 1);
1797 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
1798 opn = "sdr";
1799 break;
1800 #endif
1801 case OPC_SW:
1802 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
1803 opn = "sw";
1804 break;
1805 case OPC_SH:
1806 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUW);
1807 opn = "sh";
1808 break;
1809 case OPC_SB:
1810 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_8);
1811 opn = "sb";
1812 break;
1813 case OPC_SWL:
1814 save_cpu_state(ctx, 1);
1815 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
1816 opn = "swl";
1817 break;
1818 case OPC_SWR:
1819 save_cpu_state(ctx, 1);
1820 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
1821 opn = "swr";
1822 break;
1824 (void)opn; /* avoid a compiler warning */
1825 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1826 tcg_temp_free(t0);
1827 tcg_temp_free(t1);
1831 /* Store conditional */
1832 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1833 int base, int16_t offset)
1835 const char *opn = "st_cond";
1836 TCGv t0, t1;
1838 #ifdef CONFIG_USER_ONLY
1839 t0 = tcg_temp_local_new();
1840 t1 = tcg_temp_local_new();
1841 #else
1842 t0 = tcg_temp_new();
1843 t1 = tcg_temp_new();
1844 #endif
1845 gen_base_offset_addr(ctx, t0, base, offset);
1846 gen_load_gpr(t1, rt);
1847 switch (opc) {
1848 #if defined(TARGET_MIPS64)
1849 case OPC_SCD:
1850 save_cpu_state(ctx, 1);
1851 op_st_scd(t1, t0, rt, ctx);
1852 opn = "scd";
1853 break;
1854 #endif
1855 case OPC_SC:
1856 save_cpu_state(ctx, 1);
1857 op_st_sc(t1, t0, rt, ctx);
1858 opn = "sc";
1859 break;
1861 (void)opn; /* avoid a compiler warning */
1862 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1863 tcg_temp_free(t1);
1864 tcg_temp_free(t0);
1867 /* Load and store */
1868 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1869 int base, int16_t offset)
1871 const char *opn = "flt_ldst";
1872 TCGv t0 = tcg_temp_new();
1874 gen_base_offset_addr(ctx, t0, base, offset);
1875 /* Don't do NOP if destination is zero: we must perform the actual
1876 memory access. */
1877 switch (opc) {
1878 case OPC_LWC1:
1880 TCGv_i32 fp0 = tcg_temp_new_i32();
1881 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, MO_TESL);
1882 gen_store_fpr32(fp0, ft);
1883 tcg_temp_free_i32(fp0);
1885 opn = "lwc1";
1886 break;
1887 case OPC_SWC1:
1889 TCGv_i32 fp0 = tcg_temp_new_i32();
1890 gen_load_fpr32(fp0, ft);
1891 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
1892 tcg_temp_free_i32(fp0);
1894 opn = "swc1";
1895 break;
1896 case OPC_LDC1:
1898 TCGv_i64 fp0 = tcg_temp_new_i64();
1899 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
1900 gen_store_fpr64(ctx, fp0, ft);
1901 tcg_temp_free_i64(fp0);
1903 opn = "ldc1";
1904 break;
1905 case OPC_SDC1:
1907 TCGv_i64 fp0 = tcg_temp_new_i64();
1908 gen_load_fpr64(ctx, fp0, ft);
1909 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
1910 tcg_temp_free_i64(fp0);
1912 opn = "sdc1";
1913 break;
1914 default:
1915 MIPS_INVAL(opn);
1916 generate_exception(ctx, EXCP_RI);
1917 goto out;
1919 (void)opn; /* avoid a compiler warning */
1920 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1921 out:
1922 tcg_temp_free(t0);
1925 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
1926 int rs, int16_t imm)
1928 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
1929 check_cp1_enabled(ctx);
1930 gen_flt_ldst(ctx, op, rt, rs, imm);
1931 } else {
1932 generate_exception_err(ctx, EXCP_CpU, 1);
1936 /* Arithmetic with immediate operand */
1937 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
1938 int rt, int rs, int16_t imm)
1940 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1941 const char *opn = "imm arith";
1943 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1944 /* If no destination, treat it as a NOP.
1945 For addi, we must generate the overflow exception when needed. */
1946 MIPS_DEBUG("NOP");
1947 return;
1949 switch (opc) {
1950 case OPC_ADDI:
1952 TCGv t0 = tcg_temp_local_new();
1953 TCGv t1 = tcg_temp_new();
1954 TCGv t2 = tcg_temp_new();
1955 int l1 = gen_new_label();
1957 gen_load_gpr(t1, rs);
1958 tcg_gen_addi_tl(t0, t1, uimm);
1959 tcg_gen_ext32s_tl(t0, t0);
1961 tcg_gen_xori_tl(t1, t1, ~uimm);
1962 tcg_gen_xori_tl(t2, t0, uimm);
1963 tcg_gen_and_tl(t1, t1, t2);
1964 tcg_temp_free(t2);
1965 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1966 tcg_temp_free(t1);
1967 /* operands of same sign, result different sign */
1968 generate_exception(ctx, EXCP_OVERFLOW);
1969 gen_set_label(l1);
1970 tcg_gen_ext32s_tl(t0, t0);
1971 gen_store_gpr(t0, rt);
1972 tcg_temp_free(t0);
1974 opn = "addi";
1975 break;
1976 case OPC_ADDIU:
1977 if (rs != 0) {
1978 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1979 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1980 } else {
1981 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1983 opn = "addiu";
1984 break;
1985 #if defined(TARGET_MIPS64)
1986 case OPC_DADDI:
1988 TCGv t0 = tcg_temp_local_new();
1989 TCGv t1 = tcg_temp_new();
1990 TCGv t2 = tcg_temp_new();
1991 int l1 = gen_new_label();
1993 gen_load_gpr(t1, rs);
1994 tcg_gen_addi_tl(t0, t1, uimm);
1996 tcg_gen_xori_tl(t1, t1, ~uimm);
1997 tcg_gen_xori_tl(t2, t0, uimm);
1998 tcg_gen_and_tl(t1, t1, t2);
1999 tcg_temp_free(t2);
2000 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2001 tcg_temp_free(t1);
2002 /* operands of same sign, result different sign */
2003 generate_exception(ctx, EXCP_OVERFLOW);
2004 gen_set_label(l1);
2005 gen_store_gpr(t0, rt);
2006 tcg_temp_free(t0);
2008 opn = "daddi";
2009 break;
2010 case OPC_DADDIU:
2011 if (rs != 0) {
2012 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2013 } else {
2014 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2016 opn = "daddiu";
2017 break;
2018 #endif
2020 (void)opn; /* avoid a compiler warning */
2021 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2024 /* Logic with immediate operand */
2025 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2026 int rt, int rs, int16_t imm)
2028 target_ulong uimm;
2030 if (rt == 0) {
2031 /* If no destination, treat it as a NOP. */
2032 MIPS_DEBUG("NOP");
2033 return;
2035 uimm = (uint16_t)imm;
2036 switch (opc) {
2037 case OPC_ANDI:
2038 if (likely(rs != 0))
2039 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2040 else
2041 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2042 MIPS_DEBUG("andi %s, %s, " TARGET_FMT_lx, regnames[rt],
2043 regnames[rs], uimm);
2044 break;
2045 case OPC_ORI:
2046 if (rs != 0)
2047 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2048 else
2049 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2050 MIPS_DEBUG("ori %s, %s, " TARGET_FMT_lx, regnames[rt],
2051 regnames[rs], uimm);
2052 break;
2053 case OPC_XORI:
2054 if (likely(rs != 0))
2055 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2056 else
2057 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2058 MIPS_DEBUG("xori %s, %s, " TARGET_FMT_lx, regnames[rt],
2059 regnames[rs], uimm);
2060 break;
2061 case OPC_LUI:
2062 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2063 MIPS_DEBUG("lui %s, " TARGET_FMT_lx, regnames[rt], uimm);
2064 break;
2066 default:
2067 MIPS_DEBUG("Unknown logical immediate opcode %08x", opc);
2068 break;
2072 /* Set on less than with immediate operand */
2073 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2074 int rt, int rs, int16_t imm)
2076 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2077 const char *opn = "imm arith";
2078 TCGv t0;
2080 if (rt == 0) {
2081 /* If no destination, treat it as a NOP. */
2082 MIPS_DEBUG("NOP");
2083 return;
2085 t0 = tcg_temp_new();
2086 gen_load_gpr(t0, rs);
2087 switch (opc) {
2088 case OPC_SLTI:
2089 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2090 opn = "slti";
2091 break;
2092 case OPC_SLTIU:
2093 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2094 opn = "sltiu";
2095 break;
2097 (void)opn; /* avoid a compiler warning */
2098 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2099 tcg_temp_free(t0);
2102 /* Shifts with immediate operand */
2103 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2104 int rt, int rs, int16_t imm)
2106 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2107 const char *opn = "imm shift";
2108 TCGv t0;
2110 if (rt == 0) {
2111 /* If no destination, treat it as a NOP. */
2112 MIPS_DEBUG("NOP");
2113 return;
2116 t0 = tcg_temp_new();
2117 gen_load_gpr(t0, rs);
2118 switch (opc) {
2119 case OPC_SLL:
2120 tcg_gen_shli_tl(t0, t0, uimm);
2121 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2122 opn = "sll";
2123 break;
2124 case OPC_SRA:
2125 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2126 opn = "sra";
2127 break;
2128 case OPC_SRL:
2129 if (uimm != 0) {
2130 tcg_gen_ext32u_tl(t0, t0);
2131 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2132 } else {
2133 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2135 opn = "srl";
2136 break;
2137 case OPC_ROTR:
2138 if (uimm != 0) {
2139 TCGv_i32 t1 = tcg_temp_new_i32();
2141 tcg_gen_trunc_tl_i32(t1, t0);
2142 tcg_gen_rotri_i32(t1, t1, uimm);
2143 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2144 tcg_temp_free_i32(t1);
2145 } else {
2146 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2148 opn = "rotr";
2149 break;
2150 #if defined(TARGET_MIPS64)
2151 case OPC_DSLL:
2152 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2153 opn = "dsll";
2154 break;
2155 case OPC_DSRA:
2156 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2157 opn = "dsra";
2158 break;
2159 case OPC_DSRL:
2160 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2161 opn = "dsrl";
2162 break;
2163 case OPC_DROTR:
2164 if (uimm != 0) {
2165 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2166 } else {
2167 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2169 opn = "drotr";
2170 break;
2171 case OPC_DSLL32:
2172 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2173 opn = "dsll32";
2174 break;
2175 case OPC_DSRA32:
2176 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2177 opn = "dsra32";
2178 break;
2179 case OPC_DSRL32:
2180 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2181 opn = "dsrl32";
2182 break;
2183 case OPC_DROTR32:
2184 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2185 opn = "drotr32";
2186 break;
2187 #endif
2189 (void)opn; /* avoid a compiler warning */
2190 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
2191 tcg_temp_free(t0);
2194 /* Arithmetic */
2195 static void gen_arith(DisasContext *ctx, uint32_t opc,
2196 int rd, int rs, int rt)
2198 const char *opn = "arith";
2200 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2201 && opc != OPC_DADD && opc != OPC_DSUB) {
2202 /* If no destination, treat it as a NOP.
2203 For add & sub, we must generate the overflow exception when needed. */
2204 MIPS_DEBUG("NOP");
2205 return;
2208 switch (opc) {
2209 case OPC_ADD:
2211 TCGv t0 = tcg_temp_local_new();
2212 TCGv t1 = tcg_temp_new();
2213 TCGv t2 = tcg_temp_new();
2214 int l1 = gen_new_label();
2216 gen_load_gpr(t1, rs);
2217 gen_load_gpr(t2, rt);
2218 tcg_gen_add_tl(t0, t1, t2);
2219 tcg_gen_ext32s_tl(t0, t0);
2220 tcg_gen_xor_tl(t1, t1, t2);
2221 tcg_gen_xor_tl(t2, t0, t2);
2222 tcg_gen_andc_tl(t1, t2, t1);
2223 tcg_temp_free(t2);
2224 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2225 tcg_temp_free(t1);
2226 /* operands of same sign, result different sign */
2227 generate_exception(ctx, EXCP_OVERFLOW);
2228 gen_set_label(l1);
2229 gen_store_gpr(t0, rd);
2230 tcg_temp_free(t0);
2232 opn = "add";
2233 break;
2234 case OPC_ADDU:
2235 if (rs != 0 && rt != 0) {
2236 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2237 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2238 } else if (rs == 0 && rt != 0) {
2239 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2240 } else if (rs != 0 && rt == 0) {
2241 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2242 } else {
2243 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2245 opn = "addu";
2246 break;
2247 case OPC_SUB:
2249 TCGv t0 = tcg_temp_local_new();
2250 TCGv t1 = tcg_temp_new();
2251 TCGv t2 = tcg_temp_new();
2252 int l1 = gen_new_label();
2254 gen_load_gpr(t1, rs);
2255 gen_load_gpr(t2, rt);
2256 tcg_gen_sub_tl(t0, t1, t2);
2257 tcg_gen_ext32s_tl(t0, t0);
2258 tcg_gen_xor_tl(t2, t1, t2);
2259 tcg_gen_xor_tl(t1, t0, t1);
2260 tcg_gen_and_tl(t1, t1, t2);
2261 tcg_temp_free(t2);
2262 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2263 tcg_temp_free(t1);
2264 /* operands of different sign, first operand and result different sign */
2265 generate_exception(ctx, EXCP_OVERFLOW);
2266 gen_set_label(l1);
2267 gen_store_gpr(t0, rd);
2268 tcg_temp_free(t0);
2270 opn = "sub";
2271 break;
2272 case OPC_SUBU:
2273 if (rs != 0 && rt != 0) {
2274 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2275 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2276 } else if (rs == 0 && rt != 0) {
2277 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2278 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2279 } else if (rs != 0 && rt == 0) {
2280 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2281 } else {
2282 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2284 opn = "subu";
2285 break;
2286 #if defined(TARGET_MIPS64)
2287 case OPC_DADD:
2289 TCGv t0 = tcg_temp_local_new();
2290 TCGv t1 = tcg_temp_new();
2291 TCGv t2 = tcg_temp_new();
2292 int l1 = gen_new_label();
2294 gen_load_gpr(t1, rs);
2295 gen_load_gpr(t2, rt);
2296 tcg_gen_add_tl(t0, t1, t2);
2297 tcg_gen_xor_tl(t1, t1, t2);
2298 tcg_gen_xor_tl(t2, t0, t2);
2299 tcg_gen_andc_tl(t1, t2, t1);
2300 tcg_temp_free(t2);
2301 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2302 tcg_temp_free(t1);
2303 /* operands of same sign, result different sign */
2304 generate_exception(ctx, EXCP_OVERFLOW);
2305 gen_set_label(l1);
2306 gen_store_gpr(t0, rd);
2307 tcg_temp_free(t0);
2309 opn = "dadd";
2310 break;
2311 case OPC_DADDU:
2312 if (rs != 0 && rt != 0) {
2313 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2314 } else if (rs == 0 && rt != 0) {
2315 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2316 } else if (rs != 0 && rt == 0) {
2317 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2318 } else {
2319 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2321 opn = "daddu";
2322 break;
2323 case OPC_DSUB:
2325 TCGv t0 = tcg_temp_local_new();
2326 TCGv t1 = tcg_temp_new();
2327 TCGv t2 = tcg_temp_new();
2328 int l1 = gen_new_label();
2330 gen_load_gpr(t1, rs);
2331 gen_load_gpr(t2, rt);
2332 tcg_gen_sub_tl(t0, t1, t2);
2333 tcg_gen_xor_tl(t2, t1, t2);
2334 tcg_gen_xor_tl(t1, t0, t1);
2335 tcg_gen_and_tl(t1, t1, t2);
2336 tcg_temp_free(t2);
2337 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2338 tcg_temp_free(t1);
2339 /* operands of different sign, first operand and result different sign */
2340 generate_exception(ctx, EXCP_OVERFLOW);
2341 gen_set_label(l1);
2342 gen_store_gpr(t0, rd);
2343 tcg_temp_free(t0);
2345 opn = "dsub";
2346 break;
2347 case OPC_DSUBU:
2348 if (rs != 0 && rt != 0) {
2349 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2350 } else if (rs == 0 && rt != 0) {
2351 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2352 } else if (rs != 0 && rt == 0) {
2353 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2354 } else {
2355 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2357 opn = "dsubu";
2358 break;
2359 #endif
2360 case OPC_MUL:
2361 if (likely(rs != 0 && rt != 0)) {
2362 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2363 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2364 } else {
2365 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2367 opn = "mul";
2368 break;
2370 (void)opn; /* avoid a compiler warning */
2371 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2374 /* Conditional move */
2375 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2376 int rd, int rs, int rt)
2378 const char *opn = "cond move";
2379 TCGv t0, t1, t2;
2381 if (rd == 0) {
2382 /* If no destination, treat it as a NOP. */
2383 MIPS_DEBUG("NOP");
2384 return;
2387 t0 = tcg_temp_new();
2388 gen_load_gpr(t0, rt);
2389 t1 = tcg_const_tl(0);
2390 t2 = tcg_temp_new();
2391 gen_load_gpr(t2, rs);
2392 switch (opc) {
2393 case OPC_MOVN:
2394 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2395 opn = "movn";
2396 break;
2397 case OPC_MOVZ:
2398 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2399 opn = "movz";
2400 break;
2402 tcg_temp_free(t2);
2403 tcg_temp_free(t1);
2404 tcg_temp_free(t0);
2406 (void)opn; /* avoid a compiler warning */
2407 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2410 /* Logic */
2411 static void gen_logic(DisasContext *ctx, uint32_t opc,
2412 int rd, int rs, int rt)
2414 const char *opn = "logic";
2416 if (rd == 0) {
2417 /* If no destination, treat it as a NOP. */
2418 MIPS_DEBUG("NOP");
2419 return;
2422 switch (opc) {
2423 case OPC_AND:
2424 if (likely(rs != 0 && rt != 0)) {
2425 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2426 } else {
2427 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2429 opn = "and";
2430 break;
2431 case OPC_NOR:
2432 if (rs != 0 && rt != 0) {
2433 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2434 } else if (rs == 0 && rt != 0) {
2435 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2436 } else if (rs != 0 && rt == 0) {
2437 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2438 } else {
2439 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2441 opn = "nor";
2442 break;
2443 case OPC_OR:
2444 if (likely(rs != 0 && rt != 0)) {
2445 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2446 } else if (rs == 0 && rt != 0) {
2447 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2448 } else if (rs != 0 && rt == 0) {
2449 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2450 } else {
2451 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2453 opn = "or";
2454 break;
2455 case OPC_XOR:
2456 if (likely(rs != 0 && rt != 0)) {
2457 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2458 } else if (rs == 0 && rt != 0) {
2459 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2460 } else if (rs != 0 && rt == 0) {
2461 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2462 } else {
2463 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2465 opn = "xor";
2466 break;
2468 (void)opn; /* avoid a compiler warning */
2469 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2472 /* Set on lower than */
2473 static void gen_slt(DisasContext *ctx, uint32_t opc,
2474 int rd, int rs, int rt)
2476 const char *opn = "slt";
2477 TCGv t0, t1;
2479 if (rd == 0) {
2480 /* If no destination, treat it as a NOP. */
2481 MIPS_DEBUG("NOP");
2482 return;
2485 t0 = tcg_temp_new();
2486 t1 = tcg_temp_new();
2487 gen_load_gpr(t0, rs);
2488 gen_load_gpr(t1, rt);
2489 switch (opc) {
2490 case OPC_SLT:
2491 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2492 opn = "slt";
2493 break;
2494 case OPC_SLTU:
2495 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2496 opn = "sltu";
2497 break;
2499 (void)opn; /* avoid a compiler warning */
2500 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2501 tcg_temp_free(t0);
2502 tcg_temp_free(t1);
2505 /* Shifts */
2506 static void gen_shift(DisasContext *ctx, uint32_t opc,
2507 int rd, int rs, int rt)
2509 const char *opn = "shifts";
2510 TCGv t0, t1;
2512 if (rd == 0) {
2513 /* If no destination, treat it as a NOP.
2514 For add & sub, we must generate the overflow exception when needed. */
2515 MIPS_DEBUG("NOP");
2516 return;
2519 t0 = tcg_temp_new();
2520 t1 = tcg_temp_new();
2521 gen_load_gpr(t0, rs);
2522 gen_load_gpr(t1, rt);
2523 switch (opc) {
2524 case OPC_SLLV:
2525 tcg_gen_andi_tl(t0, t0, 0x1f);
2526 tcg_gen_shl_tl(t0, t1, t0);
2527 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2528 opn = "sllv";
2529 break;
2530 case OPC_SRAV:
2531 tcg_gen_andi_tl(t0, t0, 0x1f);
2532 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2533 opn = "srav";
2534 break;
2535 case OPC_SRLV:
2536 tcg_gen_ext32u_tl(t1, t1);
2537 tcg_gen_andi_tl(t0, t0, 0x1f);
2538 tcg_gen_shr_tl(t0, t1, t0);
2539 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2540 opn = "srlv";
2541 break;
2542 case OPC_ROTRV:
2544 TCGv_i32 t2 = tcg_temp_new_i32();
2545 TCGv_i32 t3 = tcg_temp_new_i32();
2547 tcg_gen_trunc_tl_i32(t2, t0);
2548 tcg_gen_trunc_tl_i32(t3, t1);
2549 tcg_gen_andi_i32(t2, t2, 0x1f);
2550 tcg_gen_rotr_i32(t2, t3, t2);
2551 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2552 tcg_temp_free_i32(t2);
2553 tcg_temp_free_i32(t3);
2554 opn = "rotrv";
2556 break;
2557 #if defined(TARGET_MIPS64)
2558 case OPC_DSLLV:
2559 tcg_gen_andi_tl(t0, t0, 0x3f);
2560 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2561 opn = "dsllv";
2562 break;
2563 case OPC_DSRAV:
2564 tcg_gen_andi_tl(t0, t0, 0x3f);
2565 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2566 opn = "dsrav";
2567 break;
2568 case OPC_DSRLV:
2569 tcg_gen_andi_tl(t0, t0, 0x3f);
2570 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2571 opn = "dsrlv";
2572 break;
2573 case OPC_DROTRV:
2574 tcg_gen_andi_tl(t0, t0, 0x3f);
2575 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2576 opn = "drotrv";
2577 break;
2578 #endif
2580 (void)opn; /* avoid a compiler warning */
2581 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2582 tcg_temp_free(t0);
2583 tcg_temp_free(t1);
2586 /* Arithmetic on HI/LO registers */
2587 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2589 const char *opn = "hilo";
2591 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2592 /* Treat as NOP. */
2593 MIPS_DEBUG("NOP");
2594 return;
2597 if (acc != 0) {
2598 check_dsp(ctx);
2601 switch (opc) {
2602 case OPC_MFHI:
2603 #if defined(TARGET_MIPS64)
2604 if (acc != 0) {
2605 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2606 } else
2607 #endif
2609 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2611 opn = "mfhi";
2612 break;
2613 case OPC_MFLO:
2614 #if defined(TARGET_MIPS64)
2615 if (acc != 0) {
2616 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2617 } else
2618 #endif
2620 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2622 opn = "mflo";
2623 break;
2624 case OPC_MTHI:
2625 if (reg != 0) {
2626 #if defined(TARGET_MIPS64)
2627 if (acc != 0) {
2628 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2629 } else
2630 #endif
2632 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2634 } else {
2635 tcg_gen_movi_tl(cpu_HI[acc], 0);
2637 opn = "mthi";
2638 break;
2639 case OPC_MTLO:
2640 if (reg != 0) {
2641 #if defined(TARGET_MIPS64)
2642 if (acc != 0) {
2643 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2644 } else
2645 #endif
2647 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2649 } else {
2650 tcg_gen_movi_tl(cpu_LO[acc], 0);
2652 opn = "mtlo";
2653 break;
2655 (void)opn; /* avoid a compiler warning */
2656 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2659 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
2660 int acc, int rs, int rt)
2662 const char *opn = "mul/div";
2663 TCGv t0, t1;
2665 t0 = tcg_temp_new();
2666 t1 = tcg_temp_new();
2668 gen_load_gpr(t0, rs);
2669 gen_load_gpr(t1, rt);
2671 if (acc != 0) {
2672 check_dsp(ctx);
2675 switch (opc) {
2676 case OPC_DIV:
2678 TCGv t2 = tcg_temp_new();
2679 TCGv t3 = tcg_temp_new();
2680 tcg_gen_ext32s_tl(t0, t0);
2681 tcg_gen_ext32s_tl(t1, t1);
2682 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
2683 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
2684 tcg_gen_and_tl(t2, t2, t3);
2685 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2686 tcg_gen_or_tl(t2, t2, t3);
2687 tcg_gen_movi_tl(t3, 0);
2688 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2689 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
2690 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
2691 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
2692 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
2693 tcg_temp_free(t3);
2694 tcg_temp_free(t2);
2696 opn = "div";
2697 break;
2698 case OPC_DIVU:
2700 TCGv t2 = tcg_const_tl(0);
2701 TCGv t3 = tcg_const_tl(1);
2702 tcg_gen_ext32u_tl(t0, t0);
2703 tcg_gen_ext32u_tl(t1, t1);
2704 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
2705 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
2706 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
2707 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
2708 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
2709 tcg_temp_free(t3);
2710 tcg_temp_free(t2);
2712 opn = "divu";
2713 break;
2714 case OPC_MULT:
2716 TCGv_i32 t2 = tcg_temp_new_i32();
2717 TCGv_i32 t3 = tcg_temp_new_i32();
2718 tcg_gen_trunc_tl_i32(t2, t0);
2719 tcg_gen_trunc_tl_i32(t3, t1);
2720 tcg_gen_muls2_i32(t2, t3, t2, t3);
2721 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2722 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2723 tcg_temp_free_i32(t2);
2724 tcg_temp_free_i32(t3);
2726 opn = "mult";
2727 break;
2728 case OPC_MULTU:
2730 TCGv_i32 t2 = tcg_temp_new_i32();
2731 TCGv_i32 t3 = tcg_temp_new_i32();
2732 tcg_gen_trunc_tl_i32(t2, t0);
2733 tcg_gen_trunc_tl_i32(t3, t1);
2734 tcg_gen_mulu2_i32(t2, t3, t2, t3);
2735 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
2736 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
2737 tcg_temp_free_i32(t2);
2738 tcg_temp_free_i32(t3);
2740 opn = "multu";
2741 break;
2742 #if defined(TARGET_MIPS64)
2743 case OPC_DDIV:
2745 TCGv t2 = tcg_temp_new();
2746 TCGv t3 = tcg_temp_new();
2747 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
2748 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
2749 tcg_gen_and_tl(t2, t2, t3);
2750 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
2751 tcg_gen_or_tl(t2, t2, t3);
2752 tcg_gen_movi_tl(t3, 0);
2753 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1);
2754 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
2755 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
2756 tcg_temp_free(t3);
2757 tcg_temp_free(t2);
2759 opn = "ddiv";
2760 break;
2761 case OPC_DDIVU:
2763 TCGv t2 = tcg_const_tl(0);
2764 TCGv t3 = tcg_const_tl(1);
2765 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
2766 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
2767 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
2768 tcg_temp_free(t3);
2769 tcg_temp_free(t2);
2771 opn = "ddivu";
2772 break;
2773 case OPC_DMULT:
2774 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
2775 opn = "dmult";
2776 break;
2777 case OPC_DMULTU:
2778 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
2779 opn = "dmultu";
2780 break;
2781 #endif
2782 case OPC_MADD:
2784 TCGv_i64 t2 = tcg_temp_new_i64();
2785 TCGv_i64 t3 = tcg_temp_new_i64();
2787 tcg_gen_ext_tl_i64(t2, t0);
2788 tcg_gen_ext_tl_i64(t3, t1);
2789 tcg_gen_mul_i64(t2, t2, t3);
2790 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2791 tcg_gen_add_i64(t2, t2, t3);
2792 tcg_temp_free_i64(t3);
2793 tcg_gen_trunc_i64_tl(t0, t2);
2794 tcg_gen_shri_i64(t2, t2, 32);
2795 tcg_gen_trunc_i64_tl(t1, t2);
2796 tcg_temp_free_i64(t2);
2797 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2798 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2800 opn = "madd";
2801 break;
2802 case OPC_MADDU:
2804 TCGv_i64 t2 = tcg_temp_new_i64();
2805 TCGv_i64 t3 = tcg_temp_new_i64();
2807 tcg_gen_ext32u_tl(t0, t0);
2808 tcg_gen_ext32u_tl(t1, t1);
2809 tcg_gen_extu_tl_i64(t2, t0);
2810 tcg_gen_extu_tl_i64(t3, t1);
2811 tcg_gen_mul_i64(t2, t2, t3);
2812 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2813 tcg_gen_add_i64(t2, t2, t3);
2814 tcg_temp_free_i64(t3);
2815 tcg_gen_trunc_i64_tl(t0, t2);
2816 tcg_gen_shri_i64(t2, t2, 32);
2817 tcg_gen_trunc_i64_tl(t1, t2);
2818 tcg_temp_free_i64(t2);
2819 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2820 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2822 opn = "maddu";
2823 break;
2824 case OPC_MSUB:
2826 TCGv_i64 t2 = tcg_temp_new_i64();
2827 TCGv_i64 t3 = tcg_temp_new_i64();
2829 tcg_gen_ext_tl_i64(t2, t0);
2830 tcg_gen_ext_tl_i64(t3, t1);
2831 tcg_gen_mul_i64(t2, t2, t3);
2832 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2833 tcg_gen_sub_i64(t2, t3, t2);
2834 tcg_temp_free_i64(t3);
2835 tcg_gen_trunc_i64_tl(t0, t2);
2836 tcg_gen_shri_i64(t2, t2, 32);
2837 tcg_gen_trunc_i64_tl(t1, t2);
2838 tcg_temp_free_i64(t2);
2839 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2840 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2842 opn = "msub";
2843 break;
2844 case OPC_MSUBU:
2846 TCGv_i64 t2 = tcg_temp_new_i64();
2847 TCGv_i64 t3 = tcg_temp_new_i64();
2849 tcg_gen_ext32u_tl(t0, t0);
2850 tcg_gen_ext32u_tl(t1, t1);
2851 tcg_gen_extu_tl_i64(t2, t0);
2852 tcg_gen_extu_tl_i64(t3, t1);
2853 tcg_gen_mul_i64(t2, t2, t3);
2854 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
2855 tcg_gen_sub_i64(t2, t3, t2);
2856 tcg_temp_free_i64(t3);
2857 tcg_gen_trunc_i64_tl(t0, t2);
2858 tcg_gen_shri_i64(t2, t2, 32);
2859 tcg_gen_trunc_i64_tl(t1, t2);
2860 tcg_temp_free_i64(t2);
2861 tcg_gen_ext32s_tl(cpu_LO[acc], t0);
2862 tcg_gen_ext32s_tl(cpu_HI[acc], t1);
2864 opn = "msubu";
2865 break;
2866 default:
2867 MIPS_INVAL(opn);
2868 generate_exception(ctx, EXCP_RI);
2869 goto out;
2871 (void)opn; /* avoid a compiler warning */
2872 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2873 out:
2874 tcg_temp_free(t0);
2875 tcg_temp_free(t1);
2878 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2879 int rd, int rs, int rt)
2881 const char *opn = "mul vr54xx";
2882 TCGv t0 = tcg_temp_new();
2883 TCGv t1 = tcg_temp_new();
2885 gen_load_gpr(t0, rs);
2886 gen_load_gpr(t1, rt);
2888 switch (opc) {
2889 case OPC_VR54XX_MULS:
2890 gen_helper_muls(t0, cpu_env, t0, t1);
2891 opn = "muls";
2892 break;
2893 case OPC_VR54XX_MULSU:
2894 gen_helper_mulsu(t0, cpu_env, t0, t1);
2895 opn = "mulsu";
2896 break;
2897 case OPC_VR54XX_MACC:
2898 gen_helper_macc(t0, cpu_env, t0, t1);
2899 opn = "macc";
2900 break;
2901 case OPC_VR54XX_MACCU:
2902 gen_helper_maccu(t0, cpu_env, t0, t1);
2903 opn = "maccu";
2904 break;
2905 case OPC_VR54XX_MSAC:
2906 gen_helper_msac(t0, cpu_env, t0, t1);
2907 opn = "msac";
2908 break;
2909 case OPC_VR54XX_MSACU:
2910 gen_helper_msacu(t0, cpu_env, t0, t1);
2911 opn = "msacu";
2912 break;
2913 case OPC_VR54XX_MULHI:
2914 gen_helper_mulhi(t0, cpu_env, t0, t1);
2915 opn = "mulhi";
2916 break;
2917 case OPC_VR54XX_MULHIU:
2918 gen_helper_mulhiu(t0, cpu_env, t0, t1);
2919 opn = "mulhiu";
2920 break;
2921 case OPC_VR54XX_MULSHI:
2922 gen_helper_mulshi(t0, cpu_env, t0, t1);
2923 opn = "mulshi";
2924 break;
2925 case OPC_VR54XX_MULSHIU:
2926 gen_helper_mulshiu(t0, cpu_env, t0, t1);
2927 opn = "mulshiu";
2928 break;
2929 case OPC_VR54XX_MACCHI:
2930 gen_helper_macchi(t0, cpu_env, t0, t1);
2931 opn = "macchi";
2932 break;
2933 case OPC_VR54XX_MACCHIU:
2934 gen_helper_macchiu(t0, cpu_env, t0, t1);
2935 opn = "macchiu";
2936 break;
2937 case OPC_VR54XX_MSACHI:
2938 gen_helper_msachi(t0, cpu_env, t0, t1);
2939 opn = "msachi";
2940 break;
2941 case OPC_VR54XX_MSACHIU:
2942 gen_helper_msachiu(t0, cpu_env, t0, t1);
2943 opn = "msachiu";
2944 break;
2945 default:
2946 MIPS_INVAL("mul vr54xx");
2947 generate_exception(ctx, EXCP_RI);
2948 goto out;
2950 gen_store_gpr(t0, rd);
2951 (void)opn; /* avoid a compiler warning */
2952 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2954 out:
2955 tcg_temp_free(t0);
2956 tcg_temp_free(t1);
2959 static void gen_cl (DisasContext *ctx, uint32_t opc,
2960 int rd, int rs)
2962 const char *opn = "CLx";
2963 TCGv t0;
2965 if (rd == 0) {
2966 /* Treat as NOP. */
2967 MIPS_DEBUG("NOP");
2968 return;
2970 t0 = tcg_temp_new();
2971 gen_load_gpr(t0, rs);
2972 switch (opc) {
2973 case OPC_CLO:
2974 gen_helper_clo(cpu_gpr[rd], t0);
2975 opn = "clo";
2976 break;
2977 case OPC_CLZ:
2978 gen_helper_clz(cpu_gpr[rd], t0);
2979 opn = "clz";
2980 break;
2981 #if defined(TARGET_MIPS64)
2982 case OPC_DCLO:
2983 gen_helper_dclo(cpu_gpr[rd], t0);
2984 opn = "dclo";
2985 break;
2986 case OPC_DCLZ:
2987 gen_helper_dclz(cpu_gpr[rd], t0);
2988 opn = "dclz";
2989 break;
2990 #endif
2992 (void)opn; /* avoid a compiler warning */
2993 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2994 tcg_temp_free(t0);
2997 /* Godson integer instructions */
2998 static void gen_loongson_integer(DisasContext *ctx, uint32_t opc,
2999 int rd, int rs, int rt)
3001 const char *opn = "loongson";
3002 TCGv t0, t1;
3004 if (rd == 0) {
3005 /* Treat as NOP. */
3006 MIPS_DEBUG("NOP");
3007 return;
3010 switch (opc) {
3011 case OPC_MULT_G_2E:
3012 case OPC_MULT_G_2F:
3013 case OPC_MULTU_G_2E:
3014 case OPC_MULTU_G_2F:
3015 #if defined(TARGET_MIPS64)
3016 case OPC_DMULT_G_2E:
3017 case OPC_DMULT_G_2F:
3018 case OPC_DMULTU_G_2E:
3019 case OPC_DMULTU_G_2F:
3020 #endif
3021 t0 = tcg_temp_new();
3022 t1 = tcg_temp_new();
3023 break;
3024 default:
3025 t0 = tcg_temp_local_new();
3026 t1 = tcg_temp_local_new();
3027 break;
3030 gen_load_gpr(t0, rs);
3031 gen_load_gpr(t1, rt);
3033 switch (opc) {
3034 case OPC_MULT_G_2E:
3035 case OPC_MULT_G_2F:
3036 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3037 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3038 opn = "mult.g";
3039 break;
3040 case OPC_MULTU_G_2E:
3041 case OPC_MULTU_G_2F:
3042 tcg_gen_ext32u_tl(t0, t0);
3043 tcg_gen_ext32u_tl(t1, t1);
3044 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3045 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3046 opn = "multu.g";
3047 break;
3048 case OPC_DIV_G_2E:
3049 case OPC_DIV_G_2F:
3051 int l1 = gen_new_label();
3052 int l2 = gen_new_label();
3053 int l3 = gen_new_label();
3054 tcg_gen_ext32s_tl(t0, t0);
3055 tcg_gen_ext32s_tl(t1, t1);
3056 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3057 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3058 tcg_gen_br(l3);
3059 gen_set_label(l1);
3060 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3061 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3062 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3063 tcg_gen_br(l3);
3064 gen_set_label(l2);
3065 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3066 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3067 gen_set_label(l3);
3069 opn = "div.g";
3070 break;
3071 case OPC_DIVU_G_2E:
3072 case OPC_DIVU_G_2F:
3074 int l1 = gen_new_label();
3075 int l2 = gen_new_label();
3076 tcg_gen_ext32u_tl(t0, t0);
3077 tcg_gen_ext32u_tl(t1, t1);
3078 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3079 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3080 tcg_gen_br(l2);
3081 gen_set_label(l1);
3082 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3083 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3084 gen_set_label(l2);
3086 opn = "divu.g";
3087 break;
3088 case OPC_MOD_G_2E:
3089 case OPC_MOD_G_2F:
3091 int l1 = gen_new_label();
3092 int l2 = gen_new_label();
3093 int l3 = gen_new_label();
3094 tcg_gen_ext32u_tl(t0, t0);
3095 tcg_gen_ext32u_tl(t1, t1);
3096 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3097 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
3098 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
3099 gen_set_label(l1);
3100 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3101 tcg_gen_br(l3);
3102 gen_set_label(l2);
3103 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3104 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3105 gen_set_label(l3);
3107 opn = "mod.g";
3108 break;
3109 case OPC_MODU_G_2E:
3110 case OPC_MODU_G_2F:
3112 int l1 = gen_new_label();
3113 int l2 = gen_new_label();
3114 tcg_gen_ext32u_tl(t0, t0);
3115 tcg_gen_ext32u_tl(t1, t1);
3116 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3117 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3118 tcg_gen_br(l2);
3119 gen_set_label(l1);
3120 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3121 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3122 gen_set_label(l2);
3124 opn = "modu.g";
3125 break;
3126 #if defined(TARGET_MIPS64)
3127 case OPC_DMULT_G_2E:
3128 case OPC_DMULT_G_2F:
3129 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3130 opn = "dmult.g";
3131 break;
3132 case OPC_DMULTU_G_2E:
3133 case OPC_DMULTU_G_2F:
3134 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
3135 opn = "dmultu.g";
3136 break;
3137 case OPC_DDIV_G_2E:
3138 case OPC_DDIV_G_2F:
3140 int l1 = gen_new_label();
3141 int l2 = gen_new_label();
3142 int l3 = gen_new_label();
3143 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3144 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3145 tcg_gen_br(l3);
3146 gen_set_label(l1);
3147 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3148 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3149 tcg_gen_mov_tl(cpu_gpr[rd], t0);
3150 tcg_gen_br(l3);
3151 gen_set_label(l2);
3152 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3153 gen_set_label(l3);
3155 opn = "ddiv.g";
3156 break;
3157 case OPC_DDIVU_G_2E:
3158 case OPC_DDIVU_G_2F:
3160 int l1 = gen_new_label();
3161 int l2 = gen_new_label();
3162 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3163 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3164 tcg_gen_br(l2);
3165 gen_set_label(l1);
3166 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3167 gen_set_label(l2);
3169 opn = "ddivu.g";
3170 break;
3171 case OPC_DMOD_G_2E:
3172 case OPC_DMOD_G_2F:
3174 int l1 = gen_new_label();
3175 int l2 = gen_new_label();
3176 int l3 = gen_new_label();
3177 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
3178 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
3179 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
3180 gen_set_label(l1);
3181 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3182 tcg_gen_br(l3);
3183 gen_set_label(l2);
3184 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3185 gen_set_label(l3);
3187 opn = "dmod.g";
3188 break;
3189 case OPC_DMODU_G_2E:
3190 case OPC_DMODU_G_2F:
3192 int l1 = gen_new_label();
3193 int l2 = gen_new_label();
3194 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
3195 tcg_gen_movi_tl(cpu_gpr[rd], 0);
3196 tcg_gen_br(l2);
3197 gen_set_label(l1);
3198 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3199 gen_set_label(l2);
3201 opn = "dmodu.g";
3202 break;
3203 #endif
3206 (void)opn; /* avoid a compiler warning */
3207 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
3208 tcg_temp_free(t0);
3209 tcg_temp_free(t1);
3212 /* Loongson multimedia instructions */
3213 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3215 const char *opn = "loongson_cp2";
3216 uint32_t opc, shift_max;
3217 TCGv_i64 t0, t1;
3219 opc = MASK_LMI(ctx->opcode);
3220 switch (opc) {
3221 case OPC_ADD_CP2:
3222 case OPC_SUB_CP2:
3223 case OPC_DADD_CP2:
3224 case OPC_DSUB_CP2:
3225 t0 = tcg_temp_local_new_i64();
3226 t1 = tcg_temp_local_new_i64();
3227 break;
3228 default:
3229 t0 = tcg_temp_new_i64();
3230 t1 = tcg_temp_new_i64();
3231 break;
3234 gen_load_fpr64(ctx, t0, rs);
3235 gen_load_fpr64(ctx, t1, rt);
3237 #define LMI_HELPER(UP, LO) \
3238 case OPC_##UP: gen_helper_##LO(t0, t0, t1); opn = #LO; break
3239 #define LMI_HELPER_1(UP, LO) \
3240 case OPC_##UP: gen_helper_##LO(t0, t0); opn = #LO; break
3241 #define LMI_DIRECT(UP, LO, OP) \
3242 case OPC_##UP: tcg_gen_##OP##_i64(t0, t0, t1); opn = #LO; break
3244 switch (opc) {
3245 LMI_HELPER(PADDSH, paddsh);
3246 LMI_HELPER(PADDUSH, paddush);
3247 LMI_HELPER(PADDH, paddh);
3248 LMI_HELPER(PADDW, paddw);
3249 LMI_HELPER(PADDSB, paddsb);
3250 LMI_HELPER(PADDUSB, paddusb);
3251 LMI_HELPER(PADDB, paddb);
3253 LMI_HELPER(PSUBSH, psubsh);
3254 LMI_HELPER(PSUBUSH, psubush);
3255 LMI_HELPER(PSUBH, psubh);
3256 LMI_HELPER(PSUBW, psubw);
3257 LMI_HELPER(PSUBSB, psubsb);
3258 LMI_HELPER(PSUBUSB, psubusb);
3259 LMI_HELPER(PSUBB, psubb);
3261 LMI_HELPER(PSHUFH, pshufh);
3262 LMI_HELPER(PACKSSWH, packsswh);
3263 LMI_HELPER(PACKSSHB, packsshb);
3264 LMI_HELPER(PACKUSHB, packushb);
3266 LMI_HELPER(PUNPCKLHW, punpcklhw);
3267 LMI_HELPER(PUNPCKHHW, punpckhhw);
3268 LMI_HELPER(PUNPCKLBH, punpcklbh);
3269 LMI_HELPER(PUNPCKHBH, punpckhbh);
3270 LMI_HELPER(PUNPCKLWD, punpcklwd);
3271 LMI_HELPER(PUNPCKHWD, punpckhwd);
3273 LMI_HELPER(PAVGH, pavgh);
3274 LMI_HELPER(PAVGB, pavgb);
3275 LMI_HELPER(PMAXSH, pmaxsh);
3276 LMI_HELPER(PMINSH, pminsh);
3277 LMI_HELPER(PMAXUB, pmaxub);
3278 LMI_HELPER(PMINUB, pminub);
3280 LMI_HELPER(PCMPEQW, pcmpeqw);
3281 LMI_HELPER(PCMPGTW, pcmpgtw);
3282 LMI_HELPER(PCMPEQH, pcmpeqh);
3283 LMI_HELPER(PCMPGTH, pcmpgth);
3284 LMI_HELPER(PCMPEQB, pcmpeqb);
3285 LMI_HELPER(PCMPGTB, pcmpgtb);
3287 LMI_HELPER(PSLLW, psllw);
3288 LMI_HELPER(PSLLH, psllh);
3289 LMI_HELPER(PSRLW, psrlw);
3290 LMI_HELPER(PSRLH, psrlh);
3291 LMI_HELPER(PSRAW, psraw);
3292 LMI_HELPER(PSRAH, psrah);
3294 LMI_HELPER(PMULLH, pmullh);
3295 LMI_HELPER(PMULHH, pmulhh);
3296 LMI_HELPER(PMULHUH, pmulhuh);
3297 LMI_HELPER(PMADDHW, pmaddhw);
3299 LMI_HELPER(PASUBUB, pasubub);
3300 LMI_HELPER_1(BIADD, biadd);
3301 LMI_HELPER_1(PMOVMSKB, pmovmskb);
3303 LMI_DIRECT(PADDD, paddd, add);
3304 LMI_DIRECT(PSUBD, psubd, sub);
3305 LMI_DIRECT(XOR_CP2, xor, xor);
3306 LMI_DIRECT(NOR_CP2, nor, nor);
3307 LMI_DIRECT(AND_CP2, and, and);
3308 LMI_DIRECT(PANDN, pandn, andc);
3309 LMI_DIRECT(OR, or, or);
3311 case OPC_PINSRH_0:
3312 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3313 opn = "pinsrh_0";
3314 break;
3315 case OPC_PINSRH_1:
3316 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3317 opn = "pinsrh_1";
3318 break;
3319 case OPC_PINSRH_2:
3320 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3321 opn = "pinsrh_2";
3322 break;
3323 case OPC_PINSRH_3:
3324 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3325 opn = "pinsrh_3";
3326 break;
3328 case OPC_PEXTRH:
3329 tcg_gen_andi_i64(t1, t1, 3);
3330 tcg_gen_shli_i64(t1, t1, 4);
3331 tcg_gen_shr_i64(t0, t0, t1);
3332 tcg_gen_ext16u_i64(t0, t0);
3333 opn = "pextrh";
3334 break;
3336 case OPC_ADDU_CP2:
3337 tcg_gen_add_i64(t0, t0, t1);
3338 tcg_gen_ext32s_i64(t0, t0);
3339 opn = "addu";
3340 break;
3341 case OPC_SUBU_CP2:
3342 tcg_gen_sub_i64(t0, t0, t1);
3343 tcg_gen_ext32s_i64(t0, t0);
3344 opn = "addu";
3345 break;
3347 case OPC_SLL_CP2:
3348 opn = "sll";
3349 shift_max = 32;
3350 goto do_shift;
3351 case OPC_SRL_CP2:
3352 opn = "srl";
3353 shift_max = 32;
3354 goto do_shift;
3355 case OPC_SRA_CP2:
3356 opn = "sra";
3357 shift_max = 32;
3358 goto do_shift;
3359 case OPC_DSLL_CP2:
3360 opn = "dsll";
3361 shift_max = 64;
3362 goto do_shift;
3363 case OPC_DSRL_CP2:
3364 opn = "dsrl";
3365 shift_max = 64;
3366 goto do_shift;
3367 case OPC_DSRA_CP2:
3368 opn = "dsra";
3369 shift_max = 64;
3370 goto do_shift;
3371 do_shift:
3372 /* Make sure shift count isn't TCG undefined behaviour. */
3373 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3375 switch (opc) {
3376 case OPC_SLL_CP2:
3377 case OPC_DSLL_CP2:
3378 tcg_gen_shl_i64(t0, t0, t1);
3379 break;
3380 case OPC_SRA_CP2:
3381 case OPC_DSRA_CP2:
3382 /* Since SRA is UndefinedResult without sign-extended inputs,
3383 we can treat SRA and DSRA the same. */
3384 tcg_gen_sar_i64(t0, t0, t1);
3385 break;
3386 case OPC_SRL_CP2:
3387 /* We want to shift in zeros for SRL; zero-extend first. */
3388 tcg_gen_ext32u_i64(t0, t0);
3389 /* FALLTHRU */
3390 case OPC_DSRL_CP2:
3391 tcg_gen_shr_i64(t0, t0, t1);
3392 break;
3395 if (shift_max == 32) {
3396 tcg_gen_ext32s_i64(t0, t0);
3399 /* Shifts larger than MAX produce zero. */
3400 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3401 tcg_gen_neg_i64(t1, t1);
3402 tcg_gen_and_i64(t0, t0, t1);
3403 break;
3405 case OPC_ADD_CP2:
3406 case OPC_DADD_CP2:
3408 TCGv_i64 t2 = tcg_temp_new_i64();
3409 int lab = gen_new_label();
3411 tcg_gen_mov_i64(t2, t0);
3412 tcg_gen_add_i64(t0, t1, t2);
3413 if (opc == OPC_ADD_CP2) {
3414 tcg_gen_ext32s_i64(t0, t0);
3416 tcg_gen_xor_i64(t1, t1, t2);
3417 tcg_gen_xor_i64(t2, t2, t0);
3418 tcg_gen_andc_i64(t1, t2, t1);
3419 tcg_temp_free_i64(t2);
3420 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3421 generate_exception(ctx, EXCP_OVERFLOW);
3422 gen_set_label(lab);
3424 opn = (opc == OPC_ADD_CP2 ? "add" : "dadd");
3425 break;
3428 case OPC_SUB_CP2:
3429 case OPC_DSUB_CP2:
3431 TCGv_i64 t2 = tcg_temp_new_i64();
3432 int lab = gen_new_label();
3434 tcg_gen_mov_i64(t2, t0);
3435 tcg_gen_sub_i64(t0, t1, t2);
3436 if (opc == OPC_SUB_CP2) {
3437 tcg_gen_ext32s_i64(t0, t0);
3439 tcg_gen_xor_i64(t1, t1, t2);
3440 tcg_gen_xor_i64(t2, t2, t0);
3441 tcg_gen_and_i64(t1, t1, t2);
3442 tcg_temp_free_i64(t2);
3443 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3444 generate_exception(ctx, EXCP_OVERFLOW);
3445 gen_set_label(lab);
3447 opn = (opc == OPC_SUB_CP2 ? "sub" : "dsub");
3448 break;
3451 case OPC_PMULUW:
3452 tcg_gen_ext32u_i64(t0, t0);
3453 tcg_gen_ext32u_i64(t1, t1);
3454 tcg_gen_mul_i64(t0, t0, t1);
3455 opn = "pmuluw";
3456 break;
3458 case OPC_SEQU_CP2:
3459 case OPC_SEQ_CP2:
3460 case OPC_SLTU_CP2:
3461 case OPC_SLT_CP2:
3462 case OPC_SLEU_CP2:
3463 case OPC_SLE_CP2:
3464 /* ??? Document is unclear: Set FCC[CC]. Does that mean the
3465 FD field is the CC field? */
3466 default:
3467 MIPS_INVAL(opn);
3468 generate_exception(ctx, EXCP_RI);
3469 return;
3472 #undef LMI_HELPER
3473 #undef LMI_DIRECT
3475 gen_store_fpr64(ctx, t0, rd);
3477 (void)opn; /* avoid a compiler warning */
3478 MIPS_DEBUG("%s %s, %s, %s", opn,
3479 fregnames[rd], fregnames[rs], fregnames[rt]);
3480 tcg_temp_free_i64(t0);
3481 tcg_temp_free_i64(t1);
3484 /* Traps */
3485 static void gen_trap (DisasContext *ctx, uint32_t opc,
3486 int rs, int rt, int16_t imm)
3488 int cond;
3489 TCGv t0 = tcg_temp_new();
3490 TCGv t1 = tcg_temp_new();
3492 cond = 0;
3493 /* Load needed operands */
3494 switch (opc) {
3495 case OPC_TEQ:
3496 case OPC_TGE:
3497 case OPC_TGEU:
3498 case OPC_TLT:
3499 case OPC_TLTU:
3500 case OPC_TNE:
3501 /* Compare two registers */
3502 if (rs != rt) {
3503 gen_load_gpr(t0, rs);
3504 gen_load_gpr(t1, rt);
3505 cond = 1;
3507 break;
3508 case OPC_TEQI:
3509 case OPC_TGEI:
3510 case OPC_TGEIU:
3511 case OPC_TLTI:
3512 case OPC_TLTIU:
3513 case OPC_TNEI:
3514 /* Compare register to immediate */
3515 if (rs != 0 || imm != 0) {
3516 gen_load_gpr(t0, rs);
3517 tcg_gen_movi_tl(t1, (int32_t)imm);
3518 cond = 1;
3520 break;
3522 if (cond == 0) {
3523 switch (opc) {
3524 case OPC_TEQ: /* rs == rs */
3525 case OPC_TEQI: /* r0 == 0 */
3526 case OPC_TGE: /* rs >= rs */
3527 case OPC_TGEI: /* r0 >= 0 */
3528 case OPC_TGEU: /* rs >= rs unsigned */
3529 case OPC_TGEIU: /* r0 >= 0 unsigned */
3530 /* Always trap */
3531 generate_exception(ctx, EXCP_TRAP);
3532 break;
3533 case OPC_TLT: /* rs < rs */
3534 case OPC_TLTI: /* r0 < 0 */
3535 case OPC_TLTU: /* rs < rs unsigned */
3536 case OPC_TLTIU: /* r0 < 0 unsigned */
3537 case OPC_TNE: /* rs != rs */
3538 case OPC_TNEI: /* r0 != 0 */
3539 /* Never trap: treat as NOP. */
3540 break;
3542 } else {
3543 int l1 = gen_new_label();
3545 switch (opc) {
3546 case OPC_TEQ:
3547 case OPC_TEQI:
3548 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
3549 break;
3550 case OPC_TGE:
3551 case OPC_TGEI:
3552 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
3553 break;
3554 case OPC_TGEU:
3555 case OPC_TGEIU:
3556 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
3557 break;
3558 case OPC_TLT:
3559 case OPC_TLTI:
3560 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
3561 break;
3562 case OPC_TLTU:
3563 case OPC_TLTIU:
3564 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
3565 break;
3566 case OPC_TNE:
3567 case OPC_TNEI:
3568 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
3569 break;
3571 generate_exception(ctx, EXCP_TRAP);
3572 gen_set_label(l1);
3574 tcg_temp_free(t0);
3575 tcg_temp_free(t1);
3578 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
3580 TranslationBlock *tb;
3581 tb = ctx->tb;
3582 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
3583 likely(!ctx->singlestep_enabled)) {
3584 tcg_gen_goto_tb(n);
3585 gen_save_pc(dest);
3586 tcg_gen_exit_tb((uintptr_t)tb + n);
3587 } else {
3588 gen_save_pc(dest);
3589 if (ctx->singlestep_enabled) {
3590 save_cpu_state(ctx, 0);
3591 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
3593 tcg_gen_exit_tb(0);
3597 /* Branches (before delay slot) */
3598 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
3599 int insn_bytes,
3600 int rs, int rt, int32_t offset)
3602 target_ulong btgt = -1;
3603 int blink = 0;
3604 int bcond_compute = 0;
3605 TCGv t0 = tcg_temp_new();
3606 TCGv t1 = tcg_temp_new();
3608 if (ctx->hflags & MIPS_HFLAG_BMASK) {
3609 #ifdef MIPS_DEBUG_DISAS
3610 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
3611 #endif
3612 generate_exception(ctx, EXCP_RI);
3613 goto out;
3616 /* Load needed operands */
3617 switch (opc) {
3618 case OPC_BEQ:
3619 case OPC_BEQL:
3620 case OPC_BNE:
3621 case OPC_BNEL:
3622 /* Compare two registers */
3623 if (rs != rt) {
3624 gen_load_gpr(t0, rs);
3625 gen_load_gpr(t1, rt);
3626 bcond_compute = 1;
3628 btgt = ctx->pc + insn_bytes + offset;
3629 break;
3630 case OPC_BGEZ:
3631 case OPC_BGEZAL:
3632 case OPC_BGEZALS:
3633 case OPC_BGEZALL:
3634 case OPC_BGEZL:
3635 case OPC_BGTZ:
3636 case OPC_BGTZL:
3637 case OPC_BLEZ:
3638 case OPC_BLEZL:
3639 case OPC_BLTZ:
3640 case OPC_BLTZAL:
3641 case OPC_BLTZALS:
3642 case OPC_BLTZALL:
3643 case OPC_BLTZL:
3644 /* Compare to zero */
3645 if (rs != 0) {
3646 gen_load_gpr(t0, rs);
3647 bcond_compute = 1;
3649 btgt = ctx->pc + insn_bytes + offset;
3650 break;
3651 case OPC_BPOSGE32:
3652 #if defined(TARGET_MIPS64)
3653 case OPC_BPOSGE64:
3654 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
3655 #else
3656 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
3657 #endif
3658 bcond_compute = 1;
3659 btgt = ctx->pc + insn_bytes + offset;
3660 break;
3661 case OPC_J:
3662 case OPC_JAL:
3663 case OPC_JALX:
3664 case OPC_JALS:
3665 case OPC_JALXS:
3666 /* Jump to immediate */
3667 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
3668 break;
3669 case OPC_JR:
3670 case OPC_JALR:
3671 case OPC_JALRC:
3672 case OPC_JALRS:
3673 /* Jump to register */
3674 if (offset != 0 && offset != 16) {
3675 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
3676 others are reserved. */
3677 MIPS_INVAL("jump hint");
3678 generate_exception(ctx, EXCP_RI);
3679 goto out;
3681 gen_load_gpr(btarget, rs);
3682 break;
3683 default:
3684 MIPS_INVAL("branch/jump");
3685 generate_exception(ctx, EXCP_RI);
3686 goto out;
3688 if (bcond_compute == 0) {
3689 /* No condition to be computed */
3690 switch (opc) {
3691 case OPC_BEQ: /* rx == rx */
3692 case OPC_BEQL: /* rx == rx likely */
3693 case OPC_BGEZ: /* 0 >= 0 */
3694 case OPC_BGEZL: /* 0 >= 0 likely */
3695 case OPC_BLEZ: /* 0 <= 0 */
3696 case OPC_BLEZL: /* 0 <= 0 likely */
3697 /* Always take */
3698 ctx->hflags |= MIPS_HFLAG_B;
3699 MIPS_DEBUG("balways");
3700 break;
3701 case OPC_BGEZALS:
3702 case OPC_BGEZAL: /* 0 >= 0 */
3703 case OPC_BGEZALL: /* 0 >= 0 likely */
3704 ctx->hflags |= (opc == OPC_BGEZALS
3705 ? MIPS_HFLAG_BDS16
3706 : MIPS_HFLAG_BDS32);
3707 /* Always take and link */
3708 blink = 31;
3709 ctx->hflags |= MIPS_HFLAG_B;
3710 MIPS_DEBUG("balways and link");
3711 break;
3712 case OPC_BNE: /* rx != rx */
3713 case OPC_BGTZ: /* 0 > 0 */
3714 case OPC_BLTZ: /* 0 < 0 */
3715 /* Treat as NOP. */
3716 MIPS_DEBUG("bnever (NOP)");
3717 goto out;
3718 case OPC_BLTZALS:
3719 case OPC_BLTZAL: /* 0 < 0 */
3720 ctx->hflags |= (opc == OPC_BLTZALS
3721 ? MIPS_HFLAG_BDS16
3722 : MIPS_HFLAG_BDS32);
3723 /* Handle as an unconditional branch to get correct delay
3724 slot checking. */
3725 blink = 31;
3726 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
3727 ctx->hflags |= MIPS_HFLAG_B;
3728 MIPS_DEBUG("bnever and link");
3729 break;
3730 case OPC_BLTZALL: /* 0 < 0 likely */
3731 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
3732 /* Skip the instruction in the delay slot */
3733 MIPS_DEBUG("bnever, link and skip");
3734 ctx->pc += 4;
3735 goto out;
3736 case OPC_BNEL: /* rx != rx likely */
3737 case OPC_BGTZL: /* 0 > 0 likely */
3738 case OPC_BLTZL: /* 0 < 0 likely */
3739 /* Skip the instruction in the delay slot */
3740 MIPS_DEBUG("bnever and skip");
3741 ctx->pc += 4;
3742 goto out;
3743 case OPC_J:
3744 ctx->hflags |= MIPS_HFLAG_B;
3745 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
3746 break;
3747 case OPC_JALXS:
3748 case OPC_JALX:
3749 ctx->hflags |= MIPS_HFLAG_BX;
3750 /* Fallthrough */
3751 case OPC_JALS:
3752 case OPC_JAL:
3753 blink = 31;
3754 ctx->hflags |= MIPS_HFLAG_B;
3755 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
3756 ? MIPS_HFLAG_BDS16
3757 : MIPS_HFLAG_BDS32);
3758 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
3759 break;
3760 case OPC_JR:
3761 ctx->hflags |= MIPS_HFLAG_BR;
3762 if (insn_bytes == 4)
3763 ctx->hflags |= MIPS_HFLAG_BDS32;
3764 MIPS_DEBUG("jr %s", regnames[rs]);
3765 break;
3766 case OPC_JALRS:
3767 case OPC_JALR:
3768 case OPC_JALRC:
3769 blink = rt;
3770 ctx->hflags |= MIPS_HFLAG_BR;
3771 ctx->hflags |= (opc == OPC_JALRS
3772 ? MIPS_HFLAG_BDS16
3773 : MIPS_HFLAG_BDS32);
3774 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
3775 break;
3776 default:
3777 MIPS_INVAL("branch/jump");
3778 generate_exception(ctx, EXCP_RI);
3779 goto out;
3781 } else {
3782 switch (opc) {
3783 case OPC_BEQ:
3784 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
3785 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
3786 regnames[rs], regnames[rt], btgt);
3787 goto not_likely;
3788 case OPC_BEQL:
3789 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
3790 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
3791 regnames[rs], regnames[rt], btgt);
3792 goto likely;
3793 case OPC_BNE:
3794 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
3795 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
3796 regnames[rs], regnames[rt], btgt);
3797 goto not_likely;
3798 case OPC_BNEL:
3799 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
3800 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
3801 regnames[rs], regnames[rt], btgt);
3802 goto likely;
3803 case OPC_BGEZ:
3804 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3805 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
3806 goto not_likely;
3807 case OPC_BGEZL:
3808 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3809 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3810 goto likely;
3811 case OPC_BGEZALS:
3812 case OPC_BGEZAL:
3813 ctx->hflags |= (opc == OPC_BGEZALS
3814 ? MIPS_HFLAG_BDS16
3815 : MIPS_HFLAG_BDS32);
3816 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3817 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
3818 blink = 31;
3819 goto not_likely;
3820 case OPC_BGEZALL:
3821 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
3822 blink = 31;
3823 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
3824 goto likely;
3825 case OPC_BGTZ:
3826 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
3827 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
3828 goto not_likely;
3829 case OPC_BGTZL:
3830 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
3831 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3832 goto likely;
3833 case OPC_BLEZ:
3834 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
3835 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
3836 goto not_likely;
3837 case OPC_BLEZL:
3838 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
3839 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3840 goto likely;
3841 case OPC_BLTZ:
3842 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3843 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
3844 goto not_likely;
3845 case OPC_BLTZL:
3846 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3847 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
3848 goto likely;
3849 case OPC_BPOSGE32:
3850 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
3851 MIPS_DEBUG("bposge32 " TARGET_FMT_lx, btgt);
3852 goto not_likely;
3853 #if defined(TARGET_MIPS64)
3854 case OPC_BPOSGE64:
3855 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
3856 MIPS_DEBUG("bposge64 " TARGET_FMT_lx, btgt);
3857 goto not_likely;
3858 #endif
3859 case OPC_BLTZALS:
3860 case OPC_BLTZAL:
3861 ctx->hflags |= (opc == OPC_BLTZALS
3862 ? MIPS_HFLAG_BDS16
3863 : MIPS_HFLAG_BDS32);
3864 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3865 blink = 31;
3866 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
3867 not_likely:
3868 ctx->hflags |= MIPS_HFLAG_BC;
3869 break;
3870 case OPC_BLTZALL:
3871 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
3872 blink = 31;
3873 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
3874 likely:
3875 ctx->hflags |= MIPS_HFLAG_BL;
3876 break;
3877 default:
3878 MIPS_INVAL("conditional branch/jump");
3879 generate_exception(ctx, EXCP_RI);
3880 goto out;
3883 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
3884 blink, ctx->hflags, btgt);
3886 ctx->btarget = btgt;
3887 if (blink > 0) {
3888 int post_delay = insn_bytes;
3889 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
3891 if (opc != OPC_JALRC)
3892 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
3894 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
3897 out:
3898 if (insn_bytes == 2)
3899 ctx->hflags |= MIPS_HFLAG_B16;
3900 tcg_temp_free(t0);
3901 tcg_temp_free(t1);
3904 /* special3 bitfield operations */
3905 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
3906 int rs, int lsb, int msb)
3908 TCGv t0 = tcg_temp_new();
3909 TCGv t1 = tcg_temp_new();
3911 gen_load_gpr(t1, rs);
3912 switch (opc) {
3913 case OPC_EXT:
3914 if (lsb + msb > 31)
3915 goto fail;
3916 tcg_gen_shri_tl(t0, t1, lsb);
3917 if (msb != 31) {
3918 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
3919 } else {
3920 tcg_gen_ext32s_tl(t0, t0);
3922 break;
3923 #if defined(TARGET_MIPS64)
3924 case OPC_DEXTM:
3925 tcg_gen_shri_tl(t0, t1, lsb);
3926 if (msb != 31) {
3927 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3929 break;
3930 case OPC_DEXTU:
3931 tcg_gen_shri_tl(t0, t1, lsb + 32);
3932 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3933 break;
3934 case OPC_DEXT:
3935 tcg_gen_shri_tl(t0, t1, lsb);
3936 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3937 break;
3938 #endif
3939 case OPC_INS:
3940 if (lsb > msb)
3941 goto fail;
3942 gen_load_gpr(t0, rt);
3943 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
3944 tcg_gen_ext32s_tl(t0, t0);
3945 break;
3946 #if defined(TARGET_MIPS64)
3947 case OPC_DINSM:
3948 gen_load_gpr(t0, rt);
3949 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb + 32 - lsb + 1);
3950 break;
3951 case OPC_DINSU:
3952 gen_load_gpr(t0, rt);
3953 tcg_gen_deposit_tl(t0, t0, t1, lsb + 32, msb - lsb + 1);
3954 break;
3955 case OPC_DINS:
3956 gen_load_gpr(t0, rt);
3957 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
3958 break;
3959 #endif
3960 default:
3961 fail:
3962 MIPS_INVAL("bitops");
3963 generate_exception(ctx, EXCP_RI);
3964 tcg_temp_free(t0);
3965 tcg_temp_free(t1);
3966 return;
3968 gen_store_gpr(t0, rt);
3969 tcg_temp_free(t0);
3970 tcg_temp_free(t1);
3973 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3975 TCGv t0;
3977 if (rd == 0) {
3978 /* If no destination, treat it as a NOP. */
3979 MIPS_DEBUG("NOP");
3980 return;
3983 t0 = tcg_temp_new();
3984 gen_load_gpr(t0, rt);
3985 switch (op2) {
3986 case OPC_WSBH:
3988 TCGv t1 = tcg_temp_new();
3990 tcg_gen_shri_tl(t1, t0, 8);
3991 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3992 tcg_gen_shli_tl(t0, t0, 8);
3993 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3994 tcg_gen_or_tl(t0, t0, t1);
3995 tcg_temp_free(t1);
3996 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3998 break;
3999 case OPC_SEB:
4000 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4001 break;
4002 case OPC_SEH:
4003 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4004 break;
4005 #if defined(TARGET_MIPS64)
4006 case OPC_DSBH:
4008 TCGv t1 = tcg_temp_new();
4010 tcg_gen_shri_tl(t1, t0, 8);
4011 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
4012 tcg_gen_shli_tl(t0, t0, 8);
4013 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
4014 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4015 tcg_temp_free(t1);
4017 break;
4018 case OPC_DSHD:
4020 TCGv t1 = tcg_temp_new();
4022 tcg_gen_shri_tl(t1, t0, 16);
4023 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
4024 tcg_gen_shli_tl(t0, t0, 16);
4025 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
4026 tcg_gen_or_tl(t0, t0, t1);
4027 tcg_gen_shri_tl(t1, t0, 32);
4028 tcg_gen_shli_tl(t0, t0, 32);
4029 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4030 tcg_temp_free(t1);
4032 break;
4033 #endif
4034 default:
4035 MIPS_INVAL("bsfhl");
4036 generate_exception(ctx, EXCP_RI);
4037 tcg_temp_free(t0);
4038 return;
4040 tcg_temp_free(t0);
4043 #ifndef CONFIG_USER_ONLY
4044 /* CP0 (MMU and control) */
4045 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
4047 TCGv_i32 t0 = tcg_temp_new_i32();
4049 tcg_gen_ld_i32(t0, cpu_env, off);
4050 tcg_gen_ext_i32_tl(arg, t0);
4051 tcg_temp_free_i32(t0);
4054 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
4056 tcg_gen_ld_tl(arg, cpu_env, off);
4057 tcg_gen_ext32s_tl(arg, arg);
4060 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
4062 TCGv_i32 t0 = tcg_temp_new_i32();
4064 tcg_gen_trunc_tl_i32(t0, arg);
4065 tcg_gen_st_i32(t0, cpu_env, off);
4066 tcg_temp_free_i32(t0);
4069 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
4071 tcg_gen_ext32s_tl(arg, arg);
4072 tcg_gen_st_tl(arg, cpu_env, off);
4075 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4077 const char *rn = "invalid";
4079 if (sel != 0)
4080 check_insn(ctx, ISA_MIPS32);
4082 switch (reg) {
4083 case 0:
4084 switch (sel) {
4085 case 0:
4086 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4087 rn = "Index";
4088 break;
4089 case 1:
4090 check_insn(ctx, ASE_MT);
4091 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
4092 rn = "MVPControl";
4093 break;
4094 case 2:
4095 check_insn(ctx, ASE_MT);
4096 gen_helper_mfc0_mvpconf0(arg, cpu_env);
4097 rn = "MVPConf0";
4098 break;
4099 case 3:
4100 check_insn(ctx, ASE_MT);
4101 gen_helper_mfc0_mvpconf1(arg, cpu_env);
4102 rn = "MVPConf1";
4103 break;
4104 default:
4105 goto die;
4107 break;
4108 case 1:
4109 switch (sel) {
4110 case 0:
4111 gen_helper_mfc0_random(arg, cpu_env);
4112 rn = "Random";
4113 break;
4114 case 1:
4115 check_insn(ctx, ASE_MT);
4116 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4117 rn = "VPEControl";
4118 break;
4119 case 2:
4120 check_insn(ctx, ASE_MT);
4121 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4122 rn = "VPEConf0";
4123 break;
4124 case 3:
4125 check_insn(ctx, ASE_MT);
4126 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4127 rn = "VPEConf1";
4128 break;
4129 case 4:
4130 check_insn(ctx, ASE_MT);
4131 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
4132 rn = "YQMask";
4133 break;
4134 case 5:
4135 check_insn(ctx, ASE_MT);
4136 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4137 rn = "VPESchedule";
4138 break;
4139 case 6:
4140 check_insn(ctx, ASE_MT);
4141 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4142 rn = "VPEScheFBack";
4143 break;
4144 case 7:
4145 check_insn(ctx, ASE_MT);
4146 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4147 rn = "VPEOpt";
4148 break;
4149 default:
4150 goto die;
4152 break;
4153 case 2:
4154 switch (sel) {
4155 case 0:
4156 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4157 tcg_gen_ext32s_tl(arg, arg);
4158 rn = "EntryLo0";
4159 break;
4160 case 1:
4161 check_insn(ctx, ASE_MT);
4162 gen_helper_mfc0_tcstatus(arg, cpu_env);
4163 rn = "TCStatus";
4164 break;
4165 case 2:
4166 check_insn(ctx, ASE_MT);
4167 gen_helper_mfc0_tcbind(arg, cpu_env);
4168 rn = "TCBind";
4169 break;
4170 case 3:
4171 check_insn(ctx, ASE_MT);
4172 gen_helper_mfc0_tcrestart(arg, cpu_env);
4173 rn = "TCRestart";
4174 break;
4175 case 4:
4176 check_insn(ctx, ASE_MT);
4177 gen_helper_mfc0_tchalt(arg, cpu_env);
4178 rn = "TCHalt";
4179 break;
4180 case 5:
4181 check_insn(ctx, ASE_MT);
4182 gen_helper_mfc0_tccontext(arg, cpu_env);
4183 rn = "TCContext";
4184 break;
4185 case 6:
4186 check_insn(ctx, ASE_MT);
4187 gen_helper_mfc0_tcschedule(arg, cpu_env);
4188 rn = "TCSchedule";
4189 break;
4190 case 7:
4191 check_insn(ctx, ASE_MT);
4192 gen_helper_mfc0_tcschefback(arg, cpu_env);
4193 rn = "TCScheFBack";
4194 break;
4195 default:
4196 goto die;
4198 break;
4199 case 3:
4200 switch (sel) {
4201 case 0:
4202 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4203 tcg_gen_ext32s_tl(arg, arg);
4204 rn = "EntryLo1";
4205 break;
4206 default:
4207 goto die;
4209 break;
4210 case 4:
4211 switch (sel) {
4212 case 0:
4213 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
4214 tcg_gen_ext32s_tl(arg, arg);
4215 rn = "Context";
4216 break;
4217 case 1:
4218 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
4219 rn = "ContextConfig";
4220 goto die;
4221 // break;
4222 case 2:
4223 if (ctx->ulri) {
4224 tcg_gen_ld32s_tl(arg, cpu_env,
4225 offsetof(CPUMIPSState,
4226 active_tc.CP0_UserLocal));
4227 rn = "UserLocal";
4228 } else {
4229 tcg_gen_movi_tl(arg, 0);
4231 break;
4232 default:
4233 goto die;
4235 break;
4236 case 5:
4237 switch (sel) {
4238 case 0:
4239 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
4240 rn = "PageMask";
4241 break;
4242 case 1:
4243 check_insn(ctx, ISA_MIPS32R2);
4244 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
4245 rn = "PageGrain";
4246 break;
4247 default:
4248 goto die;
4250 break;
4251 case 6:
4252 switch (sel) {
4253 case 0:
4254 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
4255 rn = "Wired";
4256 break;
4257 case 1:
4258 check_insn(ctx, ISA_MIPS32R2);
4259 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
4260 rn = "SRSConf0";
4261 break;
4262 case 2:
4263 check_insn(ctx, ISA_MIPS32R2);
4264 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
4265 rn = "SRSConf1";
4266 break;
4267 case 3:
4268 check_insn(ctx, ISA_MIPS32R2);
4269 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
4270 rn = "SRSConf2";
4271 break;
4272 case 4:
4273 check_insn(ctx, ISA_MIPS32R2);
4274 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
4275 rn = "SRSConf3";
4276 break;
4277 case 5:
4278 check_insn(ctx, ISA_MIPS32R2);
4279 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
4280 rn = "SRSConf4";
4281 break;
4282 default:
4283 goto die;
4285 break;
4286 case 7:
4287 switch (sel) {
4288 case 0:
4289 check_insn(ctx, ISA_MIPS32R2);
4290 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
4291 rn = "HWREna";
4292 break;
4293 default:
4294 goto die;
4296 break;
4297 case 8:
4298 switch (sel) {
4299 case 0:
4300 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
4301 tcg_gen_ext32s_tl(arg, arg);
4302 rn = "BadVAddr";
4303 break;
4304 default:
4305 goto die;
4307 break;
4308 case 9:
4309 switch (sel) {
4310 case 0:
4311 /* Mark as an IO operation because we read the time. */
4312 if (use_icount)
4313 gen_io_start();
4314 gen_helper_mfc0_count(arg, cpu_env);
4315 if (use_icount) {
4316 gen_io_end();
4318 /* Break the TB to be able to take timer interrupts immediately
4319 after reading count. */
4320 ctx->bstate = BS_STOP;
4321 rn = "Count";
4322 break;
4323 /* 6,7 are implementation dependent */
4324 default:
4325 goto die;
4327 break;
4328 case 10:
4329 switch (sel) {
4330 case 0:
4331 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
4332 tcg_gen_ext32s_tl(arg, arg);
4333 rn = "EntryHi";
4334 break;
4335 default:
4336 goto die;
4338 break;
4339 case 11:
4340 switch (sel) {
4341 case 0:
4342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
4343 rn = "Compare";
4344 break;
4345 /* 6,7 are implementation dependent */
4346 default:
4347 goto die;
4349 break;
4350 case 12:
4351 switch (sel) {
4352 case 0:
4353 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
4354 rn = "Status";
4355 break;
4356 case 1:
4357 check_insn(ctx, ISA_MIPS32R2);
4358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
4359 rn = "IntCtl";
4360 break;
4361 case 2:
4362 check_insn(ctx, ISA_MIPS32R2);
4363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
4364 rn = "SRSCtl";
4365 break;
4366 case 3:
4367 check_insn(ctx, ISA_MIPS32R2);
4368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4369 rn = "SRSMap";
4370 break;
4371 default:
4372 goto die;
4374 break;
4375 case 13:
4376 switch (sel) {
4377 case 0:
4378 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
4379 rn = "Cause";
4380 break;
4381 default:
4382 goto die;
4384 break;
4385 case 14:
4386 switch (sel) {
4387 case 0:
4388 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
4389 tcg_gen_ext32s_tl(arg, arg);
4390 rn = "EPC";
4391 break;
4392 default:
4393 goto die;
4395 break;
4396 case 15:
4397 switch (sel) {
4398 case 0:
4399 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
4400 rn = "PRid";
4401 break;
4402 case 1:
4403 check_insn(ctx, ISA_MIPS32R2);
4404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
4405 rn = "EBase";
4406 break;
4407 default:
4408 goto die;
4410 break;
4411 case 16:
4412 switch (sel) {
4413 case 0:
4414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
4415 rn = "Config";
4416 break;
4417 case 1:
4418 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
4419 rn = "Config1";
4420 break;
4421 case 2:
4422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
4423 rn = "Config2";
4424 break;
4425 case 3:
4426 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
4427 rn = "Config3";
4428 break;
4429 case 4:
4430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
4431 rn = "Config4";
4432 break;
4433 case 5:
4434 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
4435 rn = "Config5";
4436 break;
4437 /* 6,7 are implementation dependent */
4438 case 6:
4439 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
4440 rn = "Config6";
4441 break;
4442 case 7:
4443 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
4444 rn = "Config7";
4445 break;
4446 default:
4447 goto die;
4449 break;
4450 case 17:
4451 switch (sel) {
4452 case 0:
4453 gen_helper_mfc0_lladdr(arg, cpu_env);
4454 rn = "LLAddr";
4455 break;
4456 default:
4457 goto die;
4459 break;
4460 case 18:
4461 switch (sel) {
4462 case 0 ... 7:
4463 gen_helper_1e0i(mfc0_watchlo, arg, sel);
4464 rn = "WatchLo";
4465 break;
4466 default:
4467 goto die;
4469 break;
4470 case 19:
4471 switch (sel) {
4472 case 0 ...7:
4473 gen_helper_1e0i(mfc0_watchhi, arg, sel);
4474 rn = "WatchHi";
4475 break;
4476 default:
4477 goto die;
4479 break;
4480 case 20:
4481 switch (sel) {
4482 case 0:
4483 #if defined(TARGET_MIPS64)
4484 check_insn(ctx, ISA_MIPS3);
4485 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
4486 tcg_gen_ext32s_tl(arg, arg);
4487 rn = "XContext";
4488 break;
4489 #endif
4490 default:
4491 goto die;
4493 break;
4494 case 21:
4495 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4496 switch (sel) {
4497 case 0:
4498 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
4499 rn = "Framemask";
4500 break;
4501 default:
4502 goto die;
4504 break;
4505 case 22:
4506 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4507 rn = "'Diagnostic"; /* implementation dependent */
4508 break;
4509 case 23:
4510 switch (sel) {
4511 case 0:
4512 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
4513 rn = "Debug";
4514 break;
4515 case 1:
4516 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
4517 rn = "TraceControl";
4518 // break;
4519 case 2:
4520 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
4521 rn = "TraceControl2";
4522 // break;
4523 case 3:
4524 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
4525 rn = "UserTraceData";
4526 // break;
4527 case 4:
4528 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
4529 rn = "TraceBPC";
4530 // break;
4531 default:
4532 goto die;
4534 break;
4535 case 24:
4536 switch (sel) {
4537 case 0:
4538 /* EJTAG support */
4539 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
4540 tcg_gen_ext32s_tl(arg, arg);
4541 rn = "DEPC";
4542 break;
4543 default:
4544 goto die;
4546 break;
4547 case 25:
4548 switch (sel) {
4549 case 0:
4550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
4551 rn = "Performance0";
4552 break;
4553 case 1:
4554 // gen_helper_mfc0_performance1(arg);
4555 rn = "Performance1";
4556 // break;
4557 case 2:
4558 // gen_helper_mfc0_performance2(arg);
4559 rn = "Performance2";
4560 // break;
4561 case 3:
4562 // gen_helper_mfc0_performance3(arg);
4563 rn = "Performance3";
4564 // break;
4565 case 4:
4566 // gen_helper_mfc0_performance4(arg);
4567 rn = "Performance4";
4568 // break;
4569 case 5:
4570 // gen_helper_mfc0_performance5(arg);
4571 rn = "Performance5";
4572 // break;
4573 case 6:
4574 // gen_helper_mfc0_performance6(arg);
4575 rn = "Performance6";
4576 // break;
4577 case 7:
4578 // gen_helper_mfc0_performance7(arg);
4579 rn = "Performance7";
4580 // break;
4581 default:
4582 goto die;
4584 break;
4585 case 26:
4586 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4587 rn = "ECC";
4588 break;
4589 case 27:
4590 switch (sel) {
4591 case 0 ... 3:
4592 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4593 rn = "CacheErr";
4594 break;
4595 default:
4596 goto die;
4598 break;
4599 case 28:
4600 switch (sel) {
4601 case 0:
4602 case 2:
4603 case 4:
4604 case 6:
4605 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
4606 rn = "TagLo";
4607 break;
4608 case 1:
4609 case 3:
4610 case 5:
4611 case 7:
4612 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
4613 rn = "DataLo";
4614 break;
4615 default:
4616 goto die;
4618 break;
4619 case 29:
4620 switch (sel) {
4621 case 0:
4622 case 2:
4623 case 4:
4624 case 6:
4625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
4626 rn = "TagHi";
4627 break;
4628 case 1:
4629 case 3:
4630 case 5:
4631 case 7:
4632 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
4633 rn = "DataHi";
4634 break;
4635 default:
4636 goto die;
4638 break;
4639 case 30:
4640 switch (sel) {
4641 case 0:
4642 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
4643 tcg_gen_ext32s_tl(arg, arg);
4644 rn = "ErrorEPC";
4645 break;
4646 default:
4647 goto die;
4649 break;
4650 case 31:
4651 switch (sel) {
4652 case 0:
4653 /* EJTAG support */
4654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4655 rn = "DESAVE";
4656 break;
4657 default:
4658 goto die;
4660 break;
4661 default:
4662 goto die;
4664 (void)rn; /* avoid a compiler warning */
4665 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4666 return;
4668 die:
4669 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4670 generate_exception(ctx, EXCP_RI);
4673 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4675 const char *rn = "invalid";
4677 if (sel != 0)
4678 check_insn(ctx, ISA_MIPS32);
4680 if (use_icount)
4681 gen_io_start();
4683 switch (reg) {
4684 case 0:
4685 switch (sel) {
4686 case 0:
4687 gen_helper_mtc0_index(cpu_env, arg);
4688 rn = "Index";
4689 break;
4690 case 1:
4691 check_insn(ctx, ASE_MT);
4692 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
4693 rn = "MVPControl";
4694 break;
4695 case 2:
4696 check_insn(ctx, ASE_MT);
4697 /* ignored */
4698 rn = "MVPConf0";
4699 break;
4700 case 3:
4701 check_insn(ctx, ASE_MT);
4702 /* ignored */
4703 rn = "MVPConf1";
4704 break;
4705 default:
4706 goto die;
4708 break;
4709 case 1:
4710 switch (sel) {
4711 case 0:
4712 /* ignored */
4713 rn = "Random";
4714 break;
4715 case 1:
4716 check_insn(ctx, ASE_MT);
4717 gen_helper_mtc0_vpecontrol(cpu_env, arg);
4718 rn = "VPEControl";
4719 break;
4720 case 2:
4721 check_insn(ctx, ASE_MT);
4722 gen_helper_mtc0_vpeconf0(cpu_env, arg);
4723 rn = "VPEConf0";
4724 break;
4725 case 3:
4726 check_insn(ctx, ASE_MT);
4727 gen_helper_mtc0_vpeconf1(cpu_env, arg);
4728 rn = "VPEConf1";
4729 break;
4730 case 4:
4731 check_insn(ctx, ASE_MT);
4732 gen_helper_mtc0_yqmask(cpu_env, arg);
4733 rn = "YQMask";
4734 break;
4735 case 5:
4736 check_insn(ctx, ASE_MT);
4737 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
4738 rn = "VPESchedule";
4739 break;
4740 case 6:
4741 check_insn(ctx, ASE_MT);
4742 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4743 rn = "VPEScheFBack";
4744 break;
4745 case 7:
4746 check_insn(ctx, ASE_MT);
4747 gen_helper_mtc0_vpeopt(cpu_env, arg);
4748 rn = "VPEOpt";
4749 break;
4750 default:
4751 goto die;
4753 break;
4754 case 2:
4755 switch (sel) {
4756 case 0:
4757 gen_helper_mtc0_entrylo0(cpu_env, arg);
4758 rn = "EntryLo0";
4759 break;
4760 case 1:
4761 check_insn(ctx, ASE_MT);
4762 gen_helper_mtc0_tcstatus(cpu_env, arg);
4763 rn = "TCStatus";
4764 break;
4765 case 2:
4766 check_insn(ctx, ASE_MT);
4767 gen_helper_mtc0_tcbind(cpu_env, arg);
4768 rn = "TCBind";
4769 break;
4770 case 3:
4771 check_insn(ctx, ASE_MT);
4772 gen_helper_mtc0_tcrestart(cpu_env, arg);
4773 rn = "TCRestart";
4774 break;
4775 case 4:
4776 check_insn(ctx, ASE_MT);
4777 gen_helper_mtc0_tchalt(cpu_env, arg);
4778 rn = "TCHalt";
4779 break;
4780 case 5:
4781 check_insn(ctx, ASE_MT);
4782 gen_helper_mtc0_tccontext(cpu_env, arg);
4783 rn = "TCContext";
4784 break;
4785 case 6:
4786 check_insn(ctx, ASE_MT);
4787 gen_helper_mtc0_tcschedule(cpu_env, arg);
4788 rn = "TCSchedule";
4789 break;
4790 case 7:
4791 check_insn(ctx, ASE_MT);
4792 gen_helper_mtc0_tcschefback(cpu_env, arg);
4793 rn = "TCScheFBack";
4794 break;
4795 default:
4796 goto die;
4798 break;
4799 case 3:
4800 switch (sel) {
4801 case 0:
4802 gen_helper_mtc0_entrylo1(cpu_env, arg);
4803 rn = "EntryLo1";
4804 break;
4805 default:
4806 goto die;
4808 break;
4809 case 4:
4810 switch (sel) {
4811 case 0:
4812 gen_helper_mtc0_context(cpu_env, arg);
4813 rn = "Context";
4814 break;
4815 case 1:
4816 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
4817 rn = "ContextConfig";
4818 goto die;
4819 // break;
4820 case 2:
4821 if (ctx->ulri) {
4822 tcg_gen_st_tl(arg, cpu_env,
4823 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
4824 rn = "UserLocal";
4826 break;
4827 default:
4828 goto die;
4830 break;
4831 case 5:
4832 switch (sel) {
4833 case 0:
4834 gen_helper_mtc0_pagemask(cpu_env, arg);
4835 rn = "PageMask";
4836 break;
4837 case 1:
4838 check_insn(ctx, ISA_MIPS32R2);
4839 gen_helper_mtc0_pagegrain(cpu_env, arg);
4840 rn = "PageGrain";
4841 break;
4842 default:
4843 goto die;
4845 break;
4846 case 6:
4847 switch (sel) {
4848 case 0:
4849 gen_helper_mtc0_wired(cpu_env, arg);
4850 rn = "Wired";
4851 break;
4852 case 1:
4853 check_insn(ctx, ISA_MIPS32R2);
4854 gen_helper_mtc0_srsconf0(cpu_env, arg);
4855 rn = "SRSConf0";
4856 break;
4857 case 2:
4858 check_insn(ctx, ISA_MIPS32R2);
4859 gen_helper_mtc0_srsconf1(cpu_env, arg);
4860 rn = "SRSConf1";
4861 break;
4862 case 3:
4863 check_insn(ctx, ISA_MIPS32R2);
4864 gen_helper_mtc0_srsconf2(cpu_env, arg);
4865 rn = "SRSConf2";
4866 break;
4867 case 4:
4868 check_insn(ctx, ISA_MIPS32R2);
4869 gen_helper_mtc0_srsconf3(cpu_env, arg);
4870 rn = "SRSConf3";
4871 break;
4872 case 5:
4873 check_insn(ctx, ISA_MIPS32R2);
4874 gen_helper_mtc0_srsconf4(cpu_env, arg);
4875 rn = "SRSConf4";
4876 break;
4877 default:
4878 goto die;
4880 break;
4881 case 7:
4882 switch (sel) {
4883 case 0:
4884 check_insn(ctx, ISA_MIPS32R2);
4885 gen_helper_mtc0_hwrena(cpu_env, arg);
4886 ctx->bstate = BS_STOP;
4887 rn = "HWREna";
4888 break;
4889 default:
4890 goto die;
4892 break;
4893 case 8:
4894 /* ignored */
4895 rn = "BadVAddr";
4896 break;
4897 case 9:
4898 switch (sel) {
4899 case 0:
4900 gen_helper_mtc0_count(cpu_env, arg);
4901 rn = "Count";
4902 break;
4903 /* 6,7 are implementation dependent */
4904 default:
4905 goto die;
4907 break;
4908 case 10:
4909 switch (sel) {
4910 case 0:
4911 gen_helper_mtc0_entryhi(cpu_env, arg);
4912 rn = "EntryHi";
4913 break;
4914 default:
4915 goto die;
4917 break;
4918 case 11:
4919 switch (sel) {
4920 case 0:
4921 gen_helper_mtc0_compare(cpu_env, arg);
4922 rn = "Compare";
4923 break;
4924 /* 6,7 are implementation dependent */
4925 default:
4926 goto die;
4928 break;
4929 case 12:
4930 switch (sel) {
4931 case 0:
4932 save_cpu_state(ctx, 1);
4933 gen_helper_mtc0_status(cpu_env, arg);
4934 /* BS_STOP isn't good enough here, hflags may have changed. */
4935 gen_save_pc(ctx->pc + 4);
4936 ctx->bstate = BS_EXCP;
4937 rn = "Status";
4938 break;
4939 case 1:
4940 check_insn(ctx, ISA_MIPS32R2);
4941 gen_helper_mtc0_intctl(cpu_env, arg);
4942 /* Stop translation as we may have switched the execution mode */
4943 ctx->bstate = BS_STOP;
4944 rn = "IntCtl";
4945 break;
4946 case 2:
4947 check_insn(ctx, ISA_MIPS32R2);
4948 gen_helper_mtc0_srsctl(cpu_env, arg);
4949 /* Stop translation as we may have switched the execution mode */
4950 ctx->bstate = BS_STOP;
4951 rn = "SRSCtl";
4952 break;
4953 case 3:
4954 check_insn(ctx, ISA_MIPS32R2);
4955 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4956 /* Stop translation as we may have switched the execution mode */
4957 ctx->bstate = BS_STOP;
4958 rn = "SRSMap";
4959 break;
4960 default:
4961 goto die;
4963 break;
4964 case 13:
4965 switch (sel) {
4966 case 0:
4967 save_cpu_state(ctx, 1);
4968 gen_helper_mtc0_cause(cpu_env, arg);
4969 rn = "Cause";
4970 break;
4971 default:
4972 goto die;
4974 break;
4975 case 14:
4976 switch (sel) {
4977 case 0:
4978 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
4979 rn = "EPC";
4980 break;
4981 default:
4982 goto die;
4984 break;
4985 case 15:
4986 switch (sel) {
4987 case 0:
4988 /* ignored */
4989 rn = "PRid";
4990 break;
4991 case 1:
4992 check_insn(ctx, ISA_MIPS32R2);
4993 gen_helper_mtc0_ebase(cpu_env, arg);
4994 rn = "EBase";
4995 break;
4996 default:
4997 goto die;
4999 break;
5000 case 16:
5001 switch (sel) {
5002 case 0:
5003 gen_helper_mtc0_config0(cpu_env, arg);
5004 rn = "Config";
5005 /* Stop translation as we may have switched the execution mode */
5006 ctx->bstate = BS_STOP;
5007 break;
5008 case 1:
5009 /* ignored, read only */
5010 rn = "Config1";
5011 break;
5012 case 2:
5013 gen_helper_mtc0_config2(cpu_env, arg);
5014 rn = "Config2";
5015 /* Stop translation as we may have switched the execution mode */
5016 ctx->bstate = BS_STOP;
5017 break;
5018 case 3:
5019 /* ignored, read only */
5020 rn = "Config3";
5021 break;
5022 case 4:
5023 gen_helper_mtc0_config4(cpu_env, arg);
5024 rn = "Config4";
5025 ctx->bstate = BS_STOP;
5026 break;
5027 case 5:
5028 gen_helper_mtc0_config5(cpu_env, arg);
5029 rn = "Config5";
5030 /* Stop translation as we may have switched the execution mode */
5031 ctx->bstate = BS_STOP;
5032 break;
5033 /* 6,7 are implementation dependent */
5034 case 6:
5035 /* ignored */
5036 rn = "Config6";
5037 break;
5038 case 7:
5039 /* ignored */
5040 rn = "Config7";
5041 break;
5042 default:
5043 rn = "Invalid config selector";
5044 goto die;
5046 break;
5047 case 17:
5048 switch (sel) {
5049 case 0:
5050 gen_helper_mtc0_lladdr(cpu_env, arg);
5051 rn = "LLAddr";
5052 break;
5053 default:
5054 goto die;
5056 break;
5057 case 18:
5058 switch (sel) {
5059 case 0 ... 7:
5060 gen_helper_0e1i(mtc0_watchlo, arg, sel);
5061 rn = "WatchLo";
5062 break;
5063 default:
5064 goto die;
5066 break;
5067 case 19:
5068 switch (sel) {
5069 case 0 ... 7:
5070 gen_helper_0e1i(mtc0_watchhi, arg, sel);
5071 rn = "WatchHi";
5072 break;
5073 default:
5074 goto die;
5076 break;
5077 case 20:
5078 switch (sel) {
5079 case 0:
5080 #if defined(TARGET_MIPS64)
5081 check_insn(ctx, ISA_MIPS3);
5082 gen_helper_mtc0_xcontext(cpu_env, arg);
5083 rn = "XContext";
5084 break;
5085 #endif
5086 default:
5087 goto die;
5089 break;
5090 case 21:
5091 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5092 switch (sel) {
5093 case 0:
5094 gen_helper_mtc0_framemask(cpu_env, arg);
5095 rn = "Framemask";
5096 break;
5097 default:
5098 goto die;
5100 break;
5101 case 22:
5102 /* ignored */
5103 rn = "Diagnostic"; /* implementation dependent */
5104 break;
5105 case 23:
5106 switch (sel) {
5107 case 0:
5108 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
5109 /* BS_STOP isn't good enough here, hflags may have changed. */
5110 gen_save_pc(ctx->pc + 4);
5111 ctx->bstate = BS_EXCP;
5112 rn = "Debug";
5113 break;
5114 case 1:
5115 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
5116 rn = "TraceControl";
5117 /* Stop translation as we may have switched the execution mode */
5118 ctx->bstate = BS_STOP;
5119 // break;
5120 case 2:
5121 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
5122 rn = "TraceControl2";
5123 /* Stop translation as we may have switched the execution mode */
5124 ctx->bstate = BS_STOP;
5125 // break;
5126 case 3:
5127 /* Stop translation as we may have switched the execution mode */
5128 ctx->bstate = BS_STOP;
5129 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
5130 rn = "UserTraceData";
5131 /* Stop translation as we may have switched the execution mode */
5132 ctx->bstate = BS_STOP;
5133 // break;
5134 case 4:
5135 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
5136 /* Stop translation as we may have switched the execution mode */
5137 ctx->bstate = BS_STOP;
5138 rn = "TraceBPC";
5139 // break;
5140 default:
5141 goto die;
5143 break;
5144 case 24:
5145 switch (sel) {
5146 case 0:
5147 /* EJTAG support */
5148 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
5149 rn = "DEPC";
5150 break;
5151 default:
5152 goto die;
5154 break;
5155 case 25:
5156 switch (sel) {
5157 case 0:
5158 gen_helper_mtc0_performance0(cpu_env, arg);
5159 rn = "Performance0";
5160 break;
5161 case 1:
5162 // gen_helper_mtc0_performance1(arg);
5163 rn = "Performance1";
5164 // break;
5165 case 2:
5166 // gen_helper_mtc0_performance2(arg);
5167 rn = "Performance2";
5168 // break;
5169 case 3:
5170 // gen_helper_mtc0_performance3(arg);
5171 rn = "Performance3";
5172 // break;
5173 case 4:
5174 // gen_helper_mtc0_performance4(arg);
5175 rn = "Performance4";
5176 // break;
5177 case 5:
5178 // gen_helper_mtc0_performance5(arg);
5179 rn = "Performance5";
5180 // break;
5181 case 6:
5182 // gen_helper_mtc0_performance6(arg);
5183 rn = "Performance6";
5184 // break;
5185 case 7:
5186 // gen_helper_mtc0_performance7(arg);
5187 rn = "Performance7";
5188 // break;
5189 default:
5190 goto die;
5192 break;
5193 case 26:
5194 /* ignored */
5195 rn = "ECC";
5196 break;
5197 case 27:
5198 switch (sel) {
5199 case 0 ... 3:
5200 /* ignored */
5201 rn = "CacheErr";
5202 break;
5203 default:
5204 goto die;
5206 break;
5207 case 28:
5208 switch (sel) {
5209 case 0:
5210 case 2:
5211 case 4:
5212 case 6:
5213 gen_helper_mtc0_taglo(cpu_env, arg);
5214 rn = "TagLo";
5215 break;
5216 case 1:
5217 case 3:
5218 case 5:
5219 case 7:
5220 gen_helper_mtc0_datalo(cpu_env, arg);
5221 rn = "DataLo";
5222 break;
5223 default:
5224 goto die;
5226 break;
5227 case 29:
5228 switch (sel) {
5229 case 0:
5230 case 2:
5231 case 4:
5232 case 6:
5233 gen_helper_mtc0_taghi(cpu_env, arg);
5234 rn = "TagHi";
5235 break;
5236 case 1:
5237 case 3:
5238 case 5:
5239 case 7:
5240 gen_helper_mtc0_datahi(cpu_env, arg);
5241 rn = "DataHi";
5242 break;
5243 default:
5244 rn = "invalid sel";
5245 goto die;
5247 break;
5248 case 30:
5249 switch (sel) {
5250 case 0:
5251 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
5252 rn = "ErrorEPC";
5253 break;
5254 default:
5255 goto die;
5257 break;
5258 case 31:
5259 switch (sel) {
5260 case 0:
5261 /* EJTAG support */
5262 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5263 rn = "DESAVE";
5264 break;
5265 default:
5266 goto die;
5268 /* Stop translation as we may have switched the execution mode */
5269 ctx->bstate = BS_STOP;
5270 break;
5271 default:
5272 goto die;
5274 (void)rn; /* avoid a compiler warning */
5275 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5276 /* For simplicity assume that all writes can cause interrupts. */
5277 if (use_icount) {
5278 gen_io_end();
5279 ctx->bstate = BS_STOP;
5281 return;
5283 die:
5284 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5285 generate_exception(ctx, EXCP_RI);
5288 #if defined(TARGET_MIPS64)
5289 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5291 const char *rn = "invalid";
5293 if (sel != 0)
5294 check_insn(ctx, ISA_MIPS64);
5296 switch (reg) {
5297 case 0:
5298 switch (sel) {
5299 case 0:
5300 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5301 rn = "Index";
5302 break;
5303 case 1:
5304 check_insn(ctx, ASE_MT);
5305 gen_helper_mfc0_mvpcontrol(arg, cpu_env);
5306 rn = "MVPControl";
5307 break;
5308 case 2:
5309 check_insn(ctx, ASE_MT);
5310 gen_helper_mfc0_mvpconf0(arg, cpu_env);
5311 rn = "MVPConf0";
5312 break;
5313 case 3:
5314 check_insn(ctx, ASE_MT);
5315 gen_helper_mfc0_mvpconf1(arg, cpu_env);
5316 rn = "MVPConf1";
5317 break;
5318 default:
5319 goto die;
5321 break;
5322 case 1:
5323 switch (sel) {
5324 case 0:
5325 gen_helper_mfc0_random(arg, cpu_env);
5326 rn = "Random";
5327 break;
5328 case 1:
5329 check_insn(ctx, ASE_MT);
5330 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5331 rn = "VPEControl";
5332 break;
5333 case 2:
5334 check_insn(ctx, ASE_MT);
5335 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5336 rn = "VPEConf0";
5337 break;
5338 case 3:
5339 check_insn(ctx, ASE_MT);
5340 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5341 rn = "VPEConf1";
5342 break;
5343 case 4:
5344 check_insn(ctx, ASE_MT);
5345 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
5346 rn = "YQMask";
5347 break;
5348 case 5:
5349 check_insn(ctx, ASE_MT);
5350 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5351 rn = "VPESchedule";
5352 break;
5353 case 6:
5354 check_insn(ctx, ASE_MT);
5355 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5356 rn = "VPEScheFBack";
5357 break;
5358 case 7:
5359 check_insn(ctx, ASE_MT);
5360 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5361 rn = "VPEOpt";
5362 break;
5363 default:
5364 goto die;
5366 break;
5367 case 2:
5368 switch (sel) {
5369 case 0:
5370 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
5371 rn = "EntryLo0";
5372 break;
5373 case 1:
5374 check_insn(ctx, ASE_MT);
5375 gen_helper_mfc0_tcstatus(arg, cpu_env);
5376 rn = "TCStatus";
5377 break;
5378 case 2:
5379 check_insn(ctx, ASE_MT);
5380 gen_helper_mfc0_tcbind(arg, cpu_env);
5381 rn = "TCBind";
5382 break;
5383 case 3:
5384 check_insn(ctx, ASE_MT);
5385 gen_helper_dmfc0_tcrestart(arg, cpu_env);
5386 rn = "TCRestart";
5387 break;
5388 case 4:
5389 check_insn(ctx, ASE_MT);
5390 gen_helper_dmfc0_tchalt(arg, cpu_env);
5391 rn = "TCHalt";
5392 break;
5393 case 5:
5394 check_insn(ctx, ASE_MT);
5395 gen_helper_dmfc0_tccontext(arg, cpu_env);
5396 rn = "TCContext";
5397 break;
5398 case 6:
5399 check_insn(ctx, ASE_MT);
5400 gen_helper_dmfc0_tcschedule(arg, cpu_env);
5401 rn = "TCSchedule";
5402 break;
5403 case 7:
5404 check_insn(ctx, ASE_MT);
5405 gen_helper_dmfc0_tcschefback(arg, cpu_env);
5406 rn = "TCScheFBack";
5407 break;
5408 default:
5409 goto die;
5411 break;
5412 case 3:
5413 switch (sel) {
5414 case 0:
5415 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
5416 rn = "EntryLo1";
5417 break;
5418 default:
5419 goto die;
5421 break;
5422 case 4:
5423 switch (sel) {
5424 case 0:
5425 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
5426 rn = "Context";
5427 break;
5428 case 1:
5429 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
5430 rn = "ContextConfig";
5431 goto die;
5432 // break;
5433 case 2:
5434 if (ctx->ulri) {
5435 tcg_gen_ld_tl(arg, cpu_env,
5436 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5437 rn = "UserLocal";
5438 } else {
5439 tcg_gen_movi_tl(arg, 0);
5441 break;
5442 default:
5443 goto die;
5445 break;
5446 case 5:
5447 switch (sel) {
5448 case 0:
5449 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5450 rn = "PageMask";
5451 break;
5452 case 1:
5453 check_insn(ctx, ISA_MIPS32R2);
5454 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5455 rn = "PageGrain";
5456 break;
5457 default:
5458 goto die;
5460 break;
5461 case 6:
5462 switch (sel) {
5463 case 0:
5464 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5465 rn = "Wired";
5466 break;
5467 case 1:
5468 check_insn(ctx, ISA_MIPS32R2);
5469 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5470 rn = "SRSConf0";
5471 break;
5472 case 2:
5473 check_insn(ctx, ISA_MIPS32R2);
5474 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5475 rn = "SRSConf1";
5476 break;
5477 case 3:
5478 check_insn(ctx, ISA_MIPS32R2);
5479 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5480 rn = "SRSConf2";
5481 break;
5482 case 4:
5483 check_insn(ctx, ISA_MIPS32R2);
5484 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5485 rn = "SRSConf3";
5486 break;
5487 case 5:
5488 check_insn(ctx, ISA_MIPS32R2);
5489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5490 rn = "SRSConf4";
5491 break;
5492 default:
5493 goto die;
5495 break;
5496 case 7:
5497 switch (sel) {
5498 case 0:
5499 check_insn(ctx, ISA_MIPS32R2);
5500 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5501 rn = "HWREna";
5502 break;
5503 default:
5504 goto die;
5506 break;
5507 case 8:
5508 switch (sel) {
5509 case 0:
5510 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5511 rn = "BadVAddr";
5512 break;
5513 default:
5514 goto die;
5516 break;
5517 case 9:
5518 switch (sel) {
5519 case 0:
5520 /* Mark as an IO operation because we read the time. */
5521 if (use_icount)
5522 gen_io_start();
5523 gen_helper_mfc0_count(arg, cpu_env);
5524 if (use_icount) {
5525 gen_io_end();
5527 /* Break the TB to be able to take timer interrupts immediately
5528 after reading count. */
5529 ctx->bstate = BS_STOP;
5530 rn = "Count";
5531 break;
5532 /* 6,7 are implementation dependent */
5533 default:
5534 goto die;
5536 break;
5537 case 10:
5538 switch (sel) {
5539 case 0:
5540 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
5541 rn = "EntryHi";
5542 break;
5543 default:
5544 goto die;
5546 break;
5547 case 11:
5548 switch (sel) {
5549 case 0:
5550 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5551 rn = "Compare";
5552 break;
5553 /* 6,7 are implementation dependent */
5554 default:
5555 goto die;
5557 break;
5558 case 12:
5559 switch (sel) {
5560 case 0:
5561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5562 rn = "Status";
5563 break;
5564 case 1:
5565 check_insn(ctx, ISA_MIPS32R2);
5566 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5567 rn = "IntCtl";
5568 break;
5569 case 2:
5570 check_insn(ctx, ISA_MIPS32R2);
5571 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5572 rn = "SRSCtl";
5573 break;
5574 case 3:
5575 check_insn(ctx, ISA_MIPS32R2);
5576 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5577 rn = "SRSMap";
5578 break;
5579 default:
5580 goto die;
5582 break;
5583 case 13:
5584 switch (sel) {
5585 case 0:
5586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5587 rn = "Cause";
5588 break;
5589 default:
5590 goto die;
5592 break;
5593 case 14:
5594 switch (sel) {
5595 case 0:
5596 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5597 rn = "EPC";
5598 break;
5599 default:
5600 goto die;
5602 break;
5603 case 15:
5604 switch (sel) {
5605 case 0:
5606 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5607 rn = "PRid";
5608 break;
5609 case 1:
5610 check_insn(ctx, ISA_MIPS32R2);
5611 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
5612 rn = "EBase";
5613 break;
5614 default:
5615 goto die;
5617 break;
5618 case 16:
5619 switch (sel) {
5620 case 0:
5621 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5622 rn = "Config";
5623 break;
5624 case 1:
5625 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5626 rn = "Config1";
5627 break;
5628 case 2:
5629 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5630 rn = "Config2";
5631 break;
5632 case 3:
5633 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5634 rn = "Config3";
5635 break;
5636 /* 6,7 are implementation dependent */
5637 case 6:
5638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5639 rn = "Config6";
5640 break;
5641 case 7:
5642 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5643 rn = "Config7";
5644 break;
5645 default:
5646 goto die;
5648 break;
5649 case 17:
5650 switch (sel) {
5651 case 0:
5652 gen_helper_dmfc0_lladdr(arg, cpu_env);
5653 rn = "LLAddr";
5654 break;
5655 default:
5656 goto die;
5658 break;
5659 case 18:
5660 switch (sel) {
5661 case 0 ... 7:
5662 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
5663 rn = "WatchLo";
5664 break;
5665 default:
5666 goto die;
5668 break;
5669 case 19:
5670 switch (sel) {
5671 case 0 ... 7:
5672 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5673 rn = "WatchHi";
5674 break;
5675 default:
5676 goto die;
5678 break;
5679 case 20:
5680 switch (sel) {
5681 case 0:
5682 check_insn(ctx, ISA_MIPS3);
5683 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
5684 rn = "XContext";
5685 break;
5686 default:
5687 goto die;
5689 break;
5690 case 21:
5691 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5692 switch (sel) {
5693 case 0:
5694 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5695 rn = "Framemask";
5696 break;
5697 default:
5698 goto die;
5700 break;
5701 case 22:
5702 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5703 rn = "'Diagnostic"; /* implementation dependent */
5704 break;
5705 case 23:
5706 switch (sel) {
5707 case 0:
5708 gen_helper_mfc0_debug(arg, cpu_env); /* EJTAG support */
5709 rn = "Debug";
5710 break;
5711 case 1:
5712 // gen_helper_dmfc0_tracecontrol(arg, cpu_env); /* PDtrace support */
5713 rn = "TraceControl";
5714 // break;
5715 case 2:
5716 // gen_helper_dmfc0_tracecontrol2(arg, cpu_env); /* PDtrace support */
5717 rn = "TraceControl2";
5718 // break;
5719 case 3:
5720 // gen_helper_dmfc0_usertracedata(arg, cpu_env); /* PDtrace support */
5721 rn = "UserTraceData";
5722 // break;
5723 case 4:
5724 // gen_helper_dmfc0_tracebpc(arg, cpu_env); /* PDtrace support */
5725 rn = "TraceBPC";
5726 // break;
5727 default:
5728 goto die;
5730 break;
5731 case 24:
5732 switch (sel) {
5733 case 0:
5734 /* EJTAG support */
5735 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5736 rn = "DEPC";
5737 break;
5738 default:
5739 goto die;
5741 break;
5742 case 25:
5743 switch (sel) {
5744 case 0:
5745 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5746 rn = "Performance0";
5747 break;
5748 case 1:
5749 // gen_helper_dmfc0_performance1(arg);
5750 rn = "Performance1";
5751 // break;
5752 case 2:
5753 // gen_helper_dmfc0_performance2(arg);
5754 rn = "Performance2";
5755 // break;
5756 case 3:
5757 // gen_helper_dmfc0_performance3(arg);
5758 rn = "Performance3";
5759 // break;
5760 case 4:
5761 // gen_helper_dmfc0_performance4(arg);
5762 rn = "Performance4";
5763 // break;
5764 case 5:
5765 // gen_helper_dmfc0_performance5(arg);
5766 rn = "Performance5";
5767 // break;
5768 case 6:
5769 // gen_helper_dmfc0_performance6(arg);
5770 rn = "Performance6";
5771 // break;
5772 case 7:
5773 // gen_helper_dmfc0_performance7(arg);
5774 rn = "Performance7";
5775 // break;
5776 default:
5777 goto die;
5779 break;
5780 case 26:
5781 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5782 rn = "ECC";
5783 break;
5784 case 27:
5785 switch (sel) {
5786 /* ignored */
5787 case 0 ... 3:
5788 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5789 rn = "CacheErr";
5790 break;
5791 default:
5792 goto die;
5794 break;
5795 case 28:
5796 switch (sel) {
5797 case 0:
5798 case 2:
5799 case 4:
5800 case 6:
5801 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
5802 rn = "TagLo";
5803 break;
5804 case 1:
5805 case 3:
5806 case 5:
5807 case 7:
5808 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5809 rn = "DataLo";
5810 break;
5811 default:
5812 goto die;
5814 break;
5815 case 29:
5816 switch (sel) {
5817 case 0:
5818 case 2:
5819 case 4:
5820 case 6:
5821 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5822 rn = "TagHi";
5823 break;
5824 case 1:
5825 case 3:
5826 case 5:
5827 case 7:
5828 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5829 rn = "DataHi";
5830 break;
5831 default:
5832 goto die;
5834 break;
5835 case 30:
5836 switch (sel) {
5837 case 0:
5838 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5839 rn = "ErrorEPC";
5840 break;
5841 default:
5842 goto die;
5844 break;
5845 case 31:
5846 switch (sel) {
5847 case 0:
5848 /* EJTAG support */
5849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5850 rn = "DESAVE";
5851 break;
5852 default:
5853 goto die;
5855 break;
5856 default:
5857 goto die;
5859 (void)rn; /* avoid a compiler warning */
5860 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5861 return;
5863 die:
5864 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
5865 generate_exception(ctx, EXCP_RI);
5868 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5870 const char *rn = "invalid";
5872 if (sel != 0)
5873 check_insn(ctx, ISA_MIPS64);
5875 if (use_icount)
5876 gen_io_start();
5878 switch (reg) {
5879 case 0:
5880 switch (sel) {
5881 case 0:
5882 gen_helper_mtc0_index(cpu_env, arg);
5883 rn = "Index";
5884 break;
5885 case 1:
5886 check_insn(ctx, ASE_MT);
5887 gen_helper_mtc0_mvpcontrol(cpu_env, arg);
5888 rn = "MVPControl";
5889 break;
5890 case 2:
5891 check_insn(ctx, ASE_MT);
5892 /* ignored */
5893 rn = "MVPConf0";
5894 break;
5895 case 3:
5896 check_insn(ctx, ASE_MT);
5897 /* ignored */
5898 rn = "MVPConf1";
5899 break;
5900 default:
5901 goto die;
5903 break;
5904 case 1:
5905 switch (sel) {
5906 case 0:
5907 /* ignored */
5908 rn = "Random";
5909 break;
5910 case 1:
5911 check_insn(ctx, ASE_MT);
5912 gen_helper_mtc0_vpecontrol(cpu_env, arg);
5913 rn = "VPEControl";
5914 break;
5915 case 2:
5916 check_insn(ctx, ASE_MT);
5917 gen_helper_mtc0_vpeconf0(cpu_env, arg);
5918 rn = "VPEConf0";
5919 break;
5920 case 3:
5921 check_insn(ctx, ASE_MT);
5922 gen_helper_mtc0_vpeconf1(cpu_env, arg);
5923 rn = "VPEConf1";
5924 break;
5925 case 4:
5926 check_insn(ctx, ASE_MT);
5927 gen_helper_mtc0_yqmask(cpu_env, arg);
5928 rn = "YQMask";
5929 break;
5930 case 5:
5931 check_insn(ctx, ASE_MT);
5932 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
5933 rn = "VPESchedule";
5934 break;
5935 case 6:
5936 check_insn(ctx, ASE_MT);
5937 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5938 rn = "VPEScheFBack";
5939 break;
5940 case 7:
5941 check_insn(ctx, ASE_MT);
5942 gen_helper_mtc0_vpeopt(cpu_env, arg);
5943 rn = "VPEOpt";
5944 break;
5945 default:
5946 goto die;
5948 break;
5949 case 2:
5950 switch (sel) {
5951 case 0:
5952 gen_helper_mtc0_entrylo0(cpu_env, arg);
5953 rn = "EntryLo0";
5954 break;
5955 case 1:
5956 check_insn(ctx, ASE_MT);
5957 gen_helper_mtc0_tcstatus(cpu_env, arg);
5958 rn = "TCStatus";
5959 break;
5960 case 2:
5961 check_insn(ctx, ASE_MT);
5962 gen_helper_mtc0_tcbind(cpu_env, arg);
5963 rn = "TCBind";
5964 break;
5965 case 3:
5966 check_insn(ctx, ASE_MT);
5967 gen_helper_mtc0_tcrestart(cpu_env, arg);
5968 rn = "TCRestart";
5969 break;
5970 case 4:
5971 check_insn(ctx, ASE_MT);
5972 gen_helper_mtc0_tchalt(cpu_env, arg);
5973 rn = "TCHalt";
5974 break;
5975 case 5:
5976 check_insn(ctx, ASE_MT);
5977 gen_helper_mtc0_tccontext(cpu_env, arg);
5978 rn = "TCContext";
5979 break;
5980 case 6:
5981 check_insn(ctx, ASE_MT);
5982 gen_helper_mtc0_tcschedule(cpu_env, arg);
5983 rn = "TCSchedule";
5984 break;
5985 case 7:
5986 check_insn(ctx, ASE_MT);
5987 gen_helper_mtc0_tcschefback(cpu_env, arg);
5988 rn = "TCScheFBack";
5989 break;
5990 default:
5991 goto die;
5993 break;
5994 case 3:
5995 switch (sel) {
5996 case 0:
5997 gen_helper_mtc0_entrylo1(cpu_env, arg);
5998 rn = "EntryLo1";
5999 break;
6000 default:
6001 goto die;
6003 break;
6004 case 4:
6005 switch (sel) {
6006 case 0:
6007 gen_helper_mtc0_context(cpu_env, arg);
6008 rn = "Context";
6009 break;
6010 case 1:
6011 // gen_helper_mtc0_contextconfig(cpu_env, arg); /* SmartMIPS ASE */
6012 rn = "ContextConfig";
6013 goto die;
6014 // break;
6015 case 2:
6016 if (ctx->ulri) {
6017 tcg_gen_st_tl(arg, cpu_env,
6018 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6019 rn = "UserLocal";
6021 break;
6022 default:
6023 goto die;
6025 break;
6026 case 5:
6027 switch (sel) {
6028 case 0:
6029 gen_helper_mtc0_pagemask(cpu_env, arg);
6030 rn = "PageMask";
6031 break;
6032 case 1:
6033 check_insn(ctx, ISA_MIPS32R2);
6034 gen_helper_mtc0_pagegrain(cpu_env, arg);
6035 rn = "PageGrain";
6036 break;
6037 default:
6038 goto die;
6040 break;
6041 case 6:
6042 switch (sel) {
6043 case 0:
6044 gen_helper_mtc0_wired(cpu_env, arg);
6045 rn = "Wired";
6046 break;
6047 case 1:
6048 check_insn(ctx, ISA_MIPS32R2);
6049 gen_helper_mtc0_srsconf0(cpu_env, arg);
6050 rn = "SRSConf0";
6051 break;
6052 case 2:
6053 check_insn(ctx, ISA_MIPS32R2);
6054 gen_helper_mtc0_srsconf1(cpu_env, arg);
6055 rn = "SRSConf1";
6056 break;
6057 case 3:
6058 check_insn(ctx, ISA_MIPS32R2);
6059 gen_helper_mtc0_srsconf2(cpu_env, arg);
6060 rn = "SRSConf2";
6061 break;
6062 case 4:
6063 check_insn(ctx, ISA_MIPS32R2);
6064 gen_helper_mtc0_srsconf3(cpu_env, arg);
6065 rn = "SRSConf3";
6066 break;
6067 case 5:
6068 check_insn(ctx, ISA_MIPS32R2);
6069 gen_helper_mtc0_srsconf4(cpu_env, arg);
6070 rn = "SRSConf4";
6071 break;
6072 default:
6073 goto die;
6075 break;
6076 case 7:
6077 switch (sel) {
6078 case 0:
6079 check_insn(ctx, ISA_MIPS32R2);
6080 gen_helper_mtc0_hwrena(cpu_env, arg);
6081 ctx->bstate = BS_STOP;
6082 rn = "HWREna";
6083 break;
6084 default:
6085 goto die;
6087 break;
6088 case 8:
6089 /* ignored */
6090 rn = "BadVAddr";
6091 break;
6092 case 9:
6093 switch (sel) {
6094 case 0:
6095 gen_helper_mtc0_count(cpu_env, arg);
6096 rn = "Count";
6097 break;
6098 /* 6,7 are implementation dependent */
6099 default:
6100 goto die;
6102 /* Stop translation as we may have switched the execution mode */
6103 ctx->bstate = BS_STOP;
6104 break;
6105 case 10:
6106 switch (sel) {
6107 case 0:
6108 gen_helper_mtc0_entryhi(cpu_env, arg);
6109 rn = "EntryHi";
6110 break;
6111 default:
6112 goto die;
6114 break;
6115 case 11:
6116 switch (sel) {
6117 case 0:
6118 gen_helper_mtc0_compare(cpu_env, arg);
6119 rn = "Compare";
6120 break;
6121 /* 6,7 are implementation dependent */
6122 default:
6123 goto die;
6125 /* Stop translation as we may have switched the execution mode */
6126 ctx->bstate = BS_STOP;
6127 break;
6128 case 12:
6129 switch (sel) {
6130 case 0:
6131 save_cpu_state(ctx, 1);
6132 gen_helper_mtc0_status(cpu_env, arg);
6133 /* BS_STOP isn't good enough here, hflags may have changed. */
6134 gen_save_pc(ctx->pc + 4);
6135 ctx->bstate = BS_EXCP;
6136 rn = "Status";
6137 break;
6138 case 1:
6139 check_insn(ctx, ISA_MIPS32R2);
6140 gen_helper_mtc0_intctl(cpu_env, arg);
6141 /* Stop translation as we may have switched the execution mode */
6142 ctx->bstate = BS_STOP;
6143 rn = "IntCtl";
6144 break;
6145 case 2:
6146 check_insn(ctx, ISA_MIPS32R2);
6147 gen_helper_mtc0_srsctl(cpu_env, arg);
6148 /* Stop translation as we may have switched the execution mode */
6149 ctx->bstate = BS_STOP;
6150 rn = "SRSCtl";
6151 break;
6152 case 3:
6153 check_insn(ctx, ISA_MIPS32R2);
6154 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6155 /* Stop translation as we may have switched the execution mode */
6156 ctx->bstate = BS_STOP;
6157 rn = "SRSMap";
6158 break;
6159 default:
6160 goto die;
6162 break;
6163 case 13:
6164 switch (sel) {
6165 case 0:
6166 save_cpu_state(ctx, 1);
6167 /* Mark as an IO operation because we may trigger a software
6168 interrupt. */
6169 if (use_icount) {
6170 gen_io_start();
6172 gen_helper_mtc0_cause(cpu_env, arg);
6173 if (use_icount) {
6174 gen_io_end();
6176 /* Stop translation as we may have triggered an intetrupt */
6177 ctx->bstate = BS_STOP;
6178 rn = "Cause";
6179 break;
6180 default:
6181 goto die;
6183 break;
6184 case 14:
6185 switch (sel) {
6186 case 0:
6187 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
6188 rn = "EPC";
6189 break;
6190 default:
6191 goto die;
6193 break;
6194 case 15:
6195 switch (sel) {
6196 case 0:
6197 /* ignored */
6198 rn = "PRid";
6199 break;
6200 case 1:
6201 check_insn(ctx, ISA_MIPS32R2);
6202 gen_helper_mtc0_ebase(cpu_env, arg);
6203 rn = "EBase";
6204 break;
6205 default:
6206 goto die;
6208 break;
6209 case 16:
6210 switch (sel) {
6211 case 0:
6212 gen_helper_mtc0_config0(cpu_env, arg);
6213 rn = "Config";
6214 /* Stop translation as we may have switched the execution mode */
6215 ctx->bstate = BS_STOP;
6216 break;
6217 case 1:
6218 /* ignored, read only */
6219 rn = "Config1";
6220 break;
6221 case 2:
6222 gen_helper_mtc0_config2(cpu_env, arg);
6223 rn = "Config2";
6224 /* Stop translation as we may have switched the execution mode */
6225 ctx->bstate = BS_STOP;
6226 break;
6227 case 3:
6228 /* ignored */
6229 rn = "Config3";
6230 break;
6231 /* 6,7 are implementation dependent */
6232 default:
6233 rn = "Invalid config selector";
6234 goto die;
6236 break;
6237 case 17:
6238 switch (sel) {
6239 case 0:
6240 gen_helper_mtc0_lladdr(cpu_env, arg);
6241 rn = "LLAddr";
6242 break;
6243 default:
6244 goto die;
6246 break;
6247 case 18:
6248 switch (sel) {
6249 case 0 ... 7:
6250 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6251 rn = "WatchLo";
6252 break;
6253 default:
6254 goto die;
6256 break;
6257 case 19:
6258 switch (sel) {
6259 case 0 ... 7:
6260 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6261 rn = "WatchHi";
6262 break;
6263 default:
6264 goto die;
6266 break;
6267 case 20:
6268 switch (sel) {
6269 case 0:
6270 check_insn(ctx, ISA_MIPS3);
6271 gen_helper_mtc0_xcontext(cpu_env, arg);
6272 rn = "XContext";
6273 break;
6274 default:
6275 goto die;
6277 break;
6278 case 21:
6279 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6280 switch (sel) {
6281 case 0:
6282 gen_helper_mtc0_framemask(cpu_env, arg);
6283 rn = "Framemask";
6284 break;
6285 default:
6286 goto die;
6288 break;
6289 case 22:
6290 /* ignored */
6291 rn = "Diagnostic"; /* implementation dependent */
6292 break;
6293 case 23:
6294 switch (sel) {
6295 case 0:
6296 gen_helper_mtc0_debug(cpu_env, arg); /* EJTAG support */
6297 /* BS_STOP isn't good enough here, hflags may have changed. */
6298 gen_save_pc(ctx->pc + 4);
6299 ctx->bstate = BS_EXCP;
6300 rn = "Debug";
6301 break;
6302 case 1:
6303 // gen_helper_mtc0_tracecontrol(cpu_env, arg); /* PDtrace support */
6304 /* Stop translation as we may have switched the execution mode */
6305 ctx->bstate = BS_STOP;
6306 rn = "TraceControl";
6307 // break;
6308 case 2:
6309 // gen_helper_mtc0_tracecontrol2(cpu_env, arg); /* PDtrace support */
6310 /* Stop translation as we may have switched the execution mode */
6311 ctx->bstate = BS_STOP;
6312 rn = "TraceControl2";
6313 // break;
6314 case 3:
6315 // gen_helper_mtc0_usertracedata(cpu_env, arg); /* PDtrace support */
6316 /* Stop translation as we may have switched the execution mode */
6317 ctx->bstate = BS_STOP;
6318 rn = "UserTraceData";
6319 // break;
6320 case 4:
6321 // gen_helper_mtc0_tracebpc(cpu_env, arg); /* PDtrace support */
6322 /* Stop translation as we may have switched the execution mode */
6323 ctx->bstate = BS_STOP;
6324 rn = "TraceBPC";
6325 // break;
6326 default:
6327 goto die;
6329 break;
6330 case 24:
6331 switch (sel) {
6332 case 0:
6333 /* EJTAG support */
6334 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
6335 rn = "DEPC";
6336 break;
6337 default:
6338 goto die;
6340 break;
6341 case 25:
6342 switch (sel) {
6343 case 0:
6344 gen_helper_mtc0_performance0(cpu_env, arg);
6345 rn = "Performance0";
6346 break;
6347 case 1:
6348 // gen_helper_mtc0_performance1(cpu_env, arg);
6349 rn = "Performance1";
6350 // break;
6351 case 2:
6352 // gen_helper_mtc0_performance2(cpu_env, arg);
6353 rn = "Performance2";
6354 // break;
6355 case 3:
6356 // gen_helper_mtc0_performance3(cpu_env, arg);
6357 rn = "Performance3";
6358 // break;
6359 case 4:
6360 // gen_helper_mtc0_performance4(cpu_env, arg);
6361 rn = "Performance4";
6362 // break;
6363 case 5:
6364 // gen_helper_mtc0_performance5(cpu_env, arg);
6365 rn = "Performance5";
6366 // break;
6367 case 6:
6368 // gen_helper_mtc0_performance6(cpu_env, arg);
6369 rn = "Performance6";
6370 // break;
6371 case 7:
6372 // gen_helper_mtc0_performance7(cpu_env, arg);
6373 rn = "Performance7";
6374 // break;
6375 default:
6376 goto die;
6378 break;
6379 case 26:
6380 /* ignored */
6381 rn = "ECC";
6382 break;
6383 case 27:
6384 switch (sel) {
6385 case 0 ... 3:
6386 /* ignored */
6387 rn = "CacheErr";
6388 break;
6389 default:
6390 goto die;
6392 break;
6393 case 28:
6394 switch (sel) {
6395 case 0:
6396 case 2:
6397 case 4:
6398 case 6:
6399 gen_helper_mtc0_taglo(cpu_env, arg);
6400 rn = "TagLo";
6401 break;
6402 case 1:
6403 case 3:
6404 case 5:
6405 case 7:
6406 gen_helper_mtc0_datalo(cpu_env, arg);
6407 rn = "DataLo";
6408 break;
6409 default:
6410 goto die;
6412 break;
6413 case 29:
6414 switch (sel) {
6415 case 0:
6416 case 2:
6417 case 4:
6418 case 6:
6419 gen_helper_mtc0_taghi(cpu_env, arg);
6420 rn = "TagHi";
6421 break;
6422 case 1:
6423 case 3:
6424 case 5:
6425 case 7:
6426 gen_helper_mtc0_datahi(cpu_env, arg);
6427 rn = "DataHi";
6428 break;
6429 default:
6430 rn = "invalid sel";
6431 goto die;
6433 break;
6434 case 30:
6435 switch (sel) {
6436 case 0:
6437 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6438 rn = "ErrorEPC";
6439 break;
6440 default:
6441 goto die;
6443 break;
6444 case 31:
6445 switch (sel) {
6446 case 0:
6447 /* EJTAG support */
6448 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6449 rn = "DESAVE";
6450 break;
6451 default:
6452 goto die;
6454 /* Stop translation as we may have switched the execution mode */
6455 ctx->bstate = BS_STOP;
6456 break;
6457 default:
6458 goto die;
6460 (void)rn; /* avoid a compiler warning */
6461 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6462 /* For simplicity assume that all writes can cause interrupts. */
6463 if (use_icount) {
6464 gen_io_end();
6465 ctx->bstate = BS_STOP;
6467 return;
6469 die:
6470 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
6471 generate_exception(ctx, EXCP_RI);
6473 #endif /* TARGET_MIPS64 */
6475 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
6476 int u, int sel, int h)
6478 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6479 TCGv t0 = tcg_temp_local_new();
6481 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
6482 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6483 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
6484 tcg_gen_movi_tl(t0, -1);
6485 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6486 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6487 tcg_gen_movi_tl(t0, -1);
6488 else if (u == 0) {
6489 switch (rt) {
6490 case 1:
6491 switch (sel) {
6492 case 1:
6493 gen_helper_mftc0_vpecontrol(t0, cpu_env);
6494 break;
6495 case 2:
6496 gen_helper_mftc0_vpeconf0(t0, cpu_env);
6497 break;
6498 default:
6499 goto die;
6500 break;
6502 break;
6503 case 2:
6504 switch (sel) {
6505 case 1:
6506 gen_helper_mftc0_tcstatus(t0, cpu_env);
6507 break;
6508 case 2:
6509 gen_helper_mftc0_tcbind(t0, cpu_env);
6510 break;
6511 case 3:
6512 gen_helper_mftc0_tcrestart(t0, cpu_env);
6513 break;
6514 case 4:
6515 gen_helper_mftc0_tchalt(t0, cpu_env);
6516 break;
6517 case 5:
6518 gen_helper_mftc0_tccontext(t0, cpu_env);
6519 break;
6520 case 6:
6521 gen_helper_mftc0_tcschedule(t0, cpu_env);
6522 break;
6523 case 7:
6524 gen_helper_mftc0_tcschefback(t0, cpu_env);
6525 break;
6526 default:
6527 gen_mfc0(ctx, t0, rt, sel);
6528 break;
6530 break;
6531 case 10:
6532 switch (sel) {
6533 case 0:
6534 gen_helper_mftc0_entryhi(t0, cpu_env);
6535 break;
6536 default:
6537 gen_mfc0(ctx, t0, rt, sel);
6538 break;
6540 case 12:
6541 switch (sel) {
6542 case 0:
6543 gen_helper_mftc0_status(t0, cpu_env);
6544 break;
6545 default:
6546 gen_mfc0(ctx, t0, rt, sel);
6547 break;
6549 case 13:
6550 switch (sel) {
6551 case 0:
6552 gen_helper_mftc0_cause(t0, cpu_env);
6553 break;
6554 default:
6555 goto die;
6556 break;
6558 break;
6559 case 14:
6560 switch (sel) {
6561 case 0:
6562 gen_helper_mftc0_epc(t0, cpu_env);
6563 break;
6564 default:
6565 goto die;
6566 break;
6568 break;
6569 case 15:
6570 switch (sel) {
6571 case 1:
6572 gen_helper_mftc0_ebase(t0, cpu_env);
6573 break;
6574 default:
6575 goto die;
6576 break;
6578 break;
6579 case 16:
6580 switch (sel) {
6581 case 0 ... 7:
6582 gen_helper_mftc0_configx(t0, cpu_env, tcg_const_tl(sel));
6583 break;
6584 default:
6585 goto die;
6586 break;
6588 break;
6589 case 23:
6590 switch (sel) {
6591 case 0:
6592 gen_helper_mftc0_debug(t0, cpu_env);
6593 break;
6594 default:
6595 gen_mfc0(ctx, t0, rt, sel);
6596 break;
6598 break;
6599 default:
6600 gen_mfc0(ctx, t0, rt, sel);
6602 } else switch (sel) {
6603 /* GPR registers. */
6604 case 0:
6605 gen_helper_1e0i(mftgpr, t0, rt);
6606 break;
6607 /* Auxiliary CPU registers */
6608 case 1:
6609 switch (rt) {
6610 case 0:
6611 gen_helper_1e0i(mftlo, t0, 0);
6612 break;
6613 case 1:
6614 gen_helper_1e0i(mfthi, t0, 0);
6615 break;
6616 case 2:
6617 gen_helper_1e0i(mftacx, t0, 0);
6618 break;
6619 case 4:
6620 gen_helper_1e0i(mftlo, t0, 1);
6621 break;
6622 case 5:
6623 gen_helper_1e0i(mfthi, t0, 1);
6624 break;
6625 case 6:
6626 gen_helper_1e0i(mftacx, t0, 1);
6627 break;
6628 case 8:
6629 gen_helper_1e0i(mftlo, t0, 2);
6630 break;
6631 case 9:
6632 gen_helper_1e0i(mfthi, t0, 2);
6633 break;
6634 case 10:
6635 gen_helper_1e0i(mftacx, t0, 2);
6636 break;
6637 case 12:
6638 gen_helper_1e0i(mftlo, t0, 3);
6639 break;
6640 case 13:
6641 gen_helper_1e0i(mfthi, t0, 3);
6642 break;
6643 case 14:
6644 gen_helper_1e0i(mftacx, t0, 3);
6645 break;
6646 case 16:
6647 gen_helper_mftdsp(t0, cpu_env);
6648 break;
6649 default:
6650 goto die;
6652 break;
6653 /* Floating point (COP1). */
6654 case 2:
6655 /* XXX: For now we support only a single FPU context. */
6656 if (h == 0) {
6657 TCGv_i32 fp0 = tcg_temp_new_i32();
6659 gen_load_fpr32(fp0, rt);
6660 tcg_gen_ext_i32_tl(t0, fp0);
6661 tcg_temp_free_i32(fp0);
6662 } else {
6663 TCGv_i32 fp0 = tcg_temp_new_i32();
6665 gen_load_fpr32h(ctx, fp0, rt);
6666 tcg_gen_ext_i32_tl(t0, fp0);
6667 tcg_temp_free_i32(fp0);
6669 break;
6670 case 3:
6671 /* XXX: For now we support only a single FPU context. */
6672 gen_helper_1e0i(cfc1, t0, rt);
6673 break;
6674 /* COP2: Not implemented. */
6675 case 4:
6676 case 5:
6677 /* fall through */
6678 default:
6679 goto die;
6681 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
6682 gen_store_gpr(t0, rd);
6683 tcg_temp_free(t0);
6684 return;
6686 die:
6687 tcg_temp_free(t0);
6688 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
6689 generate_exception(ctx, EXCP_RI);
6692 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
6693 int u, int sel, int h)
6695 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
6696 TCGv t0 = tcg_temp_local_new();
6698 gen_load_gpr(t0, rt);
6699 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
6700 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
6701 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
6702 /* NOP */ ;
6703 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
6704 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
6705 /* NOP */ ;
6706 else if (u == 0) {
6707 switch (rd) {
6708 case 1:
6709 switch (sel) {
6710 case 1:
6711 gen_helper_mttc0_vpecontrol(cpu_env, t0);
6712 break;
6713 case 2:
6714 gen_helper_mttc0_vpeconf0(cpu_env, t0);
6715 break;
6716 default:
6717 goto die;
6718 break;
6720 break;
6721 case 2:
6722 switch (sel) {
6723 case 1:
6724 gen_helper_mttc0_tcstatus(cpu_env, t0);
6725 break;
6726 case 2:
6727 gen_helper_mttc0_tcbind(cpu_env, t0);
6728 break;
6729 case 3:
6730 gen_helper_mttc0_tcrestart(cpu_env, t0);
6731 break;
6732 case 4:
6733 gen_helper_mttc0_tchalt(cpu_env, t0);
6734 break;
6735 case 5:
6736 gen_helper_mttc0_tccontext(cpu_env, t0);
6737 break;
6738 case 6:
6739 gen_helper_mttc0_tcschedule(cpu_env, t0);
6740 break;
6741 case 7:
6742 gen_helper_mttc0_tcschefback(cpu_env, t0);
6743 break;
6744 default:
6745 gen_mtc0(ctx, t0, rd, sel);
6746 break;
6748 break;
6749 case 10:
6750 switch (sel) {
6751 case 0:
6752 gen_helper_mttc0_entryhi(cpu_env, t0);
6753 break;
6754 default:
6755 gen_mtc0(ctx, t0, rd, sel);
6756 break;
6758 case 12:
6759 switch (sel) {
6760 case 0:
6761 gen_helper_mttc0_status(cpu_env, t0);
6762 break;
6763 default:
6764 gen_mtc0(ctx, t0, rd, sel);
6765 break;
6767 case 13:
6768 switch (sel) {
6769 case 0:
6770 gen_helper_mttc0_cause(cpu_env, t0);
6771 break;
6772 default:
6773 goto die;
6774 break;
6776 break;
6777 case 15:
6778 switch (sel) {
6779 case 1:
6780 gen_helper_mttc0_ebase(cpu_env, t0);
6781 break;
6782 default:
6783 goto die;
6784 break;
6786 break;
6787 case 23:
6788 switch (sel) {
6789 case 0:
6790 gen_helper_mttc0_debug(cpu_env, t0);
6791 break;
6792 default:
6793 gen_mtc0(ctx, t0, rd, sel);
6794 break;
6796 break;
6797 default:
6798 gen_mtc0(ctx, t0, rd, sel);
6800 } else switch (sel) {
6801 /* GPR registers. */
6802 case 0:
6803 gen_helper_0e1i(mttgpr, t0, rd);
6804 break;
6805 /* Auxiliary CPU registers */
6806 case 1:
6807 switch (rd) {
6808 case 0:
6809 gen_helper_0e1i(mttlo, t0, 0);
6810 break;
6811 case 1:
6812 gen_helper_0e1i(mtthi, t0, 0);
6813 break;
6814 case 2:
6815 gen_helper_0e1i(mttacx, t0, 0);
6816 break;
6817 case 4:
6818 gen_helper_0e1i(mttlo, t0, 1);
6819 break;
6820 case 5:
6821 gen_helper_0e1i(mtthi, t0, 1);
6822 break;
6823 case 6:
6824 gen_helper_0e1i(mttacx, t0, 1);
6825 break;
6826 case 8:
6827 gen_helper_0e1i(mttlo, t0, 2);
6828 break;
6829 case 9:
6830 gen_helper_0e1i(mtthi, t0, 2);
6831 break;
6832 case 10:
6833 gen_helper_0e1i(mttacx, t0, 2);
6834 break;
6835 case 12:
6836 gen_helper_0e1i(mttlo, t0, 3);
6837 break;
6838 case 13:
6839 gen_helper_0e1i(mtthi, t0, 3);
6840 break;
6841 case 14:
6842 gen_helper_0e1i(mttacx, t0, 3);
6843 break;
6844 case 16:
6845 gen_helper_mttdsp(cpu_env, t0);
6846 break;
6847 default:
6848 goto die;
6850 break;
6851 /* Floating point (COP1). */
6852 case 2:
6853 /* XXX: For now we support only a single FPU context. */
6854 if (h == 0) {
6855 TCGv_i32 fp0 = tcg_temp_new_i32();
6857 tcg_gen_trunc_tl_i32(fp0, t0);
6858 gen_store_fpr32(fp0, rd);
6859 tcg_temp_free_i32(fp0);
6860 } else {
6861 TCGv_i32 fp0 = tcg_temp_new_i32();
6863 tcg_gen_trunc_tl_i32(fp0, t0);
6864 gen_store_fpr32h(ctx, fp0, rd);
6865 tcg_temp_free_i32(fp0);
6867 break;
6868 case 3:
6869 /* XXX: For now we support only a single FPU context. */
6871 TCGv_i32 fs_tmp = tcg_const_i32(rd);
6873 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
6874 tcg_temp_free_i32(fs_tmp);
6876 break;
6877 /* COP2: Not implemented. */
6878 case 4:
6879 case 5:
6880 /* fall through */
6881 default:
6882 goto die;
6884 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
6885 tcg_temp_free(t0);
6886 return;
6888 die:
6889 tcg_temp_free(t0);
6890 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
6891 generate_exception(ctx, EXCP_RI);
6894 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
6896 const char *opn = "ldst";
6898 check_cp0_enabled(ctx);
6899 switch (opc) {
6900 case OPC_MFC0:
6901 if (rt == 0) {
6902 /* Treat as NOP. */
6903 return;
6905 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6906 opn = "mfc0";
6907 break;
6908 case OPC_MTC0:
6910 TCGv t0 = tcg_temp_new();
6912 gen_load_gpr(t0, rt);
6913 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
6914 tcg_temp_free(t0);
6916 opn = "mtc0";
6917 break;
6918 #if defined(TARGET_MIPS64)
6919 case OPC_DMFC0:
6920 check_insn(ctx, ISA_MIPS3);
6921 if (rt == 0) {
6922 /* Treat as NOP. */
6923 return;
6925 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
6926 opn = "dmfc0";
6927 break;
6928 case OPC_DMTC0:
6929 check_insn(ctx, ISA_MIPS3);
6931 TCGv t0 = tcg_temp_new();
6933 gen_load_gpr(t0, rt);
6934 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
6935 tcg_temp_free(t0);
6937 opn = "dmtc0";
6938 break;
6939 #endif
6940 case OPC_MFTR:
6941 check_insn(ctx, ASE_MT);
6942 if (rd == 0) {
6943 /* Treat as NOP. */
6944 return;
6946 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
6947 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6948 opn = "mftr";
6949 break;
6950 case OPC_MTTR:
6951 check_insn(ctx, ASE_MT);
6952 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
6953 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
6954 opn = "mttr";
6955 break;
6956 case OPC_TLBWI:
6957 opn = "tlbwi";
6958 if (!env->tlb->helper_tlbwi)
6959 goto die;
6960 gen_helper_tlbwi(cpu_env);
6961 break;
6962 case OPC_TLBWR:
6963 opn = "tlbwr";
6964 if (!env->tlb->helper_tlbwr)
6965 goto die;
6966 gen_helper_tlbwr(cpu_env);
6967 break;
6968 case OPC_TLBP:
6969 opn = "tlbp";
6970 if (!env->tlb->helper_tlbp)
6971 goto die;
6972 gen_helper_tlbp(cpu_env);
6973 break;
6974 case OPC_TLBR:
6975 opn = "tlbr";
6976 if (!env->tlb->helper_tlbr)
6977 goto die;
6978 gen_helper_tlbr(cpu_env);
6979 break;
6980 case OPC_ERET:
6981 opn = "eret";
6982 check_insn(ctx, ISA_MIPS2);
6983 gen_helper_eret(cpu_env);
6984 ctx->bstate = BS_EXCP;
6985 break;
6986 case OPC_DERET:
6987 opn = "deret";
6988 check_insn(ctx, ISA_MIPS32);
6989 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6990 MIPS_INVAL(opn);
6991 generate_exception(ctx, EXCP_RI);
6992 } else {
6993 gen_helper_deret(cpu_env);
6994 ctx->bstate = BS_EXCP;
6996 break;
6997 case OPC_WAIT:
6998 opn = "wait";
6999 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
7000 /* If we get an exception, we want to restart at next instruction */
7001 ctx->pc += 4;
7002 save_cpu_state(ctx, 1);
7003 ctx->pc -= 4;
7004 gen_helper_wait(cpu_env);
7005 ctx->bstate = BS_EXCP;
7006 break;
7007 default:
7008 die:
7009 MIPS_INVAL(opn);
7010 generate_exception(ctx, EXCP_RI);
7011 return;
7013 (void)opn; /* avoid a compiler warning */
7014 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
7016 #endif /* !CONFIG_USER_ONLY */
7018 /* CP1 Branches (before delay slot) */
7019 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
7020 int32_t cc, int32_t offset)
7022 target_ulong btarget;
7023 const char *opn = "cp1 cond branch";
7024 TCGv_i32 t0 = tcg_temp_new_i32();
7026 if (cc != 0)
7027 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
7029 btarget = ctx->pc + 4 + offset;
7031 switch (op) {
7032 case OPC_BC1F:
7033 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7034 tcg_gen_not_i32(t0, t0);
7035 tcg_gen_andi_i32(t0, t0, 1);
7036 tcg_gen_extu_i32_tl(bcond, t0);
7037 opn = "bc1f";
7038 goto not_likely;
7039 case OPC_BC1FL:
7040 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7041 tcg_gen_not_i32(t0, t0);
7042 tcg_gen_andi_i32(t0, t0, 1);
7043 tcg_gen_extu_i32_tl(bcond, t0);
7044 opn = "bc1fl";
7045 goto likely;
7046 case OPC_BC1T:
7047 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7048 tcg_gen_andi_i32(t0, t0, 1);
7049 tcg_gen_extu_i32_tl(bcond, t0);
7050 opn = "bc1t";
7051 goto not_likely;
7052 case OPC_BC1TL:
7053 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7054 tcg_gen_andi_i32(t0, t0, 1);
7055 tcg_gen_extu_i32_tl(bcond, t0);
7056 opn = "bc1tl";
7057 likely:
7058 ctx->hflags |= MIPS_HFLAG_BL;
7059 break;
7060 case OPC_BC1FANY2:
7062 TCGv_i32 t1 = tcg_temp_new_i32();
7063 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7064 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7065 tcg_gen_nand_i32(t0, t0, t1);
7066 tcg_temp_free_i32(t1);
7067 tcg_gen_andi_i32(t0, t0, 1);
7068 tcg_gen_extu_i32_tl(bcond, t0);
7070 opn = "bc1any2f";
7071 goto not_likely;
7072 case OPC_BC1TANY2:
7074 TCGv_i32 t1 = tcg_temp_new_i32();
7075 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7076 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7077 tcg_gen_or_i32(t0, t0, t1);
7078 tcg_temp_free_i32(t1);
7079 tcg_gen_andi_i32(t0, t0, 1);
7080 tcg_gen_extu_i32_tl(bcond, t0);
7082 opn = "bc1any2t";
7083 goto not_likely;
7084 case OPC_BC1FANY4:
7086 TCGv_i32 t1 = tcg_temp_new_i32();
7087 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7088 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7089 tcg_gen_and_i32(t0, t0, t1);
7090 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7091 tcg_gen_and_i32(t0, t0, t1);
7092 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7093 tcg_gen_nand_i32(t0, t0, t1);
7094 tcg_temp_free_i32(t1);
7095 tcg_gen_andi_i32(t0, t0, 1);
7096 tcg_gen_extu_i32_tl(bcond, t0);
7098 opn = "bc1any4f";
7099 goto not_likely;
7100 case OPC_BC1TANY4:
7102 TCGv_i32 t1 = tcg_temp_new_i32();
7103 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
7104 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
7105 tcg_gen_or_i32(t0, t0, t1);
7106 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
7107 tcg_gen_or_i32(t0, t0, t1);
7108 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
7109 tcg_gen_or_i32(t0, t0, t1);
7110 tcg_temp_free_i32(t1);
7111 tcg_gen_andi_i32(t0, t0, 1);
7112 tcg_gen_extu_i32_tl(bcond, t0);
7114 opn = "bc1any4t";
7115 not_likely:
7116 ctx->hflags |= MIPS_HFLAG_BC;
7117 break;
7118 default:
7119 MIPS_INVAL(opn);
7120 generate_exception (ctx, EXCP_RI);
7121 goto out;
7123 (void)opn; /* avoid a compiler warning */
7124 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
7125 ctx->hflags, btarget);
7126 ctx->btarget = btarget;
7128 out:
7129 tcg_temp_free_i32(t0);
7132 /* Coprocessor 1 (FPU) */
7134 #define FOP(func, fmt) (((fmt) << 21) | (func))
7136 enum fopcode {
7137 OPC_ADD_S = FOP(0, FMT_S),
7138 OPC_SUB_S = FOP(1, FMT_S),
7139 OPC_MUL_S = FOP(2, FMT_S),
7140 OPC_DIV_S = FOP(3, FMT_S),
7141 OPC_SQRT_S = FOP(4, FMT_S),
7142 OPC_ABS_S = FOP(5, FMT_S),
7143 OPC_MOV_S = FOP(6, FMT_S),
7144 OPC_NEG_S = FOP(7, FMT_S),
7145 OPC_ROUND_L_S = FOP(8, FMT_S),
7146 OPC_TRUNC_L_S = FOP(9, FMT_S),
7147 OPC_CEIL_L_S = FOP(10, FMT_S),
7148 OPC_FLOOR_L_S = FOP(11, FMT_S),
7149 OPC_ROUND_W_S = FOP(12, FMT_S),
7150 OPC_TRUNC_W_S = FOP(13, FMT_S),
7151 OPC_CEIL_W_S = FOP(14, FMT_S),
7152 OPC_FLOOR_W_S = FOP(15, FMT_S),
7153 OPC_MOVCF_S = FOP(17, FMT_S),
7154 OPC_MOVZ_S = FOP(18, FMT_S),
7155 OPC_MOVN_S = FOP(19, FMT_S),
7156 OPC_RECIP_S = FOP(21, FMT_S),
7157 OPC_RSQRT_S = FOP(22, FMT_S),
7158 OPC_RECIP2_S = FOP(28, FMT_S),
7159 OPC_RECIP1_S = FOP(29, FMT_S),
7160 OPC_RSQRT1_S = FOP(30, FMT_S),
7161 OPC_RSQRT2_S = FOP(31, FMT_S),
7162 OPC_CVT_D_S = FOP(33, FMT_S),
7163 OPC_CVT_W_S = FOP(36, FMT_S),
7164 OPC_CVT_L_S = FOP(37, FMT_S),
7165 OPC_CVT_PS_S = FOP(38, FMT_S),
7166 OPC_CMP_F_S = FOP (48, FMT_S),
7167 OPC_CMP_UN_S = FOP (49, FMT_S),
7168 OPC_CMP_EQ_S = FOP (50, FMT_S),
7169 OPC_CMP_UEQ_S = FOP (51, FMT_S),
7170 OPC_CMP_OLT_S = FOP (52, FMT_S),
7171 OPC_CMP_ULT_S = FOP (53, FMT_S),
7172 OPC_CMP_OLE_S = FOP (54, FMT_S),
7173 OPC_CMP_ULE_S = FOP (55, FMT_S),
7174 OPC_CMP_SF_S = FOP (56, FMT_S),
7175 OPC_CMP_NGLE_S = FOP (57, FMT_S),
7176 OPC_CMP_SEQ_S = FOP (58, FMT_S),
7177 OPC_CMP_NGL_S = FOP (59, FMT_S),
7178 OPC_CMP_LT_S = FOP (60, FMT_S),
7179 OPC_CMP_NGE_S = FOP (61, FMT_S),
7180 OPC_CMP_LE_S = FOP (62, FMT_S),
7181 OPC_CMP_NGT_S = FOP (63, FMT_S),
7183 OPC_ADD_D = FOP(0, FMT_D),
7184 OPC_SUB_D = FOP(1, FMT_D),
7185 OPC_MUL_D = FOP(2, FMT_D),
7186 OPC_DIV_D = FOP(3, FMT_D),
7187 OPC_SQRT_D = FOP(4, FMT_D),
7188 OPC_ABS_D = FOP(5, FMT_D),
7189 OPC_MOV_D = FOP(6, FMT_D),
7190 OPC_NEG_D = FOP(7, FMT_D),
7191 OPC_ROUND_L_D = FOP(8, FMT_D),
7192 OPC_TRUNC_L_D = FOP(9, FMT_D),
7193 OPC_CEIL_L_D = FOP(10, FMT_D),
7194 OPC_FLOOR_L_D = FOP(11, FMT_D),
7195 OPC_ROUND_W_D = FOP(12, FMT_D),
7196 OPC_TRUNC_W_D = FOP(13, FMT_D),
7197 OPC_CEIL_W_D = FOP(14, FMT_D),
7198 OPC_FLOOR_W_D = FOP(15, FMT_D),
7199 OPC_MOVCF_D = FOP(17, FMT_D),
7200 OPC_MOVZ_D = FOP(18, FMT_D),
7201 OPC_MOVN_D = FOP(19, FMT_D),
7202 OPC_RECIP_D = FOP(21, FMT_D),
7203 OPC_RSQRT_D = FOP(22, FMT_D),
7204 OPC_RECIP2_D = FOP(28, FMT_D),
7205 OPC_RECIP1_D = FOP(29, FMT_D),
7206 OPC_RSQRT1_D = FOP(30, FMT_D),
7207 OPC_RSQRT2_D = FOP(31, FMT_D),
7208 OPC_CVT_S_D = FOP(32, FMT_D),
7209 OPC_CVT_W_D = FOP(36, FMT_D),
7210 OPC_CVT_L_D = FOP(37, FMT_D),
7211 OPC_CMP_F_D = FOP (48, FMT_D),
7212 OPC_CMP_UN_D = FOP (49, FMT_D),
7213 OPC_CMP_EQ_D = FOP (50, FMT_D),
7214 OPC_CMP_UEQ_D = FOP (51, FMT_D),
7215 OPC_CMP_OLT_D = FOP (52, FMT_D),
7216 OPC_CMP_ULT_D = FOP (53, FMT_D),
7217 OPC_CMP_OLE_D = FOP (54, FMT_D),
7218 OPC_CMP_ULE_D = FOP (55, FMT_D),
7219 OPC_CMP_SF_D = FOP (56, FMT_D),
7220 OPC_CMP_NGLE_D = FOP (57, FMT_D),
7221 OPC_CMP_SEQ_D = FOP (58, FMT_D),
7222 OPC_CMP_NGL_D = FOP (59, FMT_D),
7223 OPC_CMP_LT_D = FOP (60, FMT_D),
7224 OPC_CMP_NGE_D = FOP (61, FMT_D),
7225 OPC_CMP_LE_D = FOP (62, FMT_D),
7226 OPC_CMP_NGT_D = FOP (63, FMT_D),
7228 OPC_CVT_S_W = FOP(32, FMT_W),
7229 OPC_CVT_D_W = FOP(33, FMT_W),
7230 OPC_CVT_S_L = FOP(32, FMT_L),
7231 OPC_CVT_D_L = FOP(33, FMT_L),
7232 OPC_CVT_PS_PW = FOP(38, FMT_W),
7234 OPC_ADD_PS = FOP(0, FMT_PS),
7235 OPC_SUB_PS = FOP(1, FMT_PS),
7236 OPC_MUL_PS = FOP(2, FMT_PS),
7237 OPC_DIV_PS = FOP(3, FMT_PS),
7238 OPC_ABS_PS = FOP(5, FMT_PS),
7239 OPC_MOV_PS = FOP(6, FMT_PS),
7240 OPC_NEG_PS = FOP(7, FMT_PS),
7241 OPC_MOVCF_PS = FOP(17, FMT_PS),
7242 OPC_MOVZ_PS = FOP(18, FMT_PS),
7243 OPC_MOVN_PS = FOP(19, FMT_PS),
7244 OPC_ADDR_PS = FOP(24, FMT_PS),
7245 OPC_MULR_PS = FOP(26, FMT_PS),
7246 OPC_RECIP2_PS = FOP(28, FMT_PS),
7247 OPC_RECIP1_PS = FOP(29, FMT_PS),
7248 OPC_RSQRT1_PS = FOP(30, FMT_PS),
7249 OPC_RSQRT2_PS = FOP(31, FMT_PS),
7251 OPC_CVT_S_PU = FOP(32, FMT_PS),
7252 OPC_CVT_PW_PS = FOP(36, FMT_PS),
7253 OPC_CVT_S_PL = FOP(40, FMT_PS),
7254 OPC_PLL_PS = FOP(44, FMT_PS),
7255 OPC_PLU_PS = FOP(45, FMT_PS),
7256 OPC_PUL_PS = FOP(46, FMT_PS),
7257 OPC_PUU_PS = FOP(47, FMT_PS),
7258 OPC_CMP_F_PS = FOP (48, FMT_PS),
7259 OPC_CMP_UN_PS = FOP (49, FMT_PS),
7260 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
7261 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
7262 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
7263 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
7264 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
7265 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
7266 OPC_CMP_SF_PS = FOP (56, FMT_PS),
7267 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
7268 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
7269 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
7270 OPC_CMP_LT_PS = FOP (60, FMT_PS),
7271 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
7272 OPC_CMP_LE_PS = FOP (62, FMT_PS),
7273 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
7276 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
7278 const char *opn = "cp1 move";
7279 TCGv t0 = tcg_temp_new();
7281 switch (opc) {
7282 case OPC_MFC1:
7284 TCGv_i32 fp0 = tcg_temp_new_i32();
7286 gen_load_fpr32(fp0, fs);
7287 tcg_gen_ext_i32_tl(t0, fp0);
7288 tcg_temp_free_i32(fp0);
7290 gen_store_gpr(t0, rt);
7291 opn = "mfc1";
7292 break;
7293 case OPC_MTC1:
7294 gen_load_gpr(t0, rt);
7296 TCGv_i32 fp0 = tcg_temp_new_i32();
7298 tcg_gen_trunc_tl_i32(fp0, t0);
7299 gen_store_fpr32(fp0, fs);
7300 tcg_temp_free_i32(fp0);
7302 opn = "mtc1";
7303 break;
7304 case OPC_CFC1:
7305 gen_helper_1e0i(cfc1, t0, fs);
7306 gen_store_gpr(t0, rt);
7307 opn = "cfc1";
7308 break;
7309 case OPC_CTC1:
7310 gen_load_gpr(t0, rt);
7312 TCGv_i32 fs_tmp = tcg_const_i32(fs);
7314 gen_helper_0e2i(ctc1, t0, fs_tmp, rt);
7315 tcg_temp_free_i32(fs_tmp);
7317 opn = "ctc1";
7318 break;
7319 #if defined(TARGET_MIPS64)
7320 case OPC_DMFC1:
7321 gen_load_fpr64(ctx, t0, fs);
7322 gen_store_gpr(t0, rt);
7323 opn = "dmfc1";
7324 break;
7325 case OPC_DMTC1:
7326 gen_load_gpr(t0, rt);
7327 gen_store_fpr64(ctx, t0, fs);
7328 opn = "dmtc1";
7329 break;
7330 #endif
7331 case OPC_MFHC1:
7333 TCGv_i32 fp0 = tcg_temp_new_i32();
7335 gen_load_fpr32h(ctx, fp0, fs);
7336 tcg_gen_ext_i32_tl(t0, fp0);
7337 tcg_temp_free_i32(fp0);
7339 gen_store_gpr(t0, rt);
7340 opn = "mfhc1";
7341 break;
7342 case OPC_MTHC1:
7343 gen_load_gpr(t0, rt);
7345 TCGv_i32 fp0 = tcg_temp_new_i32();
7347 tcg_gen_trunc_tl_i32(fp0, t0);
7348 gen_store_fpr32h(ctx, fp0, fs);
7349 tcg_temp_free_i32(fp0);
7351 opn = "mthc1";
7352 break;
7353 default:
7354 MIPS_INVAL(opn);
7355 generate_exception (ctx, EXCP_RI);
7356 goto out;
7358 (void)opn; /* avoid a compiler warning */
7359 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
7361 out:
7362 tcg_temp_free(t0);
7365 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
7367 int l1;
7368 TCGCond cond;
7369 TCGv_i32 t0;
7371 if (rd == 0) {
7372 /* Treat as NOP. */
7373 return;
7376 if (tf)
7377 cond = TCG_COND_EQ;
7378 else
7379 cond = TCG_COND_NE;
7381 l1 = gen_new_label();
7382 t0 = tcg_temp_new_i32();
7383 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7384 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7385 tcg_temp_free_i32(t0);
7386 if (rs == 0) {
7387 tcg_gen_movi_tl(cpu_gpr[rd], 0);
7388 } else {
7389 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
7391 gen_set_label(l1);
7394 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
7396 int cond;
7397 TCGv_i32 t0 = tcg_temp_new_i32();
7398 int l1 = gen_new_label();
7400 if (tf)
7401 cond = TCG_COND_EQ;
7402 else
7403 cond = TCG_COND_NE;
7405 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7406 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7407 gen_load_fpr32(t0, fs);
7408 gen_store_fpr32(t0, fd);
7409 gen_set_label(l1);
7410 tcg_temp_free_i32(t0);
7413 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
7415 int cond;
7416 TCGv_i32 t0 = tcg_temp_new_i32();
7417 TCGv_i64 fp0;
7418 int l1 = gen_new_label();
7420 if (tf)
7421 cond = TCG_COND_EQ;
7422 else
7423 cond = TCG_COND_NE;
7425 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7426 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7427 tcg_temp_free_i32(t0);
7428 fp0 = tcg_temp_new_i64();
7429 gen_load_fpr64(ctx, fp0, fs);
7430 gen_store_fpr64(ctx, fp0, fd);
7431 tcg_temp_free_i64(fp0);
7432 gen_set_label(l1);
7435 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
7436 int cc, int tf)
7438 int cond;
7439 TCGv_i32 t0 = tcg_temp_new_i32();
7440 int l1 = gen_new_label();
7441 int l2 = gen_new_label();
7443 if (tf)
7444 cond = TCG_COND_EQ;
7445 else
7446 cond = TCG_COND_NE;
7448 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
7449 tcg_gen_brcondi_i32(cond, t0, 0, l1);
7450 gen_load_fpr32(t0, fs);
7451 gen_store_fpr32(t0, fd);
7452 gen_set_label(l1);
7454 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
7455 tcg_gen_brcondi_i32(cond, t0, 0, l2);
7456 gen_load_fpr32h(ctx, t0, fs);
7457 gen_store_fpr32h(ctx, t0, fd);
7458 tcg_temp_free_i32(t0);
7459 gen_set_label(l2);
7463 static void gen_farith (DisasContext *ctx, enum fopcode op1,
7464 int ft, int fs, int fd, int cc)
7466 const char *opn = "farith";
7467 const char *condnames[] = {
7468 "c.f",
7469 "c.un",
7470 "c.eq",
7471 "c.ueq",
7472 "c.olt",
7473 "c.ult",
7474 "c.ole",
7475 "c.ule",
7476 "c.sf",
7477 "c.ngle",
7478 "c.seq",
7479 "c.ngl",
7480 "c.lt",
7481 "c.nge",
7482 "c.le",
7483 "c.ngt",
7485 const char *condnames_abs[] = {
7486 "cabs.f",
7487 "cabs.un",
7488 "cabs.eq",
7489 "cabs.ueq",
7490 "cabs.olt",
7491 "cabs.ult",
7492 "cabs.ole",
7493 "cabs.ule",
7494 "cabs.sf",
7495 "cabs.ngle",
7496 "cabs.seq",
7497 "cabs.ngl",
7498 "cabs.lt",
7499 "cabs.nge",
7500 "cabs.le",
7501 "cabs.ngt",
7503 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
7504 uint32_t func = ctx->opcode & 0x3f;
7506 switch (op1) {
7507 case OPC_ADD_S:
7509 TCGv_i32 fp0 = tcg_temp_new_i32();
7510 TCGv_i32 fp1 = tcg_temp_new_i32();
7512 gen_load_fpr32(fp0, fs);
7513 gen_load_fpr32(fp1, ft);
7514 gen_helper_float_add_s(fp0, cpu_env, fp0, fp1);
7515 tcg_temp_free_i32(fp1);
7516 gen_store_fpr32(fp0, fd);
7517 tcg_temp_free_i32(fp0);
7519 opn = "add.s";
7520 optype = BINOP;
7521 break;
7522 case OPC_SUB_S:
7524 TCGv_i32 fp0 = tcg_temp_new_i32();
7525 TCGv_i32 fp1 = tcg_temp_new_i32();
7527 gen_load_fpr32(fp0, fs);
7528 gen_load_fpr32(fp1, ft);
7529 gen_helper_float_sub_s(fp0, cpu_env, fp0, fp1);
7530 tcg_temp_free_i32(fp1);
7531 gen_store_fpr32(fp0, fd);
7532 tcg_temp_free_i32(fp0);
7534 opn = "sub.s";
7535 optype = BINOP;
7536 break;
7537 case OPC_MUL_S:
7539 TCGv_i32 fp0 = tcg_temp_new_i32();
7540 TCGv_i32 fp1 = tcg_temp_new_i32();
7542 gen_load_fpr32(fp0, fs);
7543 gen_load_fpr32(fp1, ft);
7544 gen_helper_float_mul_s(fp0, cpu_env, fp0, fp1);
7545 tcg_temp_free_i32(fp1);
7546 gen_store_fpr32(fp0, fd);
7547 tcg_temp_free_i32(fp0);
7549 opn = "mul.s";
7550 optype = BINOP;
7551 break;
7552 case OPC_DIV_S:
7554 TCGv_i32 fp0 = tcg_temp_new_i32();
7555 TCGv_i32 fp1 = tcg_temp_new_i32();
7557 gen_load_fpr32(fp0, fs);
7558 gen_load_fpr32(fp1, ft);
7559 gen_helper_float_div_s(fp0, cpu_env, fp0, fp1);
7560 tcg_temp_free_i32(fp1);
7561 gen_store_fpr32(fp0, fd);
7562 tcg_temp_free_i32(fp0);
7564 opn = "div.s";
7565 optype = BINOP;
7566 break;
7567 case OPC_SQRT_S:
7569 TCGv_i32 fp0 = tcg_temp_new_i32();
7571 gen_load_fpr32(fp0, fs);
7572 gen_helper_float_sqrt_s(fp0, cpu_env, fp0);
7573 gen_store_fpr32(fp0, fd);
7574 tcg_temp_free_i32(fp0);
7576 opn = "sqrt.s";
7577 break;
7578 case OPC_ABS_S:
7580 TCGv_i32 fp0 = tcg_temp_new_i32();
7582 gen_load_fpr32(fp0, fs);
7583 gen_helper_float_abs_s(fp0, fp0);
7584 gen_store_fpr32(fp0, fd);
7585 tcg_temp_free_i32(fp0);
7587 opn = "abs.s";
7588 break;
7589 case OPC_MOV_S:
7591 TCGv_i32 fp0 = tcg_temp_new_i32();
7593 gen_load_fpr32(fp0, fs);
7594 gen_store_fpr32(fp0, fd);
7595 tcg_temp_free_i32(fp0);
7597 opn = "mov.s";
7598 break;
7599 case OPC_NEG_S:
7601 TCGv_i32 fp0 = tcg_temp_new_i32();
7603 gen_load_fpr32(fp0, fs);
7604 gen_helper_float_chs_s(fp0, fp0);
7605 gen_store_fpr32(fp0, fd);
7606 tcg_temp_free_i32(fp0);
7608 opn = "neg.s";
7609 break;
7610 case OPC_ROUND_L_S:
7611 check_cp1_64bitmode(ctx);
7613 TCGv_i32 fp32 = tcg_temp_new_i32();
7614 TCGv_i64 fp64 = tcg_temp_new_i64();
7616 gen_load_fpr32(fp32, fs);
7617 gen_helper_float_roundl_s(fp64, cpu_env, fp32);
7618 tcg_temp_free_i32(fp32);
7619 gen_store_fpr64(ctx, fp64, fd);
7620 tcg_temp_free_i64(fp64);
7622 opn = "round.l.s";
7623 break;
7624 case OPC_TRUNC_L_S:
7625 check_cp1_64bitmode(ctx);
7627 TCGv_i32 fp32 = tcg_temp_new_i32();
7628 TCGv_i64 fp64 = tcg_temp_new_i64();
7630 gen_load_fpr32(fp32, fs);
7631 gen_helper_float_truncl_s(fp64, cpu_env, fp32);
7632 tcg_temp_free_i32(fp32);
7633 gen_store_fpr64(ctx, fp64, fd);
7634 tcg_temp_free_i64(fp64);
7636 opn = "trunc.l.s";
7637 break;
7638 case OPC_CEIL_L_S:
7639 check_cp1_64bitmode(ctx);
7641 TCGv_i32 fp32 = tcg_temp_new_i32();
7642 TCGv_i64 fp64 = tcg_temp_new_i64();
7644 gen_load_fpr32(fp32, fs);
7645 gen_helper_float_ceill_s(fp64, cpu_env, fp32);
7646 tcg_temp_free_i32(fp32);
7647 gen_store_fpr64(ctx, fp64, fd);
7648 tcg_temp_free_i64(fp64);
7650 opn = "ceil.l.s";
7651 break;
7652 case OPC_FLOOR_L_S:
7653 check_cp1_64bitmode(ctx);
7655 TCGv_i32 fp32 = tcg_temp_new_i32();
7656 TCGv_i64 fp64 = tcg_temp_new_i64();
7658 gen_load_fpr32(fp32, fs);
7659 gen_helper_float_floorl_s(fp64, cpu_env, fp32);
7660 tcg_temp_free_i32(fp32);
7661 gen_store_fpr64(ctx, fp64, fd);
7662 tcg_temp_free_i64(fp64);
7664 opn = "floor.l.s";
7665 break;
7666 case OPC_ROUND_W_S:
7668 TCGv_i32 fp0 = tcg_temp_new_i32();
7670 gen_load_fpr32(fp0, fs);
7671 gen_helper_float_roundw_s(fp0, cpu_env, fp0);
7672 gen_store_fpr32(fp0, fd);
7673 tcg_temp_free_i32(fp0);
7675 opn = "round.w.s";
7676 break;
7677 case OPC_TRUNC_W_S:
7679 TCGv_i32 fp0 = tcg_temp_new_i32();
7681 gen_load_fpr32(fp0, fs);
7682 gen_helper_float_truncw_s(fp0, cpu_env, fp0);
7683 gen_store_fpr32(fp0, fd);
7684 tcg_temp_free_i32(fp0);
7686 opn = "trunc.w.s";
7687 break;
7688 case OPC_CEIL_W_S:
7690 TCGv_i32 fp0 = tcg_temp_new_i32();
7692 gen_load_fpr32(fp0, fs);
7693 gen_helper_float_ceilw_s(fp0, cpu_env, fp0);
7694 gen_store_fpr32(fp0, fd);
7695 tcg_temp_free_i32(fp0);
7697 opn = "ceil.w.s";
7698 break;
7699 case OPC_FLOOR_W_S:
7701 TCGv_i32 fp0 = tcg_temp_new_i32();
7703 gen_load_fpr32(fp0, fs);
7704 gen_helper_float_floorw_s(fp0, cpu_env, fp0);
7705 gen_store_fpr32(fp0, fd);
7706 tcg_temp_free_i32(fp0);
7708 opn = "floor.w.s";
7709 break;
7710 case OPC_MOVCF_S:
7711 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7712 opn = "movcf.s";
7713 break;
7714 case OPC_MOVZ_S:
7716 int l1 = gen_new_label();
7717 TCGv_i32 fp0;
7719 if (ft != 0) {
7720 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7722 fp0 = tcg_temp_new_i32();
7723 gen_load_fpr32(fp0, fs);
7724 gen_store_fpr32(fp0, fd);
7725 tcg_temp_free_i32(fp0);
7726 gen_set_label(l1);
7728 opn = "movz.s";
7729 break;
7730 case OPC_MOVN_S:
7732 int l1 = gen_new_label();
7733 TCGv_i32 fp0;
7735 if (ft != 0) {
7736 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7737 fp0 = tcg_temp_new_i32();
7738 gen_load_fpr32(fp0, fs);
7739 gen_store_fpr32(fp0, fd);
7740 tcg_temp_free_i32(fp0);
7741 gen_set_label(l1);
7744 opn = "movn.s";
7745 break;
7746 case OPC_RECIP_S:
7747 check_cop1x(ctx);
7749 TCGv_i32 fp0 = tcg_temp_new_i32();
7751 gen_load_fpr32(fp0, fs);
7752 gen_helper_float_recip_s(fp0, cpu_env, fp0);
7753 gen_store_fpr32(fp0, fd);
7754 tcg_temp_free_i32(fp0);
7756 opn = "recip.s";
7757 break;
7758 case OPC_RSQRT_S:
7759 check_cop1x(ctx);
7761 TCGv_i32 fp0 = tcg_temp_new_i32();
7763 gen_load_fpr32(fp0, fs);
7764 gen_helper_float_rsqrt_s(fp0, cpu_env, fp0);
7765 gen_store_fpr32(fp0, fd);
7766 tcg_temp_free_i32(fp0);
7768 opn = "rsqrt.s";
7769 break;
7770 case OPC_RECIP2_S:
7771 check_cp1_64bitmode(ctx);
7773 TCGv_i32 fp0 = tcg_temp_new_i32();
7774 TCGv_i32 fp1 = tcg_temp_new_i32();
7776 gen_load_fpr32(fp0, fs);
7777 gen_load_fpr32(fp1, ft);
7778 gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
7779 tcg_temp_free_i32(fp1);
7780 gen_store_fpr32(fp0, fd);
7781 tcg_temp_free_i32(fp0);
7783 opn = "recip2.s";
7784 break;
7785 case OPC_RECIP1_S:
7786 check_cp1_64bitmode(ctx);
7788 TCGv_i32 fp0 = tcg_temp_new_i32();
7790 gen_load_fpr32(fp0, fs);
7791 gen_helper_float_recip1_s(fp0, cpu_env, fp0);
7792 gen_store_fpr32(fp0, fd);
7793 tcg_temp_free_i32(fp0);
7795 opn = "recip1.s";
7796 break;
7797 case OPC_RSQRT1_S:
7798 check_cp1_64bitmode(ctx);
7800 TCGv_i32 fp0 = tcg_temp_new_i32();
7802 gen_load_fpr32(fp0, fs);
7803 gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
7804 gen_store_fpr32(fp0, fd);
7805 tcg_temp_free_i32(fp0);
7807 opn = "rsqrt1.s";
7808 break;
7809 case OPC_RSQRT2_S:
7810 check_cp1_64bitmode(ctx);
7812 TCGv_i32 fp0 = tcg_temp_new_i32();
7813 TCGv_i32 fp1 = tcg_temp_new_i32();
7815 gen_load_fpr32(fp0, fs);
7816 gen_load_fpr32(fp1, ft);
7817 gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
7818 tcg_temp_free_i32(fp1);
7819 gen_store_fpr32(fp0, fd);
7820 tcg_temp_free_i32(fp0);
7822 opn = "rsqrt2.s";
7823 break;
7824 case OPC_CVT_D_S:
7825 check_cp1_registers(ctx, fd);
7827 TCGv_i32 fp32 = tcg_temp_new_i32();
7828 TCGv_i64 fp64 = tcg_temp_new_i64();
7830 gen_load_fpr32(fp32, fs);
7831 gen_helper_float_cvtd_s(fp64, cpu_env, fp32);
7832 tcg_temp_free_i32(fp32);
7833 gen_store_fpr64(ctx, fp64, fd);
7834 tcg_temp_free_i64(fp64);
7836 opn = "cvt.d.s";
7837 break;
7838 case OPC_CVT_W_S:
7840 TCGv_i32 fp0 = tcg_temp_new_i32();
7842 gen_load_fpr32(fp0, fs);
7843 gen_helper_float_cvtw_s(fp0, cpu_env, fp0);
7844 gen_store_fpr32(fp0, fd);
7845 tcg_temp_free_i32(fp0);
7847 opn = "cvt.w.s";
7848 break;
7849 case OPC_CVT_L_S:
7850 check_cp1_64bitmode(ctx);
7852 TCGv_i32 fp32 = tcg_temp_new_i32();
7853 TCGv_i64 fp64 = tcg_temp_new_i64();
7855 gen_load_fpr32(fp32, fs);
7856 gen_helper_float_cvtl_s(fp64, cpu_env, fp32);
7857 tcg_temp_free_i32(fp32);
7858 gen_store_fpr64(ctx, fp64, fd);
7859 tcg_temp_free_i64(fp64);
7861 opn = "cvt.l.s";
7862 break;
7863 case OPC_CVT_PS_S:
7864 check_cp1_64bitmode(ctx);
7866 TCGv_i64 fp64 = tcg_temp_new_i64();
7867 TCGv_i32 fp32_0 = tcg_temp_new_i32();
7868 TCGv_i32 fp32_1 = tcg_temp_new_i32();
7870 gen_load_fpr32(fp32_0, fs);
7871 gen_load_fpr32(fp32_1, ft);
7872 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
7873 tcg_temp_free_i32(fp32_1);
7874 tcg_temp_free_i32(fp32_0);
7875 gen_store_fpr64(ctx, fp64, fd);
7876 tcg_temp_free_i64(fp64);
7878 opn = "cvt.ps.s";
7879 break;
7880 case OPC_CMP_F_S:
7881 case OPC_CMP_UN_S:
7882 case OPC_CMP_EQ_S:
7883 case OPC_CMP_UEQ_S:
7884 case OPC_CMP_OLT_S:
7885 case OPC_CMP_ULT_S:
7886 case OPC_CMP_OLE_S:
7887 case OPC_CMP_ULE_S:
7888 case OPC_CMP_SF_S:
7889 case OPC_CMP_NGLE_S:
7890 case OPC_CMP_SEQ_S:
7891 case OPC_CMP_NGL_S:
7892 case OPC_CMP_LT_S:
7893 case OPC_CMP_NGE_S:
7894 case OPC_CMP_LE_S:
7895 case OPC_CMP_NGT_S:
7896 if (ctx->opcode & (1 << 6)) {
7897 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
7898 opn = condnames_abs[func-48];
7899 } else {
7900 gen_cmp_s(ctx, func-48, ft, fs, cc);
7901 opn = condnames[func-48];
7903 break;
7904 case OPC_ADD_D:
7905 check_cp1_registers(ctx, fs | ft | fd);
7907 TCGv_i64 fp0 = tcg_temp_new_i64();
7908 TCGv_i64 fp1 = tcg_temp_new_i64();
7910 gen_load_fpr64(ctx, fp0, fs);
7911 gen_load_fpr64(ctx, fp1, ft);
7912 gen_helper_float_add_d(fp0, cpu_env, fp0, fp1);
7913 tcg_temp_free_i64(fp1);
7914 gen_store_fpr64(ctx, fp0, fd);
7915 tcg_temp_free_i64(fp0);
7917 opn = "add.d";
7918 optype = BINOP;
7919 break;
7920 case OPC_SUB_D:
7921 check_cp1_registers(ctx, fs | ft | fd);
7923 TCGv_i64 fp0 = tcg_temp_new_i64();
7924 TCGv_i64 fp1 = tcg_temp_new_i64();
7926 gen_load_fpr64(ctx, fp0, fs);
7927 gen_load_fpr64(ctx, fp1, ft);
7928 gen_helper_float_sub_d(fp0, cpu_env, fp0, fp1);
7929 tcg_temp_free_i64(fp1);
7930 gen_store_fpr64(ctx, fp0, fd);
7931 tcg_temp_free_i64(fp0);
7933 opn = "sub.d";
7934 optype = BINOP;
7935 break;
7936 case OPC_MUL_D:
7937 check_cp1_registers(ctx, fs | ft | fd);
7939 TCGv_i64 fp0 = tcg_temp_new_i64();
7940 TCGv_i64 fp1 = tcg_temp_new_i64();
7942 gen_load_fpr64(ctx, fp0, fs);
7943 gen_load_fpr64(ctx, fp1, ft);
7944 gen_helper_float_mul_d(fp0, cpu_env, fp0, fp1);
7945 tcg_temp_free_i64(fp1);
7946 gen_store_fpr64(ctx, fp0, fd);
7947 tcg_temp_free_i64(fp0);
7949 opn = "mul.d";
7950 optype = BINOP;
7951 break;
7952 case OPC_DIV_D:
7953 check_cp1_registers(ctx, fs | ft | fd);
7955 TCGv_i64 fp0 = tcg_temp_new_i64();
7956 TCGv_i64 fp1 = tcg_temp_new_i64();
7958 gen_load_fpr64(ctx, fp0, fs);
7959 gen_load_fpr64(ctx, fp1, ft);
7960 gen_helper_float_div_d(fp0, cpu_env, fp0, fp1);
7961 tcg_temp_free_i64(fp1);
7962 gen_store_fpr64(ctx, fp0, fd);
7963 tcg_temp_free_i64(fp0);
7965 opn = "div.d";
7966 optype = BINOP;
7967 break;
7968 case OPC_SQRT_D:
7969 check_cp1_registers(ctx, fs | fd);
7971 TCGv_i64 fp0 = tcg_temp_new_i64();
7973 gen_load_fpr64(ctx, fp0, fs);
7974 gen_helper_float_sqrt_d(fp0, cpu_env, fp0);
7975 gen_store_fpr64(ctx, fp0, fd);
7976 tcg_temp_free_i64(fp0);
7978 opn = "sqrt.d";
7979 break;
7980 case OPC_ABS_D:
7981 check_cp1_registers(ctx, fs | fd);
7983 TCGv_i64 fp0 = tcg_temp_new_i64();
7985 gen_load_fpr64(ctx, fp0, fs);
7986 gen_helper_float_abs_d(fp0, fp0);
7987 gen_store_fpr64(ctx, fp0, fd);
7988 tcg_temp_free_i64(fp0);
7990 opn = "abs.d";
7991 break;
7992 case OPC_MOV_D:
7993 check_cp1_registers(ctx, fs | fd);
7995 TCGv_i64 fp0 = tcg_temp_new_i64();
7997 gen_load_fpr64(ctx, fp0, fs);
7998 gen_store_fpr64(ctx, fp0, fd);
7999 tcg_temp_free_i64(fp0);
8001 opn = "mov.d";
8002 break;
8003 case OPC_NEG_D:
8004 check_cp1_registers(ctx, fs | fd);
8006 TCGv_i64 fp0 = tcg_temp_new_i64();
8008 gen_load_fpr64(ctx, fp0, fs);
8009 gen_helper_float_chs_d(fp0, fp0);
8010 gen_store_fpr64(ctx, fp0, fd);
8011 tcg_temp_free_i64(fp0);
8013 opn = "neg.d";
8014 break;
8015 case OPC_ROUND_L_D:
8016 check_cp1_64bitmode(ctx);
8018 TCGv_i64 fp0 = tcg_temp_new_i64();
8020 gen_load_fpr64(ctx, fp0, fs);
8021 gen_helper_float_roundl_d(fp0, cpu_env, fp0);
8022 gen_store_fpr64(ctx, fp0, fd);
8023 tcg_temp_free_i64(fp0);
8025 opn = "round.l.d";
8026 break;
8027 case OPC_TRUNC_L_D:
8028 check_cp1_64bitmode(ctx);
8030 TCGv_i64 fp0 = tcg_temp_new_i64();
8032 gen_load_fpr64(ctx, fp0, fs);
8033 gen_helper_float_truncl_d(fp0, cpu_env, fp0);
8034 gen_store_fpr64(ctx, fp0, fd);
8035 tcg_temp_free_i64(fp0);
8037 opn = "trunc.l.d";
8038 break;
8039 case OPC_CEIL_L_D:
8040 check_cp1_64bitmode(ctx);
8042 TCGv_i64 fp0 = tcg_temp_new_i64();
8044 gen_load_fpr64(ctx, fp0, fs);
8045 gen_helper_float_ceill_d(fp0, cpu_env, fp0);
8046 gen_store_fpr64(ctx, fp0, fd);
8047 tcg_temp_free_i64(fp0);
8049 opn = "ceil.l.d";
8050 break;
8051 case OPC_FLOOR_L_D:
8052 check_cp1_64bitmode(ctx);
8054 TCGv_i64 fp0 = tcg_temp_new_i64();
8056 gen_load_fpr64(ctx, fp0, fs);
8057 gen_helper_float_floorl_d(fp0, cpu_env, fp0);
8058 gen_store_fpr64(ctx, fp0, fd);
8059 tcg_temp_free_i64(fp0);
8061 opn = "floor.l.d";
8062 break;
8063 case OPC_ROUND_W_D:
8064 check_cp1_registers(ctx, fs);
8066 TCGv_i32 fp32 = tcg_temp_new_i32();
8067 TCGv_i64 fp64 = tcg_temp_new_i64();
8069 gen_load_fpr64(ctx, fp64, fs);
8070 gen_helper_float_roundw_d(fp32, cpu_env, fp64);
8071 tcg_temp_free_i64(fp64);
8072 gen_store_fpr32(fp32, fd);
8073 tcg_temp_free_i32(fp32);
8075 opn = "round.w.d";
8076 break;
8077 case OPC_TRUNC_W_D:
8078 check_cp1_registers(ctx, fs);
8080 TCGv_i32 fp32 = tcg_temp_new_i32();
8081 TCGv_i64 fp64 = tcg_temp_new_i64();
8083 gen_load_fpr64(ctx, fp64, fs);
8084 gen_helper_float_truncw_d(fp32, cpu_env, fp64);
8085 tcg_temp_free_i64(fp64);
8086 gen_store_fpr32(fp32, fd);
8087 tcg_temp_free_i32(fp32);
8089 opn = "trunc.w.d";
8090 break;
8091 case OPC_CEIL_W_D:
8092 check_cp1_registers(ctx, fs);
8094 TCGv_i32 fp32 = tcg_temp_new_i32();
8095 TCGv_i64 fp64 = tcg_temp_new_i64();
8097 gen_load_fpr64(ctx, fp64, fs);
8098 gen_helper_float_ceilw_d(fp32, cpu_env, fp64);
8099 tcg_temp_free_i64(fp64);
8100 gen_store_fpr32(fp32, fd);
8101 tcg_temp_free_i32(fp32);
8103 opn = "ceil.w.d";
8104 break;
8105 case OPC_FLOOR_W_D:
8106 check_cp1_registers(ctx, fs);
8108 TCGv_i32 fp32 = tcg_temp_new_i32();
8109 TCGv_i64 fp64 = tcg_temp_new_i64();
8111 gen_load_fpr64(ctx, fp64, fs);
8112 gen_helper_float_floorw_d(fp32, cpu_env, fp64);
8113 tcg_temp_free_i64(fp64);
8114 gen_store_fpr32(fp32, fd);
8115 tcg_temp_free_i32(fp32);
8117 opn = "floor.w.d";
8118 break;
8119 case OPC_MOVCF_D:
8120 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8121 opn = "movcf.d";
8122 break;
8123 case OPC_MOVZ_D:
8125 int l1 = gen_new_label();
8126 TCGv_i64 fp0;
8128 if (ft != 0) {
8129 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8131 fp0 = tcg_temp_new_i64();
8132 gen_load_fpr64(ctx, fp0, fs);
8133 gen_store_fpr64(ctx, fp0, fd);
8134 tcg_temp_free_i64(fp0);
8135 gen_set_label(l1);
8137 opn = "movz.d";
8138 break;
8139 case OPC_MOVN_D:
8141 int l1 = gen_new_label();
8142 TCGv_i64 fp0;
8144 if (ft != 0) {
8145 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8146 fp0 = tcg_temp_new_i64();
8147 gen_load_fpr64(ctx, fp0, fs);
8148 gen_store_fpr64(ctx, fp0, fd);
8149 tcg_temp_free_i64(fp0);
8150 gen_set_label(l1);
8153 opn = "movn.d";
8154 break;
8155 case OPC_RECIP_D:
8156 check_cp1_64bitmode(ctx);
8158 TCGv_i64 fp0 = tcg_temp_new_i64();
8160 gen_load_fpr64(ctx, fp0, fs);
8161 gen_helper_float_recip_d(fp0, cpu_env, fp0);
8162 gen_store_fpr64(ctx, fp0, fd);
8163 tcg_temp_free_i64(fp0);
8165 opn = "recip.d";
8166 break;
8167 case OPC_RSQRT_D:
8168 check_cp1_64bitmode(ctx);
8170 TCGv_i64 fp0 = tcg_temp_new_i64();
8172 gen_load_fpr64(ctx, fp0, fs);
8173 gen_helper_float_rsqrt_d(fp0, cpu_env, fp0);
8174 gen_store_fpr64(ctx, fp0, fd);
8175 tcg_temp_free_i64(fp0);
8177 opn = "rsqrt.d";
8178 break;
8179 case OPC_RECIP2_D:
8180 check_cp1_64bitmode(ctx);
8182 TCGv_i64 fp0 = tcg_temp_new_i64();
8183 TCGv_i64 fp1 = tcg_temp_new_i64();
8185 gen_load_fpr64(ctx, fp0, fs);
8186 gen_load_fpr64(ctx, fp1, ft);
8187 gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
8188 tcg_temp_free_i64(fp1);
8189 gen_store_fpr64(ctx, fp0, fd);
8190 tcg_temp_free_i64(fp0);
8192 opn = "recip2.d";
8193 break;
8194 case OPC_RECIP1_D:
8195 check_cp1_64bitmode(ctx);
8197 TCGv_i64 fp0 = tcg_temp_new_i64();
8199 gen_load_fpr64(ctx, fp0, fs);
8200 gen_helper_float_recip1_d(fp0, cpu_env, fp0);
8201 gen_store_fpr64(ctx, fp0, fd);
8202 tcg_temp_free_i64(fp0);
8204 opn = "recip1.d";
8205 break;
8206 case OPC_RSQRT1_D:
8207 check_cp1_64bitmode(ctx);
8209 TCGv_i64 fp0 = tcg_temp_new_i64();
8211 gen_load_fpr64(ctx, fp0, fs);
8212 gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
8213 gen_store_fpr64(ctx, fp0, fd);
8214 tcg_temp_free_i64(fp0);
8216 opn = "rsqrt1.d";
8217 break;
8218 case OPC_RSQRT2_D:
8219 check_cp1_64bitmode(ctx);
8221 TCGv_i64 fp0 = tcg_temp_new_i64();
8222 TCGv_i64 fp1 = tcg_temp_new_i64();
8224 gen_load_fpr64(ctx, fp0, fs);
8225 gen_load_fpr64(ctx, fp1, ft);
8226 gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
8227 tcg_temp_free_i64(fp1);
8228 gen_store_fpr64(ctx, fp0, fd);
8229 tcg_temp_free_i64(fp0);
8231 opn = "rsqrt2.d";
8232 break;
8233 case OPC_CMP_F_D:
8234 case OPC_CMP_UN_D:
8235 case OPC_CMP_EQ_D:
8236 case OPC_CMP_UEQ_D:
8237 case OPC_CMP_OLT_D:
8238 case OPC_CMP_ULT_D:
8239 case OPC_CMP_OLE_D:
8240 case OPC_CMP_ULE_D:
8241 case OPC_CMP_SF_D:
8242 case OPC_CMP_NGLE_D:
8243 case OPC_CMP_SEQ_D:
8244 case OPC_CMP_NGL_D:
8245 case OPC_CMP_LT_D:
8246 case OPC_CMP_NGE_D:
8247 case OPC_CMP_LE_D:
8248 case OPC_CMP_NGT_D:
8249 if (ctx->opcode & (1 << 6)) {
8250 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
8251 opn = condnames_abs[func-48];
8252 } else {
8253 gen_cmp_d(ctx, func-48, ft, fs, cc);
8254 opn = condnames[func-48];
8256 break;
8257 case OPC_CVT_S_D:
8258 check_cp1_registers(ctx, fs);
8260 TCGv_i32 fp32 = tcg_temp_new_i32();
8261 TCGv_i64 fp64 = tcg_temp_new_i64();
8263 gen_load_fpr64(ctx, fp64, fs);
8264 gen_helper_float_cvts_d(fp32, cpu_env, fp64);
8265 tcg_temp_free_i64(fp64);
8266 gen_store_fpr32(fp32, fd);
8267 tcg_temp_free_i32(fp32);
8269 opn = "cvt.s.d";
8270 break;
8271 case OPC_CVT_W_D:
8272 check_cp1_registers(ctx, fs);
8274 TCGv_i32 fp32 = tcg_temp_new_i32();
8275 TCGv_i64 fp64 = tcg_temp_new_i64();
8277 gen_load_fpr64(ctx, fp64, fs);
8278 gen_helper_float_cvtw_d(fp32, cpu_env, fp64);
8279 tcg_temp_free_i64(fp64);
8280 gen_store_fpr32(fp32, fd);
8281 tcg_temp_free_i32(fp32);
8283 opn = "cvt.w.d";
8284 break;
8285 case OPC_CVT_L_D:
8286 check_cp1_64bitmode(ctx);
8288 TCGv_i64 fp0 = tcg_temp_new_i64();
8290 gen_load_fpr64(ctx, fp0, fs);
8291 gen_helper_float_cvtl_d(fp0, cpu_env, fp0);
8292 gen_store_fpr64(ctx, fp0, fd);
8293 tcg_temp_free_i64(fp0);
8295 opn = "cvt.l.d";
8296 break;
8297 case OPC_CVT_S_W:
8299 TCGv_i32 fp0 = tcg_temp_new_i32();
8301 gen_load_fpr32(fp0, fs);
8302 gen_helper_float_cvts_w(fp0, cpu_env, fp0);
8303 gen_store_fpr32(fp0, fd);
8304 tcg_temp_free_i32(fp0);
8306 opn = "cvt.s.w";
8307 break;
8308 case OPC_CVT_D_W:
8309 check_cp1_registers(ctx, fd);
8311 TCGv_i32 fp32 = tcg_temp_new_i32();
8312 TCGv_i64 fp64 = tcg_temp_new_i64();
8314 gen_load_fpr32(fp32, fs);
8315 gen_helper_float_cvtd_w(fp64, cpu_env, fp32);
8316 tcg_temp_free_i32(fp32);
8317 gen_store_fpr64(ctx, fp64, fd);
8318 tcg_temp_free_i64(fp64);
8320 opn = "cvt.d.w";
8321 break;
8322 case OPC_CVT_S_L:
8323 check_cp1_64bitmode(ctx);
8325 TCGv_i32 fp32 = tcg_temp_new_i32();
8326 TCGv_i64 fp64 = tcg_temp_new_i64();
8328 gen_load_fpr64(ctx, fp64, fs);
8329 gen_helper_float_cvts_l(fp32, cpu_env, fp64);
8330 tcg_temp_free_i64(fp64);
8331 gen_store_fpr32(fp32, fd);
8332 tcg_temp_free_i32(fp32);
8334 opn = "cvt.s.l";
8335 break;
8336 case OPC_CVT_D_L:
8337 check_cp1_64bitmode(ctx);
8339 TCGv_i64 fp0 = tcg_temp_new_i64();
8341 gen_load_fpr64(ctx, fp0, fs);
8342 gen_helper_float_cvtd_l(fp0, cpu_env, fp0);
8343 gen_store_fpr64(ctx, fp0, fd);
8344 tcg_temp_free_i64(fp0);
8346 opn = "cvt.d.l";
8347 break;
8348 case OPC_CVT_PS_PW:
8349 check_cp1_64bitmode(ctx);
8351 TCGv_i64 fp0 = tcg_temp_new_i64();
8353 gen_load_fpr64(ctx, fp0, fs);
8354 gen_helper_float_cvtps_pw(fp0, cpu_env, fp0);
8355 gen_store_fpr64(ctx, fp0, fd);
8356 tcg_temp_free_i64(fp0);
8358 opn = "cvt.ps.pw";
8359 break;
8360 case OPC_ADD_PS:
8361 check_cp1_64bitmode(ctx);
8363 TCGv_i64 fp0 = tcg_temp_new_i64();
8364 TCGv_i64 fp1 = tcg_temp_new_i64();
8366 gen_load_fpr64(ctx, fp0, fs);
8367 gen_load_fpr64(ctx, fp1, ft);
8368 gen_helper_float_add_ps(fp0, cpu_env, fp0, fp1);
8369 tcg_temp_free_i64(fp1);
8370 gen_store_fpr64(ctx, fp0, fd);
8371 tcg_temp_free_i64(fp0);
8373 opn = "add.ps";
8374 break;
8375 case OPC_SUB_PS:
8376 check_cp1_64bitmode(ctx);
8378 TCGv_i64 fp0 = tcg_temp_new_i64();
8379 TCGv_i64 fp1 = tcg_temp_new_i64();
8381 gen_load_fpr64(ctx, fp0, fs);
8382 gen_load_fpr64(ctx, fp1, ft);
8383 gen_helper_float_sub_ps(fp0, cpu_env, fp0, fp1);
8384 tcg_temp_free_i64(fp1);
8385 gen_store_fpr64(ctx, fp0, fd);
8386 tcg_temp_free_i64(fp0);
8388 opn = "sub.ps";
8389 break;
8390 case OPC_MUL_PS:
8391 check_cp1_64bitmode(ctx);
8393 TCGv_i64 fp0 = tcg_temp_new_i64();
8394 TCGv_i64 fp1 = tcg_temp_new_i64();
8396 gen_load_fpr64(ctx, fp0, fs);
8397 gen_load_fpr64(ctx, fp1, ft);
8398 gen_helper_float_mul_ps(fp0, cpu_env, fp0, fp1);
8399 tcg_temp_free_i64(fp1);
8400 gen_store_fpr64(ctx, fp0, fd);
8401 tcg_temp_free_i64(fp0);
8403 opn = "mul.ps";
8404 break;
8405 case OPC_ABS_PS:
8406 check_cp1_64bitmode(ctx);
8408 TCGv_i64 fp0 = tcg_temp_new_i64();
8410 gen_load_fpr64(ctx, fp0, fs);
8411 gen_helper_float_abs_ps(fp0, fp0);
8412 gen_store_fpr64(ctx, fp0, fd);
8413 tcg_temp_free_i64(fp0);
8415 opn = "abs.ps";
8416 break;
8417 case OPC_MOV_PS:
8418 check_cp1_64bitmode(ctx);
8420 TCGv_i64 fp0 = tcg_temp_new_i64();
8422 gen_load_fpr64(ctx, fp0, fs);
8423 gen_store_fpr64(ctx, fp0, fd);
8424 tcg_temp_free_i64(fp0);
8426 opn = "mov.ps";
8427 break;
8428 case OPC_NEG_PS:
8429 check_cp1_64bitmode(ctx);
8431 TCGv_i64 fp0 = tcg_temp_new_i64();
8433 gen_load_fpr64(ctx, fp0, fs);
8434 gen_helper_float_chs_ps(fp0, fp0);
8435 gen_store_fpr64(ctx, fp0, fd);
8436 tcg_temp_free_i64(fp0);
8438 opn = "neg.ps";
8439 break;
8440 case OPC_MOVCF_PS:
8441 check_cp1_64bitmode(ctx);
8442 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
8443 opn = "movcf.ps";
8444 break;
8445 case OPC_MOVZ_PS:
8446 check_cp1_64bitmode(ctx);
8448 int l1 = gen_new_label();
8449 TCGv_i64 fp0;
8451 if (ft != 0)
8452 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
8453 fp0 = tcg_temp_new_i64();
8454 gen_load_fpr64(ctx, fp0, fs);
8455 gen_store_fpr64(ctx, fp0, fd);
8456 tcg_temp_free_i64(fp0);
8457 gen_set_label(l1);
8459 opn = "movz.ps";
8460 break;
8461 case OPC_MOVN_PS:
8462 check_cp1_64bitmode(ctx);
8464 int l1 = gen_new_label();
8465 TCGv_i64 fp0;
8467 if (ft != 0) {
8468 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
8469 fp0 = tcg_temp_new_i64();
8470 gen_load_fpr64(ctx, fp0, fs);
8471 gen_store_fpr64(ctx, fp0, fd);
8472 tcg_temp_free_i64(fp0);
8473 gen_set_label(l1);
8476 opn = "movn.ps";
8477 break;
8478 case OPC_ADDR_PS:
8479 check_cp1_64bitmode(ctx);
8481 TCGv_i64 fp0 = tcg_temp_new_i64();
8482 TCGv_i64 fp1 = tcg_temp_new_i64();
8484 gen_load_fpr64(ctx, fp0, ft);
8485 gen_load_fpr64(ctx, fp1, fs);
8486 gen_helper_float_addr_ps(fp0, cpu_env, fp0, fp1);
8487 tcg_temp_free_i64(fp1);
8488 gen_store_fpr64(ctx, fp0, fd);
8489 tcg_temp_free_i64(fp0);
8491 opn = "addr.ps";
8492 break;
8493 case OPC_MULR_PS:
8494 check_cp1_64bitmode(ctx);
8496 TCGv_i64 fp0 = tcg_temp_new_i64();
8497 TCGv_i64 fp1 = tcg_temp_new_i64();
8499 gen_load_fpr64(ctx, fp0, ft);
8500 gen_load_fpr64(ctx, fp1, fs);
8501 gen_helper_float_mulr_ps(fp0, cpu_env, fp0, fp1);
8502 tcg_temp_free_i64(fp1);
8503 gen_store_fpr64(ctx, fp0, fd);
8504 tcg_temp_free_i64(fp0);
8506 opn = "mulr.ps";
8507 break;
8508 case OPC_RECIP2_PS:
8509 check_cp1_64bitmode(ctx);
8511 TCGv_i64 fp0 = tcg_temp_new_i64();
8512 TCGv_i64 fp1 = tcg_temp_new_i64();
8514 gen_load_fpr64(ctx, fp0, fs);
8515 gen_load_fpr64(ctx, fp1, ft);
8516 gen_helper_float_recip2_ps(fp0, cpu_env, fp0, fp1);
8517 tcg_temp_free_i64(fp1);
8518 gen_store_fpr64(ctx, fp0, fd);
8519 tcg_temp_free_i64(fp0);
8521 opn = "recip2.ps";
8522 break;
8523 case OPC_RECIP1_PS:
8524 check_cp1_64bitmode(ctx);
8526 TCGv_i64 fp0 = tcg_temp_new_i64();
8528 gen_load_fpr64(ctx, fp0, fs);
8529 gen_helper_float_recip1_ps(fp0, cpu_env, fp0);
8530 gen_store_fpr64(ctx, fp0, fd);
8531 tcg_temp_free_i64(fp0);
8533 opn = "recip1.ps";
8534 break;
8535 case OPC_RSQRT1_PS:
8536 check_cp1_64bitmode(ctx);
8538 TCGv_i64 fp0 = tcg_temp_new_i64();
8540 gen_load_fpr64(ctx, fp0, fs);
8541 gen_helper_float_rsqrt1_ps(fp0, cpu_env, fp0);
8542 gen_store_fpr64(ctx, fp0, fd);
8543 tcg_temp_free_i64(fp0);
8545 opn = "rsqrt1.ps";
8546 break;
8547 case OPC_RSQRT2_PS:
8548 check_cp1_64bitmode(ctx);
8550 TCGv_i64 fp0 = tcg_temp_new_i64();
8551 TCGv_i64 fp1 = tcg_temp_new_i64();
8553 gen_load_fpr64(ctx, fp0, fs);
8554 gen_load_fpr64(ctx, fp1, ft);
8555 gen_helper_float_rsqrt2_ps(fp0, cpu_env, fp0, fp1);
8556 tcg_temp_free_i64(fp1);
8557 gen_store_fpr64(ctx, fp0, fd);
8558 tcg_temp_free_i64(fp0);
8560 opn = "rsqrt2.ps";
8561 break;
8562 case OPC_CVT_S_PU:
8563 check_cp1_64bitmode(ctx);
8565 TCGv_i32 fp0 = tcg_temp_new_i32();
8567 gen_load_fpr32h(ctx, fp0, fs);
8568 gen_helper_float_cvts_pu(fp0, cpu_env, fp0);
8569 gen_store_fpr32(fp0, fd);
8570 tcg_temp_free_i32(fp0);
8572 opn = "cvt.s.pu";
8573 break;
8574 case OPC_CVT_PW_PS:
8575 check_cp1_64bitmode(ctx);
8577 TCGv_i64 fp0 = tcg_temp_new_i64();
8579 gen_load_fpr64(ctx, fp0, fs);
8580 gen_helper_float_cvtpw_ps(fp0, cpu_env, fp0);
8581 gen_store_fpr64(ctx, fp0, fd);
8582 tcg_temp_free_i64(fp0);
8584 opn = "cvt.pw.ps";
8585 break;
8586 case OPC_CVT_S_PL:
8587 check_cp1_64bitmode(ctx);
8589 TCGv_i32 fp0 = tcg_temp_new_i32();
8591 gen_load_fpr32(fp0, fs);
8592 gen_helper_float_cvts_pl(fp0, cpu_env, fp0);
8593 gen_store_fpr32(fp0, fd);
8594 tcg_temp_free_i32(fp0);
8596 opn = "cvt.s.pl";
8597 break;
8598 case OPC_PLL_PS:
8599 check_cp1_64bitmode(ctx);
8601 TCGv_i32 fp0 = tcg_temp_new_i32();
8602 TCGv_i32 fp1 = tcg_temp_new_i32();
8604 gen_load_fpr32(fp0, fs);
8605 gen_load_fpr32(fp1, ft);
8606 gen_store_fpr32h(ctx, fp0, fd);
8607 gen_store_fpr32(fp1, fd);
8608 tcg_temp_free_i32(fp0);
8609 tcg_temp_free_i32(fp1);
8611 opn = "pll.ps";
8612 break;
8613 case OPC_PLU_PS:
8614 check_cp1_64bitmode(ctx);
8616 TCGv_i32 fp0 = tcg_temp_new_i32();
8617 TCGv_i32 fp1 = tcg_temp_new_i32();
8619 gen_load_fpr32(fp0, fs);
8620 gen_load_fpr32h(ctx, fp1, ft);
8621 gen_store_fpr32(fp1, fd);
8622 gen_store_fpr32h(ctx, fp0, fd);
8623 tcg_temp_free_i32(fp0);
8624 tcg_temp_free_i32(fp1);
8626 opn = "plu.ps";
8627 break;
8628 case OPC_PUL_PS:
8629 check_cp1_64bitmode(ctx);
8631 TCGv_i32 fp0 = tcg_temp_new_i32();
8632 TCGv_i32 fp1 = tcg_temp_new_i32();
8634 gen_load_fpr32h(ctx, fp0, fs);
8635 gen_load_fpr32(fp1, ft);
8636 gen_store_fpr32(fp1, fd);
8637 gen_store_fpr32h(ctx, fp0, fd);
8638 tcg_temp_free_i32(fp0);
8639 tcg_temp_free_i32(fp1);
8641 opn = "pul.ps";
8642 break;
8643 case OPC_PUU_PS:
8644 check_cp1_64bitmode(ctx);
8646 TCGv_i32 fp0 = tcg_temp_new_i32();
8647 TCGv_i32 fp1 = tcg_temp_new_i32();
8649 gen_load_fpr32h(ctx, fp0, fs);
8650 gen_load_fpr32h(ctx, fp1, ft);
8651 gen_store_fpr32(fp1, fd);
8652 gen_store_fpr32h(ctx, fp0, fd);
8653 tcg_temp_free_i32(fp0);
8654 tcg_temp_free_i32(fp1);
8656 opn = "puu.ps";
8657 break;
8658 case OPC_CMP_F_PS:
8659 case OPC_CMP_UN_PS:
8660 case OPC_CMP_EQ_PS:
8661 case OPC_CMP_UEQ_PS:
8662 case OPC_CMP_OLT_PS:
8663 case OPC_CMP_ULT_PS:
8664 case OPC_CMP_OLE_PS:
8665 case OPC_CMP_ULE_PS:
8666 case OPC_CMP_SF_PS:
8667 case OPC_CMP_NGLE_PS:
8668 case OPC_CMP_SEQ_PS:
8669 case OPC_CMP_NGL_PS:
8670 case OPC_CMP_LT_PS:
8671 case OPC_CMP_NGE_PS:
8672 case OPC_CMP_LE_PS:
8673 case OPC_CMP_NGT_PS:
8674 if (ctx->opcode & (1 << 6)) {
8675 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
8676 opn = condnames_abs[func-48];
8677 } else {
8678 gen_cmp_ps(ctx, func-48, ft, fs, cc);
8679 opn = condnames[func-48];
8681 break;
8682 default:
8683 MIPS_INVAL(opn);
8684 generate_exception (ctx, EXCP_RI);
8685 return;
8687 (void)opn; /* avoid a compiler warning */
8688 switch (optype) {
8689 case BINOP:
8690 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
8691 break;
8692 case CMPOP:
8693 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
8694 break;
8695 default:
8696 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
8697 break;
8701 /* Coprocessor 3 (FPU) */
8702 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
8703 int fd, int fs, int base, int index)
8705 const char *opn = "extended float load/store";
8706 int store = 0;
8707 TCGv t0 = tcg_temp_new();
8709 if (base == 0) {
8710 gen_load_gpr(t0, index);
8711 } else if (index == 0) {
8712 gen_load_gpr(t0, base);
8713 } else {
8714 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
8716 /* Don't do NOP if destination is zero: we must perform the actual
8717 memory access. */
8718 switch (opc) {
8719 case OPC_LWXC1:
8720 check_cop1x(ctx);
8722 TCGv_i32 fp0 = tcg_temp_new_i32();
8724 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
8725 tcg_gen_trunc_tl_i32(fp0, t0);
8726 gen_store_fpr32(fp0, fd);
8727 tcg_temp_free_i32(fp0);
8729 opn = "lwxc1";
8730 break;
8731 case OPC_LDXC1:
8732 check_cop1x(ctx);
8733 check_cp1_registers(ctx, fd);
8735 TCGv_i64 fp0 = tcg_temp_new_i64();
8736 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8737 gen_store_fpr64(ctx, fp0, fd);
8738 tcg_temp_free_i64(fp0);
8740 opn = "ldxc1";
8741 break;
8742 case OPC_LUXC1:
8743 check_cp1_64bitmode(ctx);
8744 tcg_gen_andi_tl(t0, t0, ~0x7);
8746 TCGv_i64 fp0 = tcg_temp_new_i64();
8748 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8749 gen_store_fpr64(ctx, fp0, fd);
8750 tcg_temp_free_i64(fp0);
8752 opn = "luxc1";
8753 break;
8754 case OPC_SWXC1:
8755 check_cop1x(ctx);
8757 TCGv_i32 fp0 = tcg_temp_new_i32();
8758 gen_load_fpr32(fp0, fs);
8759 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, MO_TEUL);
8760 tcg_temp_free_i32(fp0);
8762 opn = "swxc1";
8763 store = 1;
8764 break;
8765 case OPC_SDXC1:
8766 check_cop1x(ctx);
8767 check_cp1_registers(ctx, fs);
8769 TCGv_i64 fp0 = tcg_temp_new_i64();
8770 gen_load_fpr64(ctx, fp0, fs);
8771 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8772 tcg_temp_free_i64(fp0);
8774 opn = "sdxc1";
8775 store = 1;
8776 break;
8777 case OPC_SUXC1:
8778 check_cp1_64bitmode(ctx);
8779 tcg_gen_andi_tl(t0, t0, ~0x7);
8781 TCGv_i64 fp0 = tcg_temp_new_i64();
8782 gen_load_fpr64(ctx, fp0, fs);
8783 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, MO_TEQ);
8784 tcg_temp_free_i64(fp0);
8786 opn = "suxc1";
8787 store = 1;
8788 break;
8790 tcg_temp_free(t0);
8791 (void)opn; (void)store; /* avoid compiler warnings */
8792 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
8793 regnames[index], regnames[base]);
8796 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
8797 int fd, int fr, int fs, int ft)
8799 const char *opn = "flt3_arith";
8801 switch (opc) {
8802 case OPC_ALNV_PS:
8803 check_cp1_64bitmode(ctx);
8805 TCGv t0 = tcg_temp_local_new();
8806 TCGv_i32 fp = tcg_temp_new_i32();
8807 TCGv_i32 fph = tcg_temp_new_i32();
8808 int l1 = gen_new_label();
8809 int l2 = gen_new_label();
8811 gen_load_gpr(t0, fr);
8812 tcg_gen_andi_tl(t0, t0, 0x7);
8814 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
8815 gen_load_fpr32(fp, fs);
8816 gen_load_fpr32h(ctx, fph, fs);
8817 gen_store_fpr32(fp, fd);
8818 gen_store_fpr32h(ctx, fph, fd);
8819 tcg_gen_br(l2);
8820 gen_set_label(l1);
8821 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
8822 tcg_temp_free(t0);
8823 #ifdef TARGET_WORDS_BIGENDIAN
8824 gen_load_fpr32(fp, fs);
8825 gen_load_fpr32h(ctx, fph, ft);
8826 gen_store_fpr32h(ctx, fp, fd);
8827 gen_store_fpr32(fph, fd);
8828 #else
8829 gen_load_fpr32h(ctx, fph, fs);
8830 gen_load_fpr32(fp, ft);
8831 gen_store_fpr32(fph, fd);
8832 gen_store_fpr32h(ctx, fp, fd);
8833 #endif
8834 gen_set_label(l2);
8835 tcg_temp_free_i32(fp);
8836 tcg_temp_free_i32(fph);
8838 opn = "alnv.ps";
8839 break;
8840 case OPC_MADD_S:
8841 check_cop1x(ctx);
8843 TCGv_i32 fp0 = tcg_temp_new_i32();
8844 TCGv_i32 fp1 = tcg_temp_new_i32();
8845 TCGv_i32 fp2 = tcg_temp_new_i32();
8847 gen_load_fpr32(fp0, fs);
8848 gen_load_fpr32(fp1, ft);
8849 gen_load_fpr32(fp2, fr);
8850 gen_helper_float_madd_s(fp2, cpu_env, fp0, fp1, fp2);
8851 tcg_temp_free_i32(fp0);
8852 tcg_temp_free_i32(fp1);
8853 gen_store_fpr32(fp2, fd);
8854 tcg_temp_free_i32(fp2);
8856 opn = "madd.s";
8857 break;
8858 case OPC_MADD_D:
8859 check_cop1x(ctx);
8860 check_cp1_registers(ctx, fd | fs | ft | fr);
8862 TCGv_i64 fp0 = tcg_temp_new_i64();
8863 TCGv_i64 fp1 = tcg_temp_new_i64();
8864 TCGv_i64 fp2 = tcg_temp_new_i64();
8866 gen_load_fpr64(ctx, fp0, fs);
8867 gen_load_fpr64(ctx, fp1, ft);
8868 gen_load_fpr64(ctx, fp2, fr);
8869 gen_helper_float_madd_d(fp2, cpu_env, fp0, fp1, fp2);
8870 tcg_temp_free_i64(fp0);
8871 tcg_temp_free_i64(fp1);
8872 gen_store_fpr64(ctx, fp2, fd);
8873 tcg_temp_free_i64(fp2);
8875 opn = "madd.d";
8876 break;
8877 case OPC_MADD_PS:
8878 check_cp1_64bitmode(ctx);
8880 TCGv_i64 fp0 = tcg_temp_new_i64();
8881 TCGv_i64 fp1 = tcg_temp_new_i64();
8882 TCGv_i64 fp2 = tcg_temp_new_i64();
8884 gen_load_fpr64(ctx, fp0, fs);
8885 gen_load_fpr64(ctx, fp1, ft);
8886 gen_load_fpr64(ctx, fp2, fr);
8887 gen_helper_float_madd_ps(fp2, cpu_env, fp0, fp1, fp2);
8888 tcg_temp_free_i64(fp0);
8889 tcg_temp_free_i64(fp1);
8890 gen_store_fpr64(ctx, fp2, fd);
8891 tcg_temp_free_i64(fp2);
8893 opn = "madd.ps";
8894 break;
8895 case OPC_MSUB_S:
8896 check_cop1x(ctx);
8898 TCGv_i32 fp0 = tcg_temp_new_i32();
8899 TCGv_i32 fp1 = tcg_temp_new_i32();
8900 TCGv_i32 fp2 = tcg_temp_new_i32();
8902 gen_load_fpr32(fp0, fs);
8903 gen_load_fpr32(fp1, ft);
8904 gen_load_fpr32(fp2, fr);
8905 gen_helper_float_msub_s(fp2, cpu_env, fp0, fp1, fp2);
8906 tcg_temp_free_i32(fp0);
8907 tcg_temp_free_i32(fp1);
8908 gen_store_fpr32(fp2, fd);
8909 tcg_temp_free_i32(fp2);
8911 opn = "msub.s";
8912 break;
8913 case OPC_MSUB_D:
8914 check_cop1x(ctx);
8915 check_cp1_registers(ctx, fd | fs | ft | fr);
8917 TCGv_i64 fp0 = tcg_temp_new_i64();
8918 TCGv_i64 fp1 = tcg_temp_new_i64();
8919 TCGv_i64 fp2 = tcg_temp_new_i64();
8921 gen_load_fpr64(ctx, fp0, fs);
8922 gen_load_fpr64(ctx, fp1, ft);
8923 gen_load_fpr64(ctx, fp2, fr);
8924 gen_helper_float_msub_d(fp2, cpu_env, fp0, fp1, fp2);
8925 tcg_temp_free_i64(fp0);
8926 tcg_temp_free_i64(fp1);
8927 gen_store_fpr64(ctx, fp2, fd);
8928 tcg_temp_free_i64(fp2);
8930 opn = "msub.d";
8931 break;
8932 case OPC_MSUB_PS:
8933 check_cp1_64bitmode(ctx);
8935 TCGv_i64 fp0 = tcg_temp_new_i64();
8936 TCGv_i64 fp1 = tcg_temp_new_i64();
8937 TCGv_i64 fp2 = tcg_temp_new_i64();
8939 gen_load_fpr64(ctx, fp0, fs);
8940 gen_load_fpr64(ctx, fp1, ft);
8941 gen_load_fpr64(ctx, fp2, fr);
8942 gen_helper_float_msub_ps(fp2, cpu_env, fp0, fp1, fp2);
8943 tcg_temp_free_i64(fp0);
8944 tcg_temp_free_i64(fp1);
8945 gen_store_fpr64(ctx, fp2, fd);
8946 tcg_temp_free_i64(fp2);
8948 opn = "msub.ps";
8949 break;
8950 case OPC_NMADD_S:
8951 check_cop1x(ctx);
8953 TCGv_i32 fp0 = tcg_temp_new_i32();
8954 TCGv_i32 fp1 = tcg_temp_new_i32();
8955 TCGv_i32 fp2 = tcg_temp_new_i32();
8957 gen_load_fpr32(fp0, fs);
8958 gen_load_fpr32(fp1, ft);
8959 gen_load_fpr32(fp2, fr);
8960 gen_helper_float_nmadd_s(fp2, cpu_env, fp0, fp1, fp2);
8961 tcg_temp_free_i32(fp0);
8962 tcg_temp_free_i32(fp1);
8963 gen_store_fpr32(fp2, fd);
8964 tcg_temp_free_i32(fp2);
8966 opn = "nmadd.s";
8967 break;
8968 case OPC_NMADD_D:
8969 check_cop1x(ctx);
8970 check_cp1_registers(ctx, fd | fs | ft | fr);
8972 TCGv_i64 fp0 = tcg_temp_new_i64();
8973 TCGv_i64 fp1 = tcg_temp_new_i64();
8974 TCGv_i64 fp2 = tcg_temp_new_i64();
8976 gen_load_fpr64(ctx, fp0, fs);
8977 gen_load_fpr64(ctx, fp1, ft);
8978 gen_load_fpr64(ctx, fp2, fr);
8979 gen_helper_float_nmadd_d(fp2, cpu_env, fp0, fp1, fp2);
8980 tcg_temp_free_i64(fp0);
8981 tcg_temp_free_i64(fp1);
8982 gen_store_fpr64(ctx, fp2, fd);
8983 tcg_temp_free_i64(fp2);
8985 opn = "nmadd.d";
8986 break;
8987 case OPC_NMADD_PS:
8988 check_cp1_64bitmode(ctx);
8990 TCGv_i64 fp0 = tcg_temp_new_i64();
8991 TCGv_i64 fp1 = tcg_temp_new_i64();
8992 TCGv_i64 fp2 = tcg_temp_new_i64();
8994 gen_load_fpr64(ctx, fp0, fs);
8995 gen_load_fpr64(ctx, fp1, ft);
8996 gen_load_fpr64(ctx, fp2, fr);
8997 gen_helper_float_nmadd_ps(fp2, cpu_env, fp0, fp1, fp2);
8998 tcg_temp_free_i64(fp0);
8999 tcg_temp_free_i64(fp1);
9000 gen_store_fpr64(ctx, fp2, fd);
9001 tcg_temp_free_i64(fp2);
9003 opn = "nmadd.ps";
9004 break;
9005 case OPC_NMSUB_S:
9006 check_cop1x(ctx);
9008 TCGv_i32 fp0 = tcg_temp_new_i32();
9009 TCGv_i32 fp1 = tcg_temp_new_i32();
9010 TCGv_i32 fp2 = tcg_temp_new_i32();
9012 gen_load_fpr32(fp0, fs);
9013 gen_load_fpr32(fp1, ft);
9014 gen_load_fpr32(fp2, fr);
9015 gen_helper_float_nmsub_s(fp2, cpu_env, fp0, fp1, fp2);
9016 tcg_temp_free_i32(fp0);
9017 tcg_temp_free_i32(fp1);
9018 gen_store_fpr32(fp2, fd);
9019 tcg_temp_free_i32(fp2);
9021 opn = "nmsub.s";
9022 break;
9023 case OPC_NMSUB_D:
9024 check_cop1x(ctx);
9025 check_cp1_registers(ctx, fd | fs | ft | fr);
9027 TCGv_i64 fp0 = tcg_temp_new_i64();
9028 TCGv_i64 fp1 = tcg_temp_new_i64();
9029 TCGv_i64 fp2 = tcg_temp_new_i64();
9031 gen_load_fpr64(ctx, fp0, fs);
9032 gen_load_fpr64(ctx, fp1, ft);
9033 gen_load_fpr64(ctx, fp2, fr);
9034 gen_helper_float_nmsub_d(fp2, cpu_env, fp0, fp1, fp2);
9035 tcg_temp_free_i64(fp0);
9036 tcg_temp_free_i64(fp1);
9037 gen_store_fpr64(ctx, fp2, fd);
9038 tcg_temp_free_i64(fp2);
9040 opn = "nmsub.d";
9041 break;
9042 case OPC_NMSUB_PS:
9043 check_cp1_64bitmode(ctx);
9045 TCGv_i64 fp0 = tcg_temp_new_i64();
9046 TCGv_i64 fp1 = tcg_temp_new_i64();
9047 TCGv_i64 fp2 = tcg_temp_new_i64();
9049 gen_load_fpr64(ctx, fp0, fs);
9050 gen_load_fpr64(ctx, fp1, ft);
9051 gen_load_fpr64(ctx, fp2, fr);
9052 gen_helper_float_nmsub_ps(fp2, cpu_env, fp0, fp1, fp2);
9053 tcg_temp_free_i64(fp0);
9054 tcg_temp_free_i64(fp1);
9055 gen_store_fpr64(ctx, fp2, fd);
9056 tcg_temp_free_i64(fp2);
9058 opn = "nmsub.ps";
9059 break;
9060 default:
9061 MIPS_INVAL(opn);
9062 generate_exception (ctx, EXCP_RI);
9063 return;
9065 (void)opn; /* avoid a compiler warning */
9066 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
9067 fregnames[fs], fregnames[ft]);
9070 static void gen_rdhwr(DisasContext *ctx, int rt, int rd)
9072 TCGv t0;
9074 #if !defined(CONFIG_USER_ONLY)
9075 /* The Linux kernel will emulate rdhwr if it's not supported natively.
9076 Therefore only check the ISA in system mode. */
9077 check_insn(ctx, ISA_MIPS32R2);
9078 #endif
9079 t0 = tcg_temp_new();
9081 switch (rd) {
9082 case 0:
9083 save_cpu_state(ctx, 1);
9084 gen_helper_rdhwr_cpunum(t0, cpu_env);
9085 gen_store_gpr(t0, rt);
9086 break;
9087 case 1:
9088 save_cpu_state(ctx, 1);
9089 gen_helper_rdhwr_synci_step(t0, cpu_env);
9090 gen_store_gpr(t0, rt);
9091 break;
9092 case 2:
9093 save_cpu_state(ctx, 1);
9094 gen_helper_rdhwr_cc(t0, cpu_env);
9095 gen_store_gpr(t0, rt);
9096 break;
9097 case 3:
9098 save_cpu_state(ctx, 1);
9099 gen_helper_rdhwr_ccres(t0, cpu_env);
9100 gen_store_gpr(t0, rt);
9101 break;
9102 case 29:
9103 #if defined(CONFIG_USER_ONLY)
9104 tcg_gen_ld_tl(t0, cpu_env,
9105 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9106 gen_store_gpr(t0, rt);
9107 break;
9108 #else
9109 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
9110 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
9111 tcg_gen_ld_tl(t0, cpu_env,
9112 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
9113 gen_store_gpr(t0, rt);
9114 } else {
9115 generate_exception(ctx, EXCP_RI);
9117 break;
9118 #endif
9119 default: /* Invalid */
9120 MIPS_INVAL("rdhwr");
9121 generate_exception(ctx, EXCP_RI);
9122 break;
9124 tcg_temp_free(t0);
9127 static void handle_delay_slot(DisasContext *ctx, int insn_bytes)
9129 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9130 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
9131 /* Branches completion */
9132 ctx->hflags &= ~MIPS_HFLAG_BMASK;
9133 ctx->bstate = BS_BRANCH;
9134 save_cpu_state(ctx, 0);
9135 /* FIXME: Need to clear can_do_io. */
9136 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
9137 case MIPS_HFLAG_B:
9138 /* unconditional branch */
9139 MIPS_DEBUG("unconditional branch");
9140 if (proc_hflags & MIPS_HFLAG_BX) {
9141 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
9143 gen_goto_tb(ctx, 0, ctx->btarget);
9144 break;
9145 case MIPS_HFLAG_BL:
9146 /* blikely taken case */
9147 MIPS_DEBUG("blikely branch taken");
9148 gen_goto_tb(ctx, 0, ctx->btarget);
9149 break;
9150 case MIPS_HFLAG_BC:
9151 /* Conditional branch */
9152 MIPS_DEBUG("conditional branch");
9154 int l1 = gen_new_label();
9156 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
9157 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
9158 gen_set_label(l1);
9159 gen_goto_tb(ctx, 0, ctx->btarget);
9161 break;
9162 case MIPS_HFLAG_BR:
9163 /* unconditional branch to register */
9164 MIPS_DEBUG("branch to register");
9165 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
9166 TCGv t0 = tcg_temp_new();
9167 TCGv_i32 t1 = tcg_temp_new_i32();
9169 tcg_gen_andi_tl(t0, btarget, 0x1);
9170 tcg_gen_trunc_tl_i32(t1, t0);
9171 tcg_temp_free(t0);
9172 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
9173 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
9174 tcg_gen_or_i32(hflags, hflags, t1);
9175 tcg_temp_free_i32(t1);
9177 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
9178 } else {
9179 tcg_gen_mov_tl(cpu_PC, btarget);
9181 if (ctx->singlestep_enabled) {
9182 save_cpu_state(ctx, 0);
9183 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
9185 tcg_gen_exit_tb(0);
9186 break;
9187 default:
9188 MIPS_DEBUG("unknown branch");
9189 break;
9194 /* ISA extensions (ASEs) */
9195 /* MIPS16 extension to MIPS32 */
9197 /* MIPS16 major opcodes */
9198 enum {
9199 M16_OPC_ADDIUSP = 0x00,
9200 M16_OPC_ADDIUPC = 0x01,
9201 M16_OPC_B = 0x02,
9202 M16_OPC_JAL = 0x03,
9203 M16_OPC_BEQZ = 0x04,
9204 M16_OPC_BNEQZ = 0x05,
9205 M16_OPC_SHIFT = 0x06,
9206 M16_OPC_LD = 0x07,
9207 M16_OPC_RRIA = 0x08,
9208 M16_OPC_ADDIU8 = 0x09,
9209 M16_OPC_SLTI = 0x0a,
9210 M16_OPC_SLTIU = 0x0b,
9211 M16_OPC_I8 = 0x0c,
9212 M16_OPC_LI = 0x0d,
9213 M16_OPC_CMPI = 0x0e,
9214 M16_OPC_SD = 0x0f,
9215 M16_OPC_LB = 0x10,
9216 M16_OPC_LH = 0x11,
9217 M16_OPC_LWSP = 0x12,
9218 M16_OPC_LW = 0x13,
9219 M16_OPC_LBU = 0x14,
9220 M16_OPC_LHU = 0x15,
9221 M16_OPC_LWPC = 0x16,
9222 M16_OPC_LWU = 0x17,
9223 M16_OPC_SB = 0x18,
9224 M16_OPC_SH = 0x19,
9225 M16_OPC_SWSP = 0x1a,
9226 M16_OPC_SW = 0x1b,
9227 M16_OPC_RRR = 0x1c,
9228 M16_OPC_RR = 0x1d,
9229 M16_OPC_EXTEND = 0x1e,
9230 M16_OPC_I64 = 0x1f
9233 /* I8 funct field */
9234 enum {
9235 I8_BTEQZ = 0x0,
9236 I8_BTNEZ = 0x1,
9237 I8_SWRASP = 0x2,
9238 I8_ADJSP = 0x3,
9239 I8_SVRS = 0x4,
9240 I8_MOV32R = 0x5,
9241 I8_MOVR32 = 0x7
9244 /* RRR f field */
9245 enum {
9246 RRR_DADDU = 0x0,
9247 RRR_ADDU = 0x1,
9248 RRR_DSUBU = 0x2,
9249 RRR_SUBU = 0x3
9252 /* RR funct field */
9253 enum {
9254 RR_JR = 0x00,
9255 RR_SDBBP = 0x01,
9256 RR_SLT = 0x02,
9257 RR_SLTU = 0x03,
9258 RR_SLLV = 0x04,
9259 RR_BREAK = 0x05,
9260 RR_SRLV = 0x06,
9261 RR_SRAV = 0x07,
9262 RR_DSRL = 0x08,
9263 RR_CMP = 0x0a,
9264 RR_NEG = 0x0b,
9265 RR_AND = 0x0c,
9266 RR_OR = 0x0d,
9267 RR_XOR = 0x0e,
9268 RR_NOT = 0x0f,
9269 RR_MFHI = 0x10,
9270 RR_CNVT = 0x11,
9271 RR_MFLO = 0x12,
9272 RR_DSRA = 0x13,
9273 RR_DSLLV = 0x14,
9274 RR_DSRLV = 0x16,
9275 RR_DSRAV = 0x17,
9276 RR_MULT = 0x18,
9277 RR_MULTU = 0x19,
9278 RR_DIV = 0x1a,
9279 RR_DIVU = 0x1b,
9280 RR_DMULT = 0x1c,
9281 RR_DMULTU = 0x1d,
9282 RR_DDIV = 0x1e,
9283 RR_DDIVU = 0x1f
9286 /* I64 funct field */
9287 enum {
9288 I64_LDSP = 0x0,
9289 I64_SDSP = 0x1,
9290 I64_SDRASP = 0x2,
9291 I64_DADJSP = 0x3,
9292 I64_LDPC = 0x4,
9293 I64_DADDIU5 = 0x5,
9294 I64_DADDIUPC = 0x6,
9295 I64_DADDIUSP = 0x7
9298 /* RR ry field for CNVT */
9299 enum {
9300 RR_RY_CNVT_ZEB = 0x0,
9301 RR_RY_CNVT_ZEH = 0x1,
9302 RR_RY_CNVT_ZEW = 0x2,
9303 RR_RY_CNVT_SEB = 0x4,
9304 RR_RY_CNVT_SEH = 0x5,
9305 RR_RY_CNVT_SEW = 0x6,
9308 static int xlat (int r)
9310 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9312 return map[r];
9315 static void gen_mips16_save (DisasContext *ctx,
9316 int xsregs, int aregs,
9317 int do_ra, int do_s0, int do_s1,
9318 int framesize)
9320 TCGv t0 = tcg_temp_new();
9321 TCGv t1 = tcg_temp_new();
9322 int args, astatic;
9324 switch (aregs) {
9325 case 0:
9326 case 1:
9327 case 2:
9328 case 3:
9329 case 11:
9330 args = 0;
9331 break;
9332 case 4:
9333 case 5:
9334 case 6:
9335 case 7:
9336 args = 1;
9337 break;
9338 case 8:
9339 case 9:
9340 case 10:
9341 args = 2;
9342 break;
9343 case 12:
9344 case 13:
9345 args = 3;
9346 break;
9347 case 14:
9348 args = 4;
9349 break;
9350 default:
9351 generate_exception(ctx, EXCP_RI);
9352 return;
9355 switch (args) {
9356 case 4:
9357 gen_base_offset_addr(ctx, t0, 29, 12);
9358 gen_load_gpr(t1, 7);
9359 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9360 /* Fall through */
9361 case 3:
9362 gen_base_offset_addr(ctx, t0, 29, 8);
9363 gen_load_gpr(t1, 6);
9364 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9365 /* Fall through */
9366 case 2:
9367 gen_base_offset_addr(ctx, t0, 29, 4);
9368 gen_load_gpr(t1, 5);
9369 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9370 /* Fall through */
9371 case 1:
9372 gen_base_offset_addr(ctx, t0, 29, 0);
9373 gen_load_gpr(t1, 4);
9374 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
9377 gen_load_gpr(t0, 29);
9379 #define DECR_AND_STORE(reg) do { \
9380 tcg_gen_subi_tl(t0, t0, 4); \
9381 gen_load_gpr(t1, reg); \
9382 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \
9383 } while (0)
9385 if (do_ra) {
9386 DECR_AND_STORE(31);
9389 switch (xsregs) {
9390 case 7:
9391 DECR_AND_STORE(30);
9392 /* Fall through */
9393 case 6:
9394 DECR_AND_STORE(23);
9395 /* Fall through */
9396 case 5:
9397 DECR_AND_STORE(22);
9398 /* Fall through */
9399 case 4:
9400 DECR_AND_STORE(21);
9401 /* Fall through */
9402 case 3:
9403 DECR_AND_STORE(20);
9404 /* Fall through */
9405 case 2:
9406 DECR_AND_STORE(19);
9407 /* Fall through */
9408 case 1:
9409 DECR_AND_STORE(18);
9412 if (do_s1) {
9413 DECR_AND_STORE(17);
9415 if (do_s0) {
9416 DECR_AND_STORE(16);
9419 switch (aregs) {
9420 case 0:
9421 case 4:
9422 case 8:
9423 case 12:
9424 case 14:
9425 astatic = 0;
9426 break;
9427 case 1:
9428 case 5:
9429 case 9:
9430 case 13:
9431 astatic = 1;
9432 break;
9433 case 2:
9434 case 6:
9435 case 10:
9436 astatic = 2;
9437 break;
9438 case 3:
9439 case 7:
9440 astatic = 3;
9441 break;
9442 case 11:
9443 astatic = 4;
9444 break;
9445 default:
9446 generate_exception(ctx, EXCP_RI);
9447 return;
9450 if (astatic > 0) {
9451 DECR_AND_STORE(7);
9452 if (astatic > 1) {
9453 DECR_AND_STORE(6);
9454 if (astatic > 2) {
9455 DECR_AND_STORE(5);
9456 if (astatic > 3) {
9457 DECR_AND_STORE(4);
9462 #undef DECR_AND_STORE
9464 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9465 tcg_temp_free(t0);
9466 tcg_temp_free(t1);
9469 static void gen_mips16_restore (DisasContext *ctx,
9470 int xsregs, int aregs,
9471 int do_ra, int do_s0, int do_s1,
9472 int framesize)
9474 int astatic;
9475 TCGv t0 = tcg_temp_new();
9476 TCGv t1 = tcg_temp_new();
9478 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
9480 #define DECR_AND_LOAD(reg) do { \
9481 tcg_gen_subi_tl(t0, t0, 4); \
9482 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL); \
9483 gen_store_gpr(t1, reg); \
9484 } while (0)
9486 if (do_ra) {
9487 DECR_AND_LOAD(31);
9490 switch (xsregs) {
9491 case 7:
9492 DECR_AND_LOAD(30);
9493 /* Fall through */
9494 case 6:
9495 DECR_AND_LOAD(23);
9496 /* Fall through */
9497 case 5:
9498 DECR_AND_LOAD(22);
9499 /* Fall through */
9500 case 4:
9501 DECR_AND_LOAD(21);
9502 /* Fall through */
9503 case 3:
9504 DECR_AND_LOAD(20);
9505 /* Fall through */
9506 case 2:
9507 DECR_AND_LOAD(19);
9508 /* Fall through */
9509 case 1:
9510 DECR_AND_LOAD(18);
9513 if (do_s1) {
9514 DECR_AND_LOAD(17);
9516 if (do_s0) {
9517 DECR_AND_LOAD(16);
9520 switch (aregs) {
9521 case 0:
9522 case 4:
9523 case 8:
9524 case 12:
9525 case 14:
9526 astatic = 0;
9527 break;
9528 case 1:
9529 case 5:
9530 case 9:
9531 case 13:
9532 astatic = 1;
9533 break;
9534 case 2:
9535 case 6:
9536 case 10:
9537 astatic = 2;
9538 break;
9539 case 3:
9540 case 7:
9541 astatic = 3;
9542 break;
9543 case 11:
9544 astatic = 4;
9545 break;
9546 default:
9547 generate_exception(ctx, EXCP_RI);
9548 return;
9551 if (astatic > 0) {
9552 DECR_AND_LOAD(7);
9553 if (astatic > 1) {
9554 DECR_AND_LOAD(6);
9555 if (astatic > 2) {
9556 DECR_AND_LOAD(5);
9557 if (astatic > 3) {
9558 DECR_AND_LOAD(4);
9563 #undef DECR_AND_LOAD
9565 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
9566 tcg_temp_free(t0);
9567 tcg_temp_free(t1);
9570 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
9571 int is_64_bit, int extended)
9573 TCGv t0;
9575 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9576 generate_exception(ctx, EXCP_RI);
9577 return;
9580 t0 = tcg_temp_new();
9582 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
9583 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
9584 if (!is_64_bit) {
9585 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9588 tcg_temp_free(t0);
9591 #if defined(TARGET_MIPS64)
9592 static void decode_i64_mips16 (DisasContext *ctx,
9593 int ry, int funct, int16_t offset,
9594 int extended)
9596 switch (funct) {
9597 case I64_LDSP:
9598 check_mips_64(ctx);
9599 offset = extended ? offset : offset << 3;
9600 gen_ld(ctx, OPC_LD, ry, 29, offset);
9601 break;
9602 case I64_SDSP:
9603 check_mips_64(ctx);
9604 offset = extended ? offset : offset << 3;
9605 gen_st(ctx, OPC_SD, ry, 29, offset);
9606 break;
9607 case I64_SDRASP:
9608 check_mips_64(ctx);
9609 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
9610 gen_st(ctx, OPC_SD, 31, 29, offset);
9611 break;
9612 case I64_DADJSP:
9613 check_mips_64(ctx);
9614 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
9615 gen_arith_imm(ctx, OPC_DADDIU, 29, 29, offset);
9616 break;
9617 case I64_LDPC:
9618 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
9619 generate_exception(ctx, EXCP_RI);
9620 } else {
9621 offset = extended ? offset : offset << 3;
9622 gen_ld(ctx, OPC_LDPC, ry, 0, offset);
9624 break;
9625 case I64_DADDIU5:
9626 check_mips_64(ctx);
9627 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
9628 gen_arith_imm(ctx, OPC_DADDIU, ry, ry, offset);
9629 break;
9630 case I64_DADDIUPC:
9631 check_mips_64(ctx);
9632 offset = extended ? offset : offset << 2;
9633 gen_addiupc(ctx, ry, offset, 1, extended);
9634 break;
9635 case I64_DADDIUSP:
9636 check_mips_64(ctx);
9637 offset = extended ? offset : offset << 2;
9638 gen_arith_imm(ctx, OPC_DADDIU, ry, 29, offset);
9639 break;
9642 #endif
9644 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
9646 int extend = cpu_lduw_code(env, ctx->pc + 2);
9647 int op, rx, ry, funct, sa;
9648 int16_t imm, offset;
9650 ctx->opcode = (ctx->opcode << 16) | extend;
9651 op = (ctx->opcode >> 11) & 0x1f;
9652 sa = (ctx->opcode >> 22) & 0x1f;
9653 funct = (ctx->opcode >> 8) & 0x7;
9654 rx = xlat((ctx->opcode >> 8) & 0x7);
9655 ry = xlat((ctx->opcode >> 5) & 0x7);
9656 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
9657 | ((ctx->opcode >> 21) & 0x3f) << 5
9658 | (ctx->opcode & 0x1f));
9660 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
9661 counterparts. */
9662 switch (op) {
9663 case M16_OPC_ADDIUSP:
9664 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
9665 break;
9666 case M16_OPC_ADDIUPC:
9667 gen_addiupc(ctx, rx, imm, 0, 1);
9668 break;
9669 case M16_OPC_B:
9670 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
9671 /* No delay slot, so just process as a normal instruction */
9672 break;
9673 case M16_OPC_BEQZ:
9674 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
9675 /* No delay slot, so just process as a normal instruction */
9676 break;
9677 case M16_OPC_BNEQZ:
9678 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
9679 /* No delay slot, so just process as a normal instruction */
9680 break;
9681 case M16_OPC_SHIFT:
9682 switch (ctx->opcode & 0x3) {
9683 case 0x0:
9684 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
9685 break;
9686 case 0x1:
9687 #if defined(TARGET_MIPS64)
9688 check_mips_64(ctx);
9689 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
9690 #else
9691 generate_exception(ctx, EXCP_RI);
9692 #endif
9693 break;
9694 case 0x2:
9695 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
9696 break;
9697 case 0x3:
9698 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
9699 break;
9701 break;
9702 #if defined(TARGET_MIPS64)
9703 case M16_OPC_LD:
9704 check_mips_64(ctx);
9705 gen_ld(ctx, OPC_LD, ry, rx, offset);
9706 break;
9707 #endif
9708 case M16_OPC_RRIA:
9709 imm = ctx->opcode & 0xf;
9710 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
9711 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
9712 imm = (int16_t) (imm << 1) >> 1;
9713 if ((ctx->opcode >> 4) & 0x1) {
9714 #if defined(TARGET_MIPS64)
9715 check_mips_64(ctx);
9716 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
9717 #else
9718 generate_exception(ctx, EXCP_RI);
9719 #endif
9720 } else {
9721 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
9723 break;
9724 case M16_OPC_ADDIU8:
9725 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
9726 break;
9727 case M16_OPC_SLTI:
9728 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
9729 break;
9730 case M16_OPC_SLTIU:
9731 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
9732 break;
9733 case M16_OPC_I8:
9734 switch (funct) {
9735 case I8_BTEQZ:
9736 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
9737 break;
9738 case I8_BTNEZ:
9739 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
9740 break;
9741 case I8_SWRASP:
9742 gen_st(ctx, OPC_SW, 31, 29, imm);
9743 break;
9744 case I8_ADJSP:
9745 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm);
9746 break;
9747 case I8_SVRS:
9749 int xsregs = (ctx->opcode >> 24) & 0x7;
9750 int aregs = (ctx->opcode >> 16) & 0xf;
9751 int do_ra = (ctx->opcode >> 6) & 0x1;
9752 int do_s0 = (ctx->opcode >> 5) & 0x1;
9753 int do_s1 = (ctx->opcode >> 4) & 0x1;
9754 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
9755 | (ctx->opcode & 0xf)) << 3;
9757 if (ctx->opcode & (1 << 7)) {
9758 gen_mips16_save(ctx, xsregs, aregs,
9759 do_ra, do_s0, do_s1,
9760 framesize);
9761 } else {
9762 gen_mips16_restore(ctx, xsregs, aregs,
9763 do_ra, do_s0, do_s1,
9764 framesize);
9767 break;
9768 default:
9769 generate_exception(ctx, EXCP_RI);
9770 break;
9772 break;
9773 case M16_OPC_LI:
9774 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
9775 break;
9776 case M16_OPC_CMPI:
9777 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
9778 break;
9779 #if defined(TARGET_MIPS64)
9780 case M16_OPC_SD:
9781 gen_st(ctx, OPC_SD, ry, rx, offset);
9782 break;
9783 #endif
9784 case M16_OPC_LB:
9785 gen_ld(ctx, OPC_LB, ry, rx, offset);
9786 break;
9787 case M16_OPC_LH:
9788 gen_ld(ctx, OPC_LH, ry, rx, offset);
9789 break;
9790 case M16_OPC_LWSP:
9791 gen_ld(ctx, OPC_LW, rx, 29, offset);
9792 break;
9793 case M16_OPC_LW:
9794 gen_ld(ctx, OPC_LW, ry, rx, offset);
9795 break;
9796 case M16_OPC_LBU:
9797 gen_ld(ctx, OPC_LBU, ry, rx, offset);
9798 break;
9799 case M16_OPC_LHU:
9800 gen_ld(ctx, OPC_LHU, ry, rx, offset);
9801 break;
9802 case M16_OPC_LWPC:
9803 gen_ld(ctx, OPC_LWPC, rx, 0, offset);
9804 break;
9805 #if defined(TARGET_MIPS64)
9806 case M16_OPC_LWU:
9807 gen_ld(ctx, OPC_LWU, ry, rx, offset);
9808 break;
9809 #endif
9810 case M16_OPC_SB:
9811 gen_st(ctx, OPC_SB, ry, rx, offset);
9812 break;
9813 case M16_OPC_SH:
9814 gen_st(ctx, OPC_SH, ry, rx, offset);
9815 break;
9816 case M16_OPC_SWSP:
9817 gen_st(ctx, OPC_SW, rx, 29, offset);
9818 break;
9819 case M16_OPC_SW:
9820 gen_st(ctx, OPC_SW, ry, rx, offset);
9821 break;
9822 #if defined(TARGET_MIPS64)
9823 case M16_OPC_I64:
9824 decode_i64_mips16(ctx, ry, funct, offset, 1);
9825 break;
9826 #endif
9827 default:
9828 generate_exception(ctx, EXCP_RI);
9829 break;
9832 return 4;
9835 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx)
9837 int rx, ry;
9838 int sa;
9839 int op, cnvt_op, op1, offset;
9840 int funct;
9841 int n_bytes;
9843 op = (ctx->opcode >> 11) & 0x1f;
9844 sa = (ctx->opcode >> 2) & 0x7;
9845 sa = sa == 0 ? 8 : sa;
9846 rx = xlat((ctx->opcode >> 8) & 0x7);
9847 cnvt_op = (ctx->opcode >> 5) & 0x7;
9848 ry = xlat((ctx->opcode >> 5) & 0x7);
9849 op1 = offset = ctx->opcode & 0x1f;
9851 n_bytes = 2;
9853 switch (op) {
9854 case M16_OPC_ADDIUSP:
9856 int16_t imm = ((uint8_t) ctx->opcode) << 2;
9858 gen_arith_imm(ctx, OPC_ADDIU, rx, 29, imm);
9860 break;
9861 case M16_OPC_ADDIUPC:
9862 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
9863 break;
9864 case M16_OPC_B:
9865 offset = (ctx->opcode & 0x7ff) << 1;
9866 offset = (int16_t)(offset << 4) >> 4;
9867 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
9868 /* No delay slot, so just process as a normal instruction */
9869 break;
9870 case M16_OPC_JAL:
9871 offset = cpu_lduw_code(env, ctx->pc + 2);
9872 offset = (((ctx->opcode & 0x1f) << 21)
9873 | ((ctx->opcode >> 5) & 0x1f) << 16
9874 | offset) << 2;
9875 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
9876 gen_compute_branch(ctx, op, 4, rx, ry, offset);
9877 n_bytes = 4;
9878 break;
9879 case M16_OPC_BEQZ:
9880 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9881 /* No delay slot, so just process as a normal instruction */
9882 break;
9883 case M16_OPC_BNEQZ:
9884 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
9885 /* No delay slot, so just process as a normal instruction */
9886 break;
9887 case M16_OPC_SHIFT:
9888 switch (ctx->opcode & 0x3) {
9889 case 0x0:
9890 gen_shift_imm(ctx, OPC_SLL, rx, ry, sa);
9891 break;
9892 case 0x1:
9893 #if defined(TARGET_MIPS64)
9894 check_mips_64(ctx);
9895 gen_shift_imm(ctx, OPC_DSLL, rx, ry, sa);
9896 #else
9897 generate_exception(ctx, EXCP_RI);
9898 #endif
9899 break;
9900 case 0x2:
9901 gen_shift_imm(ctx, OPC_SRL, rx, ry, sa);
9902 break;
9903 case 0x3:
9904 gen_shift_imm(ctx, OPC_SRA, rx, ry, sa);
9905 break;
9907 break;
9908 #if defined(TARGET_MIPS64)
9909 case M16_OPC_LD:
9910 check_mips_64(ctx);
9911 gen_ld(ctx, OPC_LD, ry, rx, offset << 3);
9912 break;
9913 #endif
9914 case M16_OPC_RRIA:
9916 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
9918 if ((ctx->opcode >> 4) & 1) {
9919 #if defined(TARGET_MIPS64)
9920 check_mips_64(ctx);
9921 gen_arith_imm(ctx, OPC_DADDIU, ry, rx, imm);
9922 #else
9923 generate_exception(ctx, EXCP_RI);
9924 #endif
9925 } else {
9926 gen_arith_imm(ctx, OPC_ADDIU, ry, rx, imm);
9929 break;
9930 case M16_OPC_ADDIU8:
9932 int16_t imm = (int8_t) ctx->opcode;
9934 gen_arith_imm(ctx, OPC_ADDIU, rx, rx, imm);
9936 break;
9937 case M16_OPC_SLTI:
9939 int16_t imm = (uint8_t) ctx->opcode;
9940 gen_slt_imm(ctx, OPC_SLTI, 24, rx, imm);
9942 break;
9943 case M16_OPC_SLTIU:
9945 int16_t imm = (uint8_t) ctx->opcode;
9946 gen_slt_imm(ctx, OPC_SLTIU, 24, rx, imm);
9948 break;
9949 case M16_OPC_I8:
9951 int reg32;
9953 funct = (ctx->opcode >> 8) & 0x7;
9954 switch (funct) {
9955 case I8_BTEQZ:
9956 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
9957 ((int8_t)ctx->opcode) << 1);
9958 break;
9959 case I8_BTNEZ:
9960 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
9961 ((int8_t)ctx->opcode) << 1);
9962 break;
9963 case I8_SWRASP:
9964 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
9965 break;
9966 case I8_ADJSP:
9967 gen_arith_imm(ctx, OPC_ADDIU, 29, 29,
9968 ((int8_t)ctx->opcode) << 3);
9969 break;
9970 case I8_SVRS:
9972 int do_ra = ctx->opcode & (1 << 6);
9973 int do_s0 = ctx->opcode & (1 << 5);
9974 int do_s1 = ctx->opcode & (1 << 4);
9975 int framesize = ctx->opcode & 0xf;
9977 if (framesize == 0) {
9978 framesize = 128;
9979 } else {
9980 framesize = framesize << 3;
9983 if (ctx->opcode & (1 << 7)) {
9984 gen_mips16_save(ctx, 0, 0,
9985 do_ra, do_s0, do_s1, framesize);
9986 } else {
9987 gen_mips16_restore(ctx, 0, 0,
9988 do_ra, do_s0, do_s1, framesize);
9991 break;
9992 case I8_MOV32R:
9994 int rz = xlat(ctx->opcode & 0x7);
9996 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9997 ((ctx->opcode >> 5) & 0x7);
9998 gen_arith(ctx, OPC_ADDU, reg32, rz, 0);
10000 break;
10001 case I8_MOVR32:
10002 reg32 = ctx->opcode & 0x1f;
10003 gen_arith(ctx, OPC_ADDU, ry, reg32, 0);
10004 break;
10005 default:
10006 generate_exception(ctx, EXCP_RI);
10007 break;
10010 break;
10011 case M16_OPC_LI:
10013 int16_t imm = (uint8_t) ctx->opcode;
10015 gen_arith_imm(ctx, OPC_ADDIU, rx, 0, imm);
10017 break;
10018 case M16_OPC_CMPI:
10020 int16_t imm = (uint8_t) ctx->opcode;
10021 gen_logic_imm(ctx, OPC_XORI, 24, rx, imm);
10023 break;
10024 #if defined(TARGET_MIPS64)
10025 case M16_OPC_SD:
10026 check_mips_64(ctx);
10027 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
10028 break;
10029 #endif
10030 case M16_OPC_LB:
10031 gen_ld(ctx, OPC_LB, ry, rx, offset);
10032 break;
10033 case M16_OPC_LH:
10034 gen_ld(ctx, OPC_LH, ry, rx, offset << 1);
10035 break;
10036 case M16_OPC_LWSP:
10037 gen_ld(ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
10038 break;
10039 case M16_OPC_LW:
10040 gen_ld(ctx, OPC_LW, ry, rx, offset << 2);
10041 break;
10042 case M16_OPC_LBU:
10043 gen_ld(ctx, OPC_LBU, ry, rx, offset);
10044 break;
10045 case M16_OPC_LHU:
10046 gen_ld(ctx, OPC_LHU, ry, rx, offset << 1);
10047 break;
10048 case M16_OPC_LWPC:
10049 gen_ld(ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
10050 break;
10051 #if defined (TARGET_MIPS64)
10052 case M16_OPC_LWU:
10053 check_mips_64(ctx);
10054 gen_ld(ctx, OPC_LWU, ry, rx, offset << 2);
10055 break;
10056 #endif
10057 case M16_OPC_SB:
10058 gen_st(ctx, OPC_SB, ry, rx, offset);
10059 break;
10060 case M16_OPC_SH:
10061 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
10062 break;
10063 case M16_OPC_SWSP:
10064 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
10065 break;
10066 case M16_OPC_SW:
10067 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
10068 break;
10069 case M16_OPC_RRR:
10071 int rz = xlat((ctx->opcode >> 2) & 0x7);
10072 int mips32_op;
10074 switch (ctx->opcode & 0x3) {
10075 case RRR_ADDU:
10076 mips32_op = OPC_ADDU;
10077 break;
10078 case RRR_SUBU:
10079 mips32_op = OPC_SUBU;
10080 break;
10081 #if defined(TARGET_MIPS64)
10082 case RRR_DADDU:
10083 mips32_op = OPC_DADDU;
10084 check_mips_64(ctx);
10085 break;
10086 case RRR_DSUBU:
10087 mips32_op = OPC_DSUBU;
10088 check_mips_64(ctx);
10089 break;
10090 #endif
10091 default:
10092 generate_exception(ctx, EXCP_RI);
10093 goto done;
10096 gen_arith(ctx, mips32_op, rz, rx, ry);
10097 done:
10100 break;
10101 case M16_OPC_RR:
10102 switch (op1) {
10103 case RR_JR:
10105 int nd = (ctx->opcode >> 7) & 0x1;
10106 int link = (ctx->opcode >> 6) & 0x1;
10107 int ra = (ctx->opcode >> 5) & 0x1;
10109 if (link) {
10110 op = nd ? OPC_JALRC : OPC_JALRS;
10111 } else {
10112 op = OPC_JR;
10115 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
10117 break;
10118 case RR_SDBBP:
10119 /* XXX: not clear which exception should be raised
10120 * when in debug mode...
10122 check_insn(ctx, ISA_MIPS32);
10123 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10124 generate_exception(ctx, EXCP_DBp);
10125 } else {
10126 generate_exception(ctx, EXCP_DBp);
10128 break;
10129 case RR_SLT:
10130 gen_slt(ctx, OPC_SLT, 24, rx, ry);
10131 break;
10132 case RR_SLTU:
10133 gen_slt(ctx, OPC_SLTU, 24, rx, ry);
10134 break;
10135 case RR_BREAK:
10136 generate_exception(ctx, EXCP_BREAK);
10137 break;
10138 case RR_SLLV:
10139 gen_shift(ctx, OPC_SLLV, ry, rx, ry);
10140 break;
10141 case RR_SRLV:
10142 gen_shift(ctx, OPC_SRLV, ry, rx, ry);
10143 break;
10144 case RR_SRAV:
10145 gen_shift(ctx, OPC_SRAV, ry, rx, ry);
10146 break;
10147 #if defined (TARGET_MIPS64)
10148 case RR_DSRL:
10149 check_mips_64(ctx);
10150 gen_shift_imm(ctx, OPC_DSRL, ry, ry, sa);
10151 break;
10152 #endif
10153 case RR_CMP:
10154 gen_logic(ctx, OPC_XOR, 24, rx, ry);
10155 break;
10156 case RR_NEG:
10157 gen_arith(ctx, OPC_SUBU, rx, 0, ry);
10158 break;
10159 case RR_AND:
10160 gen_logic(ctx, OPC_AND, rx, rx, ry);
10161 break;
10162 case RR_OR:
10163 gen_logic(ctx, OPC_OR, rx, rx, ry);
10164 break;
10165 case RR_XOR:
10166 gen_logic(ctx, OPC_XOR, rx, rx, ry);
10167 break;
10168 case RR_NOT:
10169 gen_logic(ctx, OPC_NOR, rx, ry, 0);
10170 break;
10171 case RR_MFHI:
10172 gen_HILO(ctx, OPC_MFHI, 0, rx);
10173 break;
10174 case RR_CNVT:
10175 switch (cnvt_op) {
10176 case RR_RY_CNVT_ZEB:
10177 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10178 break;
10179 case RR_RY_CNVT_ZEH:
10180 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10181 break;
10182 case RR_RY_CNVT_SEB:
10183 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10184 break;
10185 case RR_RY_CNVT_SEH:
10186 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10187 break;
10188 #if defined (TARGET_MIPS64)
10189 case RR_RY_CNVT_ZEW:
10190 check_mips_64(ctx);
10191 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
10192 break;
10193 case RR_RY_CNVT_SEW:
10194 check_mips_64(ctx);
10195 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
10196 break;
10197 #endif
10198 default:
10199 generate_exception(ctx, EXCP_RI);
10200 break;
10202 break;
10203 case RR_MFLO:
10204 gen_HILO(ctx, OPC_MFLO, 0, rx);
10205 break;
10206 #if defined (TARGET_MIPS64)
10207 case RR_DSRA:
10208 check_mips_64(ctx);
10209 gen_shift_imm(ctx, OPC_DSRA, ry, ry, sa);
10210 break;
10211 case RR_DSLLV:
10212 check_mips_64(ctx);
10213 gen_shift(ctx, OPC_DSLLV, ry, rx, ry);
10214 break;
10215 case RR_DSRLV:
10216 check_mips_64(ctx);
10217 gen_shift(ctx, OPC_DSRLV, ry, rx, ry);
10218 break;
10219 case RR_DSRAV:
10220 check_mips_64(ctx);
10221 gen_shift(ctx, OPC_DSRAV, ry, rx, ry);
10222 break;
10223 #endif
10224 case RR_MULT:
10225 gen_muldiv(ctx, OPC_MULT, 0, rx, ry);
10226 break;
10227 case RR_MULTU:
10228 gen_muldiv(ctx, OPC_MULTU, 0, rx, ry);
10229 break;
10230 case RR_DIV:
10231 gen_muldiv(ctx, OPC_DIV, 0, rx, ry);
10232 break;
10233 case RR_DIVU:
10234 gen_muldiv(ctx, OPC_DIVU, 0, rx, ry);
10235 break;
10236 #if defined (TARGET_MIPS64)
10237 case RR_DMULT:
10238 check_mips_64(ctx);
10239 gen_muldiv(ctx, OPC_DMULT, 0, rx, ry);
10240 break;
10241 case RR_DMULTU:
10242 check_mips_64(ctx);
10243 gen_muldiv(ctx, OPC_DMULTU, 0, rx, ry);
10244 break;
10245 case RR_DDIV:
10246 check_mips_64(ctx);
10247 gen_muldiv(ctx, OPC_DDIV, 0, rx, ry);
10248 break;
10249 case RR_DDIVU:
10250 check_mips_64(ctx);
10251 gen_muldiv(ctx, OPC_DDIVU, 0, rx, ry);
10252 break;
10253 #endif
10254 default:
10255 generate_exception(ctx, EXCP_RI);
10256 break;
10258 break;
10259 case M16_OPC_EXTEND:
10260 decode_extended_mips16_opc(env, ctx);
10261 n_bytes = 4;
10262 break;
10263 #if defined(TARGET_MIPS64)
10264 case M16_OPC_I64:
10265 funct = (ctx->opcode >> 8) & 0x7;
10266 decode_i64_mips16(ctx, ry, funct, offset, 0);
10267 break;
10268 #endif
10269 default:
10270 generate_exception(ctx, EXCP_RI);
10271 break;
10274 return n_bytes;
10277 /* microMIPS extension to MIPS32/MIPS64 */
10280 * microMIPS32/microMIPS64 major opcodes
10282 * 1. MIPS Architecture for Programmers Volume II-B:
10283 * The microMIPS32 Instruction Set (Revision 3.05)
10285 * Table 6.2 microMIPS32 Encoding of Major Opcode Field
10287 * 2. MIPS Architecture For Programmers Volume II-A:
10288 * The MIPS64 Instruction Set (Revision 3.51)
10291 enum {
10292 POOL32A = 0x00,
10293 POOL16A = 0x01,
10294 LBU16 = 0x02,
10295 MOVE16 = 0x03,
10296 ADDI32 = 0x04,
10297 LBU32 = 0x05,
10298 SB32 = 0x06,
10299 LB32 = 0x07,
10301 POOL32B = 0x08,
10302 POOL16B = 0x09,
10303 LHU16 = 0x0a,
10304 ANDI16 = 0x0b,
10305 ADDIU32 = 0x0c,
10306 LHU32 = 0x0d,
10307 SH32 = 0x0e,
10308 LH32 = 0x0f,
10310 POOL32I = 0x10,
10311 POOL16C = 0x11,
10312 LWSP16 = 0x12,
10313 POOL16D = 0x13,
10314 ORI32 = 0x14,
10315 POOL32F = 0x15,
10316 POOL32S = 0x16, /* MIPS64 */
10317 DADDIU32 = 0x17, /* MIPS64 */
10319 /* 0x1f is reserved */
10320 POOL32C = 0x18,
10321 LWGP16 = 0x19,
10322 LW16 = 0x1a,
10323 POOL16E = 0x1b,
10324 XORI32 = 0x1c,
10325 JALS32 = 0x1d,
10326 ADDIUPC = 0x1e,
10328 /* 0x20 is reserved */
10329 RES_20 = 0x20,
10330 POOL16F = 0x21,
10331 SB16 = 0x22,
10332 BEQZ16 = 0x23,
10333 SLTI32 = 0x24,
10334 BEQ32 = 0x25,
10335 SWC132 = 0x26,
10336 LWC132 = 0x27,
10338 /* 0x28 and 0x29 are reserved */
10339 RES_28 = 0x28,
10340 RES_29 = 0x29,
10341 SH16 = 0x2a,
10342 BNEZ16 = 0x2b,
10343 SLTIU32 = 0x2c,
10344 BNE32 = 0x2d,
10345 SDC132 = 0x2e,
10346 LDC132 = 0x2f,
10348 /* 0x30 and 0x31 are reserved */
10349 RES_30 = 0x30,
10350 RES_31 = 0x31,
10351 SWSP16 = 0x32,
10352 B16 = 0x33,
10353 ANDI32 = 0x34,
10354 J32 = 0x35,
10355 SD32 = 0x36, /* MIPS64 */
10356 LD32 = 0x37, /* MIPS64 */
10358 /* 0x38 and 0x39 are reserved */
10359 RES_38 = 0x38,
10360 RES_39 = 0x39,
10361 SW16 = 0x3a,
10362 LI16 = 0x3b,
10363 JALX32 = 0x3c,
10364 JAL32 = 0x3d,
10365 SW32 = 0x3e,
10366 LW32 = 0x3f
10369 /* POOL32A encoding of minor opcode field */
10371 enum {
10372 /* These opcodes are distinguished only by bits 9..6; those bits are
10373 * what are recorded below. */
10374 SLL32 = 0x0,
10375 SRL32 = 0x1,
10376 SRA = 0x2,
10377 ROTR = 0x3,
10379 SLLV = 0x0,
10380 SRLV = 0x1,
10381 SRAV = 0x2,
10382 ROTRV = 0x3,
10383 ADD = 0x4,
10384 ADDU32 = 0x5,
10385 SUB = 0x6,
10386 SUBU32 = 0x7,
10387 MUL = 0x8,
10388 AND = 0x9,
10389 OR32 = 0xa,
10390 NOR = 0xb,
10391 XOR32 = 0xc,
10392 SLT = 0xd,
10393 SLTU = 0xe,
10395 MOVN = 0x0,
10396 MOVZ = 0x1,
10397 LWXS = 0x4,
10399 /* The following can be distinguished by their lower 6 bits. */
10400 INS = 0x0c,
10401 EXT = 0x2c,
10402 POOL32AXF = 0x3c
10405 /* POOL32AXF encoding of minor opcode field extension */
10408 * 1. MIPS Architecture for Programmers Volume II-B:
10409 * The microMIPS32 Instruction Set (Revision 3.05)
10411 * Table 6.5 POOL32Axf Encoding of Minor Opcode Extension Field
10413 * 2. MIPS Architecture for Programmers VolumeIV-e:
10414 * The MIPS DSP Application-Specific Extension
10415 * to the microMIPS32 Architecture (Revision 2.34)
10417 * Table 5.5 POOL32Axf Encoding of Minor Opcode Extension Field
10420 enum {
10421 /* bits 11..6 */
10422 TEQ = 0x00,
10423 TGE = 0x08,
10424 TGEU = 0x10,
10425 TLT = 0x20,
10426 TLTU = 0x28,
10427 TNE = 0x30,
10429 MFC0 = 0x03,
10430 MTC0 = 0x0b,
10432 /* begin of microMIPS32 DSP */
10434 /* bits 13..12 for 0x01 */
10435 MFHI_ACC = 0x0,
10436 MFLO_ACC = 0x1,
10437 MTHI_ACC = 0x2,
10438 MTLO_ACC = 0x3,
10440 /* bits 13..12 for 0x2a */
10441 MADD_ACC = 0x0,
10442 MADDU_ACC = 0x1,
10443 MSUB_ACC = 0x2,
10444 MSUBU_ACC = 0x3,
10446 /* bits 13..12 for 0x32 */
10447 MULT_ACC = 0x0,
10448 MULTU_ACC = 0x1,
10450 /* end of microMIPS32 DSP */
10452 /* bits 15..12 for 0x2c */
10453 SEB = 0x2,
10454 SEH = 0x3,
10455 CLO = 0x4,
10456 CLZ = 0x5,
10457 RDHWR = 0x6,
10458 WSBH = 0x7,
10459 MULT = 0x8,
10460 MULTU = 0x9,
10461 DIV = 0xa,
10462 DIVU = 0xb,
10463 MADD = 0xc,
10464 MADDU = 0xd,
10465 MSUB = 0xe,
10466 MSUBU = 0xf,
10468 /* bits 15..12 for 0x34 */
10469 MFC2 = 0x4,
10470 MTC2 = 0x5,
10471 MFHC2 = 0x8,
10472 MTHC2 = 0x9,
10473 CFC2 = 0xc,
10474 CTC2 = 0xd,
10476 /* bits 15..12 for 0x3c */
10477 JALR = 0x0,
10478 JR = 0x0, /* alias */
10479 JALR_HB = 0x1,
10480 JALRS = 0x4,
10481 JALRS_HB = 0x5,
10483 /* bits 15..12 for 0x05 */
10484 RDPGPR = 0xe,
10485 WRPGPR = 0xf,
10487 /* bits 15..12 for 0x0d */
10488 TLBP = 0x0,
10489 TLBR = 0x1,
10490 TLBWI = 0x2,
10491 TLBWR = 0x3,
10492 WAIT = 0x9,
10493 IRET = 0xd,
10494 DERET = 0xe,
10495 ERET = 0xf,
10497 /* bits 15..12 for 0x15 */
10498 DMT = 0x0,
10499 DVPE = 0x1,
10500 EMT = 0x2,
10501 EVPE = 0x3,
10503 /* bits 15..12 for 0x1d */
10504 DI = 0x4,
10505 EI = 0x5,
10507 /* bits 15..12 for 0x2d */
10508 SYNC = 0x6,
10509 SYSCALL = 0x8,
10510 SDBBP = 0xd,
10512 /* bits 15..12 for 0x35 */
10513 MFHI32 = 0x0,
10514 MFLO32 = 0x1,
10515 MTHI32 = 0x2,
10516 MTLO32 = 0x3,
10519 /* POOL32B encoding of minor opcode field (bits 15..12) */
10521 enum {
10522 LWC2 = 0x0,
10523 LWP = 0x1,
10524 LDP = 0x4,
10525 LWM32 = 0x5,
10526 CACHE = 0x6,
10527 LDM = 0x7,
10528 SWC2 = 0x8,
10529 SWP = 0x9,
10530 SDP = 0xc,
10531 SWM32 = 0xd,
10532 SDM = 0xf
10535 /* POOL32C encoding of minor opcode field (bits 15..12) */
10537 enum {
10538 LWL = 0x0,
10539 SWL = 0x8,
10540 LWR = 0x1,
10541 SWR = 0x9,
10542 PREF = 0x2,
10543 /* 0xa is reserved */
10544 LL = 0x3,
10545 SC = 0xb,
10546 LDL = 0x4,
10547 SDL = 0xc,
10548 LDR = 0x5,
10549 SDR = 0xd,
10550 /* 0x6 is reserved */
10551 LWU = 0xe,
10552 LLD = 0x7,
10553 SCD = 0xf
10556 /* POOL32F encoding of minor opcode field (bits 5..0) */
10558 enum {
10559 /* These are the bit 7..6 values */
10560 ADD_FMT = 0x0,
10561 MOVN_FMT = 0x0,
10563 SUB_FMT = 0x1,
10564 MOVZ_FMT = 0x1,
10566 MUL_FMT = 0x2,
10568 DIV_FMT = 0x3,
10570 /* These are the bit 8..6 values */
10571 RSQRT2_FMT = 0x0,
10572 MOVF_FMT = 0x0,
10574 LWXC1 = 0x1,
10575 MOVT_FMT = 0x1,
10577 PLL_PS = 0x2,
10578 SWXC1 = 0x2,
10580 PLU_PS = 0x3,
10581 LDXC1 = 0x3,
10583 PUL_PS = 0x4,
10584 SDXC1 = 0x4,
10585 RECIP2_FMT = 0x4,
10587 PUU_PS = 0x5,
10588 LUXC1 = 0x5,
10590 CVT_PS_S = 0x6,
10591 SUXC1 = 0x6,
10592 ADDR_PS = 0x6,
10593 PREFX = 0x6,
10595 MULR_PS = 0x7,
10597 MADD_S = 0x01,
10598 MADD_D = 0x09,
10599 MADD_PS = 0x11,
10600 ALNV_PS = 0x19,
10601 MSUB_S = 0x21,
10602 MSUB_D = 0x29,
10603 MSUB_PS = 0x31,
10605 NMADD_S = 0x02,
10606 NMADD_D = 0x0a,
10607 NMADD_PS = 0x12,
10608 NMSUB_S = 0x22,
10609 NMSUB_D = 0x2a,
10610 NMSUB_PS = 0x32,
10612 POOL32FXF = 0x3b,
10614 CABS_COND_FMT = 0x1c, /* MIPS3D */
10615 C_COND_FMT = 0x3c
10618 /* POOL32Fxf encoding of minor opcode extension field */
10620 enum {
10621 CVT_L = 0x04,
10622 RSQRT_FMT = 0x08,
10623 FLOOR_L = 0x0c,
10624 CVT_PW_PS = 0x1c,
10625 CVT_W = 0x24,
10626 SQRT_FMT = 0x28,
10627 FLOOR_W = 0x2c,
10628 CVT_PS_PW = 0x3c,
10629 CFC1 = 0x40,
10630 RECIP_FMT = 0x48,
10631 CEIL_L = 0x4c,
10632 CTC1 = 0x60,
10633 CEIL_W = 0x6c,
10634 MFC1 = 0x80,
10635 CVT_S_PL = 0x84,
10636 TRUNC_L = 0x8c,
10637 MTC1 = 0xa0,
10638 CVT_S_PU = 0xa4,
10639 TRUNC_W = 0xac,
10640 MFHC1 = 0xc0,
10641 ROUND_L = 0xcc,
10642 MTHC1 = 0xe0,
10643 ROUND_W = 0xec,
10645 MOV_FMT = 0x01,
10646 MOVF = 0x05,
10647 ABS_FMT = 0x0d,
10648 RSQRT1_FMT = 0x1d,
10649 MOVT = 0x25,
10650 NEG_FMT = 0x2d,
10651 CVT_D = 0x4d,
10652 RECIP1_FMT = 0x5d,
10653 CVT_S = 0x6d
10656 /* POOL32I encoding of minor opcode field (bits 25..21) */
10658 enum {
10659 BLTZ = 0x00,
10660 BLTZAL = 0x01,
10661 BGEZ = 0x02,
10662 BGEZAL = 0x03,
10663 BLEZ = 0x04,
10664 BNEZC = 0x05,
10665 BGTZ = 0x06,
10666 BEQZC = 0x07,
10667 TLTI = 0x08,
10668 TGEI = 0x09,
10669 TLTIU = 0x0a,
10670 TGEIU = 0x0b,
10671 TNEI = 0x0c,
10672 LUI = 0x0d,
10673 TEQI = 0x0e,
10674 SYNCI = 0x10,
10675 BLTZALS = 0x11,
10676 BGEZALS = 0x13,
10677 BC2F = 0x14,
10678 BC2T = 0x15,
10679 BPOSGE64 = 0x1a,
10680 BPOSGE32 = 0x1b,
10681 /* These overlap and are distinguished by bit16 of the instruction */
10682 BC1F = 0x1c,
10683 BC1T = 0x1d,
10684 BC1ANY2F = 0x1c,
10685 BC1ANY2T = 0x1d,
10686 BC1ANY4F = 0x1e,
10687 BC1ANY4T = 0x1f
10690 /* POOL16A encoding of minor opcode field */
10692 enum {
10693 ADDU16 = 0x0,
10694 SUBU16 = 0x1
10697 /* POOL16B encoding of minor opcode field */
10699 enum {
10700 SLL16 = 0x0,
10701 SRL16 = 0x1
10704 /* POOL16C encoding of minor opcode field */
10706 enum {
10707 NOT16 = 0x00,
10708 XOR16 = 0x04,
10709 AND16 = 0x08,
10710 OR16 = 0x0c,
10711 LWM16 = 0x10,
10712 SWM16 = 0x14,
10713 JR16 = 0x18,
10714 JRC16 = 0x1a,
10715 JALR16 = 0x1c,
10716 JALR16S = 0x1e,
10717 MFHI16 = 0x20,
10718 MFLO16 = 0x24,
10719 BREAK16 = 0x28,
10720 SDBBP16 = 0x2c,
10721 JRADDIUSP = 0x30
10724 /* POOL16D encoding of minor opcode field */
10726 enum {
10727 ADDIUS5 = 0x0,
10728 ADDIUSP = 0x1
10731 /* POOL16E encoding of minor opcode field */
10733 enum {
10734 ADDIUR2 = 0x0,
10735 ADDIUR1SP = 0x1
10738 static int mmreg (int r)
10740 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
10742 return map[r];
10745 /* Used for 16-bit store instructions. */
10746 static int mmreg2 (int r)
10748 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
10750 return map[r];
10753 #define uMIPS_RD(op) ((op >> 7) & 0x7)
10754 #define uMIPS_RS(op) ((op >> 4) & 0x7)
10755 #define uMIPS_RS2(op) uMIPS_RS(op)
10756 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
10757 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
10758 #define uMIPS_RS5(op) (op & 0x1f)
10760 /* Signed immediate */
10761 #define SIMM(op, start, width) \
10762 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
10763 << (32-width)) \
10764 >> (32-width))
10765 /* Zero-extended immediate */
10766 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
10768 static void gen_addiur1sp(DisasContext *ctx)
10770 int rd = mmreg(uMIPS_RD(ctx->opcode));
10772 gen_arith_imm(ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
10775 static void gen_addiur2(DisasContext *ctx)
10777 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
10778 int rd = mmreg(uMIPS_RD(ctx->opcode));
10779 int rs = mmreg(uMIPS_RS(ctx->opcode));
10781 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
10784 static void gen_addiusp(DisasContext *ctx)
10786 int encoded = ZIMM(ctx->opcode, 1, 9);
10787 int decoded;
10789 if (encoded <= 1) {
10790 decoded = 256 + encoded;
10791 } else if (encoded <= 255) {
10792 decoded = encoded;
10793 } else if (encoded <= 509) {
10794 decoded = encoded - 512;
10795 } else {
10796 decoded = encoded - 768;
10799 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, decoded << 2);
10802 static void gen_addius5(DisasContext *ctx)
10804 int imm = SIMM(ctx->opcode, 1, 4);
10805 int rd = (ctx->opcode >> 5) & 0x1f;
10807 gen_arith_imm(ctx, OPC_ADDIU, rd, rd, imm);
10810 static void gen_andi16(DisasContext *ctx)
10812 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
10813 31, 32, 63, 64, 255, 32768, 65535 };
10814 int rd = mmreg(uMIPS_RD(ctx->opcode));
10815 int rs = mmreg(uMIPS_RS(ctx->opcode));
10816 int encoded = ZIMM(ctx->opcode, 0, 4);
10818 gen_logic_imm(ctx, OPC_ANDI, rd, rs, decoded_imm[encoded]);
10821 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
10822 int base, int16_t offset)
10824 const char *opn = "ldst_multiple";
10825 TCGv t0, t1;
10826 TCGv_i32 t2;
10828 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10829 generate_exception(ctx, EXCP_RI);
10830 return;
10833 t0 = tcg_temp_new();
10835 gen_base_offset_addr(ctx, t0, base, offset);
10837 t1 = tcg_const_tl(reglist);
10838 t2 = tcg_const_i32(ctx->mem_idx);
10840 save_cpu_state(ctx, 1);
10841 switch (opc) {
10842 case LWM32:
10843 gen_helper_lwm(cpu_env, t0, t1, t2);
10844 opn = "lwm";
10845 break;
10846 case SWM32:
10847 gen_helper_swm(cpu_env, t0, t1, t2);
10848 opn = "swm";
10849 break;
10850 #ifdef TARGET_MIPS64
10851 case LDM:
10852 gen_helper_ldm(cpu_env, t0, t1, t2);
10853 opn = "ldm";
10854 break;
10855 case SDM:
10856 gen_helper_sdm(cpu_env, t0, t1, t2);
10857 opn = "sdm";
10858 break;
10859 #endif
10861 (void)opn;
10862 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
10863 tcg_temp_free(t0);
10864 tcg_temp_free(t1);
10865 tcg_temp_free_i32(t2);
10869 static void gen_pool16c_insn(DisasContext *ctx)
10871 int rd = mmreg((ctx->opcode >> 3) & 0x7);
10872 int rs = mmreg(ctx->opcode & 0x7);
10873 int opc;
10875 switch (((ctx->opcode) >> 4) & 0x3f) {
10876 case NOT16 + 0:
10877 case NOT16 + 1:
10878 case NOT16 + 2:
10879 case NOT16 + 3:
10880 gen_logic(ctx, OPC_NOR, rd, rs, 0);
10881 break;
10882 case XOR16 + 0:
10883 case XOR16 + 1:
10884 case XOR16 + 2:
10885 case XOR16 + 3:
10886 gen_logic(ctx, OPC_XOR, rd, rd, rs);
10887 break;
10888 case AND16 + 0:
10889 case AND16 + 1:
10890 case AND16 + 2:
10891 case AND16 + 3:
10892 gen_logic(ctx, OPC_AND, rd, rd, rs);
10893 break;
10894 case OR16 + 0:
10895 case OR16 + 1:
10896 case OR16 + 2:
10897 case OR16 + 3:
10898 gen_logic(ctx, OPC_OR, rd, rd, rs);
10899 break;
10900 case LWM16 + 0:
10901 case LWM16 + 1:
10902 case LWM16 + 2:
10903 case LWM16 + 3:
10905 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10906 int offset = ZIMM(ctx->opcode, 0, 4);
10908 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
10909 29, offset << 2);
10911 break;
10912 case SWM16 + 0:
10913 case SWM16 + 1:
10914 case SWM16 + 2:
10915 case SWM16 + 3:
10917 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
10918 int offset = ZIMM(ctx->opcode, 0, 4);
10920 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
10921 29, offset << 2);
10923 break;
10924 case JR16 + 0:
10925 case JR16 + 1:
10927 int reg = ctx->opcode & 0x1f;
10929 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10931 break;
10932 case JRC16 + 0:
10933 case JRC16 + 1:
10935 int reg = ctx->opcode & 0x1f;
10937 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
10938 /* Let normal delay slot handling in our caller take us
10939 to the branch target. */
10941 break;
10942 case JALR16 + 0:
10943 case JALR16 + 1:
10944 opc = OPC_JALR;
10945 goto do_jalr;
10946 case JALR16S + 0:
10947 case JALR16S + 1:
10948 opc = OPC_JALRS;
10949 do_jalr:
10951 int reg = ctx->opcode & 0x1f;
10953 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
10955 break;
10956 case MFHI16 + 0:
10957 case MFHI16 + 1:
10958 gen_HILO(ctx, OPC_MFHI, 0, uMIPS_RS5(ctx->opcode));
10959 break;
10960 case MFLO16 + 0:
10961 case MFLO16 + 1:
10962 gen_HILO(ctx, OPC_MFLO, 0, uMIPS_RS5(ctx->opcode));
10963 break;
10964 case BREAK16:
10965 generate_exception(ctx, EXCP_BREAK);
10966 break;
10967 case SDBBP16:
10968 /* XXX: not clear which exception should be raised
10969 * when in debug mode...
10971 check_insn(ctx, ISA_MIPS32);
10972 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10973 generate_exception(ctx, EXCP_DBp);
10974 } else {
10975 generate_exception(ctx, EXCP_DBp);
10977 break;
10978 case JRADDIUSP + 0:
10979 case JRADDIUSP + 1:
10981 int imm = ZIMM(ctx->opcode, 0, 5);
10983 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
10984 gen_arith_imm(ctx, OPC_ADDIU, 29, 29, imm << 2);
10985 /* Let normal delay slot handling in our caller take us
10986 to the branch target. */
10988 break;
10989 default:
10990 generate_exception(ctx, EXCP_RI);
10991 break;
10995 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10997 TCGv t0 = tcg_temp_new();
10998 TCGv t1 = tcg_temp_new();
11000 gen_load_gpr(t0, base);
11002 if (index != 0) {
11003 gen_load_gpr(t1, index);
11004 tcg_gen_shli_tl(t1, t1, 2);
11005 gen_op_addr_add(ctx, t0, t1, t0);
11008 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11009 gen_store_gpr(t1, rd);
11011 tcg_temp_free(t0);
11012 tcg_temp_free(t1);
11015 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
11016 int base, int16_t offset)
11018 const char *opn = "ldst_pair";
11019 TCGv t0, t1;
11021 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31) {
11022 generate_exception(ctx, EXCP_RI);
11023 return;
11026 t0 = tcg_temp_new();
11027 t1 = tcg_temp_new();
11029 gen_base_offset_addr(ctx, t0, base, offset);
11031 switch (opc) {
11032 case LWP:
11033 if (rd == base) {
11034 generate_exception(ctx, EXCP_RI);
11035 return;
11037 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11038 gen_store_gpr(t1, rd);
11039 tcg_gen_movi_tl(t1, 4);
11040 gen_op_addr_add(ctx, t0, t0, t1);
11041 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TESL);
11042 gen_store_gpr(t1, rd+1);
11043 opn = "lwp";
11044 break;
11045 case SWP:
11046 gen_load_gpr(t1, rd);
11047 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11048 tcg_gen_movi_tl(t1, 4);
11049 gen_op_addr_add(ctx, t0, t0, t1);
11050 gen_load_gpr(t1, rd+1);
11051 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL);
11052 opn = "swp";
11053 break;
11054 #ifdef TARGET_MIPS64
11055 case LDP:
11056 if (rd == base) {
11057 generate_exception(ctx, EXCP_RI);
11058 return;
11060 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11061 gen_store_gpr(t1, rd);
11062 tcg_gen_movi_tl(t1, 8);
11063 gen_op_addr_add(ctx, t0, t0, t1);
11064 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11065 gen_store_gpr(t1, rd+1);
11066 opn = "ldp";
11067 break;
11068 case SDP:
11069 gen_load_gpr(t1, rd);
11070 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11071 tcg_gen_movi_tl(t1, 8);
11072 gen_op_addr_add(ctx, t0, t0, t1);
11073 gen_load_gpr(t1, rd+1);
11074 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ);
11075 opn = "sdp";
11076 break;
11077 #endif
11079 (void)opn; /* avoid a compiler warning */
11080 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
11081 tcg_temp_free(t0);
11082 tcg_temp_free(t1);
11085 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
11087 int extension = (ctx->opcode >> 6) & 0x3f;
11088 int minor = (ctx->opcode >> 12) & 0xf;
11089 uint32_t mips32_op;
11091 switch (extension) {
11092 case TEQ:
11093 mips32_op = OPC_TEQ;
11094 goto do_trap;
11095 case TGE:
11096 mips32_op = OPC_TGE;
11097 goto do_trap;
11098 case TGEU:
11099 mips32_op = OPC_TGEU;
11100 goto do_trap;
11101 case TLT:
11102 mips32_op = OPC_TLT;
11103 goto do_trap;
11104 case TLTU:
11105 mips32_op = OPC_TLTU;
11106 goto do_trap;
11107 case TNE:
11108 mips32_op = OPC_TNE;
11109 do_trap:
11110 gen_trap(ctx, mips32_op, rs, rt, -1);
11111 break;
11112 #ifndef CONFIG_USER_ONLY
11113 case MFC0:
11114 case MFC0 + 32:
11115 check_cp0_enabled(ctx);
11116 if (rt == 0) {
11117 /* Treat as NOP. */
11118 break;
11120 gen_mfc0(ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
11121 break;
11122 case MTC0:
11123 case MTC0 + 32:
11124 check_cp0_enabled(ctx);
11126 TCGv t0 = tcg_temp_new();
11128 gen_load_gpr(t0, rt);
11129 gen_mtc0(ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
11130 tcg_temp_free(t0);
11132 break;
11133 #endif
11134 case 0x2a:
11135 switch (minor & 3) {
11136 case MADD_ACC:
11137 gen_muldiv(ctx, OPC_MADD, (ctx->opcode >> 14) & 3, rs, rt);
11138 break;
11139 case MADDU_ACC:
11140 gen_muldiv(ctx, OPC_MADDU, (ctx->opcode >> 14) & 3, rs, rt);
11141 break;
11142 case MSUB_ACC:
11143 gen_muldiv(ctx, OPC_MSUB, (ctx->opcode >> 14) & 3, rs, rt);
11144 break;
11145 case MSUBU_ACC:
11146 gen_muldiv(ctx, OPC_MSUBU, (ctx->opcode >> 14) & 3, rs, rt);
11147 break;
11148 default:
11149 goto pool32axf_invalid;
11151 break;
11152 case 0x32:
11153 switch (minor & 3) {
11154 case MULT_ACC:
11155 gen_muldiv(ctx, OPC_MULT, (ctx->opcode >> 14) & 3, rs, rt);
11156 break;
11157 case MULTU_ACC:
11158 gen_muldiv(ctx, OPC_MULTU, (ctx->opcode >> 14) & 3, rs, rt);
11159 break;
11160 default:
11161 goto pool32axf_invalid;
11163 break;
11164 case 0x2c:
11165 switch (minor) {
11166 case SEB:
11167 gen_bshfl(ctx, OPC_SEB, rs, rt);
11168 break;
11169 case SEH:
11170 gen_bshfl(ctx, OPC_SEH, rs, rt);
11171 break;
11172 case CLO:
11173 mips32_op = OPC_CLO;
11174 goto do_cl;
11175 case CLZ:
11176 mips32_op = OPC_CLZ;
11177 do_cl:
11178 check_insn(ctx, ISA_MIPS32);
11179 gen_cl(ctx, mips32_op, rt, rs);
11180 break;
11181 case RDHWR:
11182 gen_rdhwr(ctx, rt, rs);
11183 break;
11184 case WSBH:
11185 gen_bshfl(ctx, OPC_WSBH, rs, rt);
11186 break;
11187 case MULT:
11188 mips32_op = OPC_MULT;
11189 goto do_mul;
11190 case MULTU:
11191 mips32_op = OPC_MULTU;
11192 goto do_mul;
11193 case DIV:
11194 mips32_op = OPC_DIV;
11195 goto do_div;
11196 case DIVU:
11197 mips32_op = OPC_DIVU;
11198 goto do_div;
11199 do_div:
11200 check_insn(ctx, ISA_MIPS32);
11201 gen_muldiv(ctx, mips32_op, 0, rs, rt);
11202 break;
11203 case MADD:
11204 mips32_op = OPC_MADD;
11205 goto do_mul;
11206 case MADDU:
11207 mips32_op = OPC_MADDU;
11208 goto do_mul;
11209 case MSUB:
11210 mips32_op = OPC_MSUB;
11211 goto do_mul;
11212 case MSUBU:
11213 mips32_op = OPC_MSUBU;
11214 do_mul:
11215 check_insn(ctx, ISA_MIPS32);
11216 gen_muldiv(ctx, mips32_op, 0, rs, rt);
11217 break;
11218 default:
11219 goto pool32axf_invalid;
11221 break;
11222 case 0x34:
11223 switch (minor) {
11224 case MFC2:
11225 case MTC2:
11226 case MFHC2:
11227 case MTHC2:
11228 case CFC2:
11229 case CTC2:
11230 generate_exception_err(ctx, EXCP_CpU, 2);
11231 break;
11232 default:
11233 goto pool32axf_invalid;
11235 break;
11236 case 0x3c:
11237 switch (minor) {
11238 case JALR:
11239 case JALR_HB:
11240 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
11241 break;
11242 case JALRS:
11243 case JALRS_HB:
11244 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
11245 break;
11246 default:
11247 goto pool32axf_invalid;
11249 break;
11250 case 0x05:
11251 switch (minor) {
11252 case RDPGPR:
11253 check_cp0_enabled(ctx);
11254 check_insn(ctx, ISA_MIPS32R2);
11255 gen_load_srsgpr(rt, rs);
11256 break;
11257 case WRPGPR:
11258 check_cp0_enabled(ctx);
11259 check_insn(ctx, ISA_MIPS32R2);
11260 gen_store_srsgpr(rt, rs);
11261 break;
11262 default:
11263 goto pool32axf_invalid;
11265 break;
11266 #ifndef CONFIG_USER_ONLY
11267 case 0x0d:
11268 switch (minor) {
11269 case TLBP:
11270 mips32_op = OPC_TLBP;
11271 goto do_cp0;
11272 case TLBR:
11273 mips32_op = OPC_TLBR;
11274 goto do_cp0;
11275 case TLBWI:
11276 mips32_op = OPC_TLBWI;
11277 goto do_cp0;
11278 case TLBWR:
11279 mips32_op = OPC_TLBWR;
11280 goto do_cp0;
11281 case WAIT:
11282 mips32_op = OPC_WAIT;
11283 goto do_cp0;
11284 case DERET:
11285 mips32_op = OPC_DERET;
11286 goto do_cp0;
11287 case ERET:
11288 mips32_op = OPC_ERET;
11289 do_cp0:
11290 gen_cp0(env, ctx, mips32_op, rt, rs);
11291 break;
11292 default:
11293 goto pool32axf_invalid;
11295 break;
11296 case 0x1d:
11297 switch (minor) {
11298 case DI:
11299 check_cp0_enabled(ctx);
11301 TCGv t0 = tcg_temp_new();
11303 save_cpu_state(ctx, 1);
11304 gen_helper_di(t0, cpu_env);
11305 gen_store_gpr(t0, rs);
11306 /* Stop translation as we may have switched the execution mode */
11307 ctx->bstate = BS_STOP;
11308 tcg_temp_free(t0);
11310 break;
11311 case EI:
11312 check_cp0_enabled(ctx);
11314 TCGv t0 = tcg_temp_new();
11316 save_cpu_state(ctx, 1);
11317 gen_helper_ei(t0, cpu_env);
11318 gen_store_gpr(t0, rs);
11319 /* Stop translation as we may have switched the execution mode */
11320 ctx->bstate = BS_STOP;
11321 tcg_temp_free(t0);
11323 break;
11324 default:
11325 goto pool32axf_invalid;
11327 break;
11328 #endif
11329 case 0x2d:
11330 switch (minor) {
11331 case SYNC:
11332 /* NOP */
11333 break;
11334 case SYSCALL:
11335 generate_exception(ctx, EXCP_SYSCALL);
11336 ctx->bstate = BS_STOP;
11337 break;
11338 case SDBBP:
11339 check_insn(ctx, ISA_MIPS32);
11340 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11341 generate_exception(ctx, EXCP_DBp);
11342 } else {
11343 generate_exception(ctx, EXCP_DBp);
11345 break;
11346 default:
11347 goto pool32axf_invalid;
11349 break;
11350 case 0x01:
11351 switch (minor & 3) {
11352 case MFHI_ACC:
11353 gen_HILO(ctx, OPC_MFHI, minor >> 2, rs);
11354 break;
11355 case MFLO_ACC:
11356 gen_HILO(ctx, OPC_MFLO, minor >> 2, rs);
11357 break;
11358 case MTHI_ACC:
11359 gen_HILO(ctx, OPC_MTHI, minor >> 2, rs);
11360 break;
11361 case MTLO_ACC:
11362 gen_HILO(ctx, OPC_MTLO, minor >> 2, rs);
11363 break;
11364 default:
11365 goto pool32axf_invalid;
11367 break;
11368 case 0x35:
11369 switch (minor) {
11370 case MFHI32:
11371 gen_HILO(ctx, OPC_MFHI, 0, rs);
11372 break;
11373 case MFLO32:
11374 gen_HILO(ctx, OPC_MFLO, 0, rs);
11375 break;
11376 case MTHI32:
11377 gen_HILO(ctx, OPC_MTHI, 0, rs);
11378 break;
11379 case MTLO32:
11380 gen_HILO(ctx, OPC_MTLO, 0, rs);
11381 break;
11382 default:
11383 goto pool32axf_invalid;
11385 break;
11386 default:
11387 pool32axf_invalid:
11388 MIPS_INVAL("pool32axf");
11389 generate_exception(ctx, EXCP_RI);
11390 break;
11394 /* Values for microMIPS fmt field. Variable-width, depending on which
11395 formats the instruction supports. */
11397 enum {
11398 FMT_SD_S = 0,
11399 FMT_SD_D = 1,
11401 FMT_SDPS_S = 0,
11402 FMT_SDPS_D = 1,
11403 FMT_SDPS_PS = 2,
11405 FMT_SWL_S = 0,
11406 FMT_SWL_W = 1,
11407 FMT_SWL_L = 2,
11409 FMT_DWL_D = 0,
11410 FMT_DWL_W = 1,
11411 FMT_DWL_L = 2
11414 static void gen_pool32fxf(DisasContext *ctx, int rt, int rs)
11416 int extension = (ctx->opcode >> 6) & 0x3ff;
11417 uint32_t mips32_op;
11419 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
11420 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
11421 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
11423 switch (extension) {
11424 case FLOAT_1BIT_FMT(CFC1, 0):
11425 mips32_op = OPC_CFC1;
11426 goto do_cp1;
11427 case FLOAT_1BIT_FMT(CTC1, 0):
11428 mips32_op = OPC_CTC1;
11429 goto do_cp1;
11430 case FLOAT_1BIT_FMT(MFC1, 0):
11431 mips32_op = OPC_MFC1;
11432 goto do_cp1;
11433 case FLOAT_1BIT_FMT(MTC1, 0):
11434 mips32_op = OPC_MTC1;
11435 goto do_cp1;
11436 case FLOAT_1BIT_FMT(MFHC1, 0):
11437 mips32_op = OPC_MFHC1;
11438 goto do_cp1;
11439 case FLOAT_1BIT_FMT(MTHC1, 0):
11440 mips32_op = OPC_MTHC1;
11441 do_cp1:
11442 gen_cp1(ctx, mips32_op, rt, rs);
11443 break;
11445 /* Reciprocal square root */
11446 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
11447 mips32_op = OPC_RSQRT_S;
11448 goto do_unaryfp;
11449 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
11450 mips32_op = OPC_RSQRT_D;
11451 goto do_unaryfp;
11453 /* Square root */
11454 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
11455 mips32_op = OPC_SQRT_S;
11456 goto do_unaryfp;
11457 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
11458 mips32_op = OPC_SQRT_D;
11459 goto do_unaryfp;
11461 /* Reciprocal */
11462 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
11463 mips32_op = OPC_RECIP_S;
11464 goto do_unaryfp;
11465 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
11466 mips32_op = OPC_RECIP_D;
11467 goto do_unaryfp;
11469 /* Floor */
11470 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
11471 mips32_op = OPC_FLOOR_L_S;
11472 goto do_unaryfp;
11473 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
11474 mips32_op = OPC_FLOOR_L_D;
11475 goto do_unaryfp;
11476 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
11477 mips32_op = OPC_FLOOR_W_S;
11478 goto do_unaryfp;
11479 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
11480 mips32_op = OPC_FLOOR_W_D;
11481 goto do_unaryfp;
11483 /* Ceiling */
11484 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
11485 mips32_op = OPC_CEIL_L_S;
11486 goto do_unaryfp;
11487 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
11488 mips32_op = OPC_CEIL_L_D;
11489 goto do_unaryfp;
11490 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
11491 mips32_op = OPC_CEIL_W_S;
11492 goto do_unaryfp;
11493 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
11494 mips32_op = OPC_CEIL_W_D;
11495 goto do_unaryfp;
11497 /* Truncation */
11498 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
11499 mips32_op = OPC_TRUNC_L_S;
11500 goto do_unaryfp;
11501 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
11502 mips32_op = OPC_TRUNC_L_D;
11503 goto do_unaryfp;
11504 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
11505 mips32_op = OPC_TRUNC_W_S;
11506 goto do_unaryfp;
11507 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
11508 mips32_op = OPC_TRUNC_W_D;
11509 goto do_unaryfp;
11511 /* Round */
11512 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
11513 mips32_op = OPC_ROUND_L_S;
11514 goto do_unaryfp;
11515 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
11516 mips32_op = OPC_ROUND_L_D;
11517 goto do_unaryfp;
11518 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
11519 mips32_op = OPC_ROUND_W_S;
11520 goto do_unaryfp;
11521 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
11522 mips32_op = OPC_ROUND_W_D;
11523 goto do_unaryfp;
11525 /* Integer to floating-point conversion */
11526 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
11527 mips32_op = OPC_CVT_L_S;
11528 goto do_unaryfp;
11529 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
11530 mips32_op = OPC_CVT_L_D;
11531 goto do_unaryfp;
11532 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
11533 mips32_op = OPC_CVT_W_S;
11534 goto do_unaryfp;
11535 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
11536 mips32_op = OPC_CVT_W_D;
11537 goto do_unaryfp;
11539 /* Paired-foo conversions */
11540 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
11541 mips32_op = OPC_CVT_S_PL;
11542 goto do_unaryfp;
11543 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
11544 mips32_op = OPC_CVT_S_PU;
11545 goto do_unaryfp;
11546 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
11547 mips32_op = OPC_CVT_PW_PS;
11548 goto do_unaryfp;
11549 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
11550 mips32_op = OPC_CVT_PS_PW;
11551 goto do_unaryfp;
11553 /* Floating-point moves */
11554 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
11555 mips32_op = OPC_MOV_S;
11556 goto do_unaryfp;
11557 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
11558 mips32_op = OPC_MOV_D;
11559 goto do_unaryfp;
11560 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
11561 mips32_op = OPC_MOV_PS;
11562 goto do_unaryfp;
11564 /* Absolute value */
11565 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
11566 mips32_op = OPC_ABS_S;
11567 goto do_unaryfp;
11568 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
11569 mips32_op = OPC_ABS_D;
11570 goto do_unaryfp;
11571 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
11572 mips32_op = OPC_ABS_PS;
11573 goto do_unaryfp;
11575 /* Negation */
11576 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
11577 mips32_op = OPC_NEG_S;
11578 goto do_unaryfp;
11579 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
11580 mips32_op = OPC_NEG_D;
11581 goto do_unaryfp;
11582 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
11583 mips32_op = OPC_NEG_PS;
11584 goto do_unaryfp;
11586 /* Reciprocal square root step */
11587 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
11588 mips32_op = OPC_RSQRT1_S;
11589 goto do_unaryfp;
11590 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
11591 mips32_op = OPC_RSQRT1_D;
11592 goto do_unaryfp;
11593 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
11594 mips32_op = OPC_RSQRT1_PS;
11595 goto do_unaryfp;
11597 /* Reciprocal step */
11598 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
11599 mips32_op = OPC_RECIP1_S;
11600 goto do_unaryfp;
11601 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
11602 mips32_op = OPC_RECIP1_S;
11603 goto do_unaryfp;
11604 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
11605 mips32_op = OPC_RECIP1_PS;
11606 goto do_unaryfp;
11608 /* Conversions from double */
11609 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
11610 mips32_op = OPC_CVT_D_S;
11611 goto do_unaryfp;
11612 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
11613 mips32_op = OPC_CVT_D_W;
11614 goto do_unaryfp;
11615 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
11616 mips32_op = OPC_CVT_D_L;
11617 goto do_unaryfp;
11619 /* Conversions from single */
11620 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
11621 mips32_op = OPC_CVT_S_D;
11622 goto do_unaryfp;
11623 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
11624 mips32_op = OPC_CVT_S_W;
11625 goto do_unaryfp;
11626 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
11627 mips32_op = OPC_CVT_S_L;
11628 do_unaryfp:
11629 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
11630 break;
11632 /* Conditional moves on floating-point codes */
11633 case COND_FLOAT_MOV(MOVT, 0):
11634 case COND_FLOAT_MOV(MOVT, 1):
11635 case COND_FLOAT_MOV(MOVT, 2):
11636 case COND_FLOAT_MOV(MOVT, 3):
11637 case COND_FLOAT_MOV(MOVT, 4):
11638 case COND_FLOAT_MOV(MOVT, 5):
11639 case COND_FLOAT_MOV(MOVT, 6):
11640 case COND_FLOAT_MOV(MOVT, 7):
11641 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
11642 break;
11643 case COND_FLOAT_MOV(MOVF, 0):
11644 case COND_FLOAT_MOV(MOVF, 1):
11645 case COND_FLOAT_MOV(MOVF, 2):
11646 case COND_FLOAT_MOV(MOVF, 3):
11647 case COND_FLOAT_MOV(MOVF, 4):
11648 case COND_FLOAT_MOV(MOVF, 5):
11649 case COND_FLOAT_MOV(MOVF, 6):
11650 case COND_FLOAT_MOV(MOVF, 7):
11651 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
11652 break;
11653 default:
11654 MIPS_INVAL("pool32fxf");
11655 generate_exception(ctx, EXCP_RI);
11656 break;
11660 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
11661 uint16_t insn_hw1)
11663 int32_t offset;
11664 uint16_t insn;
11665 int rt, rs, rd, rr;
11666 int16_t imm;
11667 uint32_t op, minor, mips32_op;
11668 uint32_t cond, fmt, cc;
11670 insn = cpu_lduw_code(env, ctx->pc + 2);
11671 ctx->opcode = (ctx->opcode << 16) | insn;
11673 rt = (ctx->opcode >> 21) & 0x1f;
11674 rs = (ctx->opcode >> 16) & 0x1f;
11675 rd = (ctx->opcode >> 11) & 0x1f;
11676 rr = (ctx->opcode >> 6) & 0x1f;
11677 imm = (int16_t) ctx->opcode;
11679 op = (ctx->opcode >> 26) & 0x3f;
11680 switch (op) {
11681 case POOL32A:
11682 minor = ctx->opcode & 0x3f;
11683 switch (minor) {
11684 case 0x00:
11685 minor = (ctx->opcode >> 6) & 0xf;
11686 switch (minor) {
11687 case SLL32:
11688 mips32_op = OPC_SLL;
11689 goto do_shifti;
11690 case SRA:
11691 mips32_op = OPC_SRA;
11692 goto do_shifti;
11693 case SRL32:
11694 mips32_op = OPC_SRL;
11695 goto do_shifti;
11696 case ROTR:
11697 mips32_op = OPC_ROTR;
11698 do_shifti:
11699 gen_shift_imm(ctx, mips32_op, rt, rs, rd);
11700 break;
11701 default:
11702 goto pool32a_invalid;
11704 break;
11705 case 0x10:
11706 minor = (ctx->opcode >> 6) & 0xf;
11707 switch (minor) {
11708 /* Arithmetic */
11709 case ADD:
11710 mips32_op = OPC_ADD;
11711 goto do_arith;
11712 case ADDU32:
11713 mips32_op = OPC_ADDU;
11714 goto do_arith;
11715 case SUB:
11716 mips32_op = OPC_SUB;
11717 goto do_arith;
11718 case SUBU32:
11719 mips32_op = OPC_SUBU;
11720 goto do_arith;
11721 case MUL:
11722 mips32_op = OPC_MUL;
11723 do_arith:
11724 gen_arith(ctx, mips32_op, rd, rs, rt);
11725 break;
11726 /* Shifts */
11727 case SLLV:
11728 mips32_op = OPC_SLLV;
11729 goto do_shift;
11730 case SRLV:
11731 mips32_op = OPC_SRLV;
11732 goto do_shift;
11733 case SRAV:
11734 mips32_op = OPC_SRAV;
11735 goto do_shift;
11736 case ROTRV:
11737 mips32_op = OPC_ROTRV;
11738 do_shift:
11739 gen_shift(ctx, mips32_op, rd, rs, rt);
11740 break;
11741 /* Logical operations */
11742 case AND:
11743 mips32_op = OPC_AND;
11744 goto do_logic;
11745 case OR32:
11746 mips32_op = OPC_OR;
11747 goto do_logic;
11748 case NOR:
11749 mips32_op = OPC_NOR;
11750 goto do_logic;
11751 case XOR32:
11752 mips32_op = OPC_XOR;
11753 do_logic:
11754 gen_logic(ctx, mips32_op, rd, rs, rt);
11755 break;
11756 /* Set less than */
11757 case SLT:
11758 mips32_op = OPC_SLT;
11759 goto do_slt;
11760 case SLTU:
11761 mips32_op = OPC_SLTU;
11762 do_slt:
11763 gen_slt(ctx, mips32_op, rd, rs, rt);
11764 break;
11765 default:
11766 goto pool32a_invalid;
11768 break;
11769 case 0x18:
11770 minor = (ctx->opcode >> 6) & 0xf;
11771 switch (minor) {
11772 /* Conditional moves */
11773 case MOVN:
11774 mips32_op = OPC_MOVN;
11775 goto do_cmov;
11776 case MOVZ:
11777 mips32_op = OPC_MOVZ;
11778 do_cmov:
11779 gen_cond_move(ctx, mips32_op, rd, rs, rt);
11780 break;
11781 case LWXS:
11782 gen_ldxs(ctx, rs, rt, rd);
11783 break;
11784 default:
11785 goto pool32a_invalid;
11787 break;
11788 case INS:
11789 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
11790 return;
11791 case EXT:
11792 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
11793 return;
11794 case POOL32AXF:
11795 gen_pool32axf(env, ctx, rt, rs);
11796 break;
11797 case 0x07:
11798 generate_exception(ctx, EXCP_BREAK);
11799 break;
11800 default:
11801 pool32a_invalid:
11802 MIPS_INVAL("pool32a");
11803 generate_exception(ctx, EXCP_RI);
11804 break;
11806 break;
11807 case POOL32B:
11808 minor = (ctx->opcode >> 12) & 0xf;
11809 switch (minor) {
11810 case CACHE:
11811 check_cp0_enabled(ctx);
11812 /* Treat as no-op. */
11813 break;
11814 case LWC2:
11815 case SWC2:
11816 /* COP2: Not implemented. */
11817 generate_exception_err(ctx, EXCP_CpU, 2);
11818 break;
11819 case LWP:
11820 case SWP:
11821 #ifdef TARGET_MIPS64
11822 case LDP:
11823 case SDP:
11824 #endif
11825 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11826 break;
11827 case LWM32:
11828 case SWM32:
11829 #ifdef TARGET_MIPS64
11830 case LDM:
11831 case SDM:
11832 #endif
11833 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
11834 break;
11835 default:
11836 MIPS_INVAL("pool32b");
11837 generate_exception(ctx, EXCP_RI);
11838 break;
11840 break;
11841 case POOL32F:
11842 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
11843 minor = ctx->opcode & 0x3f;
11844 check_cp1_enabled(ctx);
11845 switch (minor) {
11846 case ALNV_PS:
11847 mips32_op = OPC_ALNV_PS;
11848 goto do_madd;
11849 case MADD_S:
11850 mips32_op = OPC_MADD_S;
11851 goto do_madd;
11852 case MADD_D:
11853 mips32_op = OPC_MADD_D;
11854 goto do_madd;
11855 case MADD_PS:
11856 mips32_op = OPC_MADD_PS;
11857 goto do_madd;
11858 case MSUB_S:
11859 mips32_op = OPC_MSUB_S;
11860 goto do_madd;
11861 case MSUB_D:
11862 mips32_op = OPC_MSUB_D;
11863 goto do_madd;
11864 case MSUB_PS:
11865 mips32_op = OPC_MSUB_PS;
11866 goto do_madd;
11867 case NMADD_S:
11868 mips32_op = OPC_NMADD_S;
11869 goto do_madd;
11870 case NMADD_D:
11871 mips32_op = OPC_NMADD_D;
11872 goto do_madd;
11873 case NMADD_PS:
11874 mips32_op = OPC_NMADD_PS;
11875 goto do_madd;
11876 case NMSUB_S:
11877 mips32_op = OPC_NMSUB_S;
11878 goto do_madd;
11879 case NMSUB_D:
11880 mips32_op = OPC_NMSUB_D;
11881 goto do_madd;
11882 case NMSUB_PS:
11883 mips32_op = OPC_NMSUB_PS;
11884 do_madd:
11885 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
11886 break;
11887 case CABS_COND_FMT:
11888 cond = (ctx->opcode >> 6) & 0xf;
11889 cc = (ctx->opcode >> 13) & 0x7;
11890 fmt = (ctx->opcode >> 10) & 0x3;
11891 switch (fmt) {
11892 case 0x0:
11893 gen_cmpabs_s(ctx, cond, rt, rs, cc);
11894 break;
11895 case 0x1:
11896 gen_cmpabs_d(ctx, cond, rt, rs, cc);
11897 break;
11898 case 0x2:
11899 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
11900 break;
11901 default:
11902 goto pool32f_invalid;
11904 break;
11905 case C_COND_FMT:
11906 cond = (ctx->opcode >> 6) & 0xf;
11907 cc = (ctx->opcode >> 13) & 0x7;
11908 fmt = (ctx->opcode >> 10) & 0x3;
11909 switch (fmt) {
11910 case 0x0:
11911 gen_cmp_s(ctx, cond, rt, rs, cc);
11912 break;
11913 case 0x1:
11914 gen_cmp_d(ctx, cond, rt, rs, cc);
11915 break;
11916 case 0x2:
11917 gen_cmp_ps(ctx, cond, rt, rs, cc);
11918 break;
11919 default:
11920 goto pool32f_invalid;
11922 break;
11923 case POOL32FXF:
11924 gen_pool32fxf(ctx, rt, rs);
11925 break;
11926 case 0x00:
11927 /* PLL foo */
11928 switch ((ctx->opcode >> 6) & 0x7) {
11929 case PLL_PS:
11930 mips32_op = OPC_PLL_PS;
11931 goto do_ps;
11932 case PLU_PS:
11933 mips32_op = OPC_PLU_PS;
11934 goto do_ps;
11935 case PUL_PS:
11936 mips32_op = OPC_PUL_PS;
11937 goto do_ps;
11938 case PUU_PS:
11939 mips32_op = OPC_PUU_PS;
11940 goto do_ps;
11941 case CVT_PS_S:
11942 mips32_op = OPC_CVT_PS_S;
11943 do_ps:
11944 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11945 break;
11946 default:
11947 goto pool32f_invalid;
11949 break;
11950 case 0x08:
11951 /* [LS][WDU]XC1 */
11952 switch ((ctx->opcode >> 6) & 0x7) {
11953 case LWXC1:
11954 mips32_op = OPC_LWXC1;
11955 goto do_ldst_cp1;
11956 case SWXC1:
11957 mips32_op = OPC_SWXC1;
11958 goto do_ldst_cp1;
11959 case LDXC1:
11960 mips32_op = OPC_LDXC1;
11961 goto do_ldst_cp1;
11962 case SDXC1:
11963 mips32_op = OPC_SDXC1;
11964 goto do_ldst_cp1;
11965 case LUXC1:
11966 mips32_op = OPC_LUXC1;
11967 goto do_ldst_cp1;
11968 case SUXC1:
11969 mips32_op = OPC_SUXC1;
11970 do_ldst_cp1:
11971 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
11972 break;
11973 default:
11974 goto pool32f_invalid;
11976 break;
11977 case 0x18:
11978 /* 3D insns */
11979 fmt = (ctx->opcode >> 9) & 0x3;
11980 switch ((ctx->opcode >> 6) & 0x7) {
11981 case RSQRT2_FMT:
11982 switch (fmt) {
11983 case FMT_SDPS_S:
11984 mips32_op = OPC_RSQRT2_S;
11985 goto do_3d;
11986 case FMT_SDPS_D:
11987 mips32_op = OPC_RSQRT2_D;
11988 goto do_3d;
11989 case FMT_SDPS_PS:
11990 mips32_op = OPC_RSQRT2_PS;
11991 goto do_3d;
11992 default:
11993 goto pool32f_invalid;
11995 break;
11996 case RECIP2_FMT:
11997 switch (fmt) {
11998 case FMT_SDPS_S:
11999 mips32_op = OPC_RECIP2_S;
12000 goto do_3d;
12001 case FMT_SDPS_D:
12002 mips32_op = OPC_RECIP2_D;
12003 goto do_3d;
12004 case FMT_SDPS_PS:
12005 mips32_op = OPC_RECIP2_PS;
12006 goto do_3d;
12007 default:
12008 goto pool32f_invalid;
12010 break;
12011 case ADDR_PS:
12012 mips32_op = OPC_ADDR_PS;
12013 goto do_3d;
12014 case MULR_PS:
12015 mips32_op = OPC_MULR_PS;
12016 do_3d:
12017 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12018 break;
12019 default:
12020 goto pool32f_invalid;
12022 break;
12023 case 0x20:
12024 /* MOV[FT].fmt and PREFX */
12025 cc = (ctx->opcode >> 13) & 0x7;
12026 fmt = (ctx->opcode >> 9) & 0x3;
12027 switch ((ctx->opcode >> 6) & 0x7) {
12028 case MOVF_FMT:
12029 switch (fmt) {
12030 case FMT_SDPS_S:
12031 gen_movcf_s(rs, rt, cc, 0);
12032 break;
12033 case FMT_SDPS_D:
12034 gen_movcf_d(ctx, rs, rt, cc, 0);
12035 break;
12036 case FMT_SDPS_PS:
12037 gen_movcf_ps(ctx, rs, rt, cc, 0);
12038 break;
12039 default:
12040 goto pool32f_invalid;
12042 break;
12043 case MOVT_FMT:
12044 switch (fmt) {
12045 case FMT_SDPS_S:
12046 gen_movcf_s(rs, rt, cc, 1);
12047 break;
12048 case FMT_SDPS_D:
12049 gen_movcf_d(ctx, rs, rt, cc, 1);
12050 break;
12051 case FMT_SDPS_PS:
12052 gen_movcf_ps(ctx, rs, rt, cc, 1);
12053 break;
12054 default:
12055 goto pool32f_invalid;
12057 break;
12058 case PREFX:
12059 break;
12060 default:
12061 goto pool32f_invalid;
12063 break;
12064 #define FINSN_3ARG_SDPS(prfx) \
12065 switch ((ctx->opcode >> 8) & 0x3) { \
12066 case FMT_SDPS_S: \
12067 mips32_op = OPC_##prfx##_S; \
12068 goto do_fpop; \
12069 case FMT_SDPS_D: \
12070 mips32_op = OPC_##prfx##_D; \
12071 goto do_fpop; \
12072 case FMT_SDPS_PS: \
12073 mips32_op = OPC_##prfx##_PS; \
12074 goto do_fpop; \
12075 default: \
12076 goto pool32f_invalid; \
12078 case 0x30:
12079 /* regular FP ops */
12080 switch ((ctx->opcode >> 6) & 0x3) {
12081 case ADD_FMT:
12082 FINSN_3ARG_SDPS(ADD);
12083 break;
12084 case SUB_FMT:
12085 FINSN_3ARG_SDPS(SUB);
12086 break;
12087 case MUL_FMT:
12088 FINSN_3ARG_SDPS(MUL);
12089 break;
12090 case DIV_FMT:
12091 fmt = (ctx->opcode >> 8) & 0x3;
12092 if (fmt == 1) {
12093 mips32_op = OPC_DIV_D;
12094 } else if (fmt == 0) {
12095 mips32_op = OPC_DIV_S;
12096 } else {
12097 goto pool32f_invalid;
12099 goto do_fpop;
12100 default:
12101 goto pool32f_invalid;
12103 break;
12104 case 0x38:
12105 /* cmovs */
12106 switch ((ctx->opcode >> 6) & 0x3) {
12107 case MOVN_FMT:
12108 FINSN_3ARG_SDPS(MOVN);
12109 break;
12110 case MOVZ_FMT:
12111 FINSN_3ARG_SDPS(MOVZ);
12112 break;
12113 default:
12114 goto pool32f_invalid;
12116 break;
12117 do_fpop:
12118 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
12119 break;
12120 default:
12121 pool32f_invalid:
12122 MIPS_INVAL("pool32f");
12123 generate_exception(ctx, EXCP_RI);
12124 break;
12126 } else {
12127 generate_exception_err(ctx, EXCP_CpU, 1);
12129 break;
12130 case POOL32I:
12131 minor = (ctx->opcode >> 21) & 0x1f;
12132 switch (minor) {
12133 case BLTZ:
12134 mips32_op = OPC_BLTZ;
12135 goto do_branch;
12136 case BLTZAL:
12137 mips32_op = OPC_BLTZAL;
12138 goto do_branch;
12139 case BLTZALS:
12140 mips32_op = OPC_BLTZALS;
12141 goto do_branch;
12142 case BGEZ:
12143 mips32_op = OPC_BGEZ;
12144 goto do_branch;
12145 case BGEZAL:
12146 mips32_op = OPC_BGEZAL;
12147 goto do_branch;
12148 case BGEZALS:
12149 mips32_op = OPC_BGEZALS;
12150 goto do_branch;
12151 case BLEZ:
12152 mips32_op = OPC_BLEZ;
12153 goto do_branch;
12154 case BGTZ:
12155 mips32_op = OPC_BGTZ;
12156 do_branch:
12157 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
12158 break;
12160 /* Traps */
12161 case TLTI:
12162 mips32_op = OPC_TLTI;
12163 goto do_trapi;
12164 case TGEI:
12165 mips32_op = OPC_TGEI;
12166 goto do_trapi;
12167 case TLTIU:
12168 mips32_op = OPC_TLTIU;
12169 goto do_trapi;
12170 case TGEIU:
12171 mips32_op = OPC_TGEIU;
12172 goto do_trapi;
12173 case TNEI:
12174 mips32_op = OPC_TNEI;
12175 goto do_trapi;
12176 case TEQI:
12177 mips32_op = OPC_TEQI;
12178 do_trapi:
12179 gen_trap(ctx, mips32_op, rs, -1, imm);
12180 break;
12182 case BNEZC:
12183 case BEQZC:
12184 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
12185 4, rs, 0, imm << 1);
12186 /* Compact branches don't have a delay slot, so just let
12187 the normal delay slot handling take us to the branch
12188 target. */
12189 break;
12190 case LUI:
12191 gen_logic_imm(ctx, OPC_LUI, rs, -1, imm);
12192 break;
12193 case SYNCI:
12194 break;
12195 case BC2F:
12196 case BC2T:
12197 /* COP2: Not implemented. */
12198 generate_exception_err(ctx, EXCP_CpU, 2);
12199 break;
12200 case BC1F:
12201 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
12202 goto do_cp1branch;
12203 case BC1T:
12204 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
12205 goto do_cp1branch;
12206 case BC1ANY4F:
12207 mips32_op = OPC_BC1FANY4;
12208 goto do_cp1mips3d;
12209 case BC1ANY4T:
12210 mips32_op = OPC_BC1TANY4;
12211 do_cp1mips3d:
12212 check_cop1x(ctx);
12213 check_insn(ctx, ASE_MIPS3D);
12214 /* Fall through */
12215 do_cp1branch:
12216 gen_compute_branch1(ctx, mips32_op,
12217 (ctx->opcode >> 18) & 0x7, imm << 1);
12218 break;
12219 case BPOSGE64:
12220 case BPOSGE32:
12221 /* MIPS DSP: not implemented */
12222 /* Fall through */
12223 default:
12224 MIPS_INVAL("pool32i");
12225 generate_exception(ctx, EXCP_RI);
12226 break;
12228 break;
12229 case POOL32C:
12230 minor = (ctx->opcode >> 12) & 0xf;
12231 switch (minor) {
12232 case LWL:
12233 mips32_op = OPC_LWL;
12234 goto do_ld_lr;
12235 case SWL:
12236 mips32_op = OPC_SWL;
12237 goto do_st_lr;
12238 case LWR:
12239 mips32_op = OPC_LWR;
12240 goto do_ld_lr;
12241 case SWR:
12242 mips32_op = OPC_SWR;
12243 goto do_st_lr;
12244 #if defined(TARGET_MIPS64)
12245 case LDL:
12246 mips32_op = OPC_LDL;
12247 goto do_ld_lr;
12248 case SDL:
12249 mips32_op = OPC_SDL;
12250 goto do_st_lr;
12251 case LDR:
12252 mips32_op = OPC_LDR;
12253 goto do_ld_lr;
12254 case SDR:
12255 mips32_op = OPC_SDR;
12256 goto do_st_lr;
12257 case LWU:
12258 mips32_op = OPC_LWU;
12259 goto do_ld_lr;
12260 case LLD:
12261 mips32_op = OPC_LLD;
12262 goto do_ld_lr;
12263 #endif
12264 case LL:
12265 mips32_op = OPC_LL;
12266 goto do_ld_lr;
12267 do_ld_lr:
12268 gen_ld(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
12269 break;
12270 do_st_lr:
12271 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
12272 break;
12273 case SC:
12274 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
12275 break;
12276 #if defined(TARGET_MIPS64)
12277 case SCD:
12278 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
12279 break;
12280 #endif
12281 case PREF:
12282 /* Treat as no-op */
12283 break;
12284 default:
12285 MIPS_INVAL("pool32c");
12286 generate_exception(ctx, EXCP_RI);
12287 break;
12289 break;
12290 case ADDI32:
12291 mips32_op = OPC_ADDI;
12292 goto do_addi;
12293 case ADDIU32:
12294 mips32_op = OPC_ADDIU;
12295 do_addi:
12296 gen_arith_imm(ctx, mips32_op, rt, rs, imm);
12297 break;
12299 /* Logical operations */
12300 case ORI32:
12301 mips32_op = OPC_ORI;
12302 goto do_logici;
12303 case XORI32:
12304 mips32_op = OPC_XORI;
12305 goto do_logici;
12306 case ANDI32:
12307 mips32_op = OPC_ANDI;
12308 do_logici:
12309 gen_logic_imm(ctx, mips32_op, rt, rs, imm);
12310 break;
12312 /* Set less than immediate */
12313 case SLTI32:
12314 mips32_op = OPC_SLTI;
12315 goto do_slti;
12316 case SLTIU32:
12317 mips32_op = OPC_SLTIU;
12318 do_slti:
12319 gen_slt_imm(ctx, mips32_op, rt, rs, imm);
12320 break;
12321 case JALX32:
12322 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12323 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
12324 break;
12325 case JALS32:
12326 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
12327 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
12328 break;
12329 case BEQ32:
12330 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
12331 break;
12332 case BNE32:
12333 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
12334 break;
12335 case J32:
12336 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
12337 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12338 break;
12339 case JAL32:
12340 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
12341 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
12342 break;
12343 /* Floating point (COP1) */
12344 case LWC132:
12345 mips32_op = OPC_LWC1;
12346 goto do_cop1;
12347 case LDC132:
12348 mips32_op = OPC_LDC1;
12349 goto do_cop1;
12350 case SWC132:
12351 mips32_op = OPC_SWC1;
12352 goto do_cop1;
12353 case SDC132:
12354 mips32_op = OPC_SDC1;
12355 do_cop1:
12356 gen_cop1_ldst(ctx, mips32_op, rt, rs, imm);
12357 break;
12358 case ADDIUPC:
12360 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
12361 int offset = SIMM(ctx->opcode, 0, 23) << 2;
12363 gen_addiupc(ctx, reg, offset, 0, 0);
12365 break;
12366 /* Loads and stores */
12367 case LB32:
12368 mips32_op = OPC_LB;
12369 goto do_ld;
12370 case LBU32:
12371 mips32_op = OPC_LBU;
12372 goto do_ld;
12373 case LH32:
12374 mips32_op = OPC_LH;
12375 goto do_ld;
12376 case LHU32:
12377 mips32_op = OPC_LHU;
12378 goto do_ld;
12379 case LW32:
12380 mips32_op = OPC_LW;
12381 goto do_ld;
12382 #ifdef TARGET_MIPS64
12383 case LD32:
12384 mips32_op = OPC_LD;
12385 goto do_ld;
12386 case SD32:
12387 mips32_op = OPC_SD;
12388 goto do_st;
12389 #endif
12390 case SB32:
12391 mips32_op = OPC_SB;
12392 goto do_st;
12393 case SH32:
12394 mips32_op = OPC_SH;
12395 goto do_st;
12396 case SW32:
12397 mips32_op = OPC_SW;
12398 goto do_st;
12399 do_ld:
12400 gen_ld(ctx, mips32_op, rt, rs, imm);
12401 break;
12402 do_st:
12403 gen_st(ctx, mips32_op, rt, rs, imm);
12404 break;
12405 default:
12406 generate_exception(ctx, EXCP_RI);
12407 break;
12411 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx)
12413 uint32_t op;
12415 /* make sure instructions are on a halfword boundary */
12416 if (ctx->pc & 0x1) {
12417 env->CP0_BadVAddr = ctx->pc;
12418 generate_exception(ctx, EXCP_AdEL);
12419 ctx->bstate = BS_STOP;
12420 return 2;
12423 op = (ctx->opcode >> 10) & 0x3f;
12424 /* Enforce properly-sized instructions in a delay slot */
12425 if (ctx->hflags & MIPS_HFLAG_BMASK) {
12426 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
12428 switch (op) {
12429 case POOL32A:
12430 case POOL32B:
12431 case POOL32I:
12432 case POOL32C:
12433 case ADDI32:
12434 case ADDIU32:
12435 case ORI32:
12436 case XORI32:
12437 case SLTI32:
12438 case SLTIU32:
12439 case ANDI32:
12440 case JALX32:
12441 case LBU32:
12442 case LHU32:
12443 case POOL32F:
12444 case JALS32:
12445 case BEQ32:
12446 case BNE32:
12447 case J32:
12448 case JAL32:
12449 case SB32:
12450 case SH32:
12451 case POOL32S:
12452 case ADDIUPC:
12453 case SWC132:
12454 case SDC132:
12455 case SD32:
12456 case SW32:
12457 case LB32:
12458 case LH32:
12459 case DADDIU32:
12460 case LWC132:
12461 case LDC132:
12462 case LD32:
12463 case LW32:
12464 if (bits & MIPS_HFLAG_BDS16) {
12465 generate_exception(ctx, EXCP_RI);
12466 /* Just stop translation; the user is confused. */
12467 ctx->bstate = BS_STOP;
12468 return 2;
12470 break;
12471 case POOL16A:
12472 case POOL16B:
12473 case POOL16C:
12474 case LWGP16:
12475 case POOL16F:
12476 case LBU16:
12477 case LHU16:
12478 case LWSP16:
12479 case LW16:
12480 case SB16:
12481 case SH16:
12482 case SWSP16:
12483 case SW16:
12484 case MOVE16:
12485 case ANDI16:
12486 case POOL16D:
12487 case POOL16E:
12488 case BEQZ16:
12489 case BNEZ16:
12490 case B16:
12491 case LI16:
12492 if (bits & MIPS_HFLAG_BDS32) {
12493 generate_exception(ctx, EXCP_RI);
12494 /* Just stop translation; the user is confused. */
12495 ctx->bstate = BS_STOP;
12496 return 2;
12498 break;
12499 default:
12500 break;
12503 switch (op) {
12504 case POOL16A:
12506 int rd = mmreg(uMIPS_RD(ctx->opcode));
12507 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
12508 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
12509 uint32_t opc = 0;
12511 switch (ctx->opcode & 0x1) {
12512 case ADDU16:
12513 opc = OPC_ADDU;
12514 break;
12515 case SUBU16:
12516 opc = OPC_SUBU;
12517 break;
12520 gen_arith(ctx, opc, rd, rs1, rs2);
12522 break;
12523 case POOL16B:
12525 int rd = mmreg(uMIPS_RD(ctx->opcode));
12526 int rs = mmreg(uMIPS_RS(ctx->opcode));
12527 int amount = (ctx->opcode >> 1) & 0x7;
12528 uint32_t opc = 0;
12529 amount = amount == 0 ? 8 : amount;
12531 switch (ctx->opcode & 0x1) {
12532 case SLL16:
12533 opc = OPC_SLL;
12534 break;
12535 case SRL16:
12536 opc = OPC_SRL;
12537 break;
12540 gen_shift_imm(ctx, opc, rd, rs, amount);
12542 break;
12543 case POOL16C:
12544 gen_pool16c_insn(ctx);
12545 break;
12546 case LWGP16:
12548 int rd = mmreg(uMIPS_RD(ctx->opcode));
12549 int rb = 28; /* GP */
12550 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
12552 gen_ld(ctx, OPC_LW, rd, rb, offset);
12554 break;
12555 case POOL16F:
12556 if (ctx->opcode & 1) {
12557 generate_exception(ctx, EXCP_RI);
12558 } else {
12559 /* MOVEP */
12560 int enc_dest = uMIPS_RD(ctx->opcode);
12561 int enc_rt = uMIPS_RS2(ctx->opcode);
12562 int enc_rs = uMIPS_RS1(ctx->opcode);
12563 int rd, rs, re, rt;
12564 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
12565 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
12566 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
12568 rd = rd_enc[enc_dest];
12569 re = re_enc[enc_dest];
12570 rs = rs_rt_enc[enc_rs];
12571 rt = rs_rt_enc[enc_rt];
12573 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
12574 gen_arith_imm(ctx, OPC_ADDIU, re, rt, 0);
12576 break;
12577 case LBU16:
12579 int rd = mmreg(uMIPS_RD(ctx->opcode));
12580 int rb = mmreg(uMIPS_RS(ctx->opcode));
12581 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12582 offset = (offset == 0xf ? -1 : offset);
12584 gen_ld(ctx, OPC_LBU, rd, rb, offset);
12586 break;
12587 case LHU16:
12589 int rd = mmreg(uMIPS_RD(ctx->opcode));
12590 int rb = mmreg(uMIPS_RS(ctx->opcode));
12591 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12593 gen_ld(ctx, OPC_LHU, rd, rb, offset);
12595 break;
12596 case LWSP16:
12598 int rd = (ctx->opcode >> 5) & 0x1f;
12599 int rb = 29; /* SP */
12600 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12602 gen_ld(ctx, OPC_LW, rd, rb, offset);
12604 break;
12605 case LW16:
12607 int rd = mmreg(uMIPS_RD(ctx->opcode));
12608 int rb = mmreg(uMIPS_RS(ctx->opcode));
12609 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12611 gen_ld(ctx, OPC_LW, rd, rb, offset);
12613 break;
12614 case SB16:
12616 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12617 int rb = mmreg(uMIPS_RS(ctx->opcode));
12618 int16_t offset = ZIMM(ctx->opcode, 0, 4);
12620 gen_st(ctx, OPC_SB, rd, rb, offset);
12622 break;
12623 case SH16:
12625 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12626 int rb = mmreg(uMIPS_RS(ctx->opcode));
12627 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
12629 gen_st(ctx, OPC_SH, rd, rb, offset);
12631 break;
12632 case SWSP16:
12634 int rd = (ctx->opcode >> 5) & 0x1f;
12635 int rb = 29; /* SP */
12636 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
12638 gen_st(ctx, OPC_SW, rd, rb, offset);
12640 break;
12641 case SW16:
12643 int rd = mmreg2(uMIPS_RD(ctx->opcode));
12644 int rb = mmreg(uMIPS_RS(ctx->opcode));
12645 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
12647 gen_st(ctx, OPC_SW, rd, rb, offset);
12649 break;
12650 case MOVE16:
12652 int rd = uMIPS_RD5(ctx->opcode);
12653 int rs = uMIPS_RS5(ctx->opcode);
12655 gen_arith_imm(ctx, OPC_ADDIU, rd, rs, 0);
12657 break;
12658 case ANDI16:
12659 gen_andi16(ctx);
12660 break;
12661 case POOL16D:
12662 switch (ctx->opcode & 0x1) {
12663 case ADDIUS5:
12664 gen_addius5(ctx);
12665 break;
12666 case ADDIUSP:
12667 gen_addiusp(ctx);
12668 break;
12670 break;
12671 case POOL16E:
12672 switch (ctx->opcode & 0x1) {
12673 case ADDIUR2:
12674 gen_addiur2(ctx);
12675 break;
12676 case ADDIUR1SP:
12677 gen_addiur1sp(ctx);
12678 break;
12680 break;
12681 case B16:
12682 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
12683 SIMM(ctx->opcode, 0, 10) << 1);
12684 break;
12685 case BNEZ16:
12686 case BEQZ16:
12687 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
12688 mmreg(uMIPS_RD(ctx->opcode)),
12689 0, SIMM(ctx->opcode, 0, 7) << 1);
12690 break;
12691 case LI16:
12693 int reg = mmreg(uMIPS_RD(ctx->opcode));
12694 int imm = ZIMM(ctx->opcode, 0, 7);
12696 imm = (imm == 0x7f ? -1 : imm);
12697 tcg_gen_movi_tl(cpu_gpr[reg], imm);
12699 break;
12700 case RES_20:
12701 case RES_28:
12702 case RES_29:
12703 case RES_30:
12704 case RES_31:
12705 case RES_38:
12706 case RES_39:
12707 generate_exception(ctx, EXCP_RI);
12708 break;
12709 default:
12710 decode_micromips32_opc (env, ctx, op);
12711 return 4;
12714 return 2;
12717 /* SmartMIPS extension to MIPS32 */
12719 #if defined(TARGET_MIPS64)
12721 /* MDMX extension to MIPS64 */
12723 #endif
12725 /* MIPSDSP functions. */
12726 static void gen_mipsdsp_ld(DisasContext *ctx, uint32_t opc,
12727 int rd, int base, int offset)
12729 const char *opn = "ldx";
12730 TCGv t0;
12732 check_dsp(ctx);
12733 t0 = tcg_temp_new();
12735 if (base == 0) {
12736 gen_load_gpr(t0, offset);
12737 } else if (offset == 0) {
12738 gen_load_gpr(t0, base);
12739 } else {
12740 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
12743 switch (opc) {
12744 case OPC_LBUX:
12745 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
12746 gen_store_gpr(t0, rd);
12747 opn = "lbux";
12748 break;
12749 case OPC_LHX:
12750 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESW);
12751 gen_store_gpr(t0, rd);
12752 opn = "lhx";
12753 break;
12754 case OPC_LWX:
12755 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TESL);
12756 gen_store_gpr(t0, rd);
12757 opn = "lwx";
12758 break;
12759 #if defined(TARGET_MIPS64)
12760 case OPC_LDX:
12761 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ);
12762 gen_store_gpr(t0, rd);
12763 opn = "ldx";
12764 break;
12765 #endif
12767 (void)opn; /* avoid a compiler warning */
12768 MIPS_DEBUG("%s %s, %s(%s)", opn,
12769 regnames[rd], regnames[offset], regnames[base]);
12770 tcg_temp_free(t0);
12773 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
12774 int ret, int v1, int v2)
12776 const char *opn = "mipsdsp arith";
12777 TCGv v1_t;
12778 TCGv v2_t;
12780 if (ret == 0) {
12781 /* Treat as NOP. */
12782 MIPS_DEBUG("NOP");
12783 return;
12786 v1_t = tcg_temp_new();
12787 v2_t = tcg_temp_new();
12789 gen_load_gpr(v1_t, v1);
12790 gen_load_gpr(v2_t, v2);
12792 switch (op1) {
12793 /* OPC_MULT_G_2E is equal OPC_ADDUH_QB_DSP */
12794 case OPC_MULT_G_2E:
12795 check_dspr2(ctx);
12796 switch (op2) {
12797 case OPC_ADDUH_QB:
12798 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
12799 break;
12800 case OPC_ADDUH_R_QB:
12801 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12802 break;
12803 case OPC_ADDQH_PH:
12804 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
12805 break;
12806 case OPC_ADDQH_R_PH:
12807 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12808 break;
12809 case OPC_ADDQH_W:
12810 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
12811 break;
12812 case OPC_ADDQH_R_W:
12813 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12814 break;
12815 case OPC_SUBUH_QB:
12816 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
12817 break;
12818 case OPC_SUBUH_R_QB:
12819 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
12820 break;
12821 case OPC_SUBQH_PH:
12822 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
12823 break;
12824 case OPC_SUBQH_R_PH:
12825 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
12826 break;
12827 case OPC_SUBQH_W:
12828 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
12829 break;
12830 case OPC_SUBQH_R_W:
12831 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
12832 break;
12834 break;
12835 case OPC_ABSQ_S_PH_DSP:
12836 switch (op2) {
12837 case OPC_ABSQ_S_QB:
12838 check_dspr2(ctx);
12839 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, cpu_env);
12840 break;
12841 case OPC_ABSQ_S_PH:
12842 check_dsp(ctx);
12843 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, cpu_env);
12844 break;
12845 case OPC_ABSQ_S_W:
12846 check_dsp(ctx);
12847 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, cpu_env);
12848 break;
12849 case OPC_PRECEQ_W_PHL:
12850 check_dsp(ctx);
12851 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
12852 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12853 break;
12854 case OPC_PRECEQ_W_PHR:
12855 check_dsp(ctx);
12856 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
12857 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
12858 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12859 break;
12860 case OPC_PRECEQU_PH_QBL:
12861 check_dsp(ctx);
12862 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
12863 break;
12864 case OPC_PRECEQU_PH_QBR:
12865 check_dsp(ctx);
12866 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
12867 break;
12868 case OPC_PRECEQU_PH_QBLA:
12869 check_dsp(ctx);
12870 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
12871 break;
12872 case OPC_PRECEQU_PH_QBRA:
12873 check_dsp(ctx);
12874 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
12875 break;
12876 case OPC_PRECEU_PH_QBL:
12877 check_dsp(ctx);
12878 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
12879 break;
12880 case OPC_PRECEU_PH_QBR:
12881 check_dsp(ctx);
12882 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
12883 break;
12884 case OPC_PRECEU_PH_QBLA:
12885 check_dsp(ctx);
12886 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
12887 break;
12888 case OPC_PRECEU_PH_QBRA:
12889 check_dsp(ctx);
12890 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
12891 break;
12893 break;
12894 case OPC_ADDU_QB_DSP:
12895 switch (op2) {
12896 case OPC_ADDQ_PH:
12897 check_dsp(ctx);
12898 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12899 break;
12900 case OPC_ADDQ_S_PH:
12901 check_dsp(ctx);
12902 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12903 break;
12904 case OPC_ADDQ_S_W:
12905 check_dsp(ctx);
12906 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12907 break;
12908 case OPC_ADDU_QB:
12909 check_dsp(ctx);
12910 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12911 break;
12912 case OPC_ADDU_S_QB:
12913 check_dsp(ctx);
12914 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12915 break;
12916 case OPC_ADDU_PH:
12917 check_dspr2(ctx);
12918 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12919 break;
12920 case OPC_ADDU_S_PH:
12921 check_dspr2(ctx);
12922 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12923 break;
12924 case OPC_SUBQ_PH:
12925 check_dsp(ctx);
12926 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12927 break;
12928 case OPC_SUBQ_S_PH:
12929 check_dsp(ctx);
12930 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12931 break;
12932 case OPC_SUBQ_S_W:
12933 check_dsp(ctx);
12934 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12935 break;
12936 case OPC_SUBU_QB:
12937 check_dsp(ctx);
12938 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12939 break;
12940 case OPC_SUBU_S_QB:
12941 check_dsp(ctx);
12942 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12943 break;
12944 case OPC_SUBU_PH:
12945 check_dspr2(ctx);
12946 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12947 break;
12948 case OPC_SUBU_S_PH:
12949 check_dspr2(ctx);
12950 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12951 break;
12952 case OPC_ADDSC:
12953 check_dsp(ctx);
12954 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12955 break;
12956 case OPC_ADDWC:
12957 check_dsp(ctx);
12958 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, cpu_env);
12959 break;
12960 case OPC_MODSUB:
12961 check_dsp(ctx);
12962 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
12963 break;
12964 case OPC_RADDU_W_QB:
12965 check_dsp(ctx);
12966 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
12967 break;
12969 break;
12970 case OPC_CMPU_EQ_QB_DSP:
12971 switch (op2) {
12972 case OPC_PRECR_QB_PH:
12973 check_dspr2(ctx);
12974 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12975 break;
12976 case OPC_PRECRQ_QB_PH:
12977 check_dsp(ctx);
12978 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
12979 break;
12980 case OPC_PRECR_SRA_PH_W:
12981 check_dspr2(ctx);
12983 TCGv_i32 sa_t = tcg_const_i32(v2);
12984 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
12985 cpu_gpr[ret]);
12986 tcg_temp_free_i32(sa_t);
12987 break;
12989 case OPC_PRECR_SRA_R_PH_W:
12990 check_dspr2(ctx);
12992 TCGv_i32 sa_t = tcg_const_i32(v2);
12993 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
12994 cpu_gpr[ret]);
12995 tcg_temp_free_i32(sa_t);
12996 break;
12998 case OPC_PRECRQ_PH_W:
12999 check_dsp(ctx);
13000 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
13001 break;
13002 case OPC_PRECRQ_RS_PH_W:
13003 check_dsp(ctx);
13004 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13005 break;
13006 case OPC_PRECRQU_S_QB_PH:
13007 check_dsp(ctx);
13008 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13009 break;
13011 break;
13012 #ifdef TARGET_MIPS64
13013 case OPC_ABSQ_S_QH_DSP:
13014 switch (op2) {
13015 case OPC_PRECEQ_L_PWL:
13016 check_dsp(ctx);
13017 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
13018 break;
13019 case OPC_PRECEQ_L_PWR:
13020 check_dsp(ctx);
13021 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
13022 break;
13023 case OPC_PRECEQ_PW_QHL:
13024 check_dsp(ctx);
13025 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
13026 break;
13027 case OPC_PRECEQ_PW_QHR:
13028 check_dsp(ctx);
13029 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
13030 break;
13031 case OPC_PRECEQ_PW_QHLA:
13032 check_dsp(ctx);
13033 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
13034 break;
13035 case OPC_PRECEQ_PW_QHRA:
13036 check_dsp(ctx);
13037 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
13038 break;
13039 case OPC_PRECEQU_QH_OBL:
13040 check_dsp(ctx);
13041 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
13042 break;
13043 case OPC_PRECEQU_QH_OBR:
13044 check_dsp(ctx);
13045 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
13046 break;
13047 case OPC_PRECEQU_QH_OBLA:
13048 check_dsp(ctx);
13049 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
13050 break;
13051 case OPC_PRECEQU_QH_OBRA:
13052 check_dsp(ctx);
13053 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
13054 break;
13055 case OPC_PRECEU_QH_OBL:
13056 check_dsp(ctx);
13057 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
13058 break;
13059 case OPC_PRECEU_QH_OBR:
13060 check_dsp(ctx);
13061 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
13062 break;
13063 case OPC_PRECEU_QH_OBLA:
13064 check_dsp(ctx);
13065 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
13066 break;
13067 case OPC_PRECEU_QH_OBRA:
13068 check_dsp(ctx);
13069 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
13070 break;
13071 case OPC_ABSQ_S_OB:
13072 check_dspr2(ctx);
13073 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, cpu_env);
13074 break;
13075 case OPC_ABSQ_S_PW:
13076 check_dsp(ctx);
13077 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, cpu_env);
13078 break;
13079 case OPC_ABSQ_S_QH:
13080 check_dsp(ctx);
13081 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, cpu_env);
13082 break;
13084 break;
13085 case OPC_ADDU_OB_DSP:
13086 switch (op2) {
13087 case OPC_RADDU_L_OB:
13088 check_dsp(ctx);
13089 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
13090 break;
13091 case OPC_SUBQ_PW:
13092 check_dsp(ctx);
13093 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13094 break;
13095 case OPC_SUBQ_S_PW:
13096 check_dsp(ctx);
13097 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13098 break;
13099 case OPC_SUBQ_QH:
13100 check_dsp(ctx);
13101 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13102 break;
13103 case OPC_SUBQ_S_QH:
13104 check_dsp(ctx);
13105 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13106 break;
13107 case OPC_SUBU_OB:
13108 check_dsp(ctx);
13109 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13110 break;
13111 case OPC_SUBU_S_OB:
13112 check_dsp(ctx);
13113 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13114 break;
13115 case OPC_SUBU_QH:
13116 check_dspr2(ctx);
13117 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13118 break;
13119 case OPC_SUBU_S_QH:
13120 check_dspr2(ctx);
13121 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13122 break;
13123 case OPC_SUBUH_OB:
13124 check_dspr2(ctx);
13125 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
13126 break;
13127 case OPC_SUBUH_R_OB:
13128 check_dspr2(ctx);
13129 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13130 break;
13131 case OPC_ADDQ_PW:
13132 check_dsp(ctx);
13133 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13134 break;
13135 case OPC_ADDQ_S_PW:
13136 check_dsp(ctx);
13137 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13138 break;
13139 case OPC_ADDQ_QH:
13140 check_dsp(ctx);
13141 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13142 break;
13143 case OPC_ADDQ_S_QH:
13144 check_dsp(ctx);
13145 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13146 break;
13147 case OPC_ADDU_OB:
13148 check_dsp(ctx);
13149 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13150 break;
13151 case OPC_ADDU_S_OB:
13152 check_dsp(ctx);
13153 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13154 break;
13155 case OPC_ADDU_QH:
13156 check_dspr2(ctx);
13157 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13158 break;
13159 case OPC_ADDU_S_QH:
13160 check_dspr2(ctx);
13161 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13162 break;
13163 case OPC_ADDUH_OB:
13164 check_dspr2(ctx);
13165 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
13166 break;
13167 case OPC_ADDUH_R_OB:
13168 check_dspr2(ctx);
13169 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
13170 break;
13172 break;
13173 case OPC_CMPU_EQ_OB_DSP:
13174 switch (op2) {
13175 case OPC_PRECR_OB_QH:
13176 check_dspr2(ctx);
13177 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13178 break;
13179 case OPC_PRECR_SRA_QH_PW:
13180 check_dspr2(ctx);
13182 TCGv_i32 ret_t = tcg_const_i32(ret);
13183 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
13184 tcg_temp_free_i32(ret_t);
13185 break;
13187 case OPC_PRECR_SRA_R_QH_PW:
13188 check_dspr2(ctx);
13190 TCGv_i32 sa_v = tcg_const_i32(ret);
13191 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
13192 tcg_temp_free_i32(sa_v);
13193 break;
13195 case OPC_PRECRQ_OB_QH:
13196 check_dsp(ctx);
13197 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
13198 break;
13199 case OPC_PRECRQ_PW_L:
13200 check_dsp(ctx);
13201 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
13202 break;
13203 case OPC_PRECRQ_QH_PW:
13204 check_dsp(ctx);
13205 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
13206 break;
13207 case OPC_PRECRQ_RS_QH_PW:
13208 check_dsp(ctx);
13209 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13210 break;
13211 case OPC_PRECRQU_S_OB_QH:
13212 check_dsp(ctx);
13213 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13214 break;
13216 break;
13217 #endif
13220 tcg_temp_free(v1_t);
13221 tcg_temp_free(v2_t);
13223 (void)opn; /* avoid a compiler warning */
13224 MIPS_DEBUG("%s", opn);
13227 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
13228 int ret, int v1, int v2)
13230 uint32_t op2;
13231 const char *opn = "mipsdsp shift";
13232 TCGv t0;
13233 TCGv v1_t;
13234 TCGv v2_t;
13236 if (ret == 0) {
13237 /* Treat as NOP. */
13238 MIPS_DEBUG("NOP");
13239 return;
13242 t0 = tcg_temp_new();
13243 v1_t = tcg_temp_new();
13244 v2_t = tcg_temp_new();
13246 tcg_gen_movi_tl(t0, v1);
13247 gen_load_gpr(v1_t, v1);
13248 gen_load_gpr(v2_t, v2);
13250 switch (opc) {
13251 case OPC_SHLL_QB_DSP:
13253 op2 = MASK_SHLL_QB(ctx->opcode);
13254 switch (op2) {
13255 case OPC_SHLL_QB:
13256 check_dsp(ctx);
13257 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, cpu_env);
13258 break;
13259 case OPC_SHLLV_QB:
13260 check_dsp(ctx);
13261 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13262 break;
13263 case OPC_SHLL_PH:
13264 check_dsp(ctx);
13265 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13266 break;
13267 case OPC_SHLLV_PH:
13268 check_dsp(ctx);
13269 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13270 break;
13271 case OPC_SHLL_S_PH:
13272 check_dsp(ctx);
13273 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, cpu_env);
13274 break;
13275 case OPC_SHLLV_S_PH:
13276 check_dsp(ctx);
13277 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13278 break;
13279 case OPC_SHLL_S_W:
13280 check_dsp(ctx);
13281 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, cpu_env);
13282 break;
13283 case OPC_SHLLV_S_W:
13284 check_dsp(ctx);
13285 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13286 break;
13287 case OPC_SHRL_QB:
13288 check_dsp(ctx);
13289 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
13290 break;
13291 case OPC_SHRLV_QB:
13292 check_dsp(ctx);
13293 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
13294 break;
13295 case OPC_SHRL_PH:
13296 check_dspr2(ctx);
13297 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
13298 break;
13299 case OPC_SHRLV_PH:
13300 check_dspr2(ctx);
13301 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
13302 break;
13303 case OPC_SHRA_QB:
13304 check_dspr2(ctx);
13305 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
13306 break;
13307 case OPC_SHRA_R_QB:
13308 check_dspr2(ctx);
13309 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
13310 break;
13311 case OPC_SHRAV_QB:
13312 check_dspr2(ctx);
13313 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
13314 break;
13315 case OPC_SHRAV_R_QB:
13316 check_dspr2(ctx);
13317 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
13318 break;
13319 case OPC_SHRA_PH:
13320 check_dsp(ctx);
13321 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
13322 break;
13323 case OPC_SHRA_R_PH:
13324 check_dsp(ctx);
13325 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
13326 break;
13327 case OPC_SHRAV_PH:
13328 check_dsp(ctx);
13329 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
13330 break;
13331 case OPC_SHRAV_R_PH:
13332 check_dsp(ctx);
13333 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
13334 break;
13335 case OPC_SHRA_R_W:
13336 check_dsp(ctx);
13337 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
13338 break;
13339 case OPC_SHRAV_R_W:
13340 check_dsp(ctx);
13341 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
13342 break;
13343 default: /* Invalid */
13344 MIPS_INVAL("MASK SHLL.QB");
13345 generate_exception(ctx, EXCP_RI);
13346 break;
13348 break;
13350 #ifdef TARGET_MIPS64
13351 case OPC_SHLL_OB_DSP:
13352 op2 = MASK_SHLL_OB(ctx->opcode);
13353 switch (op2) {
13354 case OPC_SHLL_PW:
13355 check_dsp(ctx);
13356 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13357 break;
13358 case OPC_SHLLV_PW:
13359 check_dsp(ctx);
13360 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13361 break;
13362 case OPC_SHLL_S_PW:
13363 check_dsp(ctx);
13364 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, cpu_env);
13365 break;
13366 case OPC_SHLLV_S_PW:
13367 check_dsp(ctx);
13368 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13369 break;
13370 case OPC_SHLL_OB:
13371 check_dsp(ctx);
13372 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, cpu_env);
13373 break;
13374 case OPC_SHLLV_OB:
13375 check_dsp(ctx);
13376 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13377 break;
13378 case OPC_SHLL_QH:
13379 check_dsp(ctx);
13380 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13381 break;
13382 case OPC_SHLLV_QH:
13383 check_dsp(ctx);
13384 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13385 break;
13386 case OPC_SHLL_S_QH:
13387 check_dsp(ctx);
13388 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, cpu_env);
13389 break;
13390 case OPC_SHLLV_S_QH:
13391 check_dsp(ctx);
13392 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, cpu_env);
13393 break;
13394 case OPC_SHRA_OB:
13395 check_dspr2(ctx);
13396 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
13397 break;
13398 case OPC_SHRAV_OB:
13399 check_dspr2(ctx);
13400 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
13401 break;
13402 case OPC_SHRA_R_OB:
13403 check_dspr2(ctx);
13404 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
13405 break;
13406 case OPC_SHRAV_R_OB:
13407 check_dspr2(ctx);
13408 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
13409 break;
13410 case OPC_SHRA_PW:
13411 check_dsp(ctx);
13412 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
13413 break;
13414 case OPC_SHRAV_PW:
13415 check_dsp(ctx);
13416 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
13417 break;
13418 case OPC_SHRA_R_PW:
13419 check_dsp(ctx);
13420 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
13421 break;
13422 case OPC_SHRAV_R_PW:
13423 check_dsp(ctx);
13424 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
13425 break;
13426 case OPC_SHRA_QH:
13427 check_dsp(ctx);
13428 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
13429 break;
13430 case OPC_SHRAV_QH:
13431 check_dsp(ctx);
13432 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
13433 break;
13434 case OPC_SHRA_R_QH:
13435 check_dsp(ctx);
13436 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
13437 break;
13438 case OPC_SHRAV_R_QH:
13439 check_dsp(ctx);
13440 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
13441 break;
13442 case OPC_SHRL_OB:
13443 check_dsp(ctx);
13444 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
13445 break;
13446 case OPC_SHRLV_OB:
13447 check_dsp(ctx);
13448 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
13449 break;
13450 case OPC_SHRL_QH:
13451 check_dspr2(ctx);
13452 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
13453 break;
13454 case OPC_SHRLV_QH:
13455 check_dspr2(ctx);
13456 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
13457 break;
13458 default: /* Invalid */
13459 MIPS_INVAL("MASK SHLL.OB");
13460 generate_exception(ctx, EXCP_RI);
13461 break;
13463 break;
13464 #endif
13467 tcg_temp_free(t0);
13468 tcg_temp_free(v1_t);
13469 tcg_temp_free(v2_t);
13470 (void)opn; /* avoid a compiler warning */
13471 MIPS_DEBUG("%s", opn);
13474 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
13475 int ret, int v1, int v2, int check_ret)
13477 const char *opn = "mipsdsp multiply";
13478 TCGv_i32 t0;
13479 TCGv v1_t;
13480 TCGv v2_t;
13482 if ((ret == 0) && (check_ret == 1)) {
13483 /* Treat as NOP. */
13484 MIPS_DEBUG("NOP");
13485 return;
13488 t0 = tcg_temp_new_i32();
13489 v1_t = tcg_temp_new();
13490 v2_t = tcg_temp_new();
13492 tcg_gen_movi_i32(t0, ret);
13493 gen_load_gpr(v1_t, v1);
13494 gen_load_gpr(v2_t, v2);
13496 switch (op1) {
13497 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13498 * the same mask and op1. */
13499 case OPC_MULT_G_2E:
13500 check_dspr2(ctx);
13501 switch (op2) {
13502 case OPC_MUL_PH:
13503 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13504 break;
13505 case OPC_MUL_S_PH:
13506 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13507 break;
13508 case OPC_MULQ_S_W:
13509 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13510 break;
13511 case OPC_MULQ_RS_W:
13512 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13513 break;
13515 break;
13516 case OPC_DPA_W_PH_DSP:
13517 switch (op2) {
13518 case OPC_DPAU_H_QBL:
13519 check_dsp(ctx);
13520 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, cpu_env);
13521 break;
13522 case OPC_DPAU_H_QBR:
13523 check_dsp(ctx);
13524 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, cpu_env);
13525 break;
13526 case OPC_DPSU_H_QBL:
13527 check_dsp(ctx);
13528 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, cpu_env);
13529 break;
13530 case OPC_DPSU_H_QBR:
13531 check_dsp(ctx);
13532 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, cpu_env);
13533 break;
13534 case OPC_DPA_W_PH:
13535 check_dspr2(ctx);
13536 gen_helper_dpa_w_ph(t0, v1_t, v2_t, cpu_env);
13537 break;
13538 case OPC_DPAX_W_PH:
13539 check_dspr2(ctx);
13540 gen_helper_dpax_w_ph(t0, v1_t, v2_t, cpu_env);
13541 break;
13542 case OPC_DPAQ_S_W_PH:
13543 check_dsp(ctx);
13544 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13545 break;
13546 case OPC_DPAQX_S_W_PH:
13547 check_dspr2(ctx);
13548 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13549 break;
13550 case OPC_DPAQX_SA_W_PH:
13551 check_dspr2(ctx);
13552 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13553 break;
13554 case OPC_DPS_W_PH:
13555 check_dspr2(ctx);
13556 gen_helper_dps_w_ph(t0, v1_t, v2_t, cpu_env);
13557 break;
13558 case OPC_DPSX_W_PH:
13559 check_dspr2(ctx);
13560 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, cpu_env);
13561 break;
13562 case OPC_DPSQ_S_W_PH:
13563 check_dsp(ctx);
13564 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13565 break;
13566 case OPC_DPSQX_S_W_PH:
13567 check_dspr2(ctx);
13568 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, cpu_env);
13569 break;
13570 case OPC_DPSQX_SA_W_PH:
13571 check_dspr2(ctx);
13572 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, cpu_env);
13573 break;
13574 case OPC_MULSAQ_S_W_PH:
13575 check_dsp(ctx);
13576 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, cpu_env);
13577 break;
13578 case OPC_DPAQ_SA_L_W:
13579 check_dsp(ctx);
13580 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13581 break;
13582 case OPC_DPSQ_SA_L_W:
13583 check_dsp(ctx);
13584 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, cpu_env);
13585 break;
13586 case OPC_MAQ_S_W_PHL:
13587 check_dsp(ctx);
13588 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, cpu_env);
13589 break;
13590 case OPC_MAQ_S_W_PHR:
13591 check_dsp(ctx);
13592 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, cpu_env);
13593 break;
13594 case OPC_MAQ_SA_W_PHL:
13595 check_dsp(ctx);
13596 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, cpu_env);
13597 break;
13598 case OPC_MAQ_SA_W_PHR:
13599 check_dsp(ctx);
13600 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, cpu_env);
13601 break;
13602 case OPC_MULSA_W_PH:
13603 check_dspr2(ctx);
13604 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, cpu_env);
13605 break;
13607 break;
13608 #ifdef TARGET_MIPS64
13609 case OPC_DPAQ_W_QH_DSP:
13611 int ac = ret & 0x03;
13612 tcg_gen_movi_i32(t0, ac);
13614 switch (op2) {
13615 case OPC_DMADD:
13616 check_dsp(ctx);
13617 gen_helper_dmadd(v1_t, v2_t, t0, cpu_env);
13618 break;
13619 case OPC_DMADDU:
13620 check_dsp(ctx);
13621 gen_helper_dmaddu(v1_t, v2_t, t0, cpu_env);
13622 break;
13623 case OPC_DMSUB:
13624 check_dsp(ctx);
13625 gen_helper_dmsub(v1_t, v2_t, t0, cpu_env);
13626 break;
13627 case OPC_DMSUBU:
13628 check_dsp(ctx);
13629 gen_helper_dmsubu(v1_t, v2_t, t0, cpu_env);
13630 break;
13631 case OPC_DPA_W_QH:
13632 check_dspr2(ctx);
13633 gen_helper_dpa_w_qh(v1_t, v2_t, t0, cpu_env);
13634 break;
13635 case OPC_DPAQ_S_W_QH:
13636 check_dsp(ctx);
13637 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13638 break;
13639 case OPC_DPAQ_SA_L_PW:
13640 check_dsp(ctx);
13641 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13642 break;
13643 case OPC_DPAU_H_OBL:
13644 check_dsp(ctx);
13645 gen_helper_dpau_h_obl(v1_t, v2_t, t0, cpu_env);
13646 break;
13647 case OPC_DPAU_H_OBR:
13648 check_dsp(ctx);
13649 gen_helper_dpau_h_obr(v1_t, v2_t, t0, cpu_env);
13650 break;
13651 case OPC_DPS_W_QH:
13652 check_dspr2(ctx);
13653 gen_helper_dps_w_qh(v1_t, v2_t, t0, cpu_env);
13654 break;
13655 case OPC_DPSQ_S_W_QH:
13656 check_dsp(ctx);
13657 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13658 break;
13659 case OPC_DPSQ_SA_L_PW:
13660 check_dsp(ctx);
13661 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, cpu_env);
13662 break;
13663 case OPC_DPSU_H_OBL:
13664 check_dsp(ctx);
13665 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, cpu_env);
13666 break;
13667 case OPC_DPSU_H_OBR:
13668 check_dsp(ctx);
13669 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, cpu_env);
13670 break;
13671 case OPC_MAQ_S_L_PWL:
13672 check_dsp(ctx);
13673 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, cpu_env);
13674 break;
13675 case OPC_MAQ_S_L_PWR:
13676 check_dsp(ctx);
13677 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, cpu_env);
13678 break;
13679 case OPC_MAQ_S_W_QHLL:
13680 check_dsp(ctx);
13681 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, cpu_env);
13682 break;
13683 case OPC_MAQ_SA_W_QHLL:
13684 check_dsp(ctx);
13685 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, cpu_env);
13686 break;
13687 case OPC_MAQ_S_W_QHLR:
13688 check_dsp(ctx);
13689 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, cpu_env);
13690 break;
13691 case OPC_MAQ_SA_W_QHLR:
13692 check_dsp(ctx);
13693 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, cpu_env);
13694 break;
13695 case OPC_MAQ_S_W_QHRL:
13696 check_dsp(ctx);
13697 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, cpu_env);
13698 break;
13699 case OPC_MAQ_SA_W_QHRL:
13700 check_dsp(ctx);
13701 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, cpu_env);
13702 break;
13703 case OPC_MAQ_S_W_QHRR:
13704 check_dsp(ctx);
13705 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, cpu_env);
13706 break;
13707 case OPC_MAQ_SA_W_QHRR:
13708 check_dsp(ctx);
13709 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, cpu_env);
13710 break;
13711 case OPC_MULSAQ_S_L_PW:
13712 check_dsp(ctx);
13713 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, cpu_env);
13714 break;
13715 case OPC_MULSAQ_S_W_QH:
13716 check_dsp(ctx);
13717 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, cpu_env);
13718 break;
13721 break;
13722 #endif
13723 case OPC_ADDU_QB_DSP:
13724 switch (op2) {
13725 case OPC_MULEU_S_PH_QBL:
13726 check_dsp(ctx);
13727 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13728 break;
13729 case OPC_MULEU_S_PH_QBR:
13730 check_dsp(ctx);
13731 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13732 break;
13733 case OPC_MULQ_RS_PH:
13734 check_dsp(ctx);
13735 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13736 break;
13737 case OPC_MULEQ_S_W_PHL:
13738 check_dsp(ctx);
13739 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13740 break;
13741 case OPC_MULEQ_S_W_PHR:
13742 check_dsp(ctx);
13743 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13744 break;
13745 case OPC_MULQ_S_PH:
13746 check_dspr2(ctx);
13747 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13748 break;
13750 break;
13751 #ifdef TARGET_MIPS64
13752 case OPC_ADDU_OB_DSP:
13753 switch (op2) {
13754 case OPC_MULEQ_S_PW_QHL:
13755 check_dsp(ctx);
13756 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13757 break;
13758 case OPC_MULEQ_S_PW_QHR:
13759 check_dsp(ctx);
13760 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13761 break;
13762 case OPC_MULEU_S_QH_OBL:
13763 check_dsp(ctx);
13764 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13765 break;
13766 case OPC_MULEU_S_QH_OBR:
13767 check_dsp(ctx);
13768 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13769 break;
13770 case OPC_MULQ_RS_QH:
13771 check_dsp(ctx);
13772 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
13773 break;
13775 break;
13776 #endif
13779 tcg_temp_free_i32(t0);
13780 tcg_temp_free(v1_t);
13781 tcg_temp_free(v2_t);
13783 (void)opn; /* avoid a compiler warning */
13784 MIPS_DEBUG("%s", opn);
13788 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
13789 int ret, int val)
13791 const char *opn = "mipsdsp Bit/ Manipulation";
13792 int16_t imm;
13793 TCGv t0;
13794 TCGv val_t;
13796 if (ret == 0) {
13797 /* Treat as NOP. */
13798 MIPS_DEBUG("NOP");
13799 return;
13802 t0 = tcg_temp_new();
13803 val_t = tcg_temp_new();
13804 gen_load_gpr(val_t, val);
13806 switch (op1) {
13807 case OPC_ABSQ_S_PH_DSP:
13808 switch (op2) {
13809 case OPC_BITREV:
13810 check_dsp(ctx);
13811 gen_helper_bitrev(cpu_gpr[ret], val_t);
13812 break;
13813 case OPC_REPL_QB:
13814 check_dsp(ctx);
13816 target_long result;
13817 imm = (ctx->opcode >> 16) & 0xFF;
13818 result = (uint32_t)imm << 24 |
13819 (uint32_t)imm << 16 |
13820 (uint32_t)imm << 8 |
13821 (uint32_t)imm;
13822 result = (int32_t)result;
13823 tcg_gen_movi_tl(cpu_gpr[ret], result);
13825 break;
13826 case OPC_REPLV_QB:
13827 check_dsp(ctx);
13828 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13829 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13830 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13831 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13832 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13833 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13834 break;
13835 case OPC_REPL_PH:
13836 check_dsp(ctx);
13838 imm = (ctx->opcode >> 16) & 0x03FF;
13839 imm = (int16_t)(imm << 6) >> 6;
13840 tcg_gen_movi_tl(cpu_gpr[ret], \
13841 (target_long)((int32_t)imm << 16 | \
13842 (uint16_t)imm));
13844 break;
13845 case OPC_REPLV_PH:
13846 check_dsp(ctx);
13847 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13848 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13849 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13850 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
13851 break;
13853 break;
13854 #ifdef TARGET_MIPS64
13855 case OPC_ABSQ_S_QH_DSP:
13856 switch (op2) {
13857 case OPC_REPL_OB:
13858 check_dsp(ctx);
13860 target_long temp;
13862 imm = (ctx->opcode >> 16) & 0xFF;
13863 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
13864 temp = (temp << 16) | temp;
13865 temp = (temp << 32) | temp;
13866 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13867 break;
13869 case OPC_REPL_PW:
13870 check_dsp(ctx);
13872 target_long temp;
13874 imm = (ctx->opcode >> 16) & 0x03FF;
13875 imm = (int16_t)(imm << 6) >> 6;
13876 temp = ((target_long)imm << 32) \
13877 | ((target_long)imm & 0xFFFFFFFF);
13878 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13879 break;
13881 case OPC_REPL_QH:
13882 check_dsp(ctx);
13884 target_long temp;
13886 imm = (ctx->opcode >> 16) & 0x03FF;
13887 imm = (int16_t)(imm << 6) >> 6;
13889 temp = ((uint64_t)(uint16_t)imm << 48) |
13890 ((uint64_t)(uint16_t)imm << 32) |
13891 ((uint64_t)(uint16_t)imm << 16) |
13892 (uint64_t)(uint16_t)imm;
13893 tcg_gen_movi_tl(cpu_gpr[ret], temp);
13894 break;
13896 case OPC_REPLV_OB:
13897 check_dsp(ctx);
13898 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
13899 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
13900 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13901 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13902 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13903 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13904 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13905 break;
13906 case OPC_REPLV_PW:
13907 check_dsp(ctx);
13908 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
13909 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13910 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13911 break;
13912 case OPC_REPLV_QH:
13913 check_dsp(ctx);
13914 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
13915 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
13916 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13917 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
13918 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
13919 break;
13921 break;
13922 #endif
13924 tcg_temp_free(t0);
13925 tcg_temp_free(val_t);
13927 (void)opn; /* avoid a compiler warning */
13928 MIPS_DEBUG("%s", opn);
13931 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
13932 uint32_t op1, uint32_t op2,
13933 int ret, int v1, int v2, int check_ret)
13935 const char *opn = "mipsdsp add compare pick";
13936 TCGv t1;
13937 TCGv v1_t;
13938 TCGv v2_t;
13940 if ((ret == 0) && (check_ret == 1)) {
13941 /* Treat as NOP. */
13942 MIPS_DEBUG("NOP");
13943 return;
13946 t1 = tcg_temp_new();
13947 v1_t = tcg_temp_new();
13948 v2_t = tcg_temp_new();
13950 gen_load_gpr(v1_t, v1);
13951 gen_load_gpr(v2_t, v2);
13953 switch (op1) {
13954 case OPC_CMPU_EQ_QB_DSP:
13955 switch (op2) {
13956 case OPC_CMPU_EQ_QB:
13957 check_dsp(ctx);
13958 gen_helper_cmpu_eq_qb(v1_t, v2_t, cpu_env);
13959 break;
13960 case OPC_CMPU_LT_QB:
13961 check_dsp(ctx);
13962 gen_helper_cmpu_lt_qb(v1_t, v2_t, cpu_env);
13963 break;
13964 case OPC_CMPU_LE_QB:
13965 check_dsp(ctx);
13966 gen_helper_cmpu_le_qb(v1_t, v2_t, cpu_env);
13967 break;
13968 case OPC_CMPGU_EQ_QB:
13969 check_dsp(ctx);
13970 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
13971 break;
13972 case OPC_CMPGU_LT_QB:
13973 check_dsp(ctx);
13974 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
13975 break;
13976 case OPC_CMPGU_LE_QB:
13977 check_dsp(ctx);
13978 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
13979 break;
13980 case OPC_CMPGDU_EQ_QB:
13981 check_dspr2(ctx);
13982 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
13983 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13984 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13985 tcg_gen_shli_tl(t1, t1, 24);
13986 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13987 break;
13988 case OPC_CMPGDU_LT_QB:
13989 check_dspr2(ctx);
13990 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
13991 tcg_gen_mov_tl(cpu_gpr[ret], t1);
13992 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
13993 tcg_gen_shli_tl(t1, t1, 24);
13994 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
13995 break;
13996 case OPC_CMPGDU_LE_QB:
13997 check_dspr2(ctx);
13998 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
13999 tcg_gen_mov_tl(cpu_gpr[ret], t1);
14000 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
14001 tcg_gen_shli_tl(t1, t1, 24);
14002 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
14003 break;
14004 case OPC_CMP_EQ_PH:
14005 check_dsp(ctx);
14006 gen_helper_cmp_eq_ph(v1_t, v2_t, cpu_env);
14007 break;
14008 case OPC_CMP_LT_PH:
14009 check_dsp(ctx);
14010 gen_helper_cmp_lt_ph(v1_t, v2_t, cpu_env);
14011 break;
14012 case OPC_CMP_LE_PH:
14013 check_dsp(ctx);
14014 gen_helper_cmp_le_ph(v1_t, v2_t, cpu_env);
14015 break;
14016 case OPC_PICK_QB:
14017 check_dsp(ctx);
14018 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14019 break;
14020 case OPC_PICK_PH:
14021 check_dsp(ctx);
14022 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14023 break;
14024 case OPC_PACKRL_PH:
14025 check_dsp(ctx);
14026 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
14027 break;
14029 break;
14030 #ifdef TARGET_MIPS64
14031 case OPC_CMPU_EQ_OB_DSP:
14032 switch (op2) {
14033 case OPC_CMP_EQ_PW:
14034 check_dsp(ctx);
14035 gen_helper_cmp_eq_pw(v1_t, v2_t, cpu_env);
14036 break;
14037 case OPC_CMP_LT_PW:
14038 check_dsp(ctx);
14039 gen_helper_cmp_lt_pw(v1_t, v2_t, cpu_env);
14040 break;
14041 case OPC_CMP_LE_PW:
14042 check_dsp(ctx);
14043 gen_helper_cmp_le_pw(v1_t, v2_t, cpu_env);
14044 break;
14045 case OPC_CMP_EQ_QH:
14046 check_dsp(ctx);
14047 gen_helper_cmp_eq_qh(v1_t, v2_t, cpu_env);
14048 break;
14049 case OPC_CMP_LT_QH:
14050 check_dsp(ctx);
14051 gen_helper_cmp_lt_qh(v1_t, v2_t, cpu_env);
14052 break;
14053 case OPC_CMP_LE_QH:
14054 check_dsp(ctx);
14055 gen_helper_cmp_le_qh(v1_t, v2_t, cpu_env);
14056 break;
14057 case OPC_CMPGDU_EQ_OB:
14058 check_dspr2(ctx);
14059 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14060 break;
14061 case OPC_CMPGDU_LT_OB:
14062 check_dspr2(ctx);
14063 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14064 break;
14065 case OPC_CMPGDU_LE_OB:
14066 check_dspr2(ctx);
14067 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14068 break;
14069 case OPC_CMPGU_EQ_OB:
14070 check_dsp(ctx);
14071 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
14072 break;
14073 case OPC_CMPGU_LT_OB:
14074 check_dsp(ctx);
14075 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
14076 break;
14077 case OPC_CMPGU_LE_OB:
14078 check_dsp(ctx);
14079 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
14080 break;
14081 case OPC_CMPU_EQ_OB:
14082 check_dsp(ctx);
14083 gen_helper_cmpu_eq_ob(v1_t, v2_t, cpu_env);
14084 break;
14085 case OPC_CMPU_LT_OB:
14086 check_dsp(ctx);
14087 gen_helper_cmpu_lt_ob(v1_t, v2_t, cpu_env);
14088 break;
14089 case OPC_CMPU_LE_OB:
14090 check_dsp(ctx);
14091 gen_helper_cmpu_le_ob(v1_t, v2_t, cpu_env);
14092 break;
14093 case OPC_PACKRL_PW:
14094 check_dsp(ctx);
14095 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
14096 break;
14097 case OPC_PICK_OB:
14098 check_dsp(ctx);
14099 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14100 break;
14101 case OPC_PICK_PW:
14102 check_dsp(ctx);
14103 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14104 break;
14105 case OPC_PICK_QH:
14106 check_dsp(ctx);
14107 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, cpu_env);
14108 break;
14110 break;
14111 #endif
14114 tcg_temp_free(t1);
14115 tcg_temp_free(v1_t);
14116 tcg_temp_free(v2_t);
14118 (void)opn; /* avoid a compiler warning */
14119 MIPS_DEBUG("%s", opn);
14122 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
14123 uint32_t op1, int rt, int rs, int sa)
14125 const char *opn = "mipsdsp append/dappend";
14126 TCGv t0;
14128 check_dspr2(ctx);
14130 if (rt == 0) {
14131 /* Treat as NOP. */
14132 MIPS_DEBUG("NOP");
14133 return;
14136 t0 = tcg_temp_new();
14137 gen_load_gpr(t0, rs);
14139 switch (op1) {
14140 case OPC_APPEND_DSP:
14141 switch (MASK_APPEND(ctx->opcode)) {
14142 case OPC_APPEND:
14143 if (sa != 0) {
14144 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
14146 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14147 break;
14148 case OPC_PREPEND:
14149 if (sa != 0) {
14150 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
14151 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14152 tcg_gen_shli_tl(t0, t0, 32 - sa);
14153 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14155 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14156 break;
14157 case OPC_BALIGN:
14158 sa &= 3;
14159 if (sa != 0 && sa != 2) {
14160 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14161 tcg_gen_ext32u_tl(t0, t0);
14162 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
14163 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14165 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
14166 break;
14167 default: /* Invalid */
14168 MIPS_INVAL("MASK APPEND");
14169 generate_exception(ctx, EXCP_RI);
14170 break;
14172 break;
14173 #ifdef TARGET_MIPS64
14174 case OPC_DAPPEND_DSP:
14175 switch (MASK_DAPPEND(ctx->opcode)) {
14176 case OPC_DAPPEND:
14177 if (sa != 0) {
14178 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
14180 break;
14181 case OPC_PREPENDD:
14182 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
14183 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
14184 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
14185 break;
14186 case OPC_PREPENDW:
14187 if (sa != 0) {
14188 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
14189 tcg_gen_shli_tl(t0, t0, 64 - sa);
14190 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14192 break;
14193 case OPC_DBALIGN:
14194 sa &= 7;
14195 if (sa != 0 && sa != 2 && sa != 4) {
14196 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
14197 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
14198 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
14200 break;
14201 default: /* Invalid */
14202 MIPS_INVAL("MASK DAPPEND");
14203 generate_exception(ctx, EXCP_RI);
14204 break;
14206 break;
14207 #endif
14209 tcg_temp_free(t0);
14210 (void)opn; /* avoid a compiler warning */
14211 MIPS_DEBUG("%s", opn);
14214 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
14215 int ret, int v1, int v2, int check_ret)
14218 const char *opn = "mipsdsp accumulator";
14219 TCGv t0;
14220 TCGv t1;
14221 TCGv v1_t;
14222 TCGv v2_t;
14223 int16_t imm;
14225 if ((ret == 0) && (check_ret == 1)) {
14226 /* Treat as NOP. */
14227 MIPS_DEBUG("NOP");
14228 return;
14231 t0 = tcg_temp_new();
14232 t1 = tcg_temp_new();
14233 v1_t = tcg_temp_new();
14234 v2_t = tcg_temp_new();
14236 gen_load_gpr(v1_t, v1);
14237 gen_load_gpr(v2_t, v2);
14239 switch (op1) {
14240 case OPC_EXTR_W_DSP:
14241 check_dsp(ctx);
14242 switch (op2) {
14243 case OPC_EXTR_W:
14244 tcg_gen_movi_tl(t0, v2);
14245 tcg_gen_movi_tl(t1, v1);
14246 gen_helper_extr_w(cpu_gpr[ret], t0, t1, cpu_env);
14247 break;
14248 case OPC_EXTR_R_W:
14249 tcg_gen_movi_tl(t0, v2);
14250 tcg_gen_movi_tl(t1, v1);
14251 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14252 break;
14253 case OPC_EXTR_RS_W:
14254 tcg_gen_movi_tl(t0, v2);
14255 tcg_gen_movi_tl(t1, v1);
14256 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14257 break;
14258 case OPC_EXTR_S_H:
14259 tcg_gen_movi_tl(t0, v2);
14260 tcg_gen_movi_tl(t1, v1);
14261 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14262 break;
14263 case OPC_EXTRV_S_H:
14264 tcg_gen_movi_tl(t0, v2);
14265 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, cpu_env);
14266 break;
14267 case OPC_EXTRV_W:
14268 tcg_gen_movi_tl(t0, v2);
14269 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14270 break;
14271 case OPC_EXTRV_R_W:
14272 tcg_gen_movi_tl(t0, v2);
14273 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14274 break;
14275 case OPC_EXTRV_RS_W:
14276 tcg_gen_movi_tl(t0, v2);
14277 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14278 break;
14279 case OPC_EXTP:
14280 tcg_gen_movi_tl(t0, v2);
14281 tcg_gen_movi_tl(t1, v1);
14282 gen_helper_extp(cpu_gpr[ret], t0, t1, cpu_env);
14283 break;
14284 case OPC_EXTPV:
14285 tcg_gen_movi_tl(t0, v2);
14286 gen_helper_extp(cpu_gpr[ret], t0, v1_t, cpu_env);
14287 break;
14288 case OPC_EXTPDP:
14289 tcg_gen_movi_tl(t0, v2);
14290 tcg_gen_movi_tl(t1, v1);
14291 gen_helper_extpdp(cpu_gpr[ret], t0, t1, cpu_env);
14292 break;
14293 case OPC_EXTPDPV:
14294 tcg_gen_movi_tl(t0, v2);
14295 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14296 break;
14297 case OPC_SHILO:
14298 imm = (ctx->opcode >> 20) & 0x3F;
14299 tcg_gen_movi_tl(t0, ret);
14300 tcg_gen_movi_tl(t1, imm);
14301 gen_helper_shilo(t0, t1, cpu_env);
14302 break;
14303 case OPC_SHILOV:
14304 tcg_gen_movi_tl(t0, ret);
14305 gen_helper_shilo(t0, v1_t, cpu_env);
14306 break;
14307 case OPC_MTHLIP:
14308 tcg_gen_movi_tl(t0, ret);
14309 gen_helper_mthlip(t0, v1_t, cpu_env);
14310 break;
14311 case OPC_WRDSP:
14312 imm = (ctx->opcode >> 11) & 0x3FF;
14313 tcg_gen_movi_tl(t0, imm);
14314 gen_helper_wrdsp(v1_t, t0, cpu_env);
14315 break;
14316 case OPC_RDDSP:
14317 imm = (ctx->opcode >> 16) & 0x03FF;
14318 tcg_gen_movi_tl(t0, imm);
14319 gen_helper_rddsp(cpu_gpr[ret], t0, cpu_env);
14320 break;
14322 break;
14323 #ifdef TARGET_MIPS64
14324 case OPC_DEXTR_W_DSP:
14325 check_dsp(ctx);
14326 switch (op2) {
14327 case OPC_DMTHLIP:
14328 tcg_gen_movi_tl(t0, ret);
14329 gen_helper_dmthlip(v1_t, t0, cpu_env);
14330 break;
14331 case OPC_DSHILO:
14333 int shift = (ctx->opcode >> 19) & 0x7F;
14334 int ac = (ctx->opcode >> 11) & 0x03;
14335 tcg_gen_movi_tl(t0, shift);
14336 tcg_gen_movi_tl(t1, ac);
14337 gen_helper_dshilo(t0, t1, cpu_env);
14338 break;
14340 case OPC_DSHILOV:
14342 int ac = (ctx->opcode >> 11) & 0x03;
14343 tcg_gen_movi_tl(t0, ac);
14344 gen_helper_dshilo(v1_t, t0, cpu_env);
14345 break;
14347 case OPC_DEXTP:
14348 tcg_gen_movi_tl(t0, v2);
14349 tcg_gen_movi_tl(t1, v1);
14351 gen_helper_dextp(cpu_gpr[ret], t0, t1, cpu_env);
14352 break;
14353 case OPC_DEXTPV:
14354 tcg_gen_movi_tl(t0, v2);
14355 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, cpu_env);
14356 break;
14357 case OPC_DEXTPDP:
14358 tcg_gen_movi_tl(t0, v2);
14359 tcg_gen_movi_tl(t1, v1);
14360 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, cpu_env);
14361 break;
14362 case OPC_DEXTPDPV:
14363 tcg_gen_movi_tl(t0, v2);
14364 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, cpu_env);
14365 break;
14366 case OPC_DEXTR_L:
14367 tcg_gen_movi_tl(t0, v2);
14368 tcg_gen_movi_tl(t1, v1);
14369 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, cpu_env);
14370 break;
14371 case OPC_DEXTR_R_L:
14372 tcg_gen_movi_tl(t0, v2);
14373 tcg_gen_movi_tl(t1, v1);
14374 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, cpu_env);
14375 break;
14376 case OPC_DEXTR_RS_L:
14377 tcg_gen_movi_tl(t0, v2);
14378 tcg_gen_movi_tl(t1, v1);
14379 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, cpu_env);
14380 break;
14381 case OPC_DEXTR_W:
14382 tcg_gen_movi_tl(t0, v2);
14383 tcg_gen_movi_tl(t1, v1);
14384 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, cpu_env);
14385 break;
14386 case OPC_DEXTR_R_W:
14387 tcg_gen_movi_tl(t0, v2);
14388 tcg_gen_movi_tl(t1, v1);
14389 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, cpu_env);
14390 break;
14391 case OPC_DEXTR_RS_W:
14392 tcg_gen_movi_tl(t0, v2);
14393 tcg_gen_movi_tl(t1, v1);
14394 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, cpu_env);
14395 break;
14396 case OPC_DEXTR_S_H:
14397 tcg_gen_movi_tl(t0, v2);
14398 tcg_gen_movi_tl(t1, v1);
14399 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14400 break;
14401 case OPC_DEXTRV_S_H:
14402 tcg_gen_movi_tl(t0, v2);
14403 tcg_gen_movi_tl(t1, v1);
14404 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, cpu_env);
14405 break;
14406 case OPC_DEXTRV_L:
14407 tcg_gen_movi_tl(t0, v2);
14408 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14409 break;
14410 case OPC_DEXTRV_R_L:
14411 tcg_gen_movi_tl(t0, v2);
14412 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14413 break;
14414 case OPC_DEXTRV_RS_L:
14415 tcg_gen_movi_tl(t0, v2);
14416 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, cpu_env);
14417 break;
14418 case OPC_DEXTRV_W:
14419 tcg_gen_movi_tl(t0, v2);
14420 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14421 break;
14422 case OPC_DEXTRV_R_W:
14423 tcg_gen_movi_tl(t0, v2);
14424 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14425 break;
14426 case OPC_DEXTRV_RS_W:
14427 tcg_gen_movi_tl(t0, v2);
14428 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, cpu_env);
14429 break;
14431 break;
14432 #endif
14435 tcg_temp_free(t0);
14436 tcg_temp_free(t1);
14437 tcg_temp_free(v1_t);
14438 tcg_temp_free(v2_t);
14440 (void)opn; /* avoid a compiler warning */
14441 MIPS_DEBUG("%s", opn);
14444 /* End MIPSDSP functions. */
14446 static void decode_opc (CPUMIPSState *env, DisasContext *ctx)
14448 int32_t offset;
14449 int rs, rt, rd, sa;
14450 uint32_t op, op1, op2;
14451 int16_t imm;
14453 /* make sure instructions are on a word boundary */
14454 if (ctx->pc & 0x3) {
14455 env->CP0_BadVAddr = ctx->pc;
14456 generate_exception(ctx, EXCP_AdEL);
14457 return;
14460 /* Handle blikely not taken case */
14461 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
14462 int l1 = gen_new_label();
14464 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
14465 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
14466 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
14467 gen_goto_tb(ctx, 1, ctx->pc + 4);
14468 gen_set_label(l1);
14471 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
14472 tcg_gen_debug_insn_start(ctx->pc);
14475 op = MASK_OP_MAJOR(ctx->opcode);
14476 rs = (ctx->opcode >> 21) & 0x1f;
14477 rt = (ctx->opcode >> 16) & 0x1f;
14478 rd = (ctx->opcode >> 11) & 0x1f;
14479 sa = (ctx->opcode >> 6) & 0x1f;
14480 imm = (int16_t)ctx->opcode;
14481 switch (op) {
14482 case OPC_SPECIAL:
14483 op1 = MASK_SPECIAL(ctx->opcode);
14484 switch (op1) {
14485 case OPC_SLL: /* Shift with immediate */
14486 case OPC_SRA:
14487 gen_shift_imm(ctx, op1, rd, rt, sa);
14488 break;
14489 case OPC_SRL:
14490 switch ((ctx->opcode >> 21) & 0x1f) {
14491 case 1:
14492 /* rotr is decoded as srl on non-R2 CPUs */
14493 if (ctx->insn_flags & ISA_MIPS32R2) {
14494 op1 = OPC_ROTR;
14496 /* Fallthrough */
14497 case 0:
14498 gen_shift_imm(ctx, op1, rd, rt, sa);
14499 break;
14500 default:
14501 generate_exception(ctx, EXCP_RI);
14502 break;
14504 break;
14505 case OPC_MOVN: /* Conditional move */
14506 case OPC_MOVZ:
14507 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
14508 INSN_LOONGSON2E | INSN_LOONGSON2F);
14509 gen_cond_move(ctx, op1, rd, rs, rt);
14510 break;
14511 case OPC_ADD ... OPC_SUBU:
14512 gen_arith(ctx, op1, rd, rs, rt);
14513 break;
14514 case OPC_SLLV: /* Shifts */
14515 case OPC_SRAV:
14516 gen_shift(ctx, op1, rd, rs, rt);
14517 break;
14518 case OPC_SRLV:
14519 switch ((ctx->opcode >> 6) & 0x1f) {
14520 case 1:
14521 /* rotrv is decoded as srlv on non-R2 CPUs */
14522 if (ctx->insn_flags & ISA_MIPS32R2) {
14523 op1 = OPC_ROTRV;
14525 /* Fallthrough */
14526 case 0:
14527 gen_shift(ctx, op1, rd, rs, rt);
14528 break;
14529 default:
14530 generate_exception(ctx, EXCP_RI);
14531 break;
14533 break;
14534 case OPC_SLT: /* Set on less than */
14535 case OPC_SLTU:
14536 gen_slt(ctx, op1, rd, rs, rt);
14537 break;
14538 case OPC_AND: /* Logic*/
14539 case OPC_OR:
14540 case OPC_NOR:
14541 case OPC_XOR:
14542 gen_logic(ctx, op1, rd, rs, rt);
14543 break;
14544 case OPC_MULT:
14545 case OPC_MULTU:
14546 if (sa) {
14547 check_insn(ctx, INSN_VR54XX);
14548 op1 = MASK_MUL_VR54XX(ctx->opcode);
14549 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
14550 } else {
14551 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14553 break;
14554 case OPC_DIV:
14555 case OPC_DIVU:
14556 gen_muldiv(ctx, op1, 0, rs, rt);
14557 break;
14558 case OPC_JR ... OPC_JALR:
14559 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
14560 break;
14561 case OPC_TGE ... OPC_TEQ: /* Traps */
14562 case OPC_TNE:
14563 gen_trap(ctx, op1, rs, rt, -1);
14564 break;
14565 case OPC_MFHI: /* Move from HI/LO */
14566 case OPC_MFLO:
14567 gen_HILO(ctx, op1, rs & 3, rd);
14568 break;
14569 case OPC_MTHI:
14570 case OPC_MTLO: /* Move to HI/LO */
14571 gen_HILO(ctx, op1, rd & 3, rs);
14572 break;
14573 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
14574 #ifdef MIPS_STRICT_STANDARD
14575 MIPS_INVAL("PMON / selsl");
14576 generate_exception(ctx, EXCP_RI);
14577 #else
14578 gen_helper_0e0i(pmon, sa);
14579 #endif
14580 break;
14581 case OPC_SYSCALL:
14582 generate_exception(ctx, EXCP_SYSCALL);
14583 ctx->bstate = BS_STOP;
14584 break;
14585 case OPC_BREAK:
14586 generate_exception(ctx, EXCP_BREAK);
14587 break;
14588 case OPC_SPIM:
14589 #ifdef MIPS_STRICT_STANDARD
14590 MIPS_INVAL("SPIM");
14591 generate_exception(ctx, EXCP_RI);
14592 #else
14593 /* Implemented as RI exception for now. */
14594 MIPS_INVAL("spim (unofficial)");
14595 generate_exception(ctx, EXCP_RI);
14596 #endif
14597 break;
14598 case OPC_SYNC:
14599 /* Treat as NOP. */
14600 break;
14602 case OPC_MOVCI:
14603 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
14604 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14605 check_cp1_enabled(ctx);
14606 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
14607 (ctx->opcode >> 16) & 1);
14608 } else {
14609 generate_exception_err(ctx, EXCP_CpU, 1);
14611 break;
14613 #if defined(TARGET_MIPS64)
14614 /* MIPS64 specific opcodes */
14615 case OPC_DSLL:
14616 case OPC_DSRA:
14617 case OPC_DSLL32:
14618 case OPC_DSRA32:
14619 check_insn(ctx, ISA_MIPS3);
14620 check_mips_64(ctx);
14621 gen_shift_imm(ctx, op1, rd, rt, sa);
14622 break;
14623 case OPC_DSRL:
14624 switch ((ctx->opcode >> 21) & 0x1f) {
14625 case 1:
14626 /* drotr is decoded as dsrl on non-R2 CPUs */
14627 if (ctx->insn_flags & ISA_MIPS32R2) {
14628 op1 = OPC_DROTR;
14630 /* Fallthrough */
14631 case 0:
14632 check_insn(ctx, ISA_MIPS3);
14633 check_mips_64(ctx);
14634 gen_shift_imm(ctx, op1, rd, rt, sa);
14635 break;
14636 default:
14637 generate_exception(ctx, EXCP_RI);
14638 break;
14640 break;
14641 case OPC_DSRL32:
14642 switch ((ctx->opcode >> 21) & 0x1f) {
14643 case 1:
14644 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
14645 if (ctx->insn_flags & ISA_MIPS32R2) {
14646 op1 = OPC_DROTR32;
14648 /* Fallthrough */
14649 case 0:
14650 check_insn(ctx, ISA_MIPS3);
14651 check_mips_64(ctx);
14652 gen_shift_imm(ctx, op1, rd, rt, sa);
14653 break;
14654 default:
14655 generate_exception(ctx, EXCP_RI);
14656 break;
14658 break;
14659 case OPC_DADD ... OPC_DSUBU:
14660 check_insn(ctx, ISA_MIPS3);
14661 check_mips_64(ctx);
14662 gen_arith(ctx, op1, rd, rs, rt);
14663 break;
14664 case OPC_DSLLV:
14665 case OPC_DSRAV:
14666 check_insn(ctx, ISA_MIPS3);
14667 check_mips_64(ctx);
14668 gen_shift(ctx, op1, rd, rs, rt);
14669 break;
14670 case OPC_DSRLV:
14671 switch ((ctx->opcode >> 6) & 0x1f) {
14672 case 1:
14673 /* drotrv is decoded as dsrlv on non-R2 CPUs */
14674 if (ctx->insn_flags & ISA_MIPS32R2) {
14675 op1 = OPC_DROTRV;
14677 /* Fallthrough */
14678 case 0:
14679 check_insn(ctx, ISA_MIPS3);
14680 check_mips_64(ctx);
14681 gen_shift(ctx, op1, rd, rs, rt);
14682 break;
14683 default:
14684 generate_exception(ctx, EXCP_RI);
14685 break;
14687 break;
14688 case OPC_DMULT ... OPC_DDIVU:
14689 check_insn(ctx, ISA_MIPS3);
14690 check_mips_64(ctx);
14691 gen_muldiv(ctx, op1, 0, rs, rt);
14692 break;
14693 #endif
14694 default: /* Invalid */
14695 MIPS_INVAL("special");
14696 generate_exception(ctx, EXCP_RI);
14697 break;
14699 break;
14700 case OPC_SPECIAL2:
14701 op1 = MASK_SPECIAL2(ctx->opcode);
14702 switch (op1) {
14703 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
14704 case OPC_MSUB ... OPC_MSUBU:
14705 check_insn(ctx, ISA_MIPS32);
14706 gen_muldiv(ctx, op1, rd & 3, rs, rt);
14707 break;
14708 case OPC_MUL:
14709 gen_arith(ctx, op1, rd, rs, rt);
14710 break;
14711 case OPC_CLO:
14712 case OPC_CLZ:
14713 check_insn(ctx, ISA_MIPS32);
14714 gen_cl(ctx, op1, rd, rs);
14715 break;
14716 case OPC_SDBBP:
14717 /* XXX: not clear which exception should be raised
14718 * when in debug mode...
14720 check_insn(ctx, ISA_MIPS32);
14721 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
14722 generate_exception(ctx, EXCP_DBp);
14723 } else {
14724 generate_exception(ctx, EXCP_DBp);
14726 /* Treat as NOP. */
14727 break;
14728 case OPC_DIV_G_2F:
14729 case OPC_DIVU_G_2F:
14730 case OPC_MULT_G_2F:
14731 case OPC_MULTU_G_2F:
14732 case OPC_MOD_G_2F:
14733 case OPC_MODU_G_2F:
14734 check_insn(ctx, INSN_LOONGSON2F);
14735 gen_loongson_integer(ctx, op1, rd, rs, rt);
14736 break;
14737 #if defined(TARGET_MIPS64)
14738 case OPC_DCLO:
14739 case OPC_DCLZ:
14740 check_insn(ctx, ISA_MIPS64);
14741 check_mips_64(ctx);
14742 gen_cl(ctx, op1, rd, rs);
14743 break;
14744 case OPC_DMULT_G_2F:
14745 case OPC_DMULTU_G_2F:
14746 case OPC_DDIV_G_2F:
14747 case OPC_DDIVU_G_2F:
14748 case OPC_DMOD_G_2F:
14749 case OPC_DMODU_G_2F:
14750 check_insn(ctx, INSN_LOONGSON2F);
14751 gen_loongson_integer(ctx, op1, rd, rs, rt);
14752 break;
14753 #endif
14754 default: /* Invalid */
14755 MIPS_INVAL("special2");
14756 generate_exception(ctx, EXCP_RI);
14757 break;
14759 break;
14760 case OPC_SPECIAL3:
14761 op1 = MASK_SPECIAL3(ctx->opcode);
14762 switch (op1) {
14763 case OPC_EXT:
14764 case OPC_INS:
14765 check_insn(ctx, ISA_MIPS32R2);
14766 gen_bitops(ctx, op1, rt, rs, sa, rd);
14767 break;
14768 case OPC_BSHFL:
14769 check_insn(ctx, ISA_MIPS32R2);
14770 op2 = MASK_BSHFL(ctx->opcode);
14771 gen_bshfl(ctx, op2, rt, rd);
14772 break;
14773 case OPC_RDHWR:
14774 gen_rdhwr(ctx, rt, rd);
14775 break;
14776 case OPC_FORK:
14777 check_insn(ctx, ASE_MT);
14779 TCGv t0 = tcg_temp_new();
14780 TCGv t1 = tcg_temp_new();
14782 gen_load_gpr(t0, rt);
14783 gen_load_gpr(t1, rs);
14784 gen_helper_fork(t0, t1);
14785 tcg_temp_free(t0);
14786 tcg_temp_free(t1);
14788 break;
14789 case OPC_YIELD:
14790 check_insn(ctx, ASE_MT);
14792 TCGv t0 = tcg_temp_new();
14794 save_cpu_state(ctx, 1);
14795 gen_load_gpr(t0, rs);
14796 gen_helper_yield(t0, cpu_env, t0);
14797 gen_store_gpr(t0, rd);
14798 tcg_temp_free(t0);
14800 break;
14801 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
14802 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
14803 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
14804 /* OPC_MULT_G_2E, OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
14805 * the same mask and op1. */
14806 if ((ctx->insn_flags & ASE_DSPR2) && (op1 == OPC_MULT_G_2E)) {
14807 op2 = MASK_ADDUH_QB(ctx->opcode);
14808 switch (op2) {
14809 case OPC_ADDUH_QB:
14810 case OPC_ADDUH_R_QB:
14811 case OPC_ADDQH_PH:
14812 case OPC_ADDQH_R_PH:
14813 case OPC_ADDQH_W:
14814 case OPC_ADDQH_R_W:
14815 case OPC_SUBUH_QB:
14816 case OPC_SUBUH_R_QB:
14817 case OPC_SUBQH_PH:
14818 case OPC_SUBQH_R_PH:
14819 case OPC_SUBQH_W:
14820 case OPC_SUBQH_R_W:
14821 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14822 break;
14823 case OPC_MUL_PH:
14824 case OPC_MUL_S_PH:
14825 case OPC_MULQ_S_W:
14826 case OPC_MULQ_RS_W:
14827 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14828 break;
14829 default:
14830 MIPS_INVAL("MASK ADDUH.QB");
14831 generate_exception(ctx, EXCP_RI);
14832 break;
14834 } else if (ctx->insn_flags & INSN_LOONGSON2E) {
14835 gen_loongson_integer(ctx, op1, rd, rs, rt);
14836 } else {
14837 generate_exception(ctx, EXCP_RI);
14839 break;
14840 case OPC_LX_DSP:
14841 op2 = MASK_LX(ctx->opcode);
14842 switch (op2) {
14843 #if defined(TARGET_MIPS64)
14844 case OPC_LDX:
14845 #endif
14846 case OPC_LBUX:
14847 case OPC_LHX:
14848 case OPC_LWX:
14849 gen_mipsdsp_ld(ctx, op2, rd, rs, rt);
14850 break;
14851 default: /* Invalid */
14852 MIPS_INVAL("MASK LX");
14853 generate_exception(ctx, EXCP_RI);
14854 break;
14856 break;
14857 case OPC_ABSQ_S_PH_DSP:
14858 op2 = MASK_ABSQ_S_PH(ctx->opcode);
14859 switch (op2) {
14860 case OPC_ABSQ_S_QB:
14861 case OPC_ABSQ_S_PH:
14862 case OPC_ABSQ_S_W:
14863 case OPC_PRECEQ_W_PHL:
14864 case OPC_PRECEQ_W_PHR:
14865 case OPC_PRECEQU_PH_QBL:
14866 case OPC_PRECEQU_PH_QBR:
14867 case OPC_PRECEQU_PH_QBLA:
14868 case OPC_PRECEQU_PH_QBRA:
14869 case OPC_PRECEU_PH_QBL:
14870 case OPC_PRECEU_PH_QBR:
14871 case OPC_PRECEU_PH_QBLA:
14872 case OPC_PRECEU_PH_QBRA:
14873 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14874 break;
14875 case OPC_BITREV:
14876 case OPC_REPL_QB:
14877 case OPC_REPLV_QB:
14878 case OPC_REPL_PH:
14879 case OPC_REPLV_PH:
14880 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
14881 break;
14882 default:
14883 MIPS_INVAL("MASK ABSQ_S.PH");
14884 generate_exception(ctx, EXCP_RI);
14885 break;
14887 break;
14888 case OPC_ADDU_QB_DSP:
14889 op2 = MASK_ADDU_QB(ctx->opcode);
14890 switch (op2) {
14891 case OPC_ADDQ_PH:
14892 case OPC_ADDQ_S_PH:
14893 case OPC_ADDQ_S_W:
14894 case OPC_ADDU_QB:
14895 case OPC_ADDU_S_QB:
14896 case OPC_ADDU_PH:
14897 case OPC_ADDU_S_PH:
14898 case OPC_SUBQ_PH:
14899 case OPC_SUBQ_S_PH:
14900 case OPC_SUBQ_S_W:
14901 case OPC_SUBU_QB:
14902 case OPC_SUBU_S_QB:
14903 case OPC_SUBU_PH:
14904 case OPC_SUBU_S_PH:
14905 case OPC_ADDSC:
14906 case OPC_ADDWC:
14907 case OPC_MODSUB:
14908 case OPC_RADDU_W_QB:
14909 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14910 break;
14911 case OPC_MULEU_S_PH_QBL:
14912 case OPC_MULEU_S_PH_QBR:
14913 case OPC_MULQ_RS_PH:
14914 case OPC_MULEQ_S_W_PHL:
14915 case OPC_MULEQ_S_W_PHR:
14916 case OPC_MULQ_S_PH:
14917 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
14918 break;
14919 default: /* Invalid */
14920 MIPS_INVAL("MASK ADDU.QB");
14921 generate_exception(ctx, EXCP_RI);
14922 break;
14925 break;
14926 case OPC_CMPU_EQ_QB_DSP:
14927 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
14928 switch (op2) {
14929 case OPC_PRECR_SRA_PH_W:
14930 case OPC_PRECR_SRA_R_PH_W:
14931 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
14932 break;
14933 case OPC_PRECR_QB_PH:
14934 case OPC_PRECRQ_QB_PH:
14935 case OPC_PRECRQ_PH_W:
14936 case OPC_PRECRQ_RS_PH_W:
14937 case OPC_PRECRQU_S_QB_PH:
14938 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
14939 break;
14940 case OPC_CMPU_EQ_QB:
14941 case OPC_CMPU_LT_QB:
14942 case OPC_CMPU_LE_QB:
14943 case OPC_CMP_EQ_PH:
14944 case OPC_CMP_LT_PH:
14945 case OPC_CMP_LE_PH:
14946 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
14947 break;
14948 case OPC_CMPGU_EQ_QB:
14949 case OPC_CMPGU_LT_QB:
14950 case OPC_CMPGU_LE_QB:
14951 case OPC_CMPGDU_EQ_QB:
14952 case OPC_CMPGDU_LT_QB:
14953 case OPC_CMPGDU_LE_QB:
14954 case OPC_PICK_QB:
14955 case OPC_PICK_PH:
14956 case OPC_PACKRL_PH:
14957 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
14958 break;
14959 default: /* Invalid */
14960 MIPS_INVAL("MASK CMPU.EQ.QB");
14961 generate_exception(ctx, EXCP_RI);
14962 break;
14964 break;
14965 case OPC_SHLL_QB_DSP:
14966 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14967 break;
14968 case OPC_DPA_W_PH_DSP:
14969 op2 = MASK_DPA_W_PH(ctx->opcode);
14970 switch (op2) {
14971 case OPC_DPAU_H_QBL:
14972 case OPC_DPAU_H_QBR:
14973 case OPC_DPSU_H_QBL:
14974 case OPC_DPSU_H_QBR:
14975 case OPC_DPA_W_PH:
14976 case OPC_DPAX_W_PH:
14977 case OPC_DPAQ_S_W_PH:
14978 case OPC_DPAQX_S_W_PH:
14979 case OPC_DPAQX_SA_W_PH:
14980 case OPC_DPS_W_PH:
14981 case OPC_DPSX_W_PH:
14982 case OPC_DPSQ_S_W_PH:
14983 case OPC_DPSQX_S_W_PH:
14984 case OPC_DPSQX_SA_W_PH:
14985 case OPC_MULSAQ_S_W_PH:
14986 case OPC_DPAQ_SA_L_W:
14987 case OPC_DPSQ_SA_L_W:
14988 case OPC_MAQ_S_W_PHL:
14989 case OPC_MAQ_S_W_PHR:
14990 case OPC_MAQ_SA_W_PHL:
14991 case OPC_MAQ_SA_W_PHR:
14992 case OPC_MULSA_W_PH:
14993 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14994 break;
14995 default: /* Invalid */
14996 MIPS_INVAL("MASK DPAW.PH");
14997 generate_exception(ctx, EXCP_RI);
14998 break;
15000 break;
15001 case OPC_INSV_DSP:
15002 op2 = MASK_INSV(ctx->opcode);
15003 switch (op2) {
15004 case OPC_INSV:
15005 check_dsp(ctx);
15007 TCGv t0, t1;
15009 if (rt == 0) {
15010 MIPS_DEBUG("NOP");
15011 break;
15014 t0 = tcg_temp_new();
15015 t1 = tcg_temp_new();
15017 gen_load_gpr(t0, rt);
15018 gen_load_gpr(t1, rs);
15020 gen_helper_insv(cpu_gpr[rt], cpu_env, t1, t0);
15022 tcg_temp_free(t0);
15023 tcg_temp_free(t1);
15024 break;
15026 default: /* Invalid */
15027 MIPS_INVAL("MASK INSV");
15028 generate_exception(ctx, EXCP_RI);
15029 break;
15031 break;
15032 case OPC_APPEND_DSP:
15033 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
15034 break;
15035 case OPC_EXTR_W_DSP:
15036 op2 = MASK_EXTR_W(ctx->opcode);
15037 switch (op2) {
15038 case OPC_EXTR_W:
15039 case OPC_EXTR_R_W:
15040 case OPC_EXTR_RS_W:
15041 case OPC_EXTR_S_H:
15042 case OPC_EXTRV_S_H:
15043 case OPC_EXTRV_W:
15044 case OPC_EXTRV_R_W:
15045 case OPC_EXTRV_RS_W:
15046 case OPC_EXTP:
15047 case OPC_EXTPV:
15048 case OPC_EXTPDP:
15049 case OPC_EXTPDPV:
15050 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
15051 break;
15052 case OPC_RDDSP:
15053 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
15054 break;
15055 case OPC_SHILO:
15056 case OPC_SHILOV:
15057 case OPC_MTHLIP:
15058 case OPC_WRDSP:
15059 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
15060 break;
15061 default: /* Invalid */
15062 MIPS_INVAL("MASK EXTR.W");
15063 generate_exception(ctx, EXCP_RI);
15064 break;
15066 break;
15067 #if defined(TARGET_MIPS64)
15068 case OPC_DEXTM ... OPC_DEXT:
15069 case OPC_DINSM ... OPC_DINS:
15070 check_insn(ctx, ISA_MIPS64R2);
15071 check_mips_64(ctx);
15072 gen_bitops(ctx, op1, rt, rs, sa, rd);
15073 break;
15074 case OPC_DBSHFL:
15075 check_insn(ctx, ISA_MIPS64R2);
15076 check_mips_64(ctx);
15077 op2 = MASK_DBSHFL(ctx->opcode);
15078 gen_bshfl(ctx, op2, rt, rd);
15079 break;
15080 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
15081 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
15082 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
15083 check_insn(ctx, INSN_LOONGSON2E);
15084 gen_loongson_integer(ctx, op1, rd, rs, rt);
15085 break;
15086 case OPC_ABSQ_S_QH_DSP:
15087 op2 = MASK_ABSQ_S_QH(ctx->opcode);
15088 switch (op2) {
15089 case OPC_PRECEQ_L_PWL:
15090 case OPC_PRECEQ_L_PWR:
15091 case OPC_PRECEQ_PW_QHL:
15092 case OPC_PRECEQ_PW_QHR:
15093 case OPC_PRECEQ_PW_QHLA:
15094 case OPC_PRECEQ_PW_QHRA:
15095 case OPC_PRECEQU_QH_OBL:
15096 case OPC_PRECEQU_QH_OBR:
15097 case OPC_PRECEQU_QH_OBLA:
15098 case OPC_PRECEQU_QH_OBRA:
15099 case OPC_PRECEU_QH_OBL:
15100 case OPC_PRECEU_QH_OBR:
15101 case OPC_PRECEU_QH_OBLA:
15102 case OPC_PRECEU_QH_OBRA:
15103 case OPC_ABSQ_S_OB:
15104 case OPC_ABSQ_S_PW:
15105 case OPC_ABSQ_S_QH:
15106 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15107 break;
15108 case OPC_REPL_OB:
15109 case OPC_REPL_PW:
15110 case OPC_REPL_QH:
15111 case OPC_REPLV_OB:
15112 case OPC_REPLV_PW:
15113 case OPC_REPLV_QH:
15114 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
15115 break;
15116 default: /* Invalid */
15117 MIPS_INVAL("MASK ABSQ_S.QH");
15118 generate_exception(ctx, EXCP_RI);
15119 break;
15121 break;
15122 case OPC_ADDU_OB_DSP:
15123 op2 = MASK_ADDU_OB(ctx->opcode);
15124 switch (op2) {
15125 case OPC_RADDU_L_OB:
15126 case OPC_SUBQ_PW:
15127 case OPC_SUBQ_S_PW:
15128 case OPC_SUBQ_QH:
15129 case OPC_SUBQ_S_QH:
15130 case OPC_SUBU_OB:
15131 case OPC_SUBU_S_OB:
15132 case OPC_SUBU_QH:
15133 case OPC_SUBU_S_QH:
15134 case OPC_SUBUH_OB:
15135 case OPC_SUBUH_R_OB:
15136 case OPC_ADDQ_PW:
15137 case OPC_ADDQ_S_PW:
15138 case OPC_ADDQ_QH:
15139 case OPC_ADDQ_S_QH:
15140 case OPC_ADDU_OB:
15141 case OPC_ADDU_S_OB:
15142 case OPC_ADDU_QH:
15143 case OPC_ADDU_S_QH:
15144 case OPC_ADDUH_OB:
15145 case OPC_ADDUH_R_OB:
15146 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15147 break;
15148 case OPC_MULEQ_S_PW_QHL:
15149 case OPC_MULEQ_S_PW_QHR:
15150 case OPC_MULEU_S_QH_OBL:
15151 case OPC_MULEU_S_QH_OBR:
15152 case OPC_MULQ_RS_QH:
15153 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
15154 break;
15155 default: /* Invalid */
15156 MIPS_INVAL("MASK ADDU.OB");
15157 generate_exception(ctx, EXCP_RI);
15158 break;
15160 break;
15161 case OPC_CMPU_EQ_OB_DSP:
15162 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
15163 switch (op2) {
15164 case OPC_PRECR_SRA_QH_PW:
15165 case OPC_PRECR_SRA_R_QH_PW:
15166 /* Return value is rt. */
15167 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
15168 break;
15169 case OPC_PRECR_OB_QH:
15170 case OPC_PRECRQ_OB_QH:
15171 case OPC_PRECRQ_PW_L:
15172 case OPC_PRECRQ_QH_PW:
15173 case OPC_PRECRQ_RS_QH_PW:
15174 case OPC_PRECRQU_S_OB_QH:
15175 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
15176 break;
15177 case OPC_CMPU_EQ_OB:
15178 case OPC_CMPU_LT_OB:
15179 case OPC_CMPU_LE_OB:
15180 case OPC_CMP_EQ_QH:
15181 case OPC_CMP_LT_QH:
15182 case OPC_CMP_LE_QH:
15183 case OPC_CMP_EQ_PW:
15184 case OPC_CMP_LT_PW:
15185 case OPC_CMP_LE_PW:
15186 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
15187 break;
15188 case OPC_CMPGDU_EQ_OB:
15189 case OPC_CMPGDU_LT_OB:
15190 case OPC_CMPGDU_LE_OB:
15191 case OPC_CMPGU_EQ_OB:
15192 case OPC_CMPGU_LT_OB:
15193 case OPC_CMPGU_LE_OB:
15194 case OPC_PACKRL_PW:
15195 case OPC_PICK_OB:
15196 case OPC_PICK_PW:
15197 case OPC_PICK_QH:
15198 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
15199 break;
15200 default: /* Invalid */
15201 MIPS_INVAL("MASK CMPU_EQ.OB");
15202 generate_exception(ctx, EXCP_RI);
15203 break;
15205 break;
15206 case OPC_DAPPEND_DSP:
15207 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
15208 break;
15209 case OPC_DEXTR_W_DSP:
15210 op2 = MASK_DEXTR_W(ctx->opcode);
15211 switch (op2) {
15212 case OPC_DEXTP:
15213 case OPC_DEXTPDP:
15214 case OPC_DEXTPDPV:
15215 case OPC_DEXTPV:
15216 case OPC_DEXTR_L:
15217 case OPC_DEXTR_R_L:
15218 case OPC_DEXTR_RS_L:
15219 case OPC_DEXTR_W:
15220 case OPC_DEXTR_R_W:
15221 case OPC_DEXTR_RS_W:
15222 case OPC_DEXTR_S_H:
15223 case OPC_DEXTRV_L:
15224 case OPC_DEXTRV_R_L:
15225 case OPC_DEXTRV_RS_L:
15226 case OPC_DEXTRV_S_H:
15227 case OPC_DEXTRV_W:
15228 case OPC_DEXTRV_R_W:
15229 case OPC_DEXTRV_RS_W:
15230 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
15231 break;
15232 case OPC_DMTHLIP:
15233 case OPC_DSHILO:
15234 case OPC_DSHILOV:
15235 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
15236 break;
15237 default: /* Invalid */
15238 MIPS_INVAL("MASK EXTR.W");
15239 generate_exception(ctx, EXCP_RI);
15240 break;
15242 break;
15243 case OPC_DPAQ_W_QH_DSP:
15244 op2 = MASK_DPAQ_W_QH(ctx->opcode);
15245 switch (op2) {
15246 case OPC_DPAU_H_OBL:
15247 case OPC_DPAU_H_OBR:
15248 case OPC_DPSU_H_OBL:
15249 case OPC_DPSU_H_OBR:
15250 case OPC_DPA_W_QH:
15251 case OPC_DPAQ_S_W_QH:
15252 case OPC_DPS_W_QH:
15253 case OPC_DPSQ_S_W_QH:
15254 case OPC_MULSAQ_S_W_QH:
15255 case OPC_DPAQ_SA_L_PW:
15256 case OPC_DPSQ_SA_L_PW:
15257 case OPC_MULSAQ_S_L_PW:
15258 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15259 break;
15260 case OPC_MAQ_S_W_QHLL:
15261 case OPC_MAQ_S_W_QHLR:
15262 case OPC_MAQ_S_W_QHRL:
15263 case OPC_MAQ_S_W_QHRR:
15264 case OPC_MAQ_SA_W_QHLL:
15265 case OPC_MAQ_SA_W_QHLR:
15266 case OPC_MAQ_SA_W_QHRL:
15267 case OPC_MAQ_SA_W_QHRR:
15268 case OPC_MAQ_S_L_PWL:
15269 case OPC_MAQ_S_L_PWR:
15270 case OPC_DMADD:
15271 case OPC_DMADDU:
15272 case OPC_DMSUB:
15273 case OPC_DMSUBU:
15274 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
15275 break;
15276 default: /* Invalid */
15277 MIPS_INVAL("MASK DPAQ.W.QH");
15278 generate_exception(ctx, EXCP_RI);
15279 break;
15281 break;
15282 case OPC_DINSV_DSP:
15283 op2 = MASK_INSV(ctx->opcode);
15284 switch (op2) {
15285 case OPC_DINSV:
15287 TCGv t0, t1;
15289 if (rt == 0) {
15290 MIPS_DEBUG("NOP");
15291 break;
15293 check_dsp(ctx);
15295 t0 = tcg_temp_new();
15296 t1 = tcg_temp_new();
15298 gen_load_gpr(t0, rt);
15299 gen_load_gpr(t1, rs);
15301 gen_helper_dinsv(cpu_gpr[rt], cpu_env, t1, t0);
15302 break;
15304 default: /* Invalid */
15305 MIPS_INVAL("MASK DINSV");
15306 generate_exception(ctx, EXCP_RI);
15307 break;
15309 break;
15310 case OPC_SHLL_OB_DSP:
15311 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
15312 break;
15313 #endif
15314 default: /* Invalid */
15315 MIPS_INVAL("special3");
15316 generate_exception(ctx, EXCP_RI);
15317 break;
15319 break;
15320 case OPC_REGIMM:
15321 op1 = MASK_REGIMM(ctx->opcode);
15322 switch (op1) {
15323 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
15324 case OPC_BLTZAL ... OPC_BGEZALL:
15325 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
15326 break;
15327 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
15328 case OPC_TNEI:
15329 gen_trap(ctx, op1, rs, -1, imm);
15330 break;
15331 case OPC_SYNCI:
15332 check_insn(ctx, ISA_MIPS32R2);
15333 /* Treat as NOP. */
15334 break;
15335 case OPC_BPOSGE32: /* MIPS DSP branch */
15336 #if defined(TARGET_MIPS64)
15337 case OPC_BPOSGE64:
15338 #endif
15339 check_dsp(ctx);
15340 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2);
15341 break;
15342 default: /* Invalid */
15343 MIPS_INVAL("regimm");
15344 generate_exception(ctx, EXCP_RI);
15345 break;
15347 break;
15348 case OPC_CP0:
15349 check_cp0_enabled(ctx);
15350 op1 = MASK_CP0(ctx->opcode);
15351 switch (op1) {
15352 case OPC_MFC0:
15353 case OPC_MTC0:
15354 case OPC_MFTR:
15355 case OPC_MTTR:
15356 #if defined(TARGET_MIPS64)
15357 case OPC_DMFC0:
15358 case OPC_DMTC0:
15359 #endif
15360 #ifndef CONFIG_USER_ONLY
15361 gen_cp0(env, ctx, op1, rt, rd);
15362 #endif /* !CONFIG_USER_ONLY */
15363 break;
15364 case OPC_C0_FIRST ... OPC_C0_LAST:
15365 #ifndef CONFIG_USER_ONLY
15366 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
15367 #endif /* !CONFIG_USER_ONLY */
15368 break;
15369 case OPC_MFMC0:
15370 #ifndef CONFIG_USER_ONLY
15372 TCGv t0 = tcg_temp_new();
15374 op2 = MASK_MFMC0(ctx->opcode);
15375 switch (op2) {
15376 case OPC_DMT:
15377 check_insn(ctx, ASE_MT);
15378 gen_helper_dmt(t0);
15379 gen_store_gpr(t0, rt);
15380 break;
15381 case OPC_EMT:
15382 check_insn(ctx, ASE_MT);
15383 gen_helper_emt(t0);
15384 gen_store_gpr(t0, rt);
15385 break;
15386 case OPC_DVPE:
15387 check_insn(ctx, ASE_MT);
15388 gen_helper_dvpe(t0, cpu_env);
15389 gen_store_gpr(t0, rt);
15390 break;
15391 case OPC_EVPE:
15392 check_insn(ctx, ASE_MT);
15393 gen_helper_evpe(t0, cpu_env);
15394 gen_store_gpr(t0, rt);
15395 break;
15396 case OPC_DI:
15397 check_insn(ctx, ISA_MIPS32R2);
15398 save_cpu_state(ctx, 1);
15399 gen_helper_di(t0, cpu_env);
15400 gen_store_gpr(t0, rt);
15401 /* Stop translation as we may have switched the execution mode */
15402 ctx->bstate = BS_STOP;
15403 break;
15404 case OPC_EI:
15405 check_insn(ctx, ISA_MIPS32R2);
15406 save_cpu_state(ctx, 1);
15407 gen_helper_ei(t0, cpu_env);
15408 gen_store_gpr(t0, rt);
15409 /* Stop translation as we may have switched the execution mode */
15410 ctx->bstate = BS_STOP;
15411 break;
15412 default: /* Invalid */
15413 MIPS_INVAL("mfmc0");
15414 generate_exception(ctx, EXCP_RI);
15415 break;
15417 tcg_temp_free(t0);
15419 #endif /* !CONFIG_USER_ONLY */
15420 break;
15421 case OPC_RDPGPR:
15422 check_insn(ctx, ISA_MIPS32R2);
15423 gen_load_srsgpr(rt, rd);
15424 break;
15425 case OPC_WRPGPR:
15426 check_insn(ctx, ISA_MIPS32R2);
15427 gen_store_srsgpr(rt, rd);
15428 break;
15429 default:
15430 MIPS_INVAL("cp0");
15431 generate_exception(ctx, EXCP_RI);
15432 break;
15434 break;
15435 case OPC_ADDI: /* Arithmetic with immediate opcode */
15436 case OPC_ADDIU:
15437 gen_arith_imm(ctx, op, rt, rs, imm);
15438 break;
15439 case OPC_SLTI: /* Set on less than with immediate opcode */
15440 case OPC_SLTIU:
15441 gen_slt_imm(ctx, op, rt, rs, imm);
15442 break;
15443 case OPC_ANDI: /* Arithmetic with immediate opcode */
15444 case OPC_LUI:
15445 case OPC_ORI:
15446 case OPC_XORI:
15447 gen_logic_imm(ctx, op, rt, rs, imm);
15448 break;
15449 case OPC_J ... OPC_JAL: /* Jump */
15450 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15451 gen_compute_branch(ctx, op, 4, rs, rt, offset);
15452 break;
15453 case OPC_BEQ ... OPC_BGTZ: /* Branch */
15454 case OPC_BEQL ... OPC_BGTZL:
15455 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
15456 break;
15457 case OPC_LB ... OPC_LWR: /* Load and stores */
15458 case OPC_LL:
15459 gen_ld(ctx, op, rt, rs, imm);
15460 break;
15461 case OPC_SB ... OPC_SW:
15462 case OPC_SWR:
15463 gen_st(ctx, op, rt, rs, imm);
15464 break;
15465 case OPC_SC:
15466 gen_st_cond(ctx, op, rt, rs, imm);
15467 break;
15468 case OPC_CACHE:
15469 check_cp0_enabled(ctx);
15470 check_insn(ctx, ISA_MIPS3 | ISA_MIPS32);
15471 /* Treat as NOP. */
15472 break;
15473 case OPC_PREF:
15474 check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
15475 /* Treat as NOP. */
15476 break;
15478 /* Floating point (COP1). */
15479 case OPC_LWC1:
15480 case OPC_LDC1:
15481 case OPC_SWC1:
15482 case OPC_SDC1:
15483 gen_cop1_ldst(ctx, op, rt, rs, imm);
15484 break;
15486 case OPC_CP1:
15487 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15488 check_cp1_enabled(ctx);
15489 op1 = MASK_CP1(ctx->opcode);
15490 switch (op1) {
15491 case OPC_MFHC1:
15492 case OPC_MTHC1:
15493 check_insn(ctx, ISA_MIPS32R2);
15494 case OPC_MFC1:
15495 case OPC_CFC1:
15496 case OPC_MTC1:
15497 case OPC_CTC1:
15498 gen_cp1(ctx, op1, rt, rd);
15499 break;
15500 #if defined(TARGET_MIPS64)
15501 case OPC_DMFC1:
15502 case OPC_DMTC1:
15503 check_insn(ctx, ISA_MIPS3);
15504 gen_cp1(ctx, op1, rt, rd);
15505 break;
15506 #endif
15507 case OPC_BC1ANY2:
15508 case OPC_BC1ANY4:
15509 check_cop1x(ctx);
15510 check_insn(ctx, ASE_MIPS3D);
15511 /* fall through */
15512 case OPC_BC1:
15513 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
15514 (rt >> 2) & 0x7, imm << 2);
15515 break;
15516 case OPC_S_FMT:
15517 case OPC_D_FMT:
15518 case OPC_W_FMT:
15519 case OPC_L_FMT:
15520 case OPC_PS_FMT:
15521 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
15522 (imm >> 8) & 0x7);
15523 break;
15524 default:
15525 MIPS_INVAL("cp1");
15526 generate_exception (ctx, EXCP_RI);
15527 break;
15529 } else {
15530 generate_exception_err(ctx, EXCP_CpU, 1);
15532 break;
15534 /* COP2. */
15535 case OPC_LWC2:
15536 case OPC_LDC2:
15537 case OPC_SWC2:
15538 case OPC_SDC2:
15539 /* COP2: Not implemented. */
15540 generate_exception_err(ctx, EXCP_CpU, 2);
15541 break;
15542 case OPC_CP2:
15543 check_insn(ctx, INSN_LOONGSON2F);
15544 /* Note that these instructions use different fields. */
15545 gen_loongson_multimedia(ctx, sa, rd, rt);
15546 break;
15548 case OPC_CP3:
15549 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
15550 check_cp1_enabled(ctx);
15551 op1 = MASK_CP3(ctx->opcode);
15552 switch (op1) {
15553 case OPC_LWXC1:
15554 case OPC_LDXC1:
15555 case OPC_LUXC1:
15556 case OPC_SWXC1:
15557 case OPC_SDXC1:
15558 case OPC_SUXC1:
15559 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
15560 break;
15561 case OPC_PREFX:
15562 /* Treat as NOP. */
15563 break;
15564 case OPC_ALNV_PS:
15565 case OPC_MADD_S:
15566 case OPC_MADD_D:
15567 case OPC_MADD_PS:
15568 case OPC_MSUB_S:
15569 case OPC_MSUB_D:
15570 case OPC_MSUB_PS:
15571 case OPC_NMADD_S:
15572 case OPC_NMADD_D:
15573 case OPC_NMADD_PS:
15574 case OPC_NMSUB_S:
15575 case OPC_NMSUB_D:
15576 case OPC_NMSUB_PS:
15577 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
15578 break;
15579 default:
15580 MIPS_INVAL("cp3");
15581 generate_exception (ctx, EXCP_RI);
15582 break;
15584 } else {
15585 generate_exception_err(ctx, EXCP_CpU, 1);
15587 break;
15589 #if defined(TARGET_MIPS64)
15590 /* MIPS64 opcodes */
15591 case OPC_LWU:
15592 case OPC_LDL ... OPC_LDR:
15593 case OPC_LLD:
15594 case OPC_LD:
15595 check_insn(ctx, ISA_MIPS3);
15596 check_mips_64(ctx);
15597 gen_ld(ctx, op, rt, rs, imm);
15598 break;
15599 case OPC_SDL ... OPC_SDR:
15600 case OPC_SD:
15601 check_insn(ctx, ISA_MIPS3);
15602 check_mips_64(ctx);
15603 gen_st(ctx, op, rt, rs, imm);
15604 break;
15605 case OPC_SCD:
15606 check_insn(ctx, ISA_MIPS3);
15607 check_mips_64(ctx);
15608 gen_st_cond(ctx, op, rt, rs, imm);
15609 break;
15610 case OPC_DADDI:
15611 case OPC_DADDIU:
15612 check_insn(ctx, ISA_MIPS3);
15613 check_mips_64(ctx);
15614 gen_arith_imm(ctx, op, rt, rs, imm);
15615 break;
15616 #endif
15617 case OPC_JALX:
15618 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
15619 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
15620 gen_compute_branch(ctx, op, 4, rs, rt, offset);
15621 break;
15622 case OPC_MDMX:
15623 check_insn(ctx, ASE_MDMX);
15624 /* MDMX: Not implemented. */
15625 default: /* Invalid */
15626 MIPS_INVAL("major opcode");
15627 generate_exception(ctx, EXCP_RI);
15628 break;
15632 static inline void
15633 gen_intermediate_code_internal(MIPSCPU *cpu, TranslationBlock *tb,
15634 bool search_pc)
15636 CPUState *cs = CPU(cpu);
15637 CPUMIPSState *env = &cpu->env;
15638 DisasContext ctx;
15639 target_ulong pc_start;
15640 uint16_t *gen_opc_end;
15641 CPUBreakpoint *bp;
15642 int j, lj = -1;
15643 int num_insns;
15644 int max_insns;
15645 int insn_bytes;
15646 int is_delay;
15648 if (search_pc)
15649 qemu_log("search pc %d\n", search_pc);
15651 pc_start = tb->pc;
15652 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
15653 ctx.pc = pc_start;
15654 ctx.saved_pc = -1;
15655 ctx.singlestep_enabled = cs->singlestep_enabled;
15656 ctx.insn_flags = env->insn_flags;
15657 ctx.CP0_Config1 = env->CP0_Config1;
15658 ctx.tb = tb;
15659 ctx.bstate = BS_NONE;
15660 /* Restore delay slot state from the tb context. */
15661 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
15662 ctx.ulri = env->CP0_Config3 & (1 << CP0C3_ULRI);
15663 restore_cpu_state(env, &ctx);
15664 #ifdef CONFIG_USER_ONLY
15665 ctx.mem_idx = MIPS_HFLAG_UM;
15666 #else
15667 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
15668 #endif
15669 num_insns = 0;
15670 max_insns = tb->cflags & CF_COUNT_MASK;
15671 if (max_insns == 0)
15672 max_insns = CF_COUNT_MASK;
15673 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
15674 gen_tb_start();
15675 while (ctx.bstate == BS_NONE) {
15676 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
15677 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
15678 if (bp->pc == ctx.pc) {
15679 save_cpu_state(&ctx, 1);
15680 ctx.bstate = BS_BRANCH;
15681 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
15682 /* Include the breakpoint location or the tb won't
15683 * be flushed when it must be. */
15684 ctx.pc += 4;
15685 goto done_generating;
15690 if (search_pc) {
15691 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
15692 if (lj < j) {
15693 lj++;
15694 while (lj < j)
15695 tcg_ctx.gen_opc_instr_start[lj++] = 0;
15697 tcg_ctx.gen_opc_pc[lj] = ctx.pc;
15698 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
15699 gen_opc_btarget[lj] = ctx.btarget;
15700 tcg_ctx.gen_opc_instr_start[lj] = 1;
15701 tcg_ctx.gen_opc_icount[lj] = num_insns;
15703 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
15704 gen_io_start();
15706 is_delay = ctx.hflags & MIPS_HFLAG_BMASK;
15707 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
15708 ctx.opcode = cpu_ldl_code(env, ctx.pc);
15709 insn_bytes = 4;
15710 decode_opc(env, &ctx);
15711 } else if (ctx.insn_flags & ASE_MICROMIPS) {
15712 ctx.opcode = cpu_lduw_code(env, ctx.pc);
15713 insn_bytes = decode_micromips_opc(env, &ctx);
15714 } else if (ctx.insn_flags & ASE_MIPS16) {
15715 ctx.opcode = cpu_lduw_code(env, ctx.pc);
15716 insn_bytes = decode_mips16_opc(env, &ctx);
15717 } else {
15718 generate_exception(&ctx, EXCP_RI);
15719 ctx.bstate = BS_STOP;
15720 break;
15722 if (is_delay) {
15723 handle_delay_slot(&ctx, insn_bytes);
15725 ctx.pc += insn_bytes;
15727 num_insns++;
15729 /* Execute a branch and its delay slot as a single instruction.
15730 This is what GDB expects and is consistent with what the
15731 hardware does (e.g. if a delay slot instruction faults, the
15732 reported PC is the PC of the branch). */
15733 if (cs->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0) {
15734 break;
15737 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
15738 break;
15740 if (tcg_ctx.gen_opc_ptr >= gen_opc_end) {
15741 break;
15744 if (num_insns >= max_insns)
15745 break;
15747 if (singlestep)
15748 break;
15750 if (tb->cflags & CF_LAST_IO) {
15751 gen_io_end();
15753 if (cs->singlestep_enabled && ctx.bstate != BS_BRANCH) {
15754 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
15755 gen_helper_0e0i(raise_exception, EXCP_DEBUG);
15756 } else {
15757 switch (ctx.bstate) {
15758 case BS_STOP:
15759 gen_goto_tb(&ctx, 0, ctx.pc);
15760 break;
15761 case BS_NONE:
15762 save_cpu_state(&ctx, 0);
15763 gen_goto_tb(&ctx, 0, ctx.pc);
15764 break;
15765 case BS_EXCP:
15766 tcg_gen_exit_tb(0);
15767 break;
15768 case BS_BRANCH:
15769 default:
15770 break;
15773 done_generating:
15774 gen_tb_end(tb, num_insns);
15775 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
15776 if (search_pc) {
15777 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
15778 lj++;
15779 while (lj <= j)
15780 tcg_ctx.gen_opc_instr_start[lj++] = 0;
15781 } else {
15782 tb->size = ctx.pc - pc_start;
15783 tb->icount = num_insns;
15785 #ifdef DEBUG_DISAS
15786 LOG_DISAS("\n");
15787 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
15788 qemu_log("IN: %s\n", lookup_symbol(pc_start));
15789 log_target_disas(env, pc_start, ctx.pc - pc_start, 0);
15790 qemu_log("\n");
15792 #endif
15795 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
15797 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, false);
15800 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
15802 gen_intermediate_code_internal(mips_env_get_cpu(env), tb, true);
15805 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
15806 int flags)
15808 int i;
15809 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
15811 #define printfpr(fp) \
15812 do { \
15813 if (is_fpu64) \
15814 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15815 " fd:%13g fs:%13g psu: %13g\n", \
15816 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
15817 (double)(fp)->fd, \
15818 (double)(fp)->fs[FP_ENDIAN_IDX], \
15819 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
15820 else { \
15821 fpr_t tmp; \
15822 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
15823 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
15824 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
15825 " fd:%13g fs:%13g psu:%13g\n", \
15826 tmp.w[FP_ENDIAN_IDX], tmp.d, \
15827 (double)tmp.fd, \
15828 (double)tmp.fs[FP_ENDIAN_IDX], \
15829 (double)tmp.fs[!FP_ENDIAN_IDX]); \
15831 } while(0)
15834 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
15835 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
15836 get_float_exception_flags(&env->active_fpu.fp_status));
15837 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
15838 fpu_fprintf(f, "%3s: ", fregnames[i]);
15839 printfpr(&env->active_fpu.fpr[i]);
15842 #undef printfpr
15845 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
15846 /* Debug help: The architecture requires 32bit code to maintain proper
15847 sign-extended values on 64bit machines. */
15849 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
15851 static void
15852 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
15853 fprintf_function cpu_fprintf,
15854 int flags)
15856 int i;
15858 if (!SIGN_EXT_P(env->active_tc.PC))
15859 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
15860 if (!SIGN_EXT_P(env->active_tc.HI[0]))
15861 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
15862 if (!SIGN_EXT_P(env->active_tc.LO[0]))
15863 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
15864 if (!SIGN_EXT_P(env->btarget))
15865 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
15867 for (i = 0; i < 32; i++) {
15868 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
15869 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
15872 if (!SIGN_EXT_P(env->CP0_EPC))
15873 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
15874 if (!SIGN_EXT_P(env->lladdr))
15875 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
15877 #endif
15879 void mips_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
15880 int flags)
15882 MIPSCPU *cpu = MIPS_CPU(cs);
15883 CPUMIPSState *env = &cpu->env;
15884 int i;
15886 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
15887 " LO=0x" TARGET_FMT_lx " ds %04x "
15888 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
15889 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
15890 env->hflags, env->btarget, env->bcond);
15891 for (i = 0; i < 32; i++) {
15892 if ((i & 3) == 0)
15893 cpu_fprintf(f, "GPR%02d:", i);
15894 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
15895 if ((i & 3) == 3)
15896 cpu_fprintf(f, "\n");
15899 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
15900 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
15901 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
15902 env->CP0_Config0, env->CP0_Config1, env->lladdr);
15903 if (env->hflags & MIPS_HFLAG_FPU)
15904 fpu_dump_state(env, f, cpu_fprintf, flags);
15905 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
15906 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
15907 #endif
15910 void mips_tcg_init(void)
15912 int i;
15913 static int inited;
15915 /* Initialize various static tables. */
15916 if (inited)
15917 return;
15919 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
15920 TCGV_UNUSED(cpu_gpr[0]);
15921 for (i = 1; i < 32; i++)
15922 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
15923 offsetof(CPUMIPSState, active_tc.gpr[i]),
15924 regnames[i]);
15926 for (i = 0; i < 32; i++) {
15927 int off = offsetof(CPUMIPSState, active_fpu.fpr[i]);
15928 fpu_f64[i] = tcg_global_mem_new_i64(TCG_AREG0, off, fregnames[i]);
15931 cpu_PC = tcg_global_mem_new(TCG_AREG0,
15932 offsetof(CPUMIPSState, active_tc.PC), "PC");
15933 for (i = 0; i < MIPS_DSP_ACC; i++) {
15934 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
15935 offsetof(CPUMIPSState, active_tc.HI[i]),
15936 regnames_HI[i]);
15937 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
15938 offsetof(CPUMIPSState, active_tc.LO[i]),
15939 regnames_LO[i]);
15940 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
15941 offsetof(CPUMIPSState, active_tc.ACX[i]),
15942 regnames_ACX[i]);
15944 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
15945 offsetof(CPUMIPSState, active_tc.DSPControl),
15946 "DSPControl");
15947 bcond = tcg_global_mem_new(TCG_AREG0,
15948 offsetof(CPUMIPSState, bcond), "bcond");
15949 btarget = tcg_global_mem_new(TCG_AREG0,
15950 offsetof(CPUMIPSState, btarget), "btarget");
15951 hflags = tcg_global_mem_new_i32(TCG_AREG0,
15952 offsetof(CPUMIPSState, hflags), "hflags");
15954 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
15955 offsetof(CPUMIPSState, active_fpu.fcr0),
15956 "fcr0");
15957 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
15958 offsetof(CPUMIPSState, active_fpu.fcr31),
15959 "fcr31");
15961 inited = 1;
15964 #include "translate_init.c"
15966 MIPSCPU *cpu_mips_init(const char *cpu_model)
15968 MIPSCPU *cpu;
15969 CPUMIPSState *env;
15970 const mips_def_t *def;
15972 def = cpu_mips_find_by_name(cpu_model);
15973 if (!def)
15974 return NULL;
15975 cpu = MIPS_CPU(object_new(TYPE_MIPS_CPU));
15976 env = &cpu->env;
15977 env->cpu_model = def;
15979 #ifndef CONFIG_USER_ONLY
15980 mmu_init(env, def);
15981 #endif
15982 fpu_init(env, def);
15983 mvp_init(env, def);
15985 object_property_set_bool(OBJECT(cpu), true, "realized", NULL);
15987 return cpu;
15990 void cpu_state_reset(CPUMIPSState *env)
15992 MIPSCPU *cpu = mips_env_get_cpu(env);
15993 CPUState *cs = CPU(cpu);
15995 /* Reset registers to their default values */
15996 env->CP0_PRid = env->cpu_model->CP0_PRid;
15997 env->CP0_Config0 = env->cpu_model->CP0_Config0;
15998 #ifdef TARGET_WORDS_BIGENDIAN
15999 env->CP0_Config0 |= (1 << CP0C0_BE);
16000 #endif
16001 env->CP0_Config1 = env->cpu_model->CP0_Config1;
16002 env->CP0_Config2 = env->cpu_model->CP0_Config2;
16003 env->CP0_Config3 = env->cpu_model->CP0_Config3;
16004 env->CP0_Config4 = env->cpu_model->CP0_Config4;
16005 env->CP0_Config4_rw_bitmask = env->cpu_model->CP0_Config4_rw_bitmask;
16006 env->CP0_Config5 = env->cpu_model->CP0_Config5;
16007 env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
16008 env->CP0_Config6 = env->cpu_model->CP0_Config6;
16009 env->CP0_Config7 = env->cpu_model->CP0_Config7;
16010 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
16011 << env->cpu_model->CP0_LLAddr_shift;
16012 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
16013 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
16014 env->CCRes = env->cpu_model->CCRes;
16015 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
16016 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
16017 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
16018 env->current_tc = 0;
16019 env->SEGBITS = env->cpu_model->SEGBITS;
16020 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
16021 #if defined(TARGET_MIPS64)
16022 if (env->cpu_model->insn_flags & ISA_MIPS3) {
16023 env->SEGMask |= 3ULL << 62;
16025 #endif
16026 env->PABITS = env->cpu_model->PABITS;
16027 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
16028 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
16029 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
16030 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
16031 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
16032 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
16033 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
16034 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
16035 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
16036 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
16037 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
16038 env->active_fpu.fcr0 = env->cpu_model->CP1_fcr0;
16039 env->insn_flags = env->cpu_model->insn_flags;
16041 #if defined(CONFIG_USER_ONLY)
16042 env->CP0_Status = (MIPS_HFLAG_UM << CP0St_KSU);
16043 # ifdef TARGET_MIPS64
16044 /* Enable 64-bit register mode. */
16045 env->CP0_Status |= (1 << CP0St_PX);
16046 # endif
16047 # ifdef TARGET_ABI_MIPSN64
16048 /* Enable 64-bit address mode. */
16049 env->CP0_Status |= (1 << CP0St_UX);
16050 # endif
16051 /* Enable access to the CPUNum, SYNCI_Step, CC, and CCRes RDHWR
16052 hardware registers. */
16053 env->CP0_HWREna |= 0x0000000F;
16054 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
16055 env->CP0_Status |= (1 << CP0St_CU1);
16057 if (env->CP0_Config3 & (1 << CP0C3_DSPP)) {
16058 env->CP0_Status |= (1 << CP0St_MX);
16060 # if defined(TARGET_MIPS64)
16061 /* For MIPS64, init FR bit to 1 if FPU unit is there and bit is writable. */
16062 if ((env->CP0_Config1 & (1 << CP0C1_FP)) &&
16063 (env->CP0_Status_rw_bitmask & (1 << CP0St_FR))) {
16064 env->CP0_Status |= (1 << CP0St_FR);
16066 # endif
16067 #else
16068 if (env->hflags & MIPS_HFLAG_BMASK) {
16069 /* If the exception was raised from a delay slot,
16070 come back to the jump. */
16071 env->CP0_ErrorEPC = env->active_tc.PC - 4;
16072 } else {
16073 env->CP0_ErrorEPC = env->active_tc.PC;
16075 env->active_tc.PC = (int32_t)0xBFC00000;
16076 env->CP0_Random = env->tlb->nb_tlb - 1;
16077 env->tlb->tlb_in_use = env->tlb->nb_tlb;
16078 env->CP0_Wired = 0;
16079 env->CP0_EBase = 0x80000000 | (cs->cpu_index & 0x3FF);
16080 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
16081 /* vectored interrupts not implemented, timer on int 7,
16082 no performance counters. */
16083 env->CP0_IntCtl = 0xe0000000;
16085 int i;
16087 for (i = 0; i < 7; i++) {
16088 env->CP0_WatchLo[i] = 0;
16089 env->CP0_WatchHi[i] = 0x80000000;
16091 env->CP0_WatchLo[7] = 0;
16092 env->CP0_WatchHi[7] = 0;
16094 /* Count register increments in debug mode, EJTAG version 1 */
16095 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
16097 cpu_mips_store_count(env, 1);
16099 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
16100 int i;
16102 /* Only TC0 on VPE 0 starts as active. */
16103 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
16104 env->tcs[i].CP0_TCBind = cs->cpu_index << CP0TCBd_CurVPE;
16105 env->tcs[i].CP0_TCHalt = 1;
16107 env->active_tc.CP0_TCHalt = 1;
16108 cs->halted = 1;
16110 if (cs->cpu_index == 0) {
16111 /* VPE0 starts up enabled. */
16112 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
16113 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
16115 /* TC0 starts up unhalted. */
16116 cs->halted = 0;
16117 env->active_tc.CP0_TCHalt = 0;
16118 env->tcs[0].CP0_TCHalt = 0;
16119 /* With thread 0 active. */
16120 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
16121 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
16124 #endif
16125 compute_hflags(env);
16126 cs->exception_index = EXCP_NONE;
16129 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
16131 env->active_tc.PC = tcg_ctx.gen_opc_pc[pc_pos];
16132 env->hflags &= ~MIPS_HFLAG_BMASK;
16133 env->hflags |= gen_opc_hflags[pc_pos];
16134 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
16135 case MIPS_HFLAG_BR:
16136 break;
16137 case MIPS_HFLAG_BC:
16138 case MIPS_HFLAG_BL:
16139 case MIPS_HFLAG_B:
16140 env->btarget = gen_opc_btarget[pc_pos];
16141 break;