1 /*
2 * MIPS emulation for QEMU - main translation routines
3 *
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
8 * Copyright (c) 2012 Jia Liu & Dongxue Zhang (MIPS ASE DSP support)
9 * Copyright (c) 2020 Philippe Mathieu-Daudé
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "qemu/osdep.h"
26 #include "translate.h"
27 #include "internal.h"
28 #include "exec/helper-proto.h"
29 #include "exec/translation-block.h"
30 #include "exec/target_page.h"
31 #include "semihosting/semihost.h"
32 #include "trace.h"
33 #include "fpu_helper.h"
34
35 #define HELPER_H "helper.h"
36 #include "exec/helper-info.c.inc"
37 #undef HELPER_H
38
39
40 /*
41 * Many system-only helpers are not reachable for user-only.
42 * Define stub generators here, so that we need not either sprinkle
43 * ifdefs through the translator, nor provide the helper function.
44 */
45 #define STUB_HELPER(NAME, ...) \
46 static inline void gen_helper_##NAME(__VA_ARGS__) \
47 { g_assert_not_reached(); }
48
49 #ifdef CONFIG_USER_ONLY
50 STUB_HELPER(cache, TCGv_env env, TCGv val, TCGv_i32 reg)
51 #endif
52
53 enum {
54 /* indirect opcode tables */
55 OPC_SPECIAL = (0x00 << 26),
56 OPC_REGIMM = (0x01 << 26),
57 OPC_CP0 = (0x10 << 26),
58 OPC_CP2 = (0x12 << 26),
59 OPC_CP3 = (0x13 << 26),
60 OPC_SPECIAL2 = (0x1C << 26),
61 OPC_SPECIAL3 = (0x1F << 26),
62 /* arithmetic with immediate */
63 OPC_ADDI = (0x08 << 26),
64 OPC_ADDIU = (0x09 << 26),
65 OPC_SLTI = (0x0A << 26),
66 OPC_SLTIU = (0x0B << 26),
67 /* logic with immediate */
68 OPC_ANDI = (0x0C << 26),
69 OPC_ORI = (0x0D << 26),
70 OPC_XORI = (0x0E << 26),
71 OPC_LUI = (0x0F << 26),
72 /* arithmetic with immediate */
73 OPC_DADDI = (0x18 << 26),
74 OPC_DADDIU = (0x19 << 26),
75 /* Jump and branches */
76 OPC_J = (0x02 << 26),
77 OPC_JAL = (0x03 << 26),
78 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
79 OPC_BEQL = (0x14 << 26),
80 OPC_BNE = (0x05 << 26),
81 OPC_BNEL = (0x15 << 26),
82 OPC_BLEZ = (0x06 << 26),
83 OPC_BLEZL = (0x16 << 26),
84 OPC_BGTZ = (0x07 << 26),
85 OPC_BGTZL = (0x17 << 26),
86 OPC_JALX = (0x1D << 26),
87 OPC_DAUI = (0x1D << 26),
88 /* Load and stores */
89 OPC_LDL = (0x1A << 26),
90 OPC_LDR = (0x1B << 26),
91 OPC_LB = (0x20 << 26),
92 OPC_LH = (0x21 << 26),
93 OPC_LWL = (0x22 << 26),
94 OPC_LW = (0x23 << 26),
95 OPC_LWPC = OPC_LW | 0x5,
96 OPC_LBU = (0x24 << 26),
97 OPC_LHU = (0x25 << 26),
98 OPC_LWR = (0x26 << 26),
99 OPC_LWU = (0x27 << 26),
100 OPC_SB = (0x28 << 26),
101 OPC_SH = (0x29 << 26),
102 OPC_SWL = (0x2A << 26),
103 OPC_SW = (0x2B << 26),
104 OPC_SDL = (0x2C << 26),
105 OPC_SDR = (0x2D << 26),
106 OPC_SWR = (0x2E << 26),
107 OPC_LL = (0x30 << 26),
108 OPC_LLD = (0x34 << 26),
109 OPC_LD = (0x37 << 26),
110 OPC_LDPC = OPC_LD | 0x5,
111 OPC_SC = (0x38 << 26),
112 OPC_SCD = (0x3C << 26),
113 OPC_SD = (0x3F << 26),
114 /* Floating point load/store */
115 OPC_LWC1 = (0x31 << 26),
116 OPC_LWC2 = (0x32 << 26),
117 OPC_LDC1 = (0x35 << 26),
118 OPC_LDC2 = (0x36 << 26),
119 OPC_SWC1 = (0x39 << 26),
120 OPC_SWC2 = (0x3A << 26),
121 OPC_SDC1 = (0x3D << 26),
122 OPC_SDC2 = (0x3E << 26),
123 /* Compact Branches */
124 OPC_BLEZALC = (0x06 << 26),
125 OPC_BGEZALC = (0x06 << 26),
126 OPC_BGEUC = (0x06 << 26),
127 OPC_BGTZALC = (0x07 << 26),
128 OPC_BLTZALC = (0x07 << 26),
129 OPC_BLTUC = (0x07 << 26),
130 OPC_BOVC = (0x08 << 26),
131 OPC_BEQZALC = (0x08 << 26),
132 OPC_BEQC = (0x08 << 26),
133 OPC_BLEZC = (0x16 << 26),
134 OPC_BGEZC = (0x16 << 26),
135 OPC_BGEC = (0x16 << 26),
136 OPC_BGTZC = (0x17 << 26),
137 OPC_BLTZC = (0x17 << 26),
138 OPC_BLTC = (0x17 << 26),
139 OPC_BNVC = (0x18 << 26),
140 OPC_BNEZALC = (0x18 << 26),
141 OPC_BNEC = (0x18 << 26),
142 OPC_BC = (0x32 << 26),
143 OPC_BEQZC = (0x36 << 26),
144 OPC_JIC = (0x36 << 26),
145 OPC_BALC = (0x3A << 26),
146 OPC_BNEZC = (0x3E << 26),
147 OPC_JIALC = (0x3E << 26),
148 /* MDMX ASE specific */
149 OPC_MDMX = (0x1E << 26),
150 /* Cache and prefetch */
151 OPC_CACHE = (0x2F << 26),
152 OPC_PREF = (0x33 << 26),
153 /* PC-relative address computation / loads */
154 OPC_PCREL = (0x3B << 26),
155 };
156
157 /* PC-relative address computation / loads */
158 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
159 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
160 enum {
161 /* Instructions determined by bits 19 and 20 */
162 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
163 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
164 OPC_LWUPC = OPC_PCREL | (2 << 19),
165
166 /* Instructions determined by bits 16 ... 20 */
167 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
168 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
169
170 /* Other */
171 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
172 };
173
174 /* MIPS special opcodes */
175 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
176
177 enum {
178 /* Shifts */
179 OPC_SLL = 0x00 | OPC_SPECIAL,
180 /* NOP is SLL r0, r0, 0 */
181 /* SSNOP is SLL r0, r0, 1 */
182 /* EHB is SLL r0, r0, 3 */
183 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
184 OPC_ROTR = OPC_SRL | (1 << 21),
185 OPC_SRA = 0x03 | OPC_SPECIAL,
186 OPC_SLLV = 0x04 | OPC_SPECIAL,
187 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
188 OPC_ROTRV = OPC_SRLV | (1 << 6),
189 OPC_SRAV = 0x07 | OPC_SPECIAL,
190 OPC_DSLLV = 0x14 | OPC_SPECIAL,
191 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
192 OPC_DROTRV = OPC_DSRLV | (1 << 6),
193 OPC_DSRAV = 0x17 | OPC_SPECIAL,
194 OPC_DSLL = 0x38 | OPC_SPECIAL,
195 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
196 OPC_DROTR = OPC_DSRL | (1 << 21),
197 OPC_DSRA = 0x3B | OPC_SPECIAL,
198 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
199 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
200 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
201 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
202 /* Multiplication / division */
203 OPC_MULT = 0x18 | OPC_SPECIAL,
204 OPC_MULTU = 0x19 | OPC_SPECIAL,
205 OPC_DIV = 0x1A | OPC_SPECIAL,
206 OPC_DIVU = 0x1B | OPC_SPECIAL,
207 OPC_DMULT = 0x1C | OPC_SPECIAL,
208 OPC_DMULTU = 0x1D | OPC_SPECIAL,
209 OPC_DDIV = 0x1E | OPC_SPECIAL,
210 OPC_DDIVU = 0x1F | OPC_SPECIAL,
211
212 /* 2 registers arithmetic / logic */
213 OPC_ADD = 0x20 | OPC_SPECIAL,
214 OPC_ADDU = 0x21 | OPC_SPECIAL,
215 OPC_SUB = 0x22 | OPC_SPECIAL,
216 OPC_SUBU = 0x23 | OPC_SPECIAL,
217 OPC_AND = 0x24 | OPC_SPECIAL,
218 OPC_OR = 0x25 | OPC_SPECIAL,
219 OPC_XOR = 0x26 | OPC_SPECIAL,
220 OPC_NOR = 0x27 | OPC_SPECIAL,
221 OPC_SLT = 0x2A | OPC_SPECIAL,
222 OPC_SLTU = 0x2B | OPC_SPECIAL,
223 OPC_DADD = 0x2C | OPC_SPECIAL,
224 OPC_DADDU = 0x2D | OPC_SPECIAL,
225 OPC_DSUB = 0x2E | OPC_SPECIAL,
226 OPC_DSUBU = 0x2F | OPC_SPECIAL,
227 /* Jumps */
228 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
229 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
230 /* Traps */
231 OPC_TGE = 0x30 | OPC_SPECIAL,
232 OPC_TGEU = 0x31 | OPC_SPECIAL,
233 OPC_TLT = 0x32 | OPC_SPECIAL,
234 OPC_TLTU = 0x33 | OPC_SPECIAL,
235 OPC_TEQ = 0x34 | OPC_SPECIAL,
236 OPC_TNE = 0x36 | OPC_SPECIAL,
237 /* HI / LO registers load & stores */
238 OPC_MFHI = 0x10 | OPC_SPECIAL,
239 OPC_MTHI = 0x11 | OPC_SPECIAL,
240 OPC_MFLO = 0x12 | OPC_SPECIAL,
241 OPC_MTLO = 0x13 | OPC_SPECIAL,
242 /* Conditional moves */
243 OPC_MOVZ = 0x0A | OPC_SPECIAL,
244 OPC_MOVN = 0x0B | OPC_SPECIAL,
245
246 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
247 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
248
249 OPC_MOVCI = 0x01 | OPC_SPECIAL,
250
251 /* Special */
252 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
253 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
254 OPC_BREAK = 0x0D | OPC_SPECIAL,
255 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
256 OPC_SYNC = 0x0F | OPC_SPECIAL,
257
258 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
259 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
260 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
261 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
262 };
263
264 /*
265 * R6 Multiply and Divide instructions have the same opcode
266 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
267 */
268 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
269
270 enum {
271 R6_OPC_MUL = OPC_MULT | (2 << 6),
272 R6_OPC_MUH = OPC_MULT | (3 << 6),
273 R6_OPC_MULU = OPC_MULTU | (2 << 6),
274 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
275 R6_OPC_DIV = OPC_DIV | (2 << 6),
276 R6_OPC_MOD = OPC_DIV | (3 << 6),
277 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
278 R6_OPC_MODU = OPC_DIVU | (3 << 6),
279
280 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
281 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
282 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
283 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
284 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
285 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
286 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
287 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
288
289 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
290 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
291 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
292 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
293 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
294 };
295
296 /* REGIMM (rt field) opcodes */
297 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
298
299 enum {
300 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
301 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
302 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
303 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
304 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
305 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
306 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
307 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
308 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
309 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
310 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
311 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
312 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
313 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
314 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
315 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
316
317 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
318 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
319 };
320
321 /* Special2 opcodes */
322 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
323
324 enum {
325 /* Multiply & xxx operations */
326 OPC_MADD = 0x00 | OPC_SPECIAL2,
327 OPC_MADDU = 0x01 | OPC_SPECIAL2,
328 OPC_MUL = 0x02 | OPC_SPECIAL2,
329 OPC_MSUB = 0x04 | OPC_SPECIAL2,
330 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
331 /* Misc */
332 OPC_CLZ = 0x20 | OPC_SPECIAL2,
333 OPC_CLO = 0x21 | OPC_SPECIAL2,
334 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
335 OPC_DCLO = 0x25 | OPC_SPECIAL2,
336 /* Special */
337 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
338 };
339
340 /* Special3 opcodes */
341 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
342
343 enum {
344 OPC_EXT = 0x00 | OPC_SPECIAL3,
345 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
346 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
347 OPC_DEXT = 0x03 | OPC_SPECIAL3,
348 OPC_INS = 0x04 | OPC_SPECIAL3,
349 OPC_DINSM = 0x05 | OPC_SPECIAL3,
350 OPC_DINSU = 0x06 | OPC_SPECIAL3,
351 OPC_DINS = 0x07 | OPC_SPECIAL3,
352 OPC_FORK = 0x08 | OPC_SPECIAL3,
353 OPC_YIELD = 0x09 | OPC_SPECIAL3,
354 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
355 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
356 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
357 OPC_GINV = 0x3D | OPC_SPECIAL3,
358
359 /* MIPS DSP Load */
360 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
361 /* MIPS DSP Arithmetic */
362 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
363 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
364 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
365 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
366 OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3,
367 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
368 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
369 /* MIPS DSP GPR-Based Shift Sub-class */
370 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
371 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
372 /* MIPS DSP Multiply Sub-class insns */
373 OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3,
374 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
375 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
376 /* DSP Bit/Manipulation Sub-class */
377 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
378 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
379 /* MIPS DSP Append Sub-class */
380 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
381 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
382 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
383 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
384 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
385
386 /* EVA */
387 OPC_LWLE = 0x19 | OPC_SPECIAL3,
388 OPC_LWRE = 0x1A | OPC_SPECIAL3,
389 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
390 OPC_SBE = 0x1C | OPC_SPECIAL3,
391 OPC_SHE = 0x1D | OPC_SPECIAL3,
392 OPC_SCE = 0x1E | OPC_SPECIAL3,
393 OPC_SWE = 0x1F | OPC_SPECIAL3,
394 OPC_SWLE = 0x21 | OPC_SPECIAL3,
395 OPC_SWRE = 0x22 | OPC_SPECIAL3,
396 OPC_PREFE = 0x23 | OPC_SPECIAL3,
397 OPC_LBUE = 0x28 | OPC_SPECIAL3,
398 OPC_LHUE = 0x29 | OPC_SPECIAL3,
399 OPC_LBE = 0x2C | OPC_SPECIAL3,
400 OPC_LHE = 0x2D | OPC_SPECIAL3,
401 OPC_LLE = 0x2E | OPC_SPECIAL3,
402 OPC_LWE = 0x2F | OPC_SPECIAL3,
403
404 /* R6 */
405 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
406 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
407 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
408 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
409 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
410 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
411 };
412
413 /* Loongson EXT load/store quad word opcodes */
414 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
415 enum {
416 OPC_GSLQ = 0x0020 | OPC_LWC2,
417 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
418 OPC_GSSHFL = OPC_LWC2,
419 OPC_GSSQ = 0x0020 | OPC_SWC2,
420 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
421 OPC_GSSHFS = OPC_SWC2,
422 };
423
424 /* Loongson EXT shifted load/store opcodes */
425 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
426 enum {
427 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
428 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
429 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
430 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
431 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
432 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
433 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
434 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
435 };
436
437 /* Loongson EXT LDC2/SDC2 opcodes */
438 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
439
440 enum {
441 OPC_GSLBX = 0x0 | OPC_LDC2,
442 OPC_GSLHX = 0x1 | OPC_LDC2,
443 OPC_GSLWX = 0x2 | OPC_LDC2,
444 OPC_GSLDX = 0x3 | OPC_LDC2,
445 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
446 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
447 OPC_GSSBX = 0x0 | OPC_SDC2,
448 OPC_GSSHX = 0x1 | OPC_SDC2,
449 OPC_GSSWX = 0x2 | OPC_SDC2,
450 OPC_GSSDX = 0x3 | OPC_SDC2,
451 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
452 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
453 };
454
455 /* BSHFL opcodes */
456 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
457
458 enum {
459 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
460 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
461 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
462 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
463 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
464 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
465 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
466 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
467 };
468
469 /* DBSHFL opcodes */
470 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
471
472 enum {
473 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
474 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
475 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
476 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
477 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
478 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
479 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
480 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
481 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
482 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
483 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
484 };
485
486 /* MIPS DSP REGIMM opcodes */
487 enum {
488 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
489 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
490 };
491
492 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
493 /* MIPS DSP Load */
494 enum {
495 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
496 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
497 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
498 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
499 };
500
501 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
502 enum {
503 /* MIPS DSP Arithmetic Sub-class */
504 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
507 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
508 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
510 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
514 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
517 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
518 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
519 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
520 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
521 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
522 /* MIPS DSP Multiply Sub-class insns */
523 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
525 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
526 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
527 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
528 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
529 };
530
531 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
532 enum {
533 /* MIPS DSP Arithmetic Sub-class */
534 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
537 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
538 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
543 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
544 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
545 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
546 /* MIPS DSP Multiply Sub-class insns */
547 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
548 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
549 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
550 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
551 };
552
553 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
554 enum {
555 /* MIPS DSP Arithmetic Sub-class */
556 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
568 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
569 /* DSP Bit/Manipulation Sub-class */
570 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
574 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
575 };
576
577 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
578 enum {
579 /* MIPS DSP Arithmetic Sub-class */
580 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
584 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
585 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
586 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
587 /* DSP Compare-Pick Sub-class */
588 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
602 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
603 };
604
605 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
606 enum {
607 /* MIPS DSP GPR-Based Shift Sub-class */
608 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
629 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
630 };
631
632 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
633 enum {
634 /* MIPS DSP Multiply Sub-class insns */
635 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
648 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
649 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
651 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
656 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
657 };
658
659 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
660 enum {
661 /* DSP Bit/Manipulation Sub-class */
662 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
663 };
664
665 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
666 enum {
667 /* MIPS DSP Append Sub-class */
668 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
669 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
670 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
671 };
672
673 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
674 enum {
675 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
676 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
687 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
688 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
689 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
690 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
691 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
692 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
693 };
694
695 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
696 enum {
697 /* MIPS DSP Arithmetic Sub-class */
698 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
714 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
715 /* DSP Bit/Manipulation Sub-class */
716 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
721 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
722 };
723
724 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
725 enum {
726 /* MIPS DSP Multiply Sub-class insns */
727 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
729 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
730 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
731 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
732 /* MIPS DSP Arithmetic Sub-class */
733 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
743 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
753 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
754 };
755
756 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
757 enum {
758 /* DSP Compare-Pick Sub-class */
759 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
777 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
778 /* MIPS DSP Arithmetic Sub-class */
779 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
786 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
787 };
788
789 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
790 enum {
791 /* DSP Append Sub-class */
792 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
793 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
794 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
795 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
796 };
797
798 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
799 enum {
800 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
801 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
802 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
821 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
822 };
823
824 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
825 enum {
826 /* DSP Bit/Manipulation Sub-class */
827 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
828 };
829
830 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
831 enum {
832 /* MIPS DSP Multiply Sub-class insns */
833 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
858 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
859 };
860
861 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
862 enum {
863 /* MIPS DSP GPR-Based Shift Sub-class */
864 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
889 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
890 };
891
892 /* Coprocessor 0 (rs field) */
893 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
894
895 enum {
896 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
897 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
898 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
899 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
900 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
901 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
902 OPC_MFTR = (0x08 << 21) | OPC_CP0,
903 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
904 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
905 OPC_MTTR = (0x0C << 21) | OPC_CP0,
906 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
907 OPC_C0 = (0x10 << 21) | OPC_CP0,
908 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
909 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
910 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
911 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
912 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
913 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
914 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
915 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
916 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
917 OPC_C0_A = (0x1A << 21) | OPC_CP0,
918 OPC_C0_B = (0x1B << 21) | OPC_CP0,
919 OPC_C0_C = (0x1C << 21) | OPC_CP0,
920 OPC_C0_D = (0x1D << 21) | OPC_CP0,
921 OPC_C0_E = (0x1E << 21) | OPC_CP0,
922 OPC_C0_F = (0x1F << 21) | OPC_CP0,
923 };
924
925 /* MFMC0 opcodes */
926 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
927
928 enum {
929 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
930 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
931 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
932 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
933 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
934 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
935 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
936 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
937 };
938
939 /* Coprocessor 0 (with rs == C0) */
940 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
941
942 enum {
943 OPC_TLBR = 0x01 | OPC_C0,
944 OPC_TLBWI = 0x02 | OPC_C0,
945 OPC_TLBINV = 0x03 | OPC_C0,
946 OPC_TLBINVF = 0x04 | OPC_C0,
947 OPC_TLBWR = 0x06 | OPC_C0,
948 OPC_TLBP = 0x08 | OPC_C0,
949 OPC_RFE = 0x10 | OPC_C0,
950 OPC_ERET = 0x18 | OPC_C0,
951 OPC_DERET = 0x1F | OPC_C0,
952 OPC_WAIT = 0x20 | OPC_C0,
953 };
954
955 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
956
957 enum {
958 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
959 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
960 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
961 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
962 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
963 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
964 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
965 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
966 OPC_BC2 = (0x08 << 21) | OPC_CP2,
967 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
968 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
969 };
970
971 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
972
973 enum {
974 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
975 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
976 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
977 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
978 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
979 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
980 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
981 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
982
983 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
984 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
985 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
986 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
987 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
988 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
989 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
990 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
991
992 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
993 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
994 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
995 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
996 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
997 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
998 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
999 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
1000
1001 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1002 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1003 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1004 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1005 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1006 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1007 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1008 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1009
1010 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1011 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1012 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1013 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1014 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1015 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1016
1017 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1018 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1019 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1020 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1021 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1022 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1023
1024 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1025 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1026 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1027 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1028 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1029 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1030
1031 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1032 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1033 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1034 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1035 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1036 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1037
1038 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1039 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1040 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1041 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1042 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1043 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1044
1045 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1046 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1047 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1048 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1049 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1050 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1051
1052 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1053 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1054 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1055 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1056 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1057 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1058
1059 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1060 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1061 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1062 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1063 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1064 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1065 };
1066
1067
1068 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1069
1070 enum {
1071 OPC_LWXC1 = 0x00 | OPC_CP3,
1072 OPC_LDXC1 = 0x01 | OPC_CP3,
1073 OPC_LUXC1 = 0x05 | OPC_CP3,
1074 OPC_SWXC1 = 0x08 | OPC_CP3,
1075 OPC_SDXC1 = 0x09 | OPC_CP3,
1076 OPC_SUXC1 = 0x0D | OPC_CP3,
1077 OPC_PREFX = 0x0F | OPC_CP3,
1078 OPC_ALNV_PS = 0x1E | OPC_CP3,
1079 OPC_MADD_S = 0x20 | OPC_CP3,
1080 OPC_MADD_D = 0x21 | OPC_CP3,
1081 OPC_MADD_PS = 0x26 | OPC_CP3,
1082 OPC_MSUB_S = 0x28 | OPC_CP3,
1083 OPC_MSUB_D = 0x29 | OPC_CP3,
1084 OPC_MSUB_PS = 0x2E | OPC_CP3,
1085 OPC_NMADD_S = 0x30 | OPC_CP3,
1086 OPC_NMADD_D = 0x31 | OPC_CP3,
1087 OPC_NMADD_PS = 0x36 | OPC_CP3,
1088 OPC_NMSUB_S = 0x38 | OPC_CP3,
1089 OPC_NMSUB_D = 0x39 | OPC_CP3,
1090 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1091 };
1092
1093 /*
1094 * MMI (MultiMedia Instruction) encodings
1095 * ======================================
1096 *
1097 * MMI instructions encoding table keys:
1098 *
1099 * * This code is reserved for future use. An attempt to execute it
1100 * causes a Reserved Instruction exception.
1101 * % This code indicates an instruction class. The instruction word
1102 * must be further decoded by examining additional tables that show
1103 * the values for other instruction fields.
1104 * # This code is reserved for the unsupported instructions DMULT,
1105 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1106 * to execute it causes a Reserved Instruction exception.
1107 *
1108 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1109 *
1110 * 31 26 0
1111 * +--------+----------------------------------------+
1112 * | opcode | |
1113 * +--------+----------------------------------------+
1114 *
1115 * opcode bits 28..26
1116 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1117 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1118 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1119 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1120 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1121 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1122 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1123 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1124 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1125 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1126 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1127 */
1128
1129 enum {
1130 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1131 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1132 };
1133
1134 /*
1135 * MMI instructions with opcode field = MMI:
1136 *
1137 * 31 26 5 0
1138 * +--------+-------------------------------+--------+
1139 * | MMI | |function|
1140 * +--------+-------------------------------+--------+
1141 *
1142 * function bits 2..0
1143 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1144 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1145 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1146 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1147 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1148 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1149 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1150 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1151 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1152 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1153 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1154 */
1155
1156 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1157 enum {
1158 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1159 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1160 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1161 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1162 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1163 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1164 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1165 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1166 };
1167
1168 /* global register indices */
1169 TCGv cpu_gpr[32], cpu_PC;
1170 /*
1171 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1172 * and the upper halves in cpu_gpr_hi[].
1173 */
1174 TCGv_i64 cpu_gpr_hi[32];
1175 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1176 static TCGv cpu_dspctrl, btarget;
1177 TCGv bcond;
1178 static TCGv cpu_lladdr, cpu_llval;
1179 static TCGv_i32 hflags;
1180 TCGv_i32 fpu_fcr0, fpu_fcr31;
1181 TCGv_i64 fpu_f64[32];
1182
1183 static const char regnames_HI[][4] = {
1184 "HI0", "HI1", "HI2", "HI3",
1185 };
1186
1187 static const char regnames_LO[][4] = {
1188 "LO0", "LO1", "LO2", "LO3",
1189 };
1190
1191 /* General purpose registers moves. */
gen_load_gpr(TCGv t,int reg)1192 void gen_load_gpr(TCGv t, int reg)
1193 {
1194 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr));
1195 if (reg == 0) {
1196 tcg_gen_movi_tl(t, 0);
1197 } else {
1198 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1199 }
1200 }
1201
gen_store_gpr(TCGv t,int reg)1202 void gen_store_gpr(TCGv t, int reg)
1203 {
1204 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr));
1205 if (reg != 0) {
1206 tcg_gen_mov_tl(cpu_gpr[reg], t);
1207 }
1208 }
1209
1210 #if defined(TARGET_MIPS64)
gen_load_gpr_hi(TCGv_i64 t,int reg)1211 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1212 {
1213 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr_hi));
1214 if (reg == 0) {
1215 tcg_gen_movi_i64(t, 0);
1216 } else {
1217 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1218 }
1219 }
1220
gen_store_gpr_hi(TCGv_i64 t,int reg)1221 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1222 {
1223 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr_hi));
1224 if (reg != 0) {
1225 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1226 }
1227 }
1228 #endif /* TARGET_MIPS64 */
1229
1230 /* Moves to/from shadow registers. */
gen_load_srsgpr(int from,int to)1231 static inline void gen_load_srsgpr(int from, int to)
1232 {
1233 TCGv t0 = tcg_temp_new();
1234
1235 if (from == 0) {
1236 tcg_gen_movi_tl(t0, 0);
1237 } else {
1238 TCGv_i32 t2 = tcg_temp_new_i32();
1239 TCGv_ptr addr = tcg_temp_new_ptr();
1240
1241 tcg_gen_ld_i32(t2, tcg_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1242 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1243 tcg_gen_andi_i32(t2, t2, 0xf);
1244 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1245 tcg_gen_ext_i32_ptr(addr, t2);
1246 tcg_gen_add_ptr(addr, tcg_env, addr);
1247
1248 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1249 }
1250 gen_store_gpr(t0, to);
1251 }
1252
gen_store_srsgpr(int from,int to)1253 static inline void gen_store_srsgpr(int from, int to)
1254 {
1255 if (to != 0) {
1256 TCGv t0 = tcg_temp_new();
1257 TCGv_i32 t2 = tcg_temp_new_i32();
1258 TCGv_ptr addr = tcg_temp_new_ptr();
1259
1260 gen_load_gpr(t0, from);
1261 tcg_gen_ld_i32(t2, tcg_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1262 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1263 tcg_gen_andi_i32(t2, t2, 0xf);
1264 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1265 tcg_gen_ext_i32_ptr(addr, t2);
1266 tcg_gen_add_ptr(addr, tcg_env, addr);
1267
1268 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1269 }
1270 }
1271
1272 /* Tests */
gen_save_pc(target_ulong pc)1273 static inline void gen_save_pc(target_ulong pc)
1274 {
1275 tcg_gen_movi_tl(cpu_PC, pc);
1276 }
1277
save_cpu_state(DisasContext * ctx,int do_save_pc)1278 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1279 {
1280 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1281 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1282 gen_save_pc(ctx->base.pc_next);
1283 ctx->saved_pc = ctx->base.pc_next;
1284 }
1285 if (ctx->hflags != ctx->saved_hflags) {
1286 tcg_gen_movi_i32(hflags, ctx->hflags);
1287 ctx->saved_hflags = ctx->hflags;
1288 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1289 case MIPS_HFLAG_BR:
1290 break;
1291 case MIPS_HFLAG_BC:
1292 case MIPS_HFLAG_BL:
1293 case MIPS_HFLAG_B:
1294 tcg_gen_movi_tl(btarget, ctx->btarget);
1295 break;
1296 }
1297 }
1298 }
1299
restore_cpu_state(CPUMIPSState * env,DisasContext * ctx)1300 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1301 {
1302 ctx->saved_hflags = ctx->hflags;
1303 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1304 case MIPS_HFLAG_BR:
1305 break;
1306 case MIPS_HFLAG_BC:
1307 case MIPS_HFLAG_BL:
1308 case MIPS_HFLAG_B:
1309 ctx->btarget = env->btarget;
1310 break;
1311 }
1312 }
1313
generate_exception_err(DisasContext * ctx,int excp,int err)1314 void generate_exception_err(DisasContext *ctx, int excp, int err)
1315 {
1316 save_cpu_state(ctx, 1);
1317 gen_helper_raise_exception_err(tcg_env, tcg_constant_i32(excp),
1318 tcg_constant_i32(err));
1319 ctx->base.is_jmp = DISAS_NORETURN;
1320 }
1321
generate_exception(DisasContext * ctx,int excp)1322 void generate_exception(DisasContext *ctx, int excp)
1323 {
1324 gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
1325 }
1326
generate_exception_end(DisasContext * ctx,int excp)1327 void generate_exception_end(DisasContext *ctx, int excp)
1328 {
1329 generate_exception_err(ctx, excp, 0);
1330 }
1331
generate_exception_break(DisasContext * ctx,int code)1332 void generate_exception_break(DisasContext *ctx, int code)
1333 {
1334 #ifdef CONFIG_USER_ONLY
1335 /* Pass the break code along to cpu_loop. */
1336 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
1337 offsetof(CPUMIPSState, error_code));
1338 #endif
1339 generate_exception_end(ctx, EXCP_BREAK);
1340 }
1341
gen_reserved_instruction(DisasContext * ctx)1342 void gen_reserved_instruction(DisasContext *ctx)
1343 {
1344 generate_exception_end(ctx, EXCP_RI);
1345 }
1346
1347 /* Floating point register moves. */
gen_load_fpr32(DisasContext * ctx,TCGv_i32 t,int reg)1348 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1349 {
1350 if (ctx->hflags & MIPS_HFLAG_FRE) {
1351 generate_exception(ctx, EXCP_RI);
1352 }
1353 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1354 }
1355
gen_store_fpr32(DisasContext * ctx,TCGv_i32 t,int reg)1356 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1357 {
1358 TCGv_i64 t64;
1359 if (ctx->hflags & MIPS_HFLAG_FRE) {
1360 generate_exception(ctx, EXCP_RI);
1361 }
1362 t64 = tcg_temp_new_i64();
1363 tcg_gen_extu_i32_i64(t64, t);
1364 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1365 }
1366
gen_load_fpr32h(DisasContext * ctx,TCGv_i32 t,int reg)1367 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1368 {
1369 if (ctx->hflags & MIPS_HFLAG_F64) {
1370 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1371 } else {
1372 gen_load_fpr32(ctx, t, reg | 1);
1373 }
1374 }
1375
gen_store_fpr32h(DisasContext * ctx,TCGv_i32 t,int reg)1376 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1377 {
1378 if (ctx->hflags & MIPS_HFLAG_F64) {
1379 TCGv_i64 t64 = tcg_temp_new_i64();
1380 tcg_gen_extu_i32_i64(t64, t);
1381 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1382 } else {
1383 gen_store_fpr32(ctx, t, reg | 1);
1384 }
1385 }
1386
gen_load_fpr64(DisasContext * ctx,TCGv_i64 t,int reg)1387 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1388 {
1389 if (ctx->hflags & MIPS_HFLAG_F64) {
1390 tcg_gen_mov_i64(t, fpu_f64[reg]);
1391 } else {
1392 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1393 }
1394 }
1395
gen_store_fpr64(DisasContext * ctx,TCGv_i64 t,int reg)1396 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1397 {
1398 if (ctx->hflags & MIPS_HFLAG_F64) {
1399 tcg_gen_mov_i64(fpu_f64[reg], t);
1400 } else {
1401 TCGv_i64 t0;
1402 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1403 t0 = tcg_temp_new_i64();
1404 tcg_gen_shri_i64(t0, t, 32);
1405 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1406 }
1407 }
1408
get_fp_bit(int cc)1409 int get_fp_bit(int cc)
1410 {
1411 if (cc) {
1412 return 24 + cc;
1413 } else {
1414 return 23;
1415 }
1416 }
1417
1418 /* Addresses computation */
gen_op_addr_add(DisasContext * ctx,TCGv ret,TCGv arg0,TCGv arg1)1419 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1420 {
1421 tcg_gen_add_tl(ret, arg0, arg1);
1422
1423 #if defined(TARGET_MIPS64)
1424 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1425 tcg_gen_ext32s_i64(ret, ret);
1426 }
1427 #endif
1428 }
1429
gen_op_addr_addi(DisasContext * ctx,TCGv ret,TCGv base,target_long ofs)1430 void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, target_long ofs)
1431 {
1432 tcg_gen_addi_tl(ret, base, ofs);
1433
1434 #if defined(TARGET_MIPS64)
1435 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1436 tcg_gen_ext32s_i64(ret, ret);
1437 }
1438 #endif
1439 }
1440
1441 /* Addresses computation (translation time) */
addr_add(DisasContext * ctx,target_long base,target_long offset)1442 static target_long addr_add(DisasContext *ctx, target_long base,
1443 target_long offset)
1444 {
1445 target_long sum = base + offset;
1446
1447 #if defined(TARGET_MIPS64)
1448 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1449 sum = (int32_t)sum;
1450 }
1451 #endif
1452 return sum;
1453 }
1454
1455 /* Sign-extract the low 32-bits to a target_long. */
gen_move_low32(TCGv ret,TCGv_i64 arg)1456 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1457 {
1458 #if defined(TARGET_MIPS64)
1459 tcg_gen_ext32s_i64(ret, arg);
1460 #else
1461 tcg_gen_extrl_i64_i32(ret, arg);
1462 #endif
1463 }
1464
1465 /* Sign-extract the high 32-bits to a target_long. */
gen_move_high32(TCGv ret,TCGv_i64 arg)1466 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1467 {
1468 #if defined(TARGET_MIPS64)
1469 tcg_gen_sari_i64(ret, arg, 32);
1470 #else
1471 tcg_gen_extrh_i64_i32(ret, arg);
1472 #endif
1473 }
1474
check_cp0_enabled(DisasContext * ctx)1475 bool check_cp0_enabled(DisasContext *ctx)
1476 {
1477 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1478 generate_exception_end(ctx, EXCP_CpU);
1479 return false;
1480 }
1481 return true;
1482 }
1483
check_cp1_enabled(DisasContext * ctx)1484 void check_cp1_enabled(DisasContext *ctx)
1485 {
1486 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1487 generate_exception_err(ctx, EXCP_CpU, 1);
1488 }
1489 }
1490
1491 /*
1492 * Verify that the processor is running with COP1X instructions enabled.
1493 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1494 * opcode tables.
1495 */
check_cop1x(DisasContext * ctx)1496 void check_cop1x(DisasContext *ctx)
1497 {
1498 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1499 gen_reserved_instruction(ctx);
1500 }
1501 }
1502
1503 /*
1504 * Verify that the processor is running with 64-bit floating-point
1505 * operations enabled.
1506 */
check_cp1_64bitmode(DisasContext * ctx)1507 void check_cp1_64bitmode(DisasContext *ctx)
1508 {
1509 if (unlikely(~ctx->hflags & MIPS_HFLAG_F64)) {
1510 gen_reserved_instruction(ctx);
1511 }
1512 }
1513
1514 /*
1515 * Verify if floating point register is valid; an operation is not defined
1516 * if bit 0 of any register specification is set and the FR bit in the
1517 * Status register equals zero, since the register numbers specify an
1518 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1519 * in the Status register equals one, both even and odd register numbers
1520 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1521 *
1522 * Multiple 64 bit wide registers can be checked by calling
1523 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1524 */
check_cp1_registers(DisasContext * ctx,int regs)1525 void check_cp1_registers(DisasContext *ctx, int regs)
1526 {
1527 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1528 gen_reserved_instruction(ctx);
1529 }
1530 }
1531
1532 /*
1533 * Verify that the processor is running with DSP instructions enabled.
1534 * This is enabled by CP0 Status register MX(24) bit.
1535 */
check_dsp(DisasContext * ctx)1536 static inline void check_dsp(DisasContext *ctx)
1537 {
1538 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1539 if (ctx->insn_flags & ASE_DSP) {
1540 generate_exception_end(ctx, EXCP_DSPDIS);
1541 } else {
1542 gen_reserved_instruction(ctx);
1543 }
1544 }
1545 }
1546
check_dsp_r2(DisasContext * ctx)1547 static inline void check_dsp_r2(DisasContext *ctx)
1548 {
1549 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1550 if (ctx->insn_flags & ASE_DSP) {
1551 generate_exception_end(ctx, EXCP_DSPDIS);
1552 } else {
1553 gen_reserved_instruction(ctx);
1554 }
1555 }
1556 }
1557
check_dsp_r3(DisasContext * ctx)1558 static inline void check_dsp_r3(DisasContext *ctx)
1559 {
1560 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1561 if (ctx->insn_flags & ASE_DSP) {
1562 generate_exception_end(ctx, EXCP_DSPDIS);
1563 } else {
1564 gen_reserved_instruction(ctx);
1565 }
1566 }
1567 }
1568
1569 /*
1570 * This code generates a "reserved instruction" exception if the
1571 * CPU does not support the instruction set corresponding to flags.
1572 */
check_insn(DisasContext * ctx,uint64_t flags)1573 void check_insn(DisasContext *ctx, uint64_t flags)
1574 {
1575 if (unlikely(!(ctx->insn_flags & flags))) {
1576 gen_reserved_instruction(ctx);
1577 }
1578 }
1579
1580 /*
1581 * This code generates a "reserved instruction" exception if the
1582 * CPU has corresponding flag set which indicates that the instruction
1583 * has been removed.
1584 */
check_insn_opc_removed(DisasContext * ctx,uint64_t flags)1585 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1586 {
1587 if (unlikely(ctx->insn_flags & flags)) {
1588 gen_reserved_instruction(ctx);
1589 }
1590 }
1591
1592 /*
1593 * The Linux kernel traps certain reserved instruction exceptions to
1594 * emulate the corresponding instructions. QEMU is the kernel in user
1595 * mode, so those traps are emulated by accepting the instructions.
1596 *
1597 * A reserved instruction exception is generated for flagged CPUs if
1598 * QEMU runs in system mode.
1599 */
check_insn_opc_user_only(DisasContext * ctx,uint64_t flags)1600 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1601 {
1602 #ifndef CONFIG_USER_ONLY
1603 check_insn_opc_removed(ctx, flags);
1604 #endif
1605 }
1606
1607 /*
1608 * This code generates a "reserved instruction" exception if the
1609 * CPU does not support 64-bit paired-single (PS) floating point data type.
1610 */
check_ps(DisasContext * ctx)1611 static inline void check_ps(DisasContext *ctx)
1612 {
1613 if (unlikely(!ctx->ps)) {
1614 generate_exception(ctx, EXCP_RI);
1615 }
1616 check_cp1_64bitmode(ctx);
1617 }
1618
decode_64bit_enabled(DisasContext * ctx)1619 bool decode_64bit_enabled(DisasContext *ctx)
1620 {
1621 return ctx->hflags & MIPS_HFLAG_64;
1622 }
1623
1624 /*
1625 * This code generates a "reserved instruction" exception if cpu is not
1626 * 64-bit or 64-bit instructions are not enabled.
1627 */
check_mips_64(DisasContext * ctx)1628 void check_mips_64(DisasContext *ctx)
1629 {
1630 if (unlikely((TARGET_LONG_BITS != 64) || !decode_64bit_enabled(ctx))) {
1631 gen_reserved_instruction(ctx);
1632 }
1633 }
1634
1635 #ifndef CONFIG_USER_ONLY
check_mvh(DisasContext * ctx)1636 static inline void check_mvh(DisasContext *ctx)
1637 {
1638 if (unlikely(!ctx->mvh)) {
1639 generate_exception(ctx, EXCP_RI);
1640 }
1641 }
1642 #endif
1643
1644 /*
1645 * This code generates a "reserved instruction" exception if the
1646 * Config5 XNP bit is set.
1647 */
check_xnp(DisasContext * ctx)1648 static inline void check_xnp(DisasContext *ctx)
1649 {
1650 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1651 gen_reserved_instruction(ctx);
1652 }
1653 }
1654
1655 #ifndef CONFIG_USER_ONLY
1656 /*
1657 * This code generates a "reserved instruction" exception if the
1658 * Config3 PW bit is NOT set.
1659 */
check_pw(DisasContext * ctx)1660 static inline void check_pw(DisasContext *ctx)
1661 {
1662 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1663 gen_reserved_instruction(ctx);
1664 }
1665 }
1666 #endif
1667
1668 /*
1669 * This code generates a "reserved instruction" exception if the
1670 * Config3 MT bit is NOT set.
1671 */
check_mt(DisasContext * ctx)1672 static inline void check_mt(DisasContext *ctx)
1673 {
1674 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1675 gen_reserved_instruction(ctx);
1676 }
1677 }
1678
1679 #ifndef CONFIG_USER_ONLY
1680 /*
1681 * This code generates a "coprocessor unusable" exception if CP0 is not
1682 * available, and, if that is not the case, generates a "reserved instruction"
1683 * exception if the Config5 MT bit is NOT set. This is needed for availability
1684 * control of some of MT ASE instructions.
1685 */
check_cp0_mt(DisasContext * ctx)1686 static inline void check_cp0_mt(DisasContext *ctx)
1687 {
1688 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1689 generate_exception_end(ctx, EXCP_CpU);
1690 } else {
1691 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1692 gen_reserved_instruction(ctx);
1693 }
1694 }
1695 }
1696 #endif
1697
1698 /*
1699 * This code generates a "reserved instruction" exception if the
1700 * Config5 NMS bit is set.
1701 */
check_nms(DisasContext * ctx)1702 static inline void check_nms(DisasContext *ctx)
1703 {
1704 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1705 gen_reserved_instruction(ctx);
1706 }
1707 }
1708
1709 /*
1710 * This code generates a "reserved instruction" exception if the
1711 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1712 * Config2 TL, and Config5 L2C are unset.
1713 */
check_nms_dl_il_sl_tl_l2c(DisasContext * ctx)1714 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1715 {
1716 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1717 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1718 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1719 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1720 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1721 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1722 gen_reserved_instruction(ctx);
1723 }
1724 }
1725
1726 /*
1727 * This code generates a "reserved instruction" exception if the
1728 * Config5 EVA bit is NOT set.
1729 */
check_eva(DisasContext * ctx)1730 static inline void check_eva(DisasContext *ctx)
1731 {
1732 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1733 gen_reserved_instruction(ctx);
1734 }
1735 }
1736
1737
1738 /*
1739 * Define small wrappers for gen_load_fpr* so that we have a uniform
1740 * calling interface for 32 and 64-bit FPRs. No sense in changing
1741 * all callers for gen_load_fpr32 when we need the CTX parameter for
1742 * this one use.
1743 */
1744 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1745 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1746 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1747 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1748 int ft, int fs, int cc) \
1749 { \
1750 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1751 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
1752 switch (ifmt) { \
1753 case FMT_PS: \
1754 check_ps(ctx); \
1755 break; \
1756 case FMT_D: \
1757 if (abs) { \
1758 check_cop1x(ctx); \
1759 } \
1760 check_cp1_registers(ctx, fs | ft); \
1761 break; \
1762 case FMT_S: \
1763 if (abs) { \
1764 check_cop1x(ctx); \
1765 } \
1766 break; \
1767 } \
1768 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1769 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
1770 switch (n) { \
1771 case 0: \
1772 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1773 break; \
1774 case 1: \
1775 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1776 break; \
1777 case 2: \
1778 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1779 break; \
1780 case 3: \
1781 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1782 break; \
1783 case 4: \
1784 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1785 break; \
1786 case 5: \
1787 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1788 break; \
1789 case 6: \
1790 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1791 break; \
1792 case 7: \
1793 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1794 break; \
1795 case 8: \
1796 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1797 break; \
1798 case 9: \
1799 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1800 break; \
1801 case 10: \
1802 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1803 break; \
1804 case 11: \
1805 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1806 break; \
1807 case 12: \
1808 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1809 break; \
1810 case 13: \
1811 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1812 break; \
1813 case 14: \
1814 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1815 break; \
1816 case 15: \
1817 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1818 break; \
1819 default: \
1820 abort(); \
1821 } \
1822 }
1823
1824 FOP_CONDS(, 0, d, FMT_D, 64)
1825 FOP_CONDS(abs, 1, d, FMT_D, 64)
1826 FOP_CONDS(, 0, s, FMT_S, 32)
1827 FOP_CONDS(abs, 1, s, FMT_S, 32)
1828 FOP_CONDS(, 0, ps, FMT_PS, 64)
1829 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1830 #undef FOP_CONDS
1831
1832 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1833 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
1834 int ft, int fs, int fd) \
1835 { \
1836 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1837 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1838 if (ifmt == FMT_D) { \
1839 check_cp1_registers(ctx, fs | ft | fd); \
1840 } \
1841 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1842 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1843 switch (n) { \
1844 case 0: \
1845 gen_helper_r6_cmp_ ## fmt ## _af(fp0, tcg_env, fp0, fp1); \
1846 break; \
1847 case 1: \
1848 gen_helper_r6_cmp_ ## fmt ## _un(fp0, tcg_env, fp0, fp1); \
1849 break; \
1850 case 2: \
1851 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, tcg_env, fp0, fp1); \
1852 break; \
1853 case 3: \
1854 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, tcg_env, fp0, fp1); \
1855 break; \
1856 case 4: \
1857 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, tcg_env, fp0, fp1); \
1858 break; \
1859 case 5: \
1860 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, tcg_env, fp0, fp1); \
1861 break; \
1862 case 6: \
1863 gen_helper_r6_cmp_ ## fmt ## _le(fp0, tcg_env, fp0, fp1); \
1864 break; \
1865 case 7: \
1866 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, tcg_env, fp0, fp1); \
1867 break; \
1868 case 8: \
1869 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, tcg_env, fp0, fp1); \
1870 break; \
1871 case 9: \
1872 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, tcg_env, fp0, fp1); \
1873 break; \
1874 case 10: \
1875 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, tcg_env, fp0, fp1); \
1876 break; \
1877 case 11: \
1878 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, tcg_env, fp0, fp1); \
1879 break; \
1880 case 12: \
1881 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, tcg_env, fp0, fp1); \
1882 break; \
1883 case 13: \
1884 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, tcg_env, fp0, fp1); \
1885 break; \
1886 case 14: \
1887 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, tcg_env, fp0, fp1); \
1888 break; \
1889 case 15: \
1890 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, tcg_env, fp0, fp1); \
1891 break; \
1892 case 17: \
1893 gen_helper_r6_cmp_ ## fmt ## _or(fp0, tcg_env, fp0, fp1); \
1894 break; \
1895 case 18: \
1896 gen_helper_r6_cmp_ ## fmt ## _une(fp0, tcg_env, fp0, fp1); \
1897 break; \
1898 case 19: \
1899 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, tcg_env, fp0, fp1); \
1900 break; \
1901 case 25: \
1902 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, tcg_env, fp0, fp1); \
1903 break; \
1904 case 26: \
1905 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, tcg_env, fp0, fp1); \
1906 break; \
1907 case 27: \
1908 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, tcg_env, fp0, fp1); \
1909 break; \
1910 default: \
1911 abort(); \
1912 } \
1913 STORE; \
1914 }
1915
1916 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1917 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
1918 #undef FOP_CONDNS
1919 #undef gen_ldcmp_fpr32
1920 #undef gen_ldcmp_fpr64
1921
1922 /* load/store instructions. */
1923 #ifdef CONFIG_USER_ONLY
1924 #define OP_LD_ATOMIC(insn, memop) \
1925 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1926 DisasContext *ctx) \
1927 { \
1928 TCGv t0 = tcg_temp_new(); \
1929 tcg_gen_mov_tl(t0, arg1); \
1930 tcg_gen_qemu_ld_tl(ret, arg1, ctx->mem_idx, memop); \
1931 tcg_gen_st_tl(t0, tcg_env, offsetof(CPUMIPSState, lladdr)); \
1932 tcg_gen_st_tl(ret, tcg_env, offsetof(CPUMIPSState, llval)); \
1933 }
1934 #else
1935 #define OP_LD_ATOMIC(insn, ignored_memop) \
1936 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1937 DisasContext *ctx) \
1938 { \
1939 gen_helper_##insn(ret, tcg_env, arg1, tcg_constant_i32(mem_idx)); \
1940 }
1941 #endif
1942 OP_LD_ATOMIC(ll, mo_endian(ctx) | MO_SL);
1943 #if defined(TARGET_MIPS64)
1944 OP_LD_ATOMIC(lld, mo_endian(ctx) | MO_UQ);
1945 #endif
1946 #undef OP_LD_ATOMIC
1947
gen_base_offset_addr(DisasContext * ctx,TCGv addr,int base,int offset)1948 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
1949 {
1950 if (base == 0) {
1951 tcg_gen_movi_tl(addr, offset);
1952 } else if (offset == 0) {
1953 gen_load_gpr(addr, base);
1954 } else {
1955 tcg_gen_movi_tl(addr, offset);
1956 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1957 }
1958 }
1959
pc_relative_pc(DisasContext * ctx)1960 static target_ulong pc_relative_pc(DisasContext *ctx)
1961 {
1962 target_ulong pc = ctx->base.pc_next;
1963
1964 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1965 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1966
1967 pc -= branch_bytes;
1968 }
1969
1970 pc &= ~(target_ulong)3;
1971 return pc;
1972 }
1973
1974 /* LWL or LDL, depending on MemOp. */
gen_lxl(DisasContext * ctx,TCGv reg,TCGv addr,int mem_idx,MemOp mop)1975 static void gen_lxl(DisasContext *ctx, TCGv reg, TCGv addr,
1976 int mem_idx, MemOp mop)
1977 {
1978 int sizem1 = memop_size(mop) - 1;
1979 TCGv t0 = tcg_temp_new();
1980 TCGv t1 = tcg_temp_new();
1981
1982 /*
1983 * Do a byte access to possibly trigger a page
1984 * fault with the unaligned address.
1985 */
1986 tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
1987 tcg_gen_andi_tl(t1, addr, sizem1);
1988 if (!disas_is_bigendian(ctx)) {
1989 tcg_gen_xori_tl(t1, t1, sizem1);
1990 }
1991 tcg_gen_shli_tl(t1, t1, 3);
1992 tcg_gen_andi_tl(t0, addr, ~sizem1);
1993 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mop);
1994 tcg_gen_shl_tl(t0, t0, t1);
1995 tcg_gen_shl_tl(t1, tcg_constant_tl(-1), t1);
1996 tcg_gen_andc_tl(t1, reg, t1);
1997 tcg_gen_or_tl(reg, t0, t1);
1998 }
1999
2000 /* LWR or LDR, depending on MemOp. */
gen_lxr(DisasContext * ctx,TCGv reg,TCGv addr,int mem_idx,MemOp mop)2001 static void gen_lxr(DisasContext *ctx, TCGv reg, TCGv addr,
2002 int mem_idx, MemOp mop)
2003 {
2004 int size = memop_size(mop);
2005 int sizem1 = size - 1;
2006 TCGv t0 = tcg_temp_new();
2007 TCGv t1 = tcg_temp_new();
2008
2009 /*
2010 * Do a byte access to possibly trigger a page
2011 * fault with the unaligned address.
2012 */
2013 tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
2014 tcg_gen_andi_tl(t1, addr, sizem1);
2015 if (disas_is_bigendian(ctx)) {
2016 tcg_gen_xori_tl(t1, t1, sizem1);
2017 }
2018 tcg_gen_shli_tl(t1, t1, 3);
2019 tcg_gen_andi_tl(t0, addr, ~sizem1);
2020 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mop);
2021 tcg_gen_shr_tl(t0, t0, t1);
2022 tcg_gen_xori_tl(t1, t1, size * 8 - 1);
2023 tcg_gen_shl_tl(t1, tcg_constant_tl(~1), t1);
2024 tcg_gen_and_tl(t1, reg, t1);
2025 tcg_gen_or_tl(reg, t0, t1);
2026 }
2027
2028 /* Load */
gen_ld(DisasContext * ctx,uint32_t opc,int rt,int base,int offset)2029 static void gen_ld(DisasContext *ctx, uint32_t opc,
2030 int rt, int base, int offset)
2031 {
2032 TCGv t0, t1;
2033 int mem_idx = ctx->mem_idx;
2034
2035 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2036 INSN_LOONGSON3A)) {
2037 /*
2038 * Loongson CPU uses a load to zero register for prefetch.
2039 * We emulate it as a NOP. On other CPU we must perform the
2040 * actual memory access.
2041 */
2042 return;
2043 }
2044
2045 t0 = tcg_temp_new();
2046 gen_base_offset_addr(ctx, t0, base, offset);
2047
2048 switch (opc) {
2049 #if defined(TARGET_MIPS64)
2050 case OPC_LWU:
2051 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UL |
2052 ctx->default_tcg_memop_mask);
2053 gen_store_gpr(t0, rt);
2054 break;
2055 case OPC_LD:
2056 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UQ |
2057 ctx->default_tcg_memop_mask);
2058 gen_store_gpr(t0, rt);
2059 break;
2060 case OPC_LLD:
2061 case R6_OPC_LLD:
2062 op_ld_lld(t0, t0, mem_idx, ctx);
2063 gen_store_gpr(t0, rt);
2064 break;
2065 case OPC_LDL:
2066 t1 = tcg_temp_new();
2067 gen_load_gpr(t1, rt);
2068 gen_lxl(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UQ);
2069 gen_store_gpr(t1, rt);
2070 break;
2071 case OPC_LDR:
2072 t1 = tcg_temp_new();
2073 gen_load_gpr(t1, rt);
2074 gen_lxr(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UQ);
2075 gen_store_gpr(t1, rt);
2076 break;
2077 case OPC_LDPC:
2078 t1 = tcg_constant_tl(pc_relative_pc(ctx));
2079 gen_op_addr_add(ctx, t0, t0, t1);
2080 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UQ);
2081 gen_store_gpr(t0, rt);
2082 break;
2083 #endif
2084 case OPC_LWPC:
2085 t1 = tcg_constant_tl(pc_relative_pc(ctx));
2086 gen_op_addr_add(ctx, t0, t0, t1);
2087 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SL);
2088 gen_store_gpr(t0, rt);
2089 break;
2090 case OPC_LWE:
2091 mem_idx = MIPS_HFLAG_UM;
2092 /* fall through */
2093 case OPC_LW:
2094 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SL |
2095 ctx->default_tcg_memop_mask);
2096 gen_store_gpr(t0, rt);
2097 break;
2098 case OPC_LHE:
2099 mem_idx = MIPS_HFLAG_UM;
2100 /* fall through */
2101 case OPC_LH:
2102 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SW |
2103 ctx->default_tcg_memop_mask);
2104 gen_store_gpr(t0, rt);
2105 break;
2106 case OPC_LHUE:
2107 mem_idx = MIPS_HFLAG_UM;
2108 /* fall through */
2109 case OPC_LHU:
2110 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UW |
2111 ctx->default_tcg_memop_mask);
2112 gen_store_gpr(t0, rt);
2113 break;
2114 case OPC_LBE:
2115 mem_idx = MIPS_HFLAG_UM;
2116 /* fall through */
2117 case OPC_LB:
2118 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2119 gen_store_gpr(t0, rt);
2120 break;
2121 case OPC_LBUE:
2122 mem_idx = MIPS_HFLAG_UM;
2123 /* fall through */
2124 case OPC_LBU:
2125 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2126 gen_store_gpr(t0, rt);
2127 break;
2128 case OPC_LWLE:
2129 mem_idx = MIPS_HFLAG_UM;
2130 /* fall through */
2131 case OPC_LWL:
2132 t1 = tcg_temp_new();
2133 gen_load_gpr(t1, rt);
2134 gen_lxl(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UL);
2135 tcg_gen_ext32s_tl(t1, t1);
2136 gen_store_gpr(t1, rt);
2137 break;
2138 case OPC_LWRE:
2139 mem_idx = MIPS_HFLAG_UM;
2140 /* fall through */
2141 case OPC_LWR:
2142 t1 = tcg_temp_new();
2143 gen_load_gpr(t1, rt);
2144 gen_lxr(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UL);
2145 tcg_gen_ext32s_tl(t1, t1);
2146 gen_store_gpr(t1, rt);
2147 break;
2148 case OPC_LLE:
2149 mem_idx = MIPS_HFLAG_UM;
2150 /* fall through */
2151 case OPC_LL:
2152 case R6_OPC_LL:
2153 op_ld_ll(t0, t0, mem_idx, ctx);
2154 gen_store_gpr(t0, rt);
2155 break;
2156 }
2157 }
2158
2159 /* Store */
gen_st(DisasContext * ctx,uint32_t opc,int rt,int base,int offset)2160 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2161 int base, int offset)
2162 {
2163 TCGv t0 = tcg_temp_new();
2164 TCGv t1 = tcg_temp_new();
2165 int mem_idx = ctx->mem_idx;
2166
2167 gen_base_offset_addr(ctx, t0, base, offset);
2168 gen_load_gpr(t1, rt);
2169 switch (opc) {
2170 #if defined(TARGET_MIPS64)
2171 case OPC_SD:
2172 tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UQ |
2173 ctx->default_tcg_memop_mask);
2174 break;
2175 case OPC_SDL:
2176 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2177 break;
2178 case OPC_SDR:
2179 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2180 break;
2181 #endif
2182 case OPC_SWE:
2183 mem_idx = MIPS_HFLAG_UM;
2184 /* fall through */
2185 case OPC_SW:
2186 tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UL |
2187 ctx->default_tcg_memop_mask);
2188 break;
2189 case OPC_SHE:
2190 mem_idx = MIPS_HFLAG_UM;
2191 /* fall through */
2192 case OPC_SH:
2193 tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UW |
2194 ctx->default_tcg_memop_mask);
2195 break;
2196 case OPC_SBE:
2197 mem_idx = MIPS_HFLAG_UM;
2198 /* fall through */
2199 case OPC_SB:
2200 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2201 break;
2202 case OPC_SWLE:
2203 mem_idx = MIPS_HFLAG_UM;
2204 /* fall through */
2205 case OPC_SWL:
2206 gen_helper_0e2i(swl, t1, t0, mem_idx);
2207 break;
2208 case OPC_SWRE:
2209 mem_idx = MIPS_HFLAG_UM;
2210 /* fall through */
2211 case OPC_SWR:
2212 gen_helper_0e2i(swr, t1, t0, mem_idx);
2213 break;
2214 }
2215 }
2216
2217
2218 /* Store conditional */
gen_st_cond(DisasContext * ctx,int rt,int base,int offset,MemOp tcg_mo,bool eva)2219 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2220 MemOp tcg_mo, bool eva)
2221 {
2222 TCGv addr, t0, val;
2223 TCGLabel *l1 = gen_new_label();
2224 TCGLabel *done = gen_new_label();
2225
2226 t0 = tcg_temp_new();
2227 addr = tcg_temp_new();
2228 /* compare the address against that of the preceding LL */
2229 gen_base_offset_addr(ctx, addr, base, offset);
2230 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2231 gen_store_gpr(tcg_constant_tl(0), rt);
2232 tcg_gen_br(done);
2233
2234 gen_set_label(l1);
2235 /* generate cmpxchg */
2236 val = tcg_temp_new();
2237 gen_load_gpr(val, rt);
2238 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2239 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2240 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2241 gen_store_gpr(t0, rt);
2242
2243 gen_set_label(done);
2244 }
2245
2246 /* Load and store */
gen_flt_ldst(DisasContext * ctx,uint32_t opc,int ft,TCGv t0)2247 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2248 TCGv t0)
2249 {
2250 /*
2251 * Don't do NOP if destination is zero: we must perform the actual
2252 * memory access.
2253 */
2254 switch (opc) {
2255 case OPC_LWC1:
2256 {
2257 TCGv_i32 fp0 = tcg_temp_new_i32();
2258 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
2259 ctx->default_tcg_memop_mask);
2260 gen_store_fpr32(ctx, fp0, ft);
2261 }
2262 break;
2263 case OPC_SWC1:
2264 {
2265 TCGv_i32 fp0 = tcg_temp_new_i32();
2266 gen_load_fpr32(ctx, fp0, ft);
2267 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
2268 ctx->default_tcg_memop_mask);
2269 }
2270 break;
2271 case OPC_LDC1:
2272 {
2273 TCGv_i64 fp0 = tcg_temp_new_i64();
2274 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
2275 ctx->default_tcg_memop_mask);
2276 gen_store_fpr64(ctx, fp0, ft);
2277 }
2278 break;
2279 case OPC_SDC1:
2280 {
2281 TCGv_i64 fp0 = tcg_temp_new_i64();
2282 gen_load_fpr64(ctx, fp0, ft);
2283 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
2284 ctx->default_tcg_memop_mask);
2285 }
2286 break;
2287 default:
2288 MIPS_INVAL("flt_ldst");
2289 gen_reserved_instruction(ctx);
2290 break;
2291 }
2292 }
2293
gen_cop1_ldst(DisasContext * ctx,uint32_t op,int rt,int rs,int16_t imm)2294 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2295 int rs, int16_t imm)
2296 {
2297 TCGv t0 = tcg_temp_new();
2298
2299 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2300 check_cp1_enabled(ctx);
2301 switch (op) {
2302 case OPC_LDC1:
2303 case OPC_SDC1:
2304 check_insn(ctx, ISA_MIPS2);
2305 /* Fallthrough */
2306 default:
2307 gen_base_offset_addr(ctx, t0, rs, imm);
2308 gen_flt_ldst(ctx, op, rt, t0);
2309 }
2310 } else {
2311 generate_exception_err(ctx, EXCP_CpU, 1);
2312 }
2313 }
2314
2315 /* Arithmetic with immediate operand */
gen_arith_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int imm)2316 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2317 int rt, int rs, int imm)
2318 {
2319 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2320
2321 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2322 /*
2323 * If no destination, treat it as a NOP.
2324 * For addi, we must generate the overflow exception when needed.
2325 */
2326 return;
2327 }
2328 switch (opc) {
2329 case OPC_ADDI:
2330 {
2331 TCGv t0 = tcg_temp_new();
2332 TCGv t1 = tcg_temp_new();
2333 TCGv t2 = tcg_temp_new();
2334 TCGLabel *l1 = gen_new_label();
2335
2336 gen_load_gpr(t1, rs);
2337 tcg_gen_addi_tl(t0, t1, uimm);
2338 tcg_gen_ext32s_tl(t0, t0);
2339
2340 tcg_gen_xori_tl(t1, t1, ~uimm);
2341 tcg_gen_xori_tl(t2, t0, uimm);
2342 tcg_gen_and_tl(t1, t1, t2);
2343 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2344 /* operands of same sign, result different sign */
2345 generate_exception(ctx, EXCP_OVERFLOW);
2346 gen_set_label(l1);
2347 tcg_gen_ext32s_tl(t0, t0);
2348 gen_store_gpr(t0, rt);
2349 }
2350 break;
2351 case OPC_ADDIU:
2352 if (rs != 0) {
2353 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2354 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2355 } else {
2356 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2357 }
2358 break;
2359 #if defined(TARGET_MIPS64)
2360 case OPC_DADDI:
2361 {
2362 TCGv t0 = tcg_temp_new();
2363 TCGv t1 = tcg_temp_new();
2364 TCGv t2 = tcg_temp_new();
2365 TCGLabel *l1 = gen_new_label();
2366
2367 gen_load_gpr(t1, rs);
2368 tcg_gen_addi_tl(t0, t1, uimm);
2369
2370 tcg_gen_xori_tl(t1, t1, ~uimm);
2371 tcg_gen_xori_tl(t2, t0, uimm);
2372 tcg_gen_and_tl(t1, t1, t2);
2373 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2374 /* operands of same sign, result different sign */
2375 generate_exception(ctx, EXCP_OVERFLOW);
2376 gen_set_label(l1);
2377 gen_store_gpr(t0, rt);
2378 }
2379 break;
2380 case OPC_DADDIU:
2381 if (rs != 0) {
2382 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2383 } else {
2384 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2385 }
2386 break;
2387 #endif
2388 }
2389 }
2390
2391 /* Logic with immediate operand */
gen_logic_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int16_t imm)2392 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2393 int rt, int rs, int16_t imm)
2394 {
2395 target_ulong uimm;
2396
2397 if (rt == 0) {
2398 /* If no destination, treat it as a NOP. */
2399 return;
2400 }
2401 uimm = (uint16_t)imm;
2402 switch (opc) {
2403 case OPC_ANDI:
2404 if (likely(rs != 0)) {
2405 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2406 } else {
2407 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2408 }
2409 break;
2410 case OPC_ORI:
2411 if (rs != 0) {
2412 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2413 } else {
2414 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2415 }
2416 break;
2417 case OPC_XORI:
2418 if (likely(rs != 0)) {
2419 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2420 } else {
2421 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2422 }
2423 break;
2424 case OPC_LUI:
2425 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2426 /* OPC_AUI */
2427 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2428 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2429 } else {
2430 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2431 }
2432 break;
2433
2434 default:
2435 break;
2436 }
2437 }
2438
2439 /* Set on less than with immediate operand */
gen_slt_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int16_t imm)2440 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2441 int rt, int rs, int16_t imm)
2442 {
2443 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2444 TCGv t0;
2445
2446 if (rt == 0) {
2447 /* If no destination, treat it as a NOP. */
2448 return;
2449 }
2450 t0 = tcg_temp_new();
2451 gen_load_gpr(t0, rs);
2452 switch (opc) {
2453 case OPC_SLTI:
2454 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2455 break;
2456 case OPC_SLTIU:
2457 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2458 break;
2459 }
2460 }
2461
2462 /* Shifts with immediate operand */
gen_shift_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int16_t imm)2463 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2464 int rt, int rs, int16_t imm)
2465 {
2466 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2467 TCGv t0;
2468
2469 if (rt == 0) {
2470 /* If no destination, treat it as a NOP. */
2471 return;
2472 }
2473
2474 t0 = tcg_temp_new();
2475 gen_load_gpr(t0, rs);
2476 switch (opc) {
2477 case OPC_SLL:
2478 tcg_gen_shli_tl(t0, t0, uimm);
2479 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2480 break;
2481 case OPC_SRA:
2482 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2483 break;
2484 case OPC_SRL:
2485 if (uimm != 0) {
2486 tcg_gen_ext32u_tl(t0, t0);
2487 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2488 } else {
2489 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2490 }
2491 break;
2492 case OPC_ROTR:
2493 if (uimm != 0) {
2494 TCGv_i32 t1 = tcg_temp_new_i32();
2495
2496 tcg_gen_trunc_tl_i32(t1, t0);
2497 tcg_gen_rotri_i32(t1, t1, uimm);
2498 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2499 } else {
2500 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2501 }
2502 break;
2503 #if defined(TARGET_MIPS64)
2504 case OPC_DSLL:
2505 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2506 break;
2507 case OPC_DSRA:
2508 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2509 break;
2510 case OPC_DSRL:
2511 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2512 break;
2513 case OPC_DROTR:
2514 if (uimm != 0) {
2515 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2516 } else {
2517 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2518 }
2519 break;
2520 case OPC_DSLL32:
2521 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2522 break;
2523 case OPC_DSRA32:
2524 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2525 break;
2526 case OPC_DSRL32:
2527 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2528 break;
2529 case OPC_DROTR32:
2530 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2531 break;
2532 #endif
2533 }
2534 }
2535
2536 /* Arithmetic */
gen_arith(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2537 static void gen_arith(DisasContext *ctx, uint32_t opc,
2538 int rd, int rs, int rt)
2539 {
2540 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2541 && opc != OPC_DADD && opc != OPC_DSUB) {
2542 /*
2543 * If no destination, treat it as a NOP.
2544 * For add & sub, we must generate the overflow exception when needed.
2545 */
2546 return;
2547 }
2548
2549 switch (opc) {
2550 case OPC_ADD:
2551 {
2552 TCGv t0 = tcg_temp_new();
2553 TCGv t1 = tcg_temp_new();
2554 TCGv t2 = tcg_temp_new();
2555 TCGLabel *l1 = gen_new_label();
2556
2557 gen_load_gpr(t1, rs);
2558 gen_load_gpr(t2, rt);
2559 tcg_gen_add_tl(t0, t1, t2);
2560 tcg_gen_ext32s_tl(t0, t0);
2561 tcg_gen_xor_tl(t1, t1, t2);
2562 tcg_gen_xor_tl(t2, t0, t2);
2563 tcg_gen_andc_tl(t1, t2, t1);
2564 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2565 /* operands of same sign, result different sign */
2566 generate_exception(ctx, EXCP_OVERFLOW);
2567 gen_set_label(l1);
2568 gen_store_gpr(t0, rd);
2569 }
2570 break;
2571 case OPC_ADDU:
2572 if (rs != 0 && rt != 0) {
2573 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2574 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2575 } else if (rs == 0 && rt != 0) {
2576 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2577 } else if (rs != 0 && rt == 0) {
2578 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2579 } else {
2580 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2581 }
2582 break;
2583 case OPC_SUB:
2584 {
2585 TCGv t0 = tcg_temp_new();
2586 TCGv t1 = tcg_temp_new();
2587 TCGv t2 = tcg_temp_new();
2588 TCGLabel *l1 = gen_new_label();
2589
2590 gen_load_gpr(t1, rs);
2591 gen_load_gpr(t2, rt);
2592 tcg_gen_sub_tl(t0, t1, t2);
2593 tcg_gen_ext32s_tl(t0, t0);
2594 tcg_gen_xor_tl(t2, t1, t2);
2595 tcg_gen_xor_tl(t1, t0, t1);
2596 tcg_gen_and_tl(t1, t1, t2);
2597 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2598 /*
2599 * operands of different sign, first operand and the result
2600 * of different sign
2601 */
2602 generate_exception(ctx, EXCP_OVERFLOW);
2603 gen_set_label(l1);
2604 gen_store_gpr(t0, rd);
2605 }
2606 break;
2607 case OPC_SUBU:
2608 if (rs != 0 && rt != 0) {
2609 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2610 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2611 } else if (rs == 0 && rt != 0) {
2612 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2613 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2614 } else if (rs != 0 && rt == 0) {
2615 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2616 } else {
2617 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2618 }
2619 break;
2620 #if defined(TARGET_MIPS64)
2621 case OPC_DADD:
2622 {
2623 TCGv t0 = tcg_temp_new();
2624 TCGv t1 = tcg_temp_new();
2625 TCGv t2 = tcg_temp_new();
2626 TCGLabel *l1 = gen_new_label();
2627
2628 gen_load_gpr(t1, rs);
2629 gen_load_gpr(t2, rt);
2630 tcg_gen_add_tl(t0, t1, t2);
2631 tcg_gen_xor_tl(t1, t1, t2);
2632 tcg_gen_xor_tl(t2, t0, t2);
2633 tcg_gen_andc_tl(t1, t2, t1);
2634 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2635 /* operands of same sign, result different sign */
2636 generate_exception(ctx, EXCP_OVERFLOW);
2637 gen_set_label(l1);
2638 gen_store_gpr(t0, rd);
2639 }
2640 break;
2641 case OPC_DADDU:
2642 if (rs != 0 && rt != 0) {
2643 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2644 } else if (rs == 0 && rt != 0) {
2645 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2646 } else if (rs != 0 && rt == 0) {
2647 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2648 } else {
2649 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2650 }
2651 break;
2652 case OPC_DSUB:
2653 {
2654 TCGv t0 = tcg_temp_new();
2655 TCGv t1 = tcg_temp_new();
2656 TCGv t2 = tcg_temp_new();
2657 TCGLabel *l1 = gen_new_label();
2658
2659 gen_load_gpr(t1, rs);
2660 gen_load_gpr(t2, rt);
2661 tcg_gen_sub_tl(t0, t1, t2);
2662 tcg_gen_xor_tl(t2, t1, t2);
2663 tcg_gen_xor_tl(t1, t0, t1);
2664 tcg_gen_and_tl(t1, t1, t2);
2665 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2666 /*
2667 * Operands of different sign, first operand and result different
2668 * sign.
2669 */
2670 generate_exception(ctx, EXCP_OVERFLOW);
2671 gen_set_label(l1);
2672 gen_store_gpr(t0, rd);
2673 }
2674 break;
2675 case OPC_DSUBU:
2676 if (rs != 0 && rt != 0) {
2677 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2678 } else if (rs == 0 && rt != 0) {
2679 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2680 } else if (rs != 0 && rt == 0) {
2681 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2682 } else {
2683 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2684 }
2685 break;
2686 #endif
2687 case OPC_MUL:
2688 if (likely(rs != 0 && rt != 0)) {
2689 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2690 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2691 } else {
2692 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2693 }
2694 break;
2695 }
2696 }
2697
2698 /* Conditional move */
gen_cond_move(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2699 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2700 int rd, int rs, int rt)
2701 {
2702 TCGv t0, t1, t2;
2703
2704 if (rd == 0) {
2705 /* If no destination, treat it as a NOP. */
2706 return;
2707 }
2708
2709 t0 = tcg_temp_new();
2710 gen_load_gpr(t0, rt);
2711 t1 = tcg_constant_tl(0);
2712 t2 = tcg_temp_new();
2713 gen_load_gpr(t2, rs);
2714 switch (opc) {
2715 case OPC_MOVN:
2716 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2717 break;
2718 case OPC_MOVZ:
2719 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2720 break;
2721 case OPC_SELNEZ:
2722 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2723 break;
2724 case OPC_SELEQZ:
2725 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2726 break;
2727 }
2728 }
2729
2730 /* Logic */
gen_logic(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2731 static void gen_logic(DisasContext *ctx, uint32_t opc,
2732 int rd, int rs, int rt)
2733 {
2734 if (rd == 0) {
2735 /* If no destination, treat it as a NOP. */
2736 return;
2737 }
2738
2739 switch (opc) {
2740 case OPC_AND:
2741 if (likely(rs != 0 && rt != 0)) {
2742 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2743 } else {
2744 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2745 }
2746 break;
2747 case OPC_NOR:
2748 if (rs != 0 && rt != 0) {
2749 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2750 } else if (rs == 0 && rt != 0) {
2751 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2752 } else if (rs != 0 && rt == 0) {
2753 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2754 } else {
2755 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2756 }
2757 break;
2758 case OPC_OR:
2759 if (likely(rs != 0 && rt != 0)) {
2760 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2761 } else if (rs == 0 && rt != 0) {
2762 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2763 } else if (rs != 0 && rt == 0) {
2764 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2765 } else {
2766 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2767 }
2768 break;
2769 case OPC_XOR:
2770 if (likely(rs != 0 && rt != 0)) {
2771 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2772 } else if (rs == 0 && rt != 0) {
2773 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2774 } else if (rs != 0 && rt == 0) {
2775 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2776 } else {
2777 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2778 }
2779 break;
2780 }
2781 }
2782
2783 /* Set on lower than */
gen_slt(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2784 static void gen_slt(DisasContext *ctx, uint32_t opc,
2785 int rd, int rs, int rt)
2786 {
2787 TCGv t0, t1;
2788
2789 if (rd == 0) {
2790 /* If no destination, treat it as a NOP. */
2791 return;
2792 }
2793
2794 t0 = tcg_temp_new();
2795 t1 = tcg_temp_new();
2796 gen_load_gpr(t0, rs);
2797 gen_load_gpr(t1, rt);
2798 switch (opc) {
2799 case OPC_SLT:
2800 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2801 break;
2802 case OPC_SLTU:
2803 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2804 break;
2805 }
2806 }
2807
2808 /* Shifts */
gen_shift(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2809 static void gen_shift(DisasContext *ctx, uint32_t opc,
2810 int rd, int rs, int rt)
2811 {
2812 TCGv t0, t1;
2813
2814 if (rd == 0) {
2815 /*
2816 * If no destination, treat it as a NOP.
2817 * For add & sub, we must generate the overflow exception when needed.
2818 */
2819 return;
2820 }
2821
2822 t0 = tcg_temp_new();
2823 t1 = tcg_temp_new();
2824 gen_load_gpr(t0, rs);
2825 gen_load_gpr(t1, rt);
2826 switch (opc) {
2827 case OPC_SLLV:
2828 tcg_gen_andi_tl(t0, t0, 0x1f);
2829 tcg_gen_shl_tl(t0, t1, t0);
2830 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2831 break;
2832 case OPC_SRAV:
2833 tcg_gen_andi_tl(t0, t0, 0x1f);
2834 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2835 break;
2836 case OPC_SRLV:
2837 tcg_gen_ext32u_tl(t1, t1);
2838 tcg_gen_andi_tl(t0, t0, 0x1f);
2839 tcg_gen_shr_tl(t0, t1, t0);
2840 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2841 break;
2842 case OPC_ROTRV:
2843 {
2844 TCGv_i32 t2 = tcg_temp_new_i32();
2845 TCGv_i32 t3 = tcg_temp_new_i32();
2846
2847 tcg_gen_trunc_tl_i32(t2, t0);
2848 tcg_gen_trunc_tl_i32(t3, t1);
2849 tcg_gen_andi_i32(t2, t2, 0x1f);
2850 tcg_gen_rotr_i32(t2, t3, t2);
2851 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2852 }
2853 break;
2854 #if defined(TARGET_MIPS64)
2855 case OPC_DSLLV:
2856 tcg_gen_andi_tl(t0, t0, 0x3f);
2857 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2858 break;
2859 case OPC_DSRAV:
2860 tcg_gen_andi_tl(t0, t0, 0x3f);
2861 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2862 break;
2863 case OPC_DSRLV:
2864 tcg_gen_andi_tl(t0, t0, 0x3f);
2865 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2866 break;
2867 case OPC_DROTRV:
2868 tcg_gen_andi_tl(t0, t0, 0x3f);
2869 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2870 break;
2871 #endif
2872 }
2873 }
2874
2875 /* Arithmetic on HI/LO registers */
gen_HILO(DisasContext * ctx,uint32_t opc,int acc,int reg)2876 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2877 {
2878 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2879 /* Treat as NOP. */
2880 return;
2881 }
2882
2883 if (acc != 0) {
2884 check_dsp(ctx);
2885 }
2886
2887 switch (opc) {
2888 case OPC_MFHI:
2889 #if defined(TARGET_MIPS64)
2890 if (acc != 0) {
2891 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2892 } else
2893 #endif
2894 {
2895 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2896 }
2897 break;
2898 case OPC_MFLO:
2899 #if defined(TARGET_MIPS64)
2900 if (acc != 0) {
2901 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2902 } else
2903 #endif
2904 {
2905 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2906 }
2907 break;
2908 case OPC_MTHI:
2909 if (reg != 0) {
2910 #if defined(TARGET_MIPS64)
2911 if (acc != 0) {
2912 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2913 } else
2914 #endif
2915 {
2916 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2917 }
2918 } else {
2919 tcg_gen_movi_tl(cpu_HI[acc], 0);
2920 }
2921 break;
2922 case OPC_MTLO:
2923 if (reg != 0) {
2924 #if defined(TARGET_MIPS64)
2925 if (acc != 0) {
2926 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2927 } else
2928 #endif
2929 {
2930 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2931 }
2932 } else {
2933 tcg_gen_movi_tl(cpu_LO[acc], 0);
2934 }
2935 break;
2936 }
2937 }
2938
gen_r6_ld(target_long addr,int reg,int memidx,MemOp memop)2939 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
2940 MemOp memop)
2941 {
2942 TCGv t0 = tcg_temp_new();
2943 tcg_gen_qemu_ld_tl(t0, tcg_constant_tl(addr), memidx, memop);
2944 gen_store_gpr(t0, reg);
2945 }
2946
gen_pcrel(DisasContext * ctx,int opc,target_ulong pc,int rs)2947 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
2948 int rs)
2949 {
2950 target_long offset;
2951 target_long addr;
2952
2953 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
2954 case OPC_ADDIUPC:
2955 if (rs != 0) {
2956 offset = sextract32(ctx->opcode << 2, 0, 21);
2957 addr = addr_add(ctx, pc, offset);
2958 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2959 }
2960 break;
2961 case R6_OPC_LWPC:
2962 offset = sextract32(ctx->opcode << 2, 0, 21);
2963 addr = addr_add(ctx, pc, offset);
2964 gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_SL);
2965 break;
2966 #if defined(TARGET_MIPS64)
2967 case OPC_LWUPC:
2968 check_mips_64(ctx);
2969 offset = sextract32(ctx->opcode << 2, 0, 21);
2970 addr = addr_add(ctx, pc, offset);
2971 gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_UL);
2972 break;
2973 #endif
2974 default:
2975 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
2976 case OPC_AUIPC:
2977 if (rs != 0) {
2978 offset = sextract32(ctx->opcode, 0, 16) << 16;
2979 addr = addr_add(ctx, pc, offset);
2980 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2981 }
2982 break;
2983 case OPC_ALUIPC:
2984 if (rs != 0) {
2985 offset = sextract32(ctx->opcode, 0, 16) << 16;
2986 addr = ~0xFFFF & addr_add(ctx, pc, offset);
2987 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2988 }
2989 break;
2990 #if defined(TARGET_MIPS64)
2991 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
2992 case R6_OPC_LDPC + (1 << 16):
2993 case R6_OPC_LDPC + (2 << 16):
2994 case R6_OPC_LDPC + (3 << 16):
2995 check_mips_64(ctx);
2996 offset = sextract32(ctx->opcode << 3, 0, 21);
2997 addr = addr_add(ctx, (pc & ~0x7), offset);
2998 gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
2999 break;
3000 #endif
3001 default:
3002 MIPS_INVAL("OPC_PCREL");
3003 gen_reserved_instruction(ctx);
3004 break;
3005 }
3006 break;
3007 }
3008 }
3009
gen_r6_muldiv(DisasContext * ctx,int opc,int rd,int rs,int rt)3010 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3011 {
3012 TCGv t0, t1;
3013
3014 if (rd == 0) {
3015 /* Treat as NOP. */
3016 return;
3017 }
3018
3019 t0 = tcg_temp_new();
3020 t1 = tcg_temp_new();
3021
3022 gen_load_gpr(t0, rs);
3023 gen_load_gpr(t1, rt);
3024
3025 switch (opc) {
3026 case R6_OPC_DIV:
3027 {
3028 TCGv t2 = tcg_temp_new();
3029 TCGv t3 = tcg_temp_new();
3030 tcg_gen_ext32s_tl(t0, t0);
3031 tcg_gen_ext32s_tl(t1, t1);
3032 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3033 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3034 tcg_gen_and_tl(t2, t2, t3);
3035 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3036 tcg_gen_or_tl(t2, t2, t3);
3037 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3038 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3039 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3040 }
3041 break;
3042 case R6_OPC_MOD:
3043 {
3044 TCGv t2 = tcg_temp_new();
3045 TCGv t3 = tcg_temp_new();
3046 tcg_gen_ext32s_tl(t0, t0);
3047 tcg_gen_ext32s_tl(t1, t1);
3048 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3049 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3050 tcg_gen_and_tl(t2, t2, t3);
3051 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3052 tcg_gen_or_tl(t2, t2, t3);
3053 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3054 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3055 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3056 }
3057 break;
3058 case R6_OPC_DIVU:
3059 {
3060 tcg_gen_ext32u_tl(t0, t0);
3061 tcg_gen_ext32u_tl(t1, t1);
3062 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3063 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3064 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3065 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3066 }
3067 break;
3068 case R6_OPC_MODU:
3069 {
3070 tcg_gen_ext32u_tl(t0, t0);
3071 tcg_gen_ext32u_tl(t1, t1);
3072 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3073 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3074 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3075 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3076 }
3077 break;
3078 case R6_OPC_MUL:
3079 {
3080 TCGv_i32 t2 = tcg_temp_new_i32();
3081 TCGv_i32 t3 = tcg_temp_new_i32();
3082 tcg_gen_trunc_tl_i32(t2, t0);
3083 tcg_gen_trunc_tl_i32(t3, t1);
3084 tcg_gen_mul_i32(t2, t2, t3);
3085 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3086 }
3087 break;
3088 case R6_OPC_MUH:
3089 {
3090 TCGv_i32 t2 = tcg_temp_new_i32();
3091 TCGv_i32 t3 = tcg_temp_new_i32();
3092 tcg_gen_trunc_tl_i32(t2, t0);
3093 tcg_gen_trunc_tl_i32(t3, t1);
3094 tcg_gen_muls2_i32(t2, t3, t2, t3);
3095 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3096 }
3097 break;
3098 case R6_OPC_MULU:
3099 {
3100 TCGv_i32 t2 = tcg_temp_new_i32();
3101 TCGv_i32 t3 = tcg_temp_new_i32();
3102 tcg_gen_trunc_tl_i32(t2, t0);
3103 tcg_gen_trunc_tl_i32(t3, t1);
3104 tcg_gen_mul_i32(t2, t2, t3);
3105 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3106 }
3107 break;
3108 case R6_OPC_MUHU:
3109 {
3110 TCGv_i32 t2 = tcg_temp_new_i32();
3111 TCGv_i32 t3 = tcg_temp_new_i32();
3112 tcg_gen_trunc_tl_i32(t2, t0);
3113 tcg_gen_trunc_tl_i32(t3, t1);
3114 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3115 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3116 }
3117 break;
3118 #if defined(TARGET_MIPS64)
3119 case R6_OPC_DDIV:
3120 {
3121 TCGv t2 = tcg_temp_new();
3122 TCGv t3 = tcg_temp_new();
3123 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3124 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3125 tcg_gen_and_tl(t2, t2, t3);
3126 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3127 tcg_gen_or_tl(t2, t2, t3);
3128 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3129 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3130 }
3131 break;
3132 case R6_OPC_DMOD:
3133 {
3134 TCGv t2 = tcg_temp_new();
3135 TCGv t3 = tcg_temp_new();
3136 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3137 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3138 tcg_gen_and_tl(t2, t2, t3);
3139 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3140 tcg_gen_or_tl(t2, t2, t3);
3141 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3142 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3143 }
3144 break;
3145 case R6_OPC_DDIVU:
3146 {
3147 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3148 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3149 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3150 }
3151 break;
3152 case R6_OPC_DMODU:
3153 {
3154 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3155 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3156 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3157 }
3158 break;
3159 case R6_OPC_DMUL:
3160 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3161 break;
3162 case R6_OPC_DMUH:
3163 {
3164 TCGv t2 = tcg_temp_new();
3165 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3166 }
3167 break;
3168 case R6_OPC_DMULU:
3169 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3170 break;
3171 case R6_OPC_DMUHU:
3172 {
3173 TCGv t2 = tcg_temp_new();
3174 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3175 }
3176 break;
3177 #endif
3178 default:
3179 MIPS_INVAL("r6 mul/div");
3180 gen_reserved_instruction(ctx);
3181 break;
3182 }
3183 }
3184
3185 #if defined(TARGET_MIPS64)
gen_div1_tx79(DisasContext * ctx,uint32_t opc,int rs,int rt)3186 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3187 {
3188 TCGv t0, t1;
3189
3190 t0 = tcg_temp_new();
3191 t1 = tcg_temp_new();
3192
3193 gen_load_gpr(t0, rs);
3194 gen_load_gpr(t1, rt);
3195
3196 switch (opc) {
3197 case MMI_OPC_DIV1:
3198 {
3199 TCGv t2 = tcg_temp_new();
3200 TCGv t3 = tcg_temp_new();
3201 tcg_gen_ext32s_tl(t0, t0);
3202 tcg_gen_ext32s_tl(t1, t1);
3203 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3204 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3205 tcg_gen_and_tl(t2, t2, t3);
3206 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3207 tcg_gen_or_tl(t2, t2, t3);
3208 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3209 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3210 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3211 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3212 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3213 }
3214 break;
3215 case MMI_OPC_DIVU1:
3216 {
3217 TCGv t2 = tcg_constant_tl(0);
3218 TCGv t3 = tcg_constant_tl(1);
3219 tcg_gen_ext32u_tl(t0, t0);
3220 tcg_gen_ext32u_tl(t1, t1);
3221 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3222 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3223 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3224 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3225 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3226 }
3227 break;
3228 default:
3229 MIPS_INVAL("div1 TX79");
3230 gen_reserved_instruction(ctx);
3231 break;
3232 }
3233 }
3234 #endif
3235
gen_muldiv(DisasContext * ctx,uint32_t opc,int acc,int rs,int rt)3236 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3237 int acc, int rs, int rt)
3238 {
3239 TCGv t0, t1;
3240
3241 t0 = tcg_temp_new();
3242 t1 = tcg_temp_new();
3243
3244 gen_load_gpr(t0, rs);
3245 gen_load_gpr(t1, rt);
3246
3247 if (acc != 0) {
3248 check_dsp(ctx);
3249 }
3250
3251 switch (opc) {
3252 case OPC_DIV:
3253 {
3254 TCGv t2 = tcg_temp_new();
3255 TCGv t3 = tcg_temp_new();
3256 tcg_gen_ext32s_tl(t0, t0);
3257 tcg_gen_ext32s_tl(t1, t1);
3258 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3259 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3260 tcg_gen_and_tl(t2, t2, t3);
3261 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3262 tcg_gen_or_tl(t2, t2, t3);
3263 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3264 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3265 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3266 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3267 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3268 }
3269 break;
3270 case OPC_DIVU:
3271 {
3272 TCGv t2 = tcg_constant_tl(0);
3273 TCGv t3 = tcg_constant_tl(1);
3274 tcg_gen_ext32u_tl(t0, t0);
3275 tcg_gen_ext32u_tl(t1, t1);
3276 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3277 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3278 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3279 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3280 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3281 }
3282 break;
3283 case OPC_MULT:
3284 {
3285 TCGv_i32 t2 = tcg_temp_new_i32();
3286 TCGv_i32 t3 = tcg_temp_new_i32();
3287 tcg_gen_trunc_tl_i32(t2, t0);
3288 tcg_gen_trunc_tl_i32(t3, t1);
3289 tcg_gen_muls2_i32(t2, t3, t2, t3);
3290 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3291 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3292 }
3293 break;
3294 case OPC_MULTU:
3295 {
3296 TCGv_i32 t2 = tcg_temp_new_i32();
3297 TCGv_i32 t3 = tcg_temp_new_i32();
3298 tcg_gen_trunc_tl_i32(t2, t0);
3299 tcg_gen_trunc_tl_i32(t3, t1);
3300 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3301 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3302 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3303 }
3304 break;
3305 #if defined(TARGET_MIPS64)
3306 case OPC_DDIV:
3307 {
3308 TCGv t2 = tcg_temp_new();
3309 TCGv t3 = tcg_temp_new();
3310 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3311 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3312 tcg_gen_and_tl(t2, t2, t3);
3313 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3314 tcg_gen_or_tl(t2, t2, t3);
3315 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3316 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3317 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3318 }
3319 break;
3320 case OPC_DDIVU:
3321 {
3322 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3323 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3324 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3325 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3326 }
3327 break;
3328 case OPC_DMULT:
3329 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3330 break;
3331 case OPC_DMULTU:
3332 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3333 break;
3334 #endif
3335 case OPC_MADD:
3336 {
3337 TCGv_i64 t2 = tcg_temp_new_i64();
3338 TCGv_i64 t3 = tcg_temp_new_i64();
3339
3340 tcg_gen_ext_tl_i64(t2, t0);
3341 tcg_gen_ext_tl_i64(t3, t1);
3342 tcg_gen_mul_i64(t2, t2, t3);
3343 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3344 tcg_gen_add_i64(t2, t2, t3);
3345 gen_move_low32(cpu_LO[acc], t2);
3346 gen_move_high32(cpu_HI[acc], t2);
3347 }
3348 break;
3349 case OPC_MADDU:
3350 {
3351 TCGv_i64 t2 = tcg_temp_new_i64();
3352 TCGv_i64 t3 = tcg_temp_new_i64();
3353
3354 tcg_gen_ext32u_tl(t0, t0);
3355 tcg_gen_ext32u_tl(t1, t1);
3356 tcg_gen_extu_tl_i64(t2, t0);
3357 tcg_gen_extu_tl_i64(t3, t1);
3358 tcg_gen_mul_i64(t2, t2, t3);
3359 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3360 tcg_gen_add_i64(t2, t2, t3);
3361 gen_move_low32(cpu_LO[acc], t2);
3362 gen_move_high32(cpu_HI[acc], t2);
3363 }
3364 break;
3365 case OPC_MSUB:
3366 {
3367 TCGv_i64 t2 = tcg_temp_new_i64();
3368 TCGv_i64 t3 = tcg_temp_new_i64();
3369
3370 tcg_gen_ext_tl_i64(t2, t0);
3371 tcg_gen_ext_tl_i64(t3, t1);
3372 tcg_gen_mul_i64(t2, t2, t3);
3373 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3374 tcg_gen_sub_i64(t2, t3, t2);
3375 gen_move_low32(cpu_LO[acc], t2);
3376 gen_move_high32(cpu_HI[acc], t2);
3377 }
3378 break;
3379 case OPC_MSUBU:
3380 {
3381 TCGv_i64 t2 = tcg_temp_new_i64();
3382 TCGv_i64 t3 = tcg_temp_new_i64();
3383
3384 tcg_gen_ext32u_tl(t0, t0);
3385 tcg_gen_ext32u_tl(t1, t1);
3386 tcg_gen_extu_tl_i64(t2, t0);
3387 tcg_gen_extu_tl_i64(t3, t1);
3388 tcg_gen_mul_i64(t2, t2, t3);
3389 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3390 tcg_gen_sub_i64(t2, t3, t2);
3391 gen_move_low32(cpu_LO[acc], t2);
3392 gen_move_high32(cpu_HI[acc], t2);
3393 }
3394 break;
3395 default:
3396 MIPS_INVAL("mul/div");
3397 gen_reserved_instruction(ctx);
3398 break;
3399 }
3400 }
3401
3402 /*
3403 * These MULT[U] and MADD[U] instructions implemented in for example
3404 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3405 * architectures are special three-operand variants with the syntax
3406 *
3407 * MULT[U][1] rd, rs, rt
3408 *
3409 * such that
3410 *
3411 * (rd, LO, HI) <- rs * rt
3412 *
3413 * and
3414 *
3415 * MADD[U][1] rd, rs, rt
3416 *
3417 * such that
3418 *
3419 * (rd, LO, HI) <- (LO, HI) + rs * rt
3420 *
3421 * where the low-order 32-bits of the result is placed into both the
3422 * GPR rd and the special register LO. The high-order 32-bits of the
3423 * result is placed into the special register HI.
3424 *
3425 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3426 * which is the zero register that always reads as 0.
3427 */
gen_mul_txx9(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)3428 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3429 int rd, int rs, int rt)
3430 {
3431 TCGv t0 = tcg_temp_new();
3432 TCGv t1 = tcg_temp_new();
3433 int acc = 0;
3434
3435 gen_load_gpr(t0, rs);
3436 gen_load_gpr(t1, rt);
3437
3438 switch (opc) {
3439 case MMI_OPC_MULT1:
3440 acc = 1;
3441 /* Fall through */
3442 case OPC_MULT:
3443 {
3444 TCGv_i32 t2 = tcg_temp_new_i32();
3445 TCGv_i32 t3 = tcg_temp_new_i32();
3446 tcg_gen_trunc_tl_i32(t2, t0);
3447 tcg_gen_trunc_tl_i32(t3, t1);
3448 tcg_gen_muls2_i32(t2, t3, t2, t3);
3449 if (rd) {
3450 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3451 }
3452 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3453 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3454 }
3455 break;
3456 case MMI_OPC_MULTU1:
3457 acc = 1;
3458 /* Fall through */
3459 case OPC_MULTU:
3460 {
3461 TCGv_i32 t2 = tcg_temp_new_i32();
3462 TCGv_i32 t3 = tcg_temp_new_i32();
3463 tcg_gen_trunc_tl_i32(t2, t0);
3464 tcg_gen_trunc_tl_i32(t3, t1);
3465 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3466 if (rd) {
3467 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3468 }
3469 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3470 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3471 }
3472 break;
3473 case MMI_OPC_MADD1:
3474 acc = 1;
3475 /* Fall through */
3476 case MMI_OPC_MADD:
3477 {
3478 TCGv_i64 t2 = tcg_temp_new_i64();
3479 TCGv_i64 t3 = tcg_temp_new_i64();
3480
3481 tcg_gen_ext_tl_i64(t2, t0);
3482 tcg_gen_ext_tl_i64(t3, t1);
3483 tcg_gen_mul_i64(t2, t2, t3);
3484 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3485 tcg_gen_add_i64(t2, t2, t3);
3486 gen_move_low32(cpu_LO[acc], t2);
3487 gen_move_high32(cpu_HI[acc], t2);
3488 if (rd) {
3489 gen_move_low32(cpu_gpr[rd], t2);
3490 }
3491 }
3492 break;
3493 case MMI_OPC_MADDU1:
3494 acc = 1;
3495 /* Fall through */
3496 case MMI_OPC_MADDU:
3497 {
3498 TCGv_i64 t2 = tcg_temp_new_i64();
3499 TCGv_i64 t3 = tcg_temp_new_i64();
3500
3501 tcg_gen_ext32u_tl(t0, t0);
3502 tcg_gen_ext32u_tl(t1, t1);
3503 tcg_gen_extu_tl_i64(t2, t0);
3504 tcg_gen_extu_tl_i64(t3, t1);
3505 tcg_gen_mul_i64(t2, t2, t3);
3506 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3507 tcg_gen_add_i64(t2, t2, t3);
3508 gen_move_low32(cpu_LO[acc], t2);
3509 gen_move_high32(cpu_HI[acc], t2);
3510 if (rd) {
3511 gen_move_low32(cpu_gpr[rd], t2);
3512 }
3513 }
3514 break;
3515 default:
3516 MIPS_INVAL("mul/madd TXx9");
3517 gen_reserved_instruction(ctx);
3518 break;
3519 }
3520 }
3521
gen_cl(DisasContext * ctx,uint32_t opc,int rd,int rs)3522 static void gen_cl(DisasContext *ctx, uint32_t opc,
3523 int rd, int rs)
3524 {
3525 TCGv t0;
3526
3527 if (rd == 0) {
3528 /* Treat as NOP. */
3529 return;
3530 }
3531 t0 = cpu_gpr[rd];
3532 gen_load_gpr(t0, rs);
3533
3534 switch (opc) {
3535 case OPC_CLO:
3536 case R6_OPC_CLO:
3537 #if defined(TARGET_MIPS64)
3538 case OPC_DCLO:
3539 case R6_OPC_DCLO:
3540 #endif
3541 tcg_gen_not_tl(t0, t0);
3542 break;
3543 }
3544
3545 switch (opc) {
3546 case OPC_CLO:
3547 case R6_OPC_CLO:
3548 case OPC_CLZ:
3549 case R6_OPC_CLZ:
3550 tcg_gen_ext32u_tl(t0, t0);
3551 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3552 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3553 break;
3554 #if defined(TARGET_MIPS64)
3555 case OPC_DCLO:
3556 case R6_OPC_DCLO:
3557 case OPC_DCLZ:
3558 case R6_OPC_DCLZ:
3559 tcg_gen_clzi_i64(t0, t0, 64);
3560 break;
3561 #endif
3562 }
3563 }
3564
3565 /* Loongson multimedia instructions */
gen_loongson_multimedia(DisasContext * ctx,int rd,int rs,int rt)3566 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3567 {
3568 uint32_t opc, shift_max;
3569 TCGv_i64 t0, t1;
3570 TCGCond cond;
3571
3572 opc = MASK_LMMI(ctx->opcode);
3573 check_cp1_enabled(ctx);
3574
3575 t0 = tcg_temp_new_i64();
3576 t1 = tcg_temp_new_i64();
3577 gen_load_fpr64(ctx, t0, rs);
3578 gen_load_fpr64(ctx, t1, rt);
3579
3580 switch (opc) {
3581 case OPC_PADDSH:
3582 gen_helper_paddsh(t0, t0, t1);
3583 break;
3584 case OPC_PADDUSH:
3585 gen_helper_paddush(t0, t0, t1);
3586 break;
3587 case OPC_PADDH:
3588 gen_helper_paddh(t0, t0, t1);
3589 break;
3590 case OPC_PADDW:
3591 gen_helper_paddw(t0, t0, t1);
3592 break;
3593 case OPC_PADDSB:
3594 gen_helper_paddsb(t0, t0, t1);
3595 break;
3596 case OPC_PADDUSB:
3597 gen_helper_paddusb(t0, t0, t1);
3598 break;
3599 case OPC_PADDB:
3600 gen_helper_paddb(t0, t0, t1);
3601 break;
3602
3603 case OPC_PSUBSH:
3604 gen_helper_psubsh(t0, t0, t1);
3605 break;
3606 case OPC_PSUBUSH:
3607 gen_helper_psubush(t0, t0, t1);
3608 break;
3609 case OPC_PSUBH:
3610 gen_helper_psubh(t0, t0, t1);
3611 break;
3612 case OPC_PSUBW:
3613 gen_helper_psubw(t0, t0, t1);
3614 break;
3615 case OPC_PSUBSB:
3616 gen_helper_psubsb(t0, t0, t1);
3617 break;
3618 case OPC_PSUBUSB:
3619 gen_helper_psubusb(t0, t0, t1);
3620 break;
3621 case OPC_PSUBB:
3622 gen_helper_psubb(t0, t0, t1);
3623 break;
3624
3625 case OPC_PSHUFH:
3626 gen_helper_pshufh(t0, t0, t1);
3627 break;
3628 case OPC_PACKSSWH:
3629 gen_helper_packsswh(t0, t0, t1);
3630 break;
3631 case OPC_PACKSSHB:
3632 gen_helper_packsshb(t0, t0, t1);
3633 break;
3634 case OPC_PACKUSHB:
3635 gen_helper_packushb(t0, t0, t1);
3636 break;
3637
3638 case OPC_PUNPCKLHW:
3639 gen_helper_punpcklhw(t0, t0, t1);
3640 break;
3641 case OPC_PUNPCKHHW:
3642 gen_helper_punpckhhw(t0, t0, t1);
3643 break;
3644 case OPC_PUNPCKLBH:
3645 gen_helper_punpcklbh(t0, t0, t1);
3646 break;
3647 case OPC_PUNPCKHBH:
3648 gen_helper_punpckhbh(t0, t0, t1);
3649 break;
3650 case OPC_PUNPCKLWD:
3651 gen_helper_punpcklwd(t0, t0, t1);
3652 break;
3653 case OPC_PUNPCKHWD:
3654 gen_helper_punpckhwd(t0, t0, t1);
3655 break;
3656
3657 case OPC_PAVGH:
3658 gen_helper_pavgh(t0, t0, t1);
3659 break;
3660 case OPC_PAVGB:
3661 gen_helper_pavgb(t0, t0, t1);
3662 break;
3663 case OPC_PMAXSH:
3664 gen_helper_pmaxsh(t0, t0, t1);
3665 break;
3666 case OPC_PMINSH:
3667 gen_helper_pminsh(t0, t0, t1);
3668 break;
3669 case OPC_PMAXUB:
3670 gen_helper_pmaxub(t0, t0, t1);
3671 break;
3672 case OPC_PMINUB:
3673 gen_helper_pminub(t0, t0, t1);
3674 break;
3675
3676 case OPC_PCMPEQW:
3677 gen_helper_pcmpeqw(t0, t0, t1);
3678 break;
3679 case OPC_PCMPGTW:
3680 gen_helper_pcmpgtw(t0, t0, t1);
3681 break;
3682 case OPC_PCMPEQH:
3683 gen_helper_pcmpeqh(t0, t0, t1);
3684 break;
3685 case OPC_PCMPGTH:
3686 gen_helper_pcmpgth(t0, t0, t1);
3687 break;
3688 case OPC_PCMPEQB:
3689 gen_helper_pcmpeqb(t0, t0, t1);
3690 break;
3691 case OPC_PCMPGTB:
3692 gen_helper_pcmpgtb(t0, t0, t1);
3693 break;
3694
3695 case OPC_PSLLW:
3696 gen_helper_psllw(t0, t0, t1);
3697 break;
3698 case OPC_PSLLH:
3699 gen_helper_psllh(t0, t0, t1);
3700 break;
3701 case OPC_PSRLW:
3702 gen_helper_psrlw(t0, t0, t1);
3703 break;
3704 case OPC_PSRLH:
3705 gen_helper_psrlh(t0, t0, t1);
3706 break;
3707 case OPC_PSRAW:
3708 gen_helper_psraw(t0, t0, t1);
3709 break;
3710 case OPC_PSRAH:
3711 gen_helper_psrah(t0, t0, t1);
3712 break;
3713
3714 case OPC_PMULLH:
3715 gen_helper_pmullh(t0, t0, t1);
3716 break;
3717 case OPC_PMULHH:
3718 gen_helper_pmulhh(t0, t0, t1);
3719 break;
3720 case OPC_PMULHUH:
3721 gen_helper_pmulhuh(t0, t0, t1);
3722 break;
3723 case OPC_PMADDHW:
3724 gen_helper_pmaddhw(t0, t0, t1);
3725 break;
3726
3727 case OPC_PASUBUB:
3728 gen_helper_pasubub(t0, t0, t1);
3729 break;
3730 case OPC_BIADD:
3731 gen_helper_biadd(t0, t0);
3732 break;
3733 case OPC_PMOVMSKB:
3734 gen_helper_pmovmskb(t0, t0);
3735 break;
3736
3737 case OPC_PADDD:
3738 tcg_gen_add_i64(t0, t0, t1);
3739 break;
3740 case OPC_PSUBD:
3741 tcg_gen_sub_i64(t0, t0, t1);
3742 break;
3743 case OPC_XOR_CP2:
3744 tcg_gen_xor_i64(t0, t0, t1);
3745 break;
3746 case OPC_NOR_CP2:
3747 tcg_gen_nor_i64(t0, t0, t1);
3748 break;
3749 case OPC_AND_CP2:
3750 tcg_gen_and_i64(t0, t0, t1);
3751 break;
3752 case OPC_OR_CP2:
3753 tcg_gen_or_i64(t0, t0, t1);
3754 break;
3755
3756 case OPC_PANDN:
3757 tcg_gen_andc_i64(t0, t1, t0);
3758 break;
3759
3760 case OPC_PINSRH_0:
3761 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3762 break;
3763 case OPC_PINSRH_1:
3764 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3765 break;
3766 case OPC_PINSRH_2:
3767 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3768 break;
3769 case OPC_PINSRH_3:
3770 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3771 break;
3772
3773 case OPC_PEXTRH:
3774 tcg_gen_andi_i64(t1, t1, 3);
3775 tcg_gen_shli_i64(t1, t1, 4);
3776 tcg_gen_shr_i64(t0, t0, t1);
3777 tcg_gen_ext16u_i64(t0, t0);
3778 break;
3779
3780 case OPC_ADDU_CP2:
3781 tcg_gen_add_i64(t0, t0, t1);
3782 tcg_gen_ext32s_i64(t0, t0);
3783 break;
3784 case OPC_SUBU_CP2:
3785 tcg_gen_sub_i64(t0, t0, t1);
3786 tcg_gen_ext32s_i64(t0, t0);
3787 break;
3788
3789 case OPC_SLL_CP2:
3790 shift_max = 32;
3791 goto do_shift;
3792 case OPC_SRL_CP2:
3793 shift_max = 32;
3794 goto do_shift;
3795 case OPC_SRA_CP2:
3796 shift_max = 32;
3797 goto do_shift;
3798 case OPC_DSLL_CP2:
3799 shift_max = 64;
3800 goto do_shift;
3801 case OPC_DSRL_CP2:
3802 shift_max = 64;
3803 goto do_shift;
3804 case OPC_DSRA_CP2:
3805 shift_max = 64;
3806 goto do_shift;
3807 do_shift:
3808 /* Make sure shift count isn't TCG undefined behaviour. */
3809 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3810
3811 switch (opc) {
3812 case OPC_SLL_CP2:
3813 case OPC_DSLL_CP2:
3814 tcg_gen_shl_i64(t0, t0, t1);
3815 break;
3816 case OPC_SRA_CP2:
3817 case OPC_DSRA_CP2:
3818 /*
3819 * Since SRA is UndefinedResult without sign-extended inputs,
3820 * we can treat SRA and DSRA the same.
3821 */
3822 tcg_gen_sar_i64(t0, t0, t1);
3823 break;
3824 case OPC_SRL_CP2:
3825 /* We want to shift in zeros for SRL; zero-extend first. */
3826 tcg_gen_ext32u_i64(t0, t0);
3827 /* FALLTHRU */
3828 case OPC_DSRL_CP2:
3829 tcg_gen_shr_i64(t0, t0, t1);
3830 break;
3831 }
3832
3833 if (shift_max == 32) {
3834 tcg_gen_ext32s_i64(t0, t0);
3835 }
3836
3837 /* Shifts larger than MAX produce zero. */
3838 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3839 tcg_gen_neg_i64(t1, t1);
3840 tcg_gen_and_i64(t0, t0, t1);
3841 break;
3842
3843 case OPC_ADD_CP2:
3844 case OPC_DADD_CP2:
3845 {
3846 TCGv_i64 t2 = tcg_temp_new_i64();
3847 TCGLabel *lab = gen_new_label();
3848
3849 tcg_gen_mov_i64(t2, t0);
3850 tcg_gen_add_i64(t0, t1, t2);
3851 if (opc == OPC_ADD_CP2) {
3852 tcg_gen_ext32s_i64(t0, t0);
3853 }
3854 tcg_gen_xor_i64(t1, t1, t2);
3855 tcg_gen_xor_i64(t2, t2, t0);
3856 tcg_gen_andc_i64(t1, t2, t1);
3857 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3858 generate_exception(ctx, EXCP_OVERFLOW);
3859 gen_set_label(lab);
3860 break;
3861 }
3862
3863 case OPC_SUB_CP2:
3864 case OPC_DSUB_CP2:
3865 {
3866 TCGv_i64 t2 = tcg_temp_new_i64();
3867 TCGLabel *lab = gen_new_label();
3868
3869 tcg_gen_mov_i64(t2, t0);
3870 tcg_gen_sub_i64(t0, t1, t2);
3871 if (opc == OPC_SUB_CP2) {
3872 tcg_gen_ext32s_i64(t0, t0);
3873 }
3874 tcg_gen_xor_i64(t1, t1, t2);
3875 tcg_gen_xor_i64(t2, t2, t0);
3876 tcg_gen_and_i64(t1, t1, t2);
3877 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3878 generate_exception(ctx, EXCP_OVERFLOW);
3879 gen_set_label(lab);
3880 break;
3881 }
3882
3883 case OPC_PMULUW:
3884 tcg_gen_ext32u_i64(t0, t0);
3885 tcg_gen_ext32u_i64(t1, t1);
3886 tcg_gen_mul_i64(t0, t0, t1);
3887 break;
3888
3889 case OPC_SEQU_CP2:
3890 case OPC_SEQ_CP2:
3891 cond = TCG_COND_EQ;
3892 goto do_cc_cond;
3893 break;
3894 case OPC_SLTU_CP2:
3895 cond = TCG_COND_LTU;
3896 goto do_cc_cond;
3897 break;
3898 case OPC_SLT_CP2:
3899 cond = TCG_COND_LT;
3900 goto do_cc_cond;
3901 break;
3902 case OPC_SLEU_CP2:
3903 cond = TCG_COND_LEU;
3904 goto do_cc_cond;
3905 break;
3906 case OPC_SLE_CP2:
3907 cond = TCG_COND_LE;
3908 do_cc_cond:
3909 {
3910 int cc = (ctx->opcode >> 8) & 0x7;
3911 TCGv_i64 t64 = tcg_temp_new_i64();
3912 TCGv_i32 t32 = tcg_temp_new_i32();
3913
3914 tcg_gen_setcond_i64(cond, t64, t0, t1);
3915 tcg_gen_extrl_i64_i32(t32, t64);
3916 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
3917 get_fp_bit(cc), 1);
3918 }
3919 return;
3920 default:
3921 MIPS_INVAL("loongson_cp2");
3922 gen_reserved_instruction(ctx);
3923 return;
3924 }
3925
3926 gen_store_fpr64(ctx, t0, rd);
3927 }
3928
gen_loongson_lswc2(DisasContext * ctx,int rt,int rs,int rd)3929 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
3930 int rs, int rd)
3931 {
3932 TCGv t0, t1;
3933 TCGv_i32 fp0;
3934 #if defined(TARGET_MIPS64)
3935 int lsq_rt1 = ctx->opcode & 0x1f;
3936 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
3937 #endif
3938 int shf_offset = sextract32(ctx->opcode, 6, 8);
3939
3940 t0 = tcg_temp_new();
3941
3942 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
3943 #if defined(TARGET_MIPS64)
3944 case OPC_GSLQ:
3945 t1 = tcg_temp_new();
3946 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3947 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3948 ctx->default_tcg_memop_mask);
3949 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3950 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3951 ctx->default_tcg_memop_mask);
3952 gen_store_gpr(t1, rt);
3953 gen_store_gpr(t0, lsq_rt1);
3954 break;
3955 case OPC_GSLQC1:
3956 check_cp1_enabled(ctx);
3957 t1 = tcg_temp_new();
3958 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3959 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3960 ctx->default_tcg_memop_mask);
3961 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3962 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3963 ctx->default_tcg_memop_mask);
3964 gen_store_fpr64(ctx, t1, rt);
3965 gen_store_fpr64(ctx, t0, lsq_rt1);
3966 break;
3967 case OPC_GSSQ:
3968 t1 = tcg_temp_new();
3969 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3970 gen_load_gpr(t1, rt);
3971 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3972 ctx->default_tcg_memop_mask);
3973 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3974 gen_load_gpr(t1, lsq_rt1);
3975 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3976 ctx->default_tcg_memop_mask);
3977 break;
3978 case OPC_GSSQC1:
3979 check_cp1_enabled(ctx);
3980 t1 = tcg_temp_new();
3981 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3982 gen_load_fpr64(ctx, t1, rt);
3983 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3984 ctx->default_tcg_memop_mask);
3985 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3986 gen_load_fpr64(ctx, t1, lsq_rt1);
3987 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3988 ctx->default_tcg_memop_mask);
3989 break;
3990 #endif
3991 case OPC_GSSHFL:
3992 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
3993 case OPC_GSLWLC1:
3994 check_cp1_enabled(ctx);
3995 gen_base_offset_addr(ctx, t0, rs, shf_offset);
3996 fp0 = tcg_temp_new_i32();
3997 gen_load_fpr32(ctx, fp0, rt);
3998 t1 = tcg_temp_new();
3999 tcg_gen_ext_i32_tl(t1, fp0);
4000 gen_lxl(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
4001 tcg_gen_trunc_tl_i32(fp0, t1);
4002 gen_store_fpr32(ctx, fp0, rt);
4003 break;
4004 case OPC_GSLWRC1:
4005 check_cp1_enabled(ctx);
4006 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4007 fp0 = tcg_temp_new_i32();
4008 gen_load_fpr32(ctx, fp0, rt);
4009 t1 = tcg_temp_new();
4010 tcg_gen_ext_i32_tl(t1, fp0);
4011 gen_lxr(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
4012 tcg_gen_trunc_tl_i32(fp0, t1);
4013 gen_store_fpr32(ctx, fp0, rt);
4014 break;
4015 #if defined(TARGET_MIPS64)
4016 case OPC_GSLDLC1:
4017 check_cp1_enabled(ctx);
4018 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4019 t1 = tcg_temp_new();
4020 gen_load_fpr64(ctx, t1, rt);
4021 gen_lxl(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
4022 gen_store_fpr64(ctx, t1, rt);
4023 break;
4024 case OPC_GSLDRC1:
4025 check_cp1_enabled(ctx);
4026 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4027 t1 = tcg_temp_new();
4028 gen_load_fpr64(ctx, t1, rt);
4029 gen_lxr(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
4030 gen_store_fpr64(ctx, t1, rt);
4031 break;
4032 #endif
4033 default:
4034 MIPS_INVAL("loongson_gsshfl");
4035 gen_reserved_instruction(ctx);
4036 break;
4037 }
4038 break;
4039 case OPC_GSSHFS:
4040 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4041 case OPC_GSSWLC1:
4042 check_cp1_enabled(ctx);
4043 t1 = tcg_temp_new();
4044 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4045 fp0 = tcg_temp_new_i32();
4046 gen_load_fpr32(ctx, fp0, rt);
4047 tcg_gen_ext_i32_tl(t1, fp0);
4048 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4049 break;
4050 case OPC_GSSWRC1:
4051 check_cp1_enabled(ctx);
4052 t1 = tcg_temp_new();
4053 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4054 fp0 = tcg_temp_new_i32();
4055 gen_load_fpr32(ctx, fp0, rt);
4056 tcg_gen_ext_i32_tl(t1, fp0);
4057 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4058 break;
4059 #if defined(TARGET_MIPS64)
4060 case OPC_GSSDLC1:
4061 check_cp1_enabled(ctx);
4062 t1 = tcg_temp_new();
4063 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4064 gen_load_fpr64(ctx, t1, rt);
4065 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4066 break;
4067 case OPC_GSSDRC1:
4068 check_cp1_enabled(ctx);
4069 t1 = tcg_temp_new();
4070 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4071 gen_load_fpr64(ctx, t1, rt);
4072 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4073 break;
4074 #endif
4075 default:
4076 MIPS_INVAL("loongson_gsshfs");
4077 gen_reserved_instruction(ctx);
4078 break;
4079 }
4080 break;
4081 default:
4082 MIPS_INVAL("loongson_gslsq");
4083 gen_reserved_instruction(ctx);
4084 break;
4085 }
4086 }
4087
4088 /* Loongson EXT LDC2/SDC2 */
gen_loongson_lsdc2(DisasContext * ctx,int rt,int rs,int rd)4089 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4090 int rs, int rd)
4091 {
4092 int offset = sextract32(ctx->opcode, 3, 8);
4093 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4094 TCGv t0, t1;
4095 TCGv_i32 fp0;
4096
4097 /* Pre-conditions */
4098 switch (opc) {
4099 case OPC_GSLBX:
4100 case OPC_GSLHX:
4101 case OPC_GSLWX:
4102 case OPC_GSLDX:
4103 /* prefetch, implement as NOP */
4104 if (rt == 0) {
4105 return;
4106 }
4107 break;
4108 case OPC_GSSBX:
4109 case OPC_GSSHX:
4110 case OPC_GSSWX:
4111 case OPC_GSSDX:
4112 break;
4113 case OPC_GSLWXC1:
4114 #if defined(TARGET_MIPS64)
4115 case OPC_GSLDXC1:
4116 #endif
4117 check_cp1_enabled(ctx);
4118 /* prefetch, implement as NOP */
4119 if (rt == 0) {
4120 return;
4121 }
4122 break;
4123 case OPC_GSSWXC1:
4124 #if defined(TARGET_MIPS64)
4125 case OPC_GSSDXC1:
4126 #endif
4127 check_cp1_enabled(ctx);
4128 break;
4129 default:
4130 MIPS_INVAL("loongson_lsdc2");
4131 gen_reserved_instruction(ctx);
4132 return;
4133 break;
4134 }
4135
4136 t0 = tcg_temp_new();
4137
4138 gen_base_offset_addr(ctx, t0, rs, offset);
4139 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4140
4141 switch (opc) {
4142 case OPC_GSLBX:
4143 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4144 gen_store_gpr(t0, rt);
4145 break;
4146 case OPC_GSLHX:
4147 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SW |
4148 ctx->default_tcg_memop_mask);
4149 gen_store_gpr(t0, rt);
4150 break;
4151 case OPC_GSLWX:
4152 gen_base_offset_addr(ctx, t0, rs, offset);
4153 if (rd) {
4154 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4155 }
4156 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
4157 ctx->default_tcg_memop_mask);
4158 gen_store_gpr(t0, rt);
4159 break;
4160 #if defined(TARGET_MIPS64)
4161 case OPC_GSLDX:
4162 gen_base_offset_addr(ctx, t0, rs, offset);
4163 if (rd) {
4164 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4165 }
4166 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4167 ctx->default_tcg_memop_mask);
4168 gen_store_gpr(t0, rt);
4169 break;
4170 #endif
4171 case OPC_GSLWXC1:
4172 gen_base_offset_addr(ctx, t0, rs, offset);
4173 if (rd) {
4174 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4175 }
4176 fp0 = tcg_temp_new_i32();
4177 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
4178 ctx->default_tcg_memop_mask);
4179 gen_store_fpr32(ctx, fp0, rt);
4180 break;
4181 #if defined(TARGET_MIPS64)
4182 case OPC_GSLDXC1:
4183 gen_base_offset_addr(ctx, t0, rs, offset);
4184 if (rd) {
4185 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4186 }
4187 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4188 ctx->default_tcg_memop_mask);
4189 gen_store_fpr64(ctx, t0, rt);
4190 break;
4191 #endif
4192 case OPC_GSSBX:
4193 t1 = tcg_temp_new();
4194 gen_load_gpr(t1, rt);
4195 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4196 break;
4197 case OPC_GSSHX:
4198 t1 = tcg_temp_new();
4199 gen_load_gpr(t1, rt);
4200 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UW |
4201 ctx->default_tcg_memop_mask);
4202 break;
4203 case OPC_GSSWX:
4204 t1 = tcg_temp_new();
4205 gen_load_gpr(t1, rt);
4206 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
4207 ctx->default_tcg_memop_mask);
4208 break;
4209 #if defined(TARGET_MIPS64)
4210 case OPC_GSSDX:
4211 t1 = tcg_temp_new();
4212 gen_load_gpr(t1, rt);
4213 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4214 ctx->default_tcg_memop_mask);
4215 break;
4216 #endif
4217 case OPC_GSSWXC1:
4218 fp0 = tcg_temp_new_i32();
4219 gen_load_fpr32(ctx, fp0, rt);
4220 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
4221 ctx->default_tcg_memop_mask);
4222 break;
4223 #if defined(TARGET_MIPS64)
4224 case OPC_GSSDXC1:
4225 t1 = tcg_temp_new();
4226 gen_load_fpr64(ctx, t1, rt);
4227 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4228 ctx->default_tcg_memop_mask);
4229 break;
4230 #endif
4231 default:
4232 break;
4233 }
4234 }
4235
4236 /* Traps */
gen_trap(DisasContext * ctx,uint32_t opc,int rs,int rt,int16_t imm,int code)4237 static void gen_trap(DisasContext *ctx, uint32_t opc,
4238 int rs, int rt, int16_t imm, int code)
4239 {
4240 int cond;
4241 TCGv t0 = tcg_temp_new();
4242 TCGv t1 = tcg_temp_new();
4243
4244 cond = 0;
4245 /* Load needed operands */
4246 switch (opc) {
4247 case OPC_TEQ:
4248 case OPC_TGE:
4249 case OPC_TGEU:
4250 case OPC_TLT:
4251 case OPC_TLTU:
4252 case OPC_TNE:
4253 /* Compare two registers */
4254 if (rs != rt) {
4255 gen_load_gpr(t0, rs);
4256 gen_load_gpr(t1, rt);
4257 cond = 1;
4258 }
4259 break;
4260 case OPC_TEQI:
4261 case OPC_TGEI:
4262 case OPC_TGEIU:
4263 case OPC_TLTI:
4264 case OPC_TLTIU:
4265 case OPC_TNEI:
4266 /* Compare register to immediate */
4267 if (rs != 0 || imm != 0) {
4268 gen_load_gpr(t0, rs);
4269 tcg_gen_movi_tl(t1, (int32_t)imm);
4270 cond = 1;
4271 }
4272 break;
4273 }
4274 if (cond == 0) {
4275 switch (opc) {
4276 case OPC_TEQ: /* rs == rs */
4277 case OPC_TEQI: /* r0 == 0 */
4278 case OPC_TGE: /* rs >= rs */
4279 case OPC_TGEI: /* r0 >= 0 */
4280 case OPC_TGEU: /* rs >= rs unsigned */
4281 case OPC_TGEIU: /* r0 >= 0 unsigned */
4282 /* Always trap */
4283 #ifdef CONFIG_USER_ONLY
4284 /* Pass the break code along to cpu_loop. */
4285 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
4286 offsetof(CPUMIPSState, error_code));
4287 #endif
4288 generate_exception_end(ctx, EXCP_TRAP);
4289 break;
4290 case OPC_TLT: /* rs < rs */
4291 case OPC_TLTI: /* r0 < 0 */
4292 case OPC_TLTU: /* rs < rs unsigned */
4293 case OPC_TLTIU: /* r0 < 0 unsigned */
4294 case OPC_TNE: /* rs != rs */
4295 case OPC_TNEI: /* r0 != 0 */
4296 /* Never trap: treat as NOP. */
4297 break;
4298 }
4299 } else {
4300 TCGLabel *l1 = gen_new_label();
4301
4302 switch (opc) {
4303 case OPC_TEQ:
4304 case OPC_TEQI:
4305 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4306 break;
4307 case OPC_TGE:
4308 case OPC_TGEI:
4309 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4310 break;
4311 case OPC_TGEU:
4312 case OPC_TGEIU:
4313 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4314 break;
4315 case OPC_TLT:
4316 case OPC_TLTI:
4317 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4318 break;
4319 case OPC_TLTU:
4320 case OPC_TLTIU:
4321 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4322 break;
4323 case OPC_TNE:
4324 case OPC_TNEI:
4325 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4326 break;
4327 }
4328 #ifdef CONFIG_USER_ONLY
4329 /* Pass the break code along to cpu_loop. */
4330 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
4331 offsetof(CPUMIPSState, error_code));
4332 #endif
4333 /* Like save_cpu_state, only don't update saved values. */
4334 if (ctx->base.pc_next != ctx->saved_pc) {
4335 gen_save_pc(ctx->base.pc_next);
4336 }
4337 if (ctx->hflags != ctx->saved_hflags) {
4338 tcg_gen_movi_i32(hflags, ctx->hflags);
4339 }
4340 generate_exception(ctx, EXCP_TRAP);
4341 gen_set_label(l1);
4342 }
4343 }
4344
gen_goto_tb(DisasContext * ctx,int n,target_ulong dest)4345 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4346 {
4347 if (translator_use_goto_tb(&ctx->base, dest)) {
4348 tcg_gen_goto_tb(n);
4349 gen_save_pc(dest);
4350 tcg_gen_exit_tb(ctx->base.tb, n);
4351 } else {
4352 gen_save_pc(dest);
4353 tcg_gen_lookup_and_goto_ptr();
4354 }
4355 }
4356
4357 /* Branches (before delay slot) */
gen_compute_branch(DisasContext * ctx,uint32_t opc,int insn_bytes,int rs,int rt,int32_t offset,int delayslot_size)4358 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
4359 int insn_bytes,
4360 int rs, int rt, int32_t offset,
4361 int delayslot_size)
4362 {
4363 target_ulong btgt = -1;
4364 int blink = 0;
4365 int bcond_compute = 0;
4366 TCGv t0 = tcg_temp_new();
4367 TCGv t1 = tcg_temp_new();
4368
4369 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4370 #ifdef MIPS_DEBUG_DISAS
4371 LOG_DISAS("Branch in delay / forbidden slot at PC 0x%016"
4372 VADDR_PRIx "\n", ctx->base.pc_next);
4373 #endif
4374 gen_reserved_instruction(ctx);
4375 goto out;
4376 }
4377
4378 /* Load needed operands */
4379 switch (opc) {
4380 case OPC_BEQ:
4381 case OPC_BEQL:
4382 case OPC_BNE:
4383 case OPC_BNEL:
4384 /* Compare two registers */
4385 if (rs != rt) {
4386 gen_load_gpr(t0, rs);
4387 gen_load_gpr(t1, rt);
4388 bcond_compute = 1;
4389 }
4390 btgt = ctx->base.pc_next + insn_bytes + offset;
4391 break;
4392 case OPC_BGEZ:
4393 case OPC_BGEZAL:
4394 case OPC_BGEZALL:
4395 case OPC_BGEZL:
4396 case OPC_BGTZ:
4397 case OPC_BGTZL:
4398 case OPC_BLEZ:
4399 case OPC_BLEZL:
4400 case OPC_BLTZ:
4401 case OPC_BLTZAL:
4402 case OPC_BLTZALL:
4403 case OPC_BLTZL:
4404 /* Compare to zero */
4405 if (rs != 0) {
4406 gen_load_gpr(t0, rs);
4407 bcond_compute = 1;
4408 }
4409 btgt = ctx->base.pc_next + insn_bytes + offset;
4410 break;
4411 case OPC_BPOSGE32:
4412 #if defined(TARGET_MIPS64)
4413 case OPC_BPOSGE64:
4414 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4415 #else
4416 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4417 #endif
4418 bcond_compute = 1;
4419 btgt = ctx->base.pc_next + insn_bytes + offset;
4420 break;
4421 case OPC_J:
4422 case OPC_JAL:
4423 {
4424 /* Jump to immediate */
4425 int jal_mask = ctx->hflags & MIPS_HFLAG_M16 ? 0xF8000000
4426 : 0xF0000000;
4427 btgt = ((ctx->base.pc_next + insn_bytes) & jal_mask)
4428 | (uint32_t)offset;
4429 break;
4430 }
4431 case OPC_JALX:
4432 /* Jump to immediate */
4433 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4434 (uint32_t)offset;
4435 break;
4436 case OPC_JR:
4437 case OPC_JALR:
4438 /* Jump to register */
4439 if (offset != 0 && offset != 16) {
4440 /*
4441 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4442 * others are reserved.
4443 */
4444 MIPS_INVAL("jump hint");
4445 gen_reserved_instruction(ctx);
4446 goto out;
4447 }
4448 gen_load_gpr(btarget, rs);
4449 break;
4450 default:
4451 MIPS_INVAL("branch/jump");
4452 gen_reserved_instruction(ctx);
4453 goto out;
4454 }
4455 if (bcond_compute == 0) {
4456 /* No condition to be computed */
4457 switch (opc) {
4458 case OPC_BEQ: /* rx == rx */
4459 case OPC_BEQL: /* rx == rx likely */
4460 case OPC_BGEZ: /* 0 >= 0 */
4461 case OPC_BGEZL: /* 0 >= 0 likely */
4462 case OPC_BLEZ: /* 0 <= 0 */
4463 case OPC_BLEZL: /* 0 <= 0 likely */
4464 /* Always take */
4465 ctx->hflags |= MIPS_HFLAG_B;
4466 break;
4467 case OPC_BGEZAL: /* 0 >= 0 */
4468 case OPC_BGEZALL: /* 0 >= 0 likely */
4469 /* Always take and link */
4470 blink = 31;
4471 ctx->hflags |= MIPS_HFLAG_B;
4472 break;
4473 case OPC_BNE: /* rx != rx */
4474 case OPC_BGTZ: /* 0 > 0 */
4475 case OPC_BLTZ: /* 0 < 0 */
4476 /* Treat as NOP. */
4477 goto out;
4478 case OPC_BLTZAL: /* 0 < 0 */
4479 /*
4480 * Handle as an unconditional branch to get correct delay
4481 * slot checking.
4482 */
4483 blink = 31;
4484 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
4485 ctx->hflags |= MIPS_HFLAG_B;
4486 break;
4487 case OPC_BLTZALL: /* 0 < 0 likely */
4488 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4489 /* Skip the instruction in the delay slot */
4490 ctx->base.pc_next += 4;
4491 goto out;
4492 case OPC_BNEL: /* rx != rx likely */
4493 case OPC_BGTZL: /* 0 > 0 likely */
4494 case OPC_BLTZL: /* 0 < 0 likely */
4495 /* Skip the instruction in the delay slot */
4496 ctx->base.pc_next += 4;
4497 goto out;
4498 case OPC_J:
4499 ctx->hflags |= MIPS_HFLAG_B;
4500 break;
4501 case OPC_JALX:
4502 ctx->hflags |= MIPS_HFLAG_BX;
4503 /* Fallthrough */
4504 case OPC_JAL:
4505 blink = 31;
4506 ctx->hflags |= MIPS_HFLAG_B;
4507 break;
4508 case OPC_JR:
4509 ctx->hflags |= MIPS_HFLAG_BR;
4510 break;
4511 case OPC_JALR:
4512 blink = rt;
4513 ctx->hflags |= MIPS_HFLAG_BR;
4514 break;
4515 default:
4516 MIPS_INVAL("branch/jump");
4517 gen_reserved_instruction(ctx);
4518 goto out;
4519 }
4520 } else {
4521 switch (opc) {
4522 case OPC_BEQ:
4523 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4524 goto not_likely;
4525 case OPC_BEQL:
4526 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4527 goto likely;
4528 case OPC_BNE:
4529 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4530 goto not_likely;
4531 case OPC_BNEL:
4532 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4533 goto likely;
4534 case OPC_BGEZ:
4535 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4536 goto not_likely;
4537 case OPC_BGEZL:
4538 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4539 goto likely;
4540 case OPC_BGEZAL:
4541 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4542 blink = 31;
4543 goto not_likely;
4544 case OPC_BGEZALL:
4545 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4546 blink = 31;
4547 goto likely;
4548 case OPC_BGTZ:
4549 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4550 goto not_likely;
4551 case OPC_BGTZL:
4552 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4553 goto likely;
4554 case OPC_BLEZ:
4555 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4556 goto not_likely;
4557 case OPC_BLEZL:
4558 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4559 goto likely;
4560 case OPC_BLTZ:
4561 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4562 goto not_likely;
4563 case OPC_BLTZL:
4564 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4565 goto likely;
4566 case OPC_BPOSGE32:
4567 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4568 goto not_likely;
4569 #if defined(TARGET_MIPS64)
4570 case OPC_BPOSGE64:
4571 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4572 goto not_likely;
4573 #endif
4574 case OPC_BLTZAL:
4575 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4576 blink = 31;
4577 not_likely:
4578 ctx->hflags |= MIPS_HFLAG_BC;
4579 break;
4580 case OPC_BLTZALL:
4581 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4582 blink = 31;
4583 likely:
4584 ctx->hflags |= MIPS_HFLAG_BL;
4585 break;
4586 default:
4587 MIPS_INVAL("conditional branch/jump");
4588 gen_reserved_instruction(ctx);
4589 goto out;
4590 }
4591 }
4592
4593 ctx->btarget = btgt;
4594
4595 switch (delayslot_size) {
4596 case 2:
4597 ctx->hflags |= MIPS_HFLAG_BDS16;
4598 break;
4599 case 4:
4600 ctx->hflags |= MIPS_HFLAG_BDS32;
4601 break;
4602 }
4603
4604 if (blink > 0) {
4605 int post_delay = insn_bytes + delayslot_size;
4606 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4607
4608 tcg_gen_movi_tl(cpu_gpr[blink],
4609 ctx->base.pc_next + post_delay + lowbit);
4610 }
4611
4612 out:
4613 if (insn_bytes == 2) {
4614 ctx->hflags |= MIPS_HFLAG_B16;
4615 }
4616 }
4617
4618
4619 /* special3 bitfield operations */
gen_bitops(DisasContext * ctx,uint32_t opc,int rt,int rs,int lsb,int msb)4620 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
4621 int rs, int lsb, int msb)
4622 {
4623 TCGv t0 = tcg_temp_new();
4624 TCGv t1 = tcg_temp_new();
4625
4626 gen_load_gpr(t1, rs);
4627 switch (opc) {
4628 case OPC_EXT:
4629 if (lsb + msb > 31) {
4630 goto fail;
4631 }
4632 if (msb != 31) {
4633 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4634 } else {
4635 /*
4636 * The two checks together imply that lsb == 0,
4637 * so this is a simple sign-extension.
4638 */
4639 tcg_gen_ext32s_tl(t0, t1);
4640 }
4641 break;
4642 #if defined(TARGET_MIPS64)
4643 case OPC_DEXTU:
4644 lsb += 32;
4645 goto do_dext;
4646 case OPC_DEXTM:
4647 msb += 32;
4648 goto do_dext;
4649 case OPC_DEXT:
4650 do_dext:
4651 if (lsb + msb > 63) {
4652 goto fail;
4653 }
4654 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4655 break;
4656 #endif
4657 case OPC_INS:
4658 if (lsb > msb) {
4659 goto fail;
4660 }
4661 gen_load_gpr(t0, rt);
4662 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4663 tcg_gen_ext32s_tl(t0, t0);
4664 break;
4665 #if defined(TARGET_MIPS64)
4666 case OPC_DINSU:
4667 lsb += 32;
4668 /* FALLTHRU */
4669 case OPC_DINSM:
4670 msb += 32;
4671 /* FALLTHRU */
4672 case OPC_DINS:
4673 if (lsb > msb) {
4674 goto fail;
4675 }
4676 gen_load_gpr(t0, rt);
4677 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4678 break;
4679 #endif
4680 default:
4681 fail:
4682 MIPS_INVAL("bitops");
4683 gen_reserved_instruction(ctx);
4684 return;
4685 }
4686 gen_store_gpr(t0, rt);
4687 }
4688
gen_bshfl(DisasContext * ctx,uint32_t op2,int rt,int rd)4689 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
4690 {
4691 TCGv t0;
4692
4693 if (rd == 0) {
4694 /* If no destination, treat it as a NOP. */
4695 return;
4696 }
4697
4698 t0 = tcg_temp_new();
4699 gen_load_gpr(t0, rt);
4700 switch (op2) {
4701 case OPC_WSBH:
4702 {
4703 TCGv t1 = tcg_temp_new();
4704 TCGv t2 = tcg_constant_tl(0x00FF00FF);
4705
4706 tcg_gen_shri_tl(t1, t0, 8);
4707 tcg_gen_and_tl(t1, t1, t2);
4708 tcg_gen_and_tl(t0, t0, t2);
4709 tcg_gen_shli_tl(t0, t0, 8);
4710 tcg_gen_or_tl(t0, t0, t1);
4711 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4712 }
4713 break;
4714 case OPC_SEB:
4715 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4716 break;
4717 case OPC_SEH:
4718 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4719 break;
4720 #if defined(TARGET_MIPS64)
4721 case OPC_DSBH:
4722 {
4723 TCGv t1 = tcg_temp_new();
4724 TCGv t2 = tcg_constant_tl(0x00FF00FF00FF00FFULL);
4725
4726 tcg_gen_shri_tl(t1, t0, 8);
4727 tcg_gen_and_tl(t1, t1, t2);
4728 tcg_gen_and_tl(t0, t0, t2);
4729 tcg_gen_shli_tl(t0, t0, 8);
4730 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4731 }
4732 break;
4733 case OPC_DSHD:
4734 {
4735 TCGv t1 = tcg_temp_new();
4736 TCGv t2 = tcg_constant_tl(0x0000FFFF0000FFFFULL);
4737
4738 tcg_gen_shri_tl(t1, t0, 16);
4739 tcg_gen_and_tl(t1, t1, t2);
4740 tcg_gen_and_tl(t0, t0, t2);
4741 tcg_gen_shli_tl(t0, t0, 16);
4742 tcg_gen_or_tl(t0, t0, t1);
4743 tcg_gen_shri_tl(t1, t0, 32);
4744 tcg_gen_shli_tl(t0, t0, 32);
4745 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4746 }
4747 break;
4748 #endif
4749 default:
4750 MIPS_INVAL("bsfhl");
4751 gen_reserved_instruction(ctx);
4752 return;
4753 }
4754 }
4755
gen_align_bits(DisasContext * ctx,int wordsz,int rd,int rs,int rt,int bits)4756 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
4757 int rt, int bits)
4758 {
4759 TCGv t0;
4760 if (rd == 0) {
4761 /* Treat as NOP. */
4762 return;
4763 }
4764 t0 = tcg_temp_new();
4765 if (bits == 0 || bits == wordsz) {
4766 if (bits == 0) {
4767 gen_load_gpr(t0, rt);
4768 } else {
4769 gen_load_gpr(t0, rs);
4770 }
4771 switch (wordsz) {
4772 case 32:
4773 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4774 break;
4775 #if defined(TARGET_MIPS64)
4776 case 64:
4777 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4778 break;
4779 #endif
4780 }
4781 } else {
4782 TCGv t1 = tcg_temp_new();
4783 gen_load_gpr(t0, rt);
4784 gen_load_gpr(t1, rs);
4785 switch (wordsz) {
4786 case 32:
4787 {
4788 TCGv_i64 t2 = tcg_temp_new_i64();
4789 tcg_gen_concat_tl_i64(t2, t1, t0);
4790 tcg_gen_shri_i64(t2, t2, 32 - bits);
4791 gen_move_low32(cpu_gpr[rd], t2);
4792 }
4793 break;
4794 #if defined(TARGET_MIPS64)
4795 case 64:
4796 tcg_gen_shli_tl(t0, t0, bits);
4797 tcg_gen_shri_tl(t1, t1, 64 - bits);
4798 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4799 break;
4800 #endif
4801 }
4802 }
4803 }
4804
gen_align(DisasContext * ctx,int wordsz,int rd,int rs,int rt,int bp)4805 void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp)
4806 {
4807 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
4808 }
4809
gen_bitswap(DisasContext * ctx,int opc,int rd,int rt)4810 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4811 {
4812 TCGv t0;
4813 if (rd == 0) {
4814 /* Treat as NOP. */
4815 return;
4816 }
4817 t0 = tcg_temp_new();
4818 gen_load_gpr(t0, rt);
4819 switch (opc) {
4820 case OPC_BITSWAP:
4821 gen_helper_bitswap(cpu_gpr[rd], t0);
4822 break;
4823 #if defined(TARGET_MIPS64)
4824 case OPC_DBITSWAP:
4825 gen_helper_dbitswap(cpu_gpr[rd], t0);
4826 break;
4827 #endif
4828 }
4829 }
4830
4831 #ifndef CONFIG_USER_ONLY
4832 /* CP0 (MMU and control) */
gen_mthc0_entrylo(TCGv arg,target_ulong off)4833 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4834 {
4835 TCGv_i64 t0 = tcg_temp_new_i64();
4836 TCGv_i64 t1 = tcg_temp_new_i64();
4837
4838 tcg_gen_ext_tl_i64(t0, arg);
4839 tcg_gen_ld_i64(t1, tcg_env, off);
4840 #if defined(TARGET_MIPS64)
4841 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4842 #else
4843 tcg_gen_concat32_i64(t1, t1, t0);
4844 #endif
4845 tcg_gen_st_i64(t1, tcg_env, off);
4846 }
4847
gen_mthc0_store64(TCGv arg,target_ulong off)4848 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4849 {
4850 TCGv_i64 t0 = tcg_temp_new_i64();
4851 TCGv_i64 t1 = tcg_temp_new_i64();
4852
4853 tcg_gen_ext_tl_i64(t0, arg);
4854 tcg_gen_ld_i64(t1, tcg_env, off);
4855 tcg_gen_concat32_i64(t1, t1, t0);
4856 tcg_gen_st_i64(t1, tcg_env, off);
4857 }
4858
gen_mfhc0_entrylo(TCGv arg,target_ulong off)4859 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4860 {
4861 TCGv_i64 t0 = tcg_temp_new_i64();
4862
4863 tcg_gen_ld_i64(t0, tcg_env, off);
4864 #if defined(TARGET_MIPS64)
4865 tcg_gen_shri_i64(t0, t0, 30);
4866 #else
4867 tcg_gen_shri_i64(t0, t0, 32);
4868 #endif
4869 gen_move_low32(arg, t0);
4870 }
4871
gen_mfhc0_load64(TCGv arg,target_ulong off,int shift)4872 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4873 {
4874 TCGv_i64 t0 = tcg_temp_new_i64();
4875
4876 tcg_gen_ld_i64(t0, tcg_env, off);
4877 tcg_gen_shri_i64(t0, t0, 32 + shift);
4878 gen_move_low32(arg, t0);
4879 }
4880
gen_mfc0_load32(TCGv arg,target_ulong off)4881 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4882 {
4883 TCGv_i32 t0 = tcg_temp_new_i32();
4884
4885 tcg_gen_ld_i32(t0, tcg_env, off);
4886 tcg_gen_ext_i32_tl(arg, t0);
4887 }
4888
gen_mfc0_load64(TCGv arg,target_ulong off)4889 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4890 {
4891 tcg_gen_ld_tl(arg, tcg_env, off);
4892 tcg_gen_ext32s_tl(arg, arg);
4893 }
4894
gen_mtc0_store32(TCGv arg,target_ulong off)4895 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
4896 {
4897 TCGv_i32 t0 = tcg_temp_new_i32();
4898
4899 tcg_gen_trunc_tl_i32(t0, arg);
4900 tcg_gen_st_i32(t0, tcg_env, off);
4901 }
4902
4903 #define CP0_CHECK(c) \
4904 do { \
4905 if (!(c)) { \
4906 goto cp0_unimplemented; \
4907 } \
4908 } while (0)
4909
gen_mfhc0(DisasContext * ctx,TCGv arg,int reg,int sel)4910 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4911 {
4912 const char *register_name = "invalid";
4913
4914 switch (reg) {
4915 case CP0_REGISTER_02:
4916 switch (sel) {
4917 case 0:
4918 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4919 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4920 register_name = "EntryLo0";
4921 break;
4922 default:
4923 goto cp0_unimplemented;
4924 }
4925 break;
4926 case CP0_REGISTER_03:
4927 switch (sel) {
4928 case CP0_REG03__ENTRYLO1:
4929 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4930 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4931 register_name = "EntryLo1";
4932 break;
4933 default:
4934 goto cp0_unimplemented;
4935 }
4936 break;
4937 case CP0_REGISTER_17:
4938 switch (sel) {
4939 case CP0_REG17__LLADDR:
4940 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
4941 ctx->CP0_LLAddr_shift);
4942 register_name = "LLAddr";
4943 break;
4944 case CP0_REG17__MAAR:
4945 CP0_CHECK(ctx->mrp);
4946 gen_helper_mfhc0_maar(arg, tcg_env);
4947 register_name = "MAAR";
4948 break;
4949 default:
4950 goto cp0_unimplemented;
4951 }
4952 break;
4953 case CP0_REGISTER_19:
4954 switch (sel) {
4955 case CP0_REG19__WATCHHI0:
4956 case CP0_REG19__WATCHHI1:
4957 case CP0_REG19__WATCHHI2:
4958 case CP0_REG19__WATCHHI3:
4959 case CP0_REG19__WATCHHI4:
4960 case CP0_REG19__WATCHHI5:
4961 case CP0_REG19__WATCHHI6:
4962 case CP0_REG19__WATCHHI7:
4963 /* upper 32 bits are only available when Config5MI != 0 */
4964 CP0_CHECK(ctx->mi);
4965 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
4966 register_name = "WatchHi";
4967 break;
4968 default:
4969 goto cp0_unimplemented;
4970 }
4971 break;
4972 case CP0_REGISTER_28:
4973 switch (sel) {
4974 case 0:
4975 case 2:
4976 case 4:
4977 case 6:
4978 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4979 register_name = "TagLo";
4980 break;
4981 default:
4982 goto cp0_unimplemented;
4983 }
4984 break;
4985 default:
4986 goto cp0_unimplemented;
4987 }
4988 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
4989 return;
4990
4991 cp0_unimplemented:
4992 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
4993 register_name, reg, sel);
4994 tcg_gen_movi_tl(arg, 0);
4995 }
4996
gen_mthc0(DisasContext * ctx,TCGv arg,int reg,int sel)4997 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4998 {
4999 const char *register_name = "invalid";
5000 uint64_t mask = ctx->PAMask >> 36;
5001
5002 switch (reg) {
5003 case CP0_REGISTER_02:
5004 switch (sel) {
5005 case 0:
5006 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5007 tcg_gen_andi_tl(arg, arg, mask);
5008 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5009 register_name = "EntryLo0";
5010 break;
5011 default:
5012 goto cp0_unimplemented;
5013 }
5014 break;
5015 case CP0_REGISTER_03:
5016 switch (sel) {
5017 case CP0_REG03__ENTRYLO1:
5018 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5019 tcg_gen_andi_tl(arg, arg, mask);
5020 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5021 register_name = "EntryLo1";
5022 break;
5023 default:
5024 goto cp0_unimplemented;
5025 }
5026 break;
5027 case CP0_REGISTER_17:
5028 switch (sel) {
5029 case CP0_REG17__LLADDR:
5030 /*
5031 * LLAddr is read-only (the only exception is bit 0 if LLB is
5032 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5033 * relevant for modern MIPS cores supporting MTHC0, therefore
5034 * treating MTHC0 to LLAddr as NOP.
5035 */
5036 register_name = "LLAddr";
5037 break;
5038 case CP0_REG17__MAAR:
5039 CP0_CHECK(ctx->mrp);
5040 gen_helper_mthc0_maar(tcg_env, arg);
5041 register_name = "MAAR";
5042 break;
5043 default:
5044 goto cp0_unimplemented;
5045 }
5046 break;
5047 case CP0_REGISTER_19:
5048 switch (sel) {
5049 case CP0_REG19__WATCHHI0:
5050 case CP0_REG19__WATCHHI1:
5051 case CP0_REG19__WATCHHI2:
5052 case CP0_REG19__WATCHHI3:
5053 case CP0_REG19__WATCHHI4:
5054 case CP0_REG19__WATCHHI5:
5055 case CP0_REG19__WATCHHI6:
5056 case CP0_REG19__WATCHHI7:
5057 /* upper 32 bits are only available when Config5MI != 0 */
5058 CP0_CHECK(ctx->mi);
5059 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5060 register_name = "WatchHi";
5061 break;
5062 default:
5063 goto cp0_unimplemented;
5064 }
5065 break;
5066 case CP0_REGISTER_28:
5067 switch (sel) {
5068 case 0:
5069 case 2:
5070 case 4:
5071 case 6:
5072 tcg_gen_andi_tl(arg, arg, mask);
5073 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5074 register_name = "TagLo";
5075 break;
5076 default:
5077 goto cp0_unimplemented;
5078 }
5079 break;
5080 default:
5081 goto cp0_unimplemented;
5082 }
5083 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5084 return;
5085
5086 cp0_unimplemented:
5087 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5088 register_name, reg, sel);
5089 }
5090
gen_mfc0_unimplemented(DisasContext * ctx,TCGv arg)5091 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5092 {
5093 if (ctx->insn_flags & ISA_MIPS_R6) {
5094 tcg_gen_movi_tl(arg, 0);
5095 } else {
5096 tcg_gen_movi_tl(arg, ~0);
5097 }
5098 }
5099
gen_mfc0(DisasContext * ctx,TCGv arg,int reg,int sel)5100 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5101 {
5102 const char *register_name = "invalid";
5103
5104 if (sel != 0) {
5105 check_insn(ctx, ISA_MIPS_R1);
5106 }
5107
5108 switch (reg) {
5109 case CP0_REGISTER_00:
5110 switch (sel) {
5111 case CP0_REG00__INDEX:
5112 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5113 register_name = "Index";
5114 break;
5115 case CP0_REG00__MVPCONTROL:
5116 CP0_CHECK(disas_mt_available(ctx));
5117 gen_helper_mfc0_mvpcontrol(arg, tcg_env);
5118 register_name = "MVPControl";
5119 break;
5120 case CP0_REG00__MVPCONF0:
5121 CP0_CHECK(disas_mt_available(ctx));
5122 gen_helper_mfc0_mvpconf0(arg, tcg_env);
5123 register_name = "MVPConf0";
5124 break;
5125 case CP0_REG00__MVPCONF1:
5126 CP0_CHECK(disas_mt_available(ctx));
5127 gen_helper_mfc0_mvpconf1(arg, tcg_env);
5128 register_name = "MVPConf1";
5129 break;
5130 case CP0_REG00__VPCONTROL:
5131 CP0_CHECK(ctx->vp);
5132 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5133 register_name = "VPControl";
5134 break;
5135 default:
5136 goto cp0_unimplemented;
5137 }
5138 break;
5139 case CP0_REGISTER_01:
5140 switch (sel) {
5141 case CP0_REG01__RANDOM:
5142 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
5143 gen_helper_mfc0_random(arg, tcg_env);
5144 register_name = "Random";
5145 break;
5146 case CP0_REG01__VPECONTROL:
5147 CP0_CHECK(disas_mt_available(ctx));
5148 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5149 register_name = "VPEControl";
5150 break;
5151 case CP0_REG01__VPECONF0:
5152 CP0_CHECK(disas_mt_available(ctx));
5153 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5154 register_name = "VPEConf0";
5155 break;
5156 case CP0_REG01__VPECONF1:
5157 CP0_CHECK(disas_mt_available(ctx));
5158 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5159 register_name = "VPEConf1";
5160 break;
5161 case CP0_REG01__YQMASK:
5162 CP0_CHECK(disas_mt_available(ctx));
5163 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5164 register_name = "YQMask";
5165 break;
5166 case CP0_REG01__VPESCHEDULE:
5167 CP0_CHECK(disas_mt_available(ctx));
5168 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5169 register_name = "VPESchedule";
5170 break;
5171 case CP0_REG01__VPESCHEFBACK:
5172 CP0_CHECK(disas_mt_available(ctx));
5173 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5174 register_name = "VPEScheFBack";
5175 break;
5176 case CP0_REG01__VPEOPT:
5177 CP0_CHECK(disas_mt_available(ctx));
5178 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5179 register_name = "VPEOpt";
5180 break;
5181 default:
5182 goto cp0_unimplemented;
5183 }
5184 break;
5185 case CP0_REGISTER_02:
5186 switch (sel) {
5187 case CP0_REG02__ENTRYLO0:
5188 {
5189 TCGv_i64 tmp = tcg_temp_new_i64();
5190 tcg_gen_ld_i64(tmp, tcg_env,
5191 offsetof(CPUMIPSState, CP0_EntryLo0));
5192 #if defined(TARGET_MIPS64)
5193 if (ctx->rxi) {
5194 /* Move RI/XI fields to bits 31:30 */
5195 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5196 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5197 }
5198 #endif
5199 gen_move_low32(arg, tmp);
5200 }
5201 register_name = "EntryLo0";
5202 break;
5203 case CP0_REG02__TCSTATUS:
5204 CP0_CHECK(disas_mt_available(ctx));
5205 gen_helper_mfc0_tcstatus(arg, tcg_env);
5206 register_name = "TCStatus";
5207 break;
5208 case CP0_REG02__TCBIND:
5209 CP0_CHECK(disas_mt_available(ctx));
5210 gen_helper_mfc0_tcbind(arg, tcg_env);
5211 register_name = "TCBind";
5212 break;
5213 case CP0_REG02__TCRESTART:
5214 CP0_CHECK(disas_mt_available(ctx));
5215 gen_helper_mfc0_tcrestart(arg, tcg_env);
5216 register_name = "TCRestart";
5217 break;
5218 case CP0_REG02__TCHALT:
5219 CP0_CHECK(disas_mt_available(ctx));
5220 gen_helper_mfc0_tchalt(arg, tcg_env);
5221 register_name = "TCHalt";
5222 break;
5223 case CP0_REG02__TCCONTEXT:
5224 CP0_CHECK(disas_mt_available(ctx));
5225 gen_helper_mfc0_tccontext(arg, tcg_env);
5226 register_name = "TCContext";
5227 break;
5228 case CP0_REG02__TCSCHEDULE:
5229 CP0_CHECK(disas_mt_available(ctx));
5230 gen_helper_mfc0_tcschedule(arg, tcg_env);
5231 register_name = "TCSchedule";
5232 break;
5233 case CP0_REG02__TCSCHEFBACK:
5234 CP0_CHECK(disas_mt_available(ctx));
5235 gen_helper_mfc0_tcschefback(arg, tcg_env);
5236 register_name = "TCScheFBack";
5237 break;
5238 default:
5239 goto cp0_unimplemented;
5240 }
5241 break;
5242 case CP0_REGISTER_03:
5243 switch (sel) {
5244 case CP0_REG03__ENTRYLO1:
5245 {
5246 TCGv_i64 tmp = tcg_temp_new_i64();
5247 tcg_gen_ld_i64(tmp, tcg_env,
5248 offsetof(CPUMIPSState, CP0_EntryLo1));
5249 #if defined(TARGET_MIPS64)
5250 if (ctx->rxi) {
5251 /* Move RI/XI fields to bits 31:30 */
5252 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5253 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5254 }
5255 #endif
5256 gen_move_low32(arg, tmp);
5257 }
5258 register_name = "EntryLo1";
5259 break;
5260 case CP0_REG03__GLOBALNUM:
5261 CP0_CHECK(ctx->vp);
5262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5263 register_name = "GlobalNumber";
5264 break;
5265 default:
5266 goto cp0_unimplemented;
5267 }
5268 break;
5269 case CP0_REGISTER_04:
5270 switch (sel) {
5271 case CP0_REG04__CONTEXT:
5272 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_Context));
5273 tcg_gen_ext32s_tl(arg, arg);
5274 register_name = "Context";
5275 break;
5276 case CP0_REG04__CONTEXTCONFIG:
5277 /* SmartMIPS ASE */
5278 /* gen_helper_mfc0_contextconfig(arg); */
5279 register_name = "ContextConfig";
5280 goto cp0_unimplemented;
5281 case CP0_REG04__USERLOCAL:
5282 CP0_CHECK(ctx->ulri);
5283 tcg_gen_ld_tl(arg, tcg_env,
5284 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5285 tcg_gen_ext32s_tl(arg, arg);
5286 register_name = "UserLocal";
5287 break;
5288 case CP0_REG04__MMID:
5289 CP0_CHECK(ctx->mi);
5290 gen_helper_mtc0_memorymapid(tcg_env, arg);
5291 register_name = "MMID";
5292 break;
5293 default:
5294 goto cp0_unimplemented;
5295 }
5296 break;
5297 case CP0_REGISTER_05:
5298 switch (sel) {
5299 case CP0_REG05__PAGEMASK:
5300 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5301 register_name = "PageMask";
5302 break;
5303 case CP0_REG05__PAGEGRAIN:
5304 check_insn(ctx, ISA_MIPS_R2);
5305 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5306 register_name = "PageGrain";
5307 break;
5308 case CP0_REG05__SEGCTL0:
5309 CP0_CHECK(ctx->sc);
5310 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5311 tcg_gen_ext32s_tl(arg, arg);
5312 register_name = "SegCtl0";
5313 break;
5314 case CP0_REG05__SEGCTL1:
5315 CP0_CHECK(ctx->sc);
5316 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5317 tcg_gen_ext32s_tl(arg, arg);
5318 register_name = "SegCtl1";
5319 break;
5320 case CP0_REG05__SEGCTL2:
5321 CP0_CHECK(ctx->sc);
5322 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5323 tcg_gen_ext32s_tl(arg, arg);
5324 register_name = "SegCtl2";
5325 break;
5326 case CP0_REG05__PWBASE:
5327 check_pw(ctx);
5328 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
5329 register_name = "PWBase";
5330 break;
5331 case CP0_REG05__PWFIELD:
5332 check_pw(ctx);
5333 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
5334 register_name = "PWField";
5335 break;
5336 case CP0_REG05__PWSIZE:
5337 check_pw(ctx);
5338 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
5339 register_name = "PWSize";
5340 break;
5341 default:
5342 goto cp0_unimplemented;
5343 }
5344 break;
5345 case CP0_REGISTER_06:
5346 switch (sel) {
5347 case CP0_REG06__WIRED:
5348 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5349 register_name = "Wired";
5350 break;
5351 case CP0_REG06__SRSCONF0:
5352 check_insn(ctx, ISA_MIPS_R2);
5353 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5354 register_name = "SRSConf0";
5355 break;
5356 case CP0_REG06__SRSCONF1:
5357 check_insn(ctx, ISA_MIPS_R2);
5358 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5359 register_name = "SRSConf1";
5360 break;
5361 case CP0_REG06__SRSCONF2:
5362 check_insn(ctx, ISA_MIPS_R2);
5363 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5364 register_name = "SRSConf2";
5365 break;
5366 case CP0_REG06__SRSCONF3:
5367 check_insn(ctx, ISA_MIPS_R2);
5368 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5369 register_name = "SRSConf3";
5370 break;
5371 case CP0_REG06__SRSCONF4:
5372 check_insn(ctx, ISA_MIPS_R2);
5373 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5374 register_name = "SRSConf4";
5375 break;
5376 case CP0_REG06__PWCTL:
5377 check_pw(ctx);
5378 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
5379 register_name = "PWCtl";
5380 break;
5381 default:
5382 goto cp0_unimplemented;
5383 }
5384 break;
5385 case CP0_REGISTER_07:
5386 switch (sel) {
5387 case CP0_REG07__HWRENA:
5388 check_insn(ctx, ISA_MIPS_R2);
5389 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5390 register_name = "HWREna";
5391 break;
5392 default:
5393 goto cp0_unimplemented;
5394 }
5395 break;
5396 case CP0_REGISTER_08:
5397 switch (sel) {
5398 case CP0_REG08__BADVADDR:
5399 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5400 tcg_gen_ext32s_tl(arg, arg);
5401 register_name = "BadVAddr";
5402 break;
5403 case CP0_REG08__BADINSTR:
5404 CP0_CHECK(ctx->bi);
5405 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5406 register_name = "BadInstr";
5407 break;
5408 case CP0_REG08__BADINSTRP:
5409 CP0_CHECK(ctx->bp);
5410 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5411 register_name = "BadInstrP";
5412 break;
5413 case CP0_REG08__BADINSTRX:
5414 CP0_CHECK(ctx->bi);
5415 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5416 tcg_gen_andi_tl(arg, arg, ~0xffff);
5417 register_name = "BadInstrX";
5418 break;
5419 default:
5420 goto cp0_unimplemented;
5421 }
5422 break;
5423 case CP0_REGISTER_09:
5424 switch (sel) {
5425 case CP0_REG09__COUNT:
5426 /* Mark as an IO operation because we read the time. */
5427 translator_io_start(&ctx->base);
5428
5429 gen_helper_mfc0_count(arg, tcg_env);
5430 /*
5431 * Break the TB to be able to take timer interrupts immediately
5432 * after reading count. DISAS_STOP isn't sufficient, we need to
5433 * ensure we break completely out of translated code.
5434 */
5435 gen_save_pc(ctx->base.pc_next + 4);
5436 ctx->base.is_jmp = DISAS_EXIT;
5437 register_name = "Count";
5438 break;
5439 default:
5440 goto cp0_unimplemented;
5441 }
5442 break;
5443 case CP0_REGISTER_10:
5444 switch (sel) {
5445 case CP0_REG10__ENTRYHI:
5446 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryHi));
5447 tcg_gen_ext32s_tl(arg, arg);
5448 register_name = "EntryHi";
5449 break;
5450 default:
5451 goto cp0_unimplemented;
5452 }
5453 break;
5454 case CP0_REGISTER_11:
5455 switch (sel) {
5456 case CP0_REG11__COMPARE:
5457 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5458 register_name = "Compare";
5459 break;
5460 /* 6,7 are implementation dependent */
5461 default:
5462 goto cp0_unimplemented;
5463 }
5464 break;
5465 case CP0_REGISTER_12:
5466 switch (sel) {
5467 case CP0_REG12__STATUS:
5468 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5469 register_name = "Status";
5470 break;
5471 case CP0_REG12__INTCTL:
5472 check_insn(ctx, ISA_MIPS_R2);
5473 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5474 register_name = "IntCtl";
5475 break;
5476 case CP0_REG12__SRSCTL:
5477 check_insn(ctx, ISA_MIPS_R2);
5478 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5479 register_name = "SRSCtl";
5480 break;
5481 case CP0_REG12__SRSMAP:
5482 check_insn(ctx, ISA_MIPS_R2);
5483 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5484 register_name = "SRSMap";
5485 break;
5486 default:
5487 goto cp0_unimplemented;
5488 }
5489 break;
5490 case CP0_REGISTER_13:
5491 switch (sel) {
5492 case CP0_REG13__CAUSE:
5493 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5494 register_name = "Cause";
5495 break;
5496 default:
5497 goto cp0_unimplemented;
5498 }
5499 break;
5500 case CP0_REGISTER_14:
5501 switch (sel) {
5502 case CP0_REG14__EPC:
5503 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
5504 tcg_gen_ext32s_tl(arg, arg);
5505 register_name = "EPC";
5506 break;
5507 default:
5508 goto cp0_unimplemented;
5509 }
5510 break;
5511 case CP0_REGISTER_15:
5512 switch (sel) {
5513 case CP0_REG15__PRID:
5514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5515 register_name = "PRid";
5516 break;
5517 case CP0_REG15__EBASE:
5518 check_insn(ctx, ISA_MIPS_R2);
5519 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EBase));
5520 tcg_gen_ext32s_tl(arg, arg);
5521 register_name = "EBase";
5522 break;
5523 case CP0_REG15__CMGCRBASE:
5524 check_insn(ctx, ISA_MIPS_R2);
5525 CP0_CHECK(ctx->cmgcr);
5526 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5527 tcg_gen_ext32s_tl(arg, arg);
5528 register_name = "CMGCRBase";
5529 break;
5530 default:
5531 goto cp0_unimplemented;
5532 }
5533 break;
5534 case CP0_REGISTER_16:
5535 switch (sel) {
5536 case CP0_REG16__CONFIG:
5537 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5538 register_name = "Config";
5539 break;
5540 case CP0_REG16__CONFIG1:
5541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5542 register_name = "Config1";
5543 break;
5544 case CP0_REG16__CONFIG2:
5545 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5546 register_name = "Config2";
5547 break;
5548 case CP0_REG16__CONFIG3:
5549 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5550 register_name = "Config3";
5551 break;
5552 case CP0_REG16__CONFIG4:
5553 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5554 register_name = "Config4";
5555 break;
5556 case CP0_REG16__CONFIG5:
5557 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5558 register_name = "Config5";
5559 break;
5560 /* 6,7 are implementation dependent */
5561 case CP0_REG16__CONFIG6:
5562 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5563 register_name = "Config6";
5564 break;
5565 case CP0_REG16__CONFIG7:
5566 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5567 register_name = "Config7";
5568 break;
5569 default:
5570 goto cp0_unimplemented;
5571 }
5572 break;
5573 case CP0_REGISTER_17:
5574 switch (sel) {
5575 case CP0_REG17__LLADDR:
5576 gen_helper_mfc0_lladdr(arg, tcg_env);
5577 register_name = "LLAddr";
5578 break;
5579 case CP0_REG17__MAAR:
5580 CP0_CHECK(ctx->mrp);
5581 gen_helper_mfc0_maar(arg, tcg_env);
5582 register_name = "MAAR";
5583 break;
5584 case CP0_REG17__MAARI:
5585 CP0_CHECK(ctx->mrp);
5586 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5587 register_name = "MAARI";
5588 break;
5589 default:
5590 goto cp0_unimplemented;
5591 }
5592 break;
5593 case CP0_REGISTER_18:
5594 switch (sel) {
5595 case CP0_REG18__WATCHLO0:
5596 case CP0_REG18__WATCHLO1:
5597 case CP0_REG18__WATCHLO2:
5598 case CP0_REG18__WATCHLO3:
5599 case CP0_REG18__WATCHLO4:
5600 case CP0_REG18__WATCHLO5:
5601 case CP0_REG18__WATCHLO6:
5602 case CP0_REG18__WATCHLO7:
5603 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5604 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5605 register_name = "WatchLo";
5606 break;
5607 default:
5608 goto cp0_unimplemented;
5609 }
5610 break;
5611 case CP0_REGISTER_19:
5612 switch (sel) {
5613 case CP0_REG19__WATCHHI0:
5614 case CP0_REG19__WATCHHI1:
5615 case CP0_REG19__WATCHHI2:
5616 case CP0_REG19__WATCHHI3:
5617 case CP0_REG19__WATCHHI4:
5618 case CP0_REG19__WATCHHI5:
5619 case CP0_REG19__WATCHHI6:
5620 case CP0_REG19__WATCHHI7:
5621 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5622 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5623 register_name = "WatchHi";
5624 break;
5625 default:
5626 goto cp0_unimplemented;
5627 }
5628 break;
5629 case CP0_REGISTER_20:
5630 switch (sel) {
5631 case CP0_REG20__XCONTEXT:
5632 #if defined(TARGET_MIPS64)
5633 check_insn(ctx, ISA_MIPS3);
5634 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_XContext));
5635 tcg_gen_ext32s_tl(arg, arg);
5636 register_name = "XContext";
5637 break;
5638 #endif
5639 default:
5640 goto cp0_unimplemented;
5641 }
5642 break;
5643 case CP0_REGISTER_21:
5644 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5645 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
5646 switch (sel) {
5647 case 0:
5648 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5649 register_name = "Framemask";
5650 break;
5651 default:
5652 goto cp0_unimplemented;
5653 }
5654 break;
5655 case CP0_REGISTER_22:
5656 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5657 register_name = "'Diagnostic"; /* implementation dependent */
5658 break;
5659 case CP0_REGISTER_23:
5660 switch (sel) {
5661 case CP0_REG23__DEBUG:
5662 gen_helper_mfc0_debug(arg, tcg_env); /* EJTAG support */
5663 register_name = "Debug";
5664 break;
5665 case CP0_REG23__TRACECONTROL:
5666 /* PDtrace support */
5667 /* gen_helper_mfc0_tracecontrol(arg); */
5668 register_name = "TraceControl";
5669 goto cp0_unimplemented;
5670 case CP0_REG23__TRACECONTROL2:
5671 /* PDtrace support */
5672 /* gen_helper_mfc0_tracecontrol2(arg); */
5673 register_name = "TraceControl2";
5674 goto cp0_unimplemented;
5675 case CP0_REG23__USERTRACEDATA1:
5676 /* PDtrace support */
5677 /* gen_helper_mfc0_usertracedata1(arg);*/
5678 register_name = "UserTraceData1";
5679 goto cp0_unimplemented;
5680 case CP0_REG23__TRACEIBPC:
5681 /* PDtrace support */
5682 /* gen_helper_mfc0_traceibpc(arg); */
5683 register_name = "TraceIBPC";
5684 goto cp0_unimplemented;
5685 case CP0_REG23__TRACEDBPC:
5686 /* PDtrace support */
5687 /* gen_helper_mfc0_tracedbpc(arg); */
5688 register_name = "TraceDBPC";
5689 goto cp0_unimplemented;
5690 default:
5691 goto cp0_unimplemented;
5692 }
5693 break;
5694 case CP0_REGISTER_24:
5695 switch (sel) {
5696 case CP0_REG24__DEPC:
5697 /* EJTAG support */
5698 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
5699 tcg_gen_ext32s_tl(arg, arg);
5700 register_name = "DEPC";
5701 break;
5702 default:
5703 goto cp0_unimplemented;
5704 }
5705 break;
5706 case CP0_REGISTER_25:
5707 switch (sel) {
5708 case CP0_REG25__PERFCTL0:
5709 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5710 register_name = "Performance0";
5711 break;
5712 case CP0_REG25__PERFCNT0:
5713 /* gen_helper_mfc0_performance1(arg); */
5714 register_name = "Performance1";
5715 goto cp0_unimplemented;
5716 case CP0_REG25__PERFCTL1:
5717 /* gen_helper_mfc0_performance2(arg); */
5718 register_name = "Performance2";
5719 goto cp0_unimplemented;
5720 case CP0_REG25__PERFCNT1:
5721 /* gen_helper_mfc0_performance3(arg); */
5722 register_name = "Performance3";
5723 goto cp0_unimplemented;
5724 case CP0_REG25__PERFCTL2:
5725 /* gen_helper_mfc0_performance4(arg); */
5726 register_name = "Performance4";
5727 goto cp0_unimplemented;
5728 case CP0_REG25__PERFCNT2:
5729 /* gen_helper_mfc0_performance5(arg); */
5730 register_name = "Performance5";
5731 goto cp0_unimplemented;
5732 case CP0_REG25__PERFCTL3:
5733 /* gen_helper_mfc0_performance6(arg); */
5734 register_name = "Performance6";
5735 goto cp0_unimplemented;
5736 case CP0_REG25__PERFCNT3:
5737 /* gen_helper_mfc0_performance7(arg); */
5738 register_name = "Performance7";
5739 goto cp0_unimplemented;
5740 default:
5741 goto cp0_unimplemented;
5742 }
5743 break;
5744 case CP0_REGISTER_26:
5745 switch (sel) {
5746 case CP0_REG26__ERRCTL:
5747 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5748 register_name = "ErrCtl";
5749 break;
5750 default:
5751 goto cp0_unimplemented;
5752 }
5753 break;
5754 case CP0_REGISTER_27:
5755 switch (sel) {
5756 case CP0_REG27__CACHERR:
5757 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5758 register_name = "CacheErr";
5759 break;
5760 default:
5761 goto cp0_unimplemented;
5762 }
5763 break;
5764 case CP0_REGISTER_28:
5765 switch (sel) {
5766 case CP0_REG28__TAGLO:
5767 case CP0_REG28__TAGLO1:
5768 case CP0_REG28__TAGLO2:
5769 case CP0_REG28__TAGLO3:
5770 {
5771 TCGv_i64 tmp = tcg_temp_new_i64();
5772 tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUMIPSState, CP0_TagLo));
5773 gen_move_low32(arg, tmp);
5774 }
5775 register_name = "TagLo";
5776 break;
5777 case CP0_REG28__DATALO:
5778 case CP0_REG28__DATALO1:
5779 case CP0_REG28__DATALO2:
5780 case CP0_REG28__DATALO3:
5781 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5782 register_name = "DataLo";
5783 break;
5784 default:
5785 goto cp0_unimplemented;
5786 }
5787 break;
5788 case CP0_REGISTER_29:
5789 switch (sel) {
5790 case CP0_REG29__TAGHI:
5791 case CP0_REG29__TAGHI1:
5792 case CP0_REG29__TAGHI2:
5793 case CP0_REG29__TAGHI3:
5794 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5795 register_name = "TagHi";
5796 break;
5797 case CP0_REG29__DATAHI:
5798 case CP0_REG29__DATAHI1:
5799 case CP0_REG29__DATAHI2:
5800 case CP0_REG29__DATAHI3:
5801 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5802 register_name = "DataHi";
5803 break;
5804 default:
5805 goto cp0_unimplemented;
5806 }
5807 break;
5808 case CP0_REGISTER_30:
5809 switch (sel) {
5810 case CP0_REG30__ERROREPC:
5811 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5812 tcg_gen_ext32s_tl(arg, arg);
5813 register_name = "ErrorEPC";
5814 break;
5815 default:
5816 goto cp0_unimplemented;
5817 }
5818 break;
5819 case CP0_REGISTER_31:
5820 switch (sel) {
5821 case CP0_REG31__DESAVE:
5822 /* EJTAG support */
5823 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5824 register_name = "DESAVE";
5825 break;
5826 case CP0_REG31__KSCRATCH1:
5827 case CP0_REG31__KSCRATCH2:
5828 case CP0_REG31__KSCRATCH3:
5829 case CP0_REG31__KSCRATCH4:
5830 case CP0_REG31__KSCRATCH5:
5831 case CP0_REG31__KSCRATCH6:
5832 CP0_CHECK(ctx->kscrexist & (1 << sel));
5833 tcg_gen_ld_tl(arg, tcg_env,
5834 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
5835 tcg_gen_ext32s_tl(arg, arg);
5836 register_name = "KScratch";
5837 break;
5838 default:
5839 goto cp0_unimplemented;
5840 }
5841 break;
5842 default:
5843 goto cp0_unimplemented;
5844 }
5845 trace_mips_translate_c0("mfc0", register_name, reg, sel);
5846 return;
5847
5848 cp0_unimplemented:
5849 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
5850 register_name, reg, sel);
5851 gen_mfc0_unimplemented(ctx, arg);
5852 }
5853
gen_mtc0(DisasContext * ctx,TCGv arg,int reg,int sel)5854 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5855 {
5856 const char *register_name = "invalid";
5857 bool icount;
5858
5859 if (sel != 0) {
5860 check_insn(ctx, ISA_MIPS_R1);
5861 }
5862
5863 icount = translator_io_start(&ctx->base);
5864
5865 switch (reg) {
5866 case CP0_REGISTER_00:
5867 switch (sel) {
5868 case CP0_REG00__INDEX:
5869 gen_helper_mtc0_index(tcg_env, arg);
5870 register_name = "Index";
5871 break;
5872 case CP0_REG00__MVPCONTROL:
5873 CP0_CHECK(disas_mt_available(ctx));
5874 gen_helper_mtc0_mvpcontrol(tcg_env, arg);
5875 register_name = "MVPControl";
5876 break;
5877 case CP0_REG00__MVPCONF0:
5878 CP0_CHECK(disas_mt_available(ctx));
5879 /* ignored */
5880 register_name = "MVPConf0";
5881 break;
5882 case CP0_REG00__MVPCONF1:
5883 CP0_CHECK(disas_mt_available(ctx));
5884 /* ignored */
5885 register_name = "MVPConf1";
5886 break;
5887 case CP0_REG00__VPCONTROL:
5888 CP0_CHECK(ctx->vp);
5889 /* ignored */
5890 register_name = "VPControl";
5891 break;
5892 default:
5893 goto cp0_unimplemented;
5894 }
5895 break;
5896 case CP0_REGISTER_01:
5897 switch (sel) {
5898 case CP0_REG01__RANDOM:
5899 /* ignored */
5900 register_name = "Random";
5901 break;
5902 case CP0_REG01__VPECONTROL:
5903 CP0_CHECK(disas_mt_available(ctx));
5904 gen_helper_mtc0_vpecontrol(tcg_env, arg);
5905 register_name = "VPEControl";
5906 break;
5907 case CP0_REG01__VPECONF0:
5908 CP0_CHECK(disas_mt_available(ctx));
5909 gen_helper_mtc0_vpeconf0(tcg_env, arg);
5910 register_name = "VPEConf0";
5911 break;
5912 case CP0_REG01__VPECONF1:
5913 CP0_CHECK(disas_mt_available(ctx));
5914 gen_helper_mtc0_vpeconf1(tcg_env, arg);
5915 register_name = "VPEConf1";
5916 break;
5917 case CP0_REG01__YQMASK:
5918 CP0_CHECK(disas_mt_available(ctx));
5919 gen_helper_mtc0_yqmask(tcg_env, arg);
5920 register_name = "YQMask";
5921 break;
5922 case CP0_REG01__VPESCHEDULE:
5923 CP0_CHECK(disas_mt_available(ctx));
5924 tcg_gen_st_tl(arg, tcg_env,
5925 offsetof(CPUMIPSState, CP0_VPESchedule));
5926 register_name = "VPESchedule";
5927 break;
5928 case CP0_REG01__VPESCHEFBACK:
5929 CP0_CHECK(disas_mt_available(ctx));
5930 tcg_gen_st_tl(arg, tcg_env,
5931 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5932 register_name = "VPEScheFBack";
5933 break;
5934 case CP0_REG01__VPEOPT:
5935 CP0_CHECK(disas_mt_available(ctx));
5936 gen_helper_mtc0_vpeopt(tcg_env, arg);
5937 register_name = "VPEOpt";
5938 break;
5939 default:
5940 goto cp0_unimplemented;
5941 }
5942 break;
5943 case CP0_REGISTER_02:
5944 switch (sel) {
5945 case CP0_REG02__ENTRYLO0:
5946 gen_helper_mtc0_entrylo0(tcg_env, arg);
5947 register_name = "EntryLo0";
5948 break;
5949 case CP0_REG02__TCSTATUS:
5950 CP0_CHECK(disas_mt_available(ctx));
5951 gen_helper_mtc0_tcstatus(tcg_env, arg);
5952 register_name = "TCStatus";
5953 break;
5954 case CP0_REG02__TCBIND:
5955 CP0_CHECK(disas_mt_available(ctx));
5956 gen_helper_mtc0_tcbind(tcg_env, arg);
5957 register_name = "TCBind";
5958 break;
5959 case CP0_REG02__TCRESTART:
5960 CP0_CHECK(disas_mt_available(ctx));
5961 gen_helper_mtc0_tcrestart(tcg_env, arg);
5962 register_name = "TCRestart";
5963 break;
5964 case CP0_REG02__TCHALT:
5965 CP0_CHECK(disas_mt_available(ctx));
5966 gen_helper_mtc0_tchalt(tcg_env, arg);
5967 register_name = "TCHalt";
5968 break;
5969 case CP0_REG02__TCCONTEXT:
5970 CP0_CHECK(disas_mt_available(ctx));
5971 gen_helper_mtc0_tccontext(tcg_env, arg);
5972 register_name = "TCContext";
5973 break;
5974 case CP0_REG02__TCSCHEDULE:
5975 CP0_CHECK(disas_mt_available(ctx));
5976 gen_helper_mtc0_tcschedule(tcg_env, arg);
5977 register_name = "TCSchedule";
5978 break;
5979 case CP0_REG02__TCSCHEFBACK:
5980 CP0_CHECK(disas_mt_available(ctx));
5981 gen_helper_mtc0_tcschefback(tcg_env, arg);
5982 register_name = "TCScheFBack";
5983 break;
5984 default:
5985 goto cp0_unimplemented;
5986 }
5987 break;
5988 case CP0_REGISTER_03:
5989 switch (sel) {
5990 case CP0_REG03__ENTRYLO1:
5991 gen_helper_mtc0_entrylo1(tcg_env, arg);
5992 register_name = "EntryLo1";
5993 break;
5994 case CP0_REG03__GLOBALNUM:
5995 CP0_CHECK(ctx->vp);
5996 /* ignored */
5997 register_name = "GlobalNumber";
5998 break;
5999 default:
6000 goto cp0_unimplemented;
6001 }
6002 break;
6003 case CP0_REGISTER_04:
6004 switch (sel) {
6005 case CP0_REG04__CONTEXT:
6006 gen_helper_mtc0_context(tcg_env, arg);
6007 register_name = "Context";
6008 break;
6009 case CP0_REG04__CONTEXTCONFIG:
6010 /* SmartMIPS ASE */
6011 /* gen_helper_mtc0_contextconfig(arg); */
6012 register_name = "ContextConfig";
6013 goto cp0_unimplemented;
6014 case CP0_REG04__USERLOCAL:
6015 CP0_CHECK(ctx->ulri);
6016 tcg_gen_st_tl(arg, tcg_env,
6017 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6018 register_name = "UserLocal";
6019 break;
6020 case CP0_REG04__MMID:
6021 CP0_CHECK(ctx->mi);
6022 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6023 register_name = "MMID";
6024 break;
6025 default:
6026 goto cp0_unimplemented;
6027 }
6028 break;
6029 case CP0_REGISTER_05:
6030 switch (sel) {
6031 case CP0_REG05__PAGEMASK:
6032 gen_helper_mtc0_pagemask(tcg_env, arg);
6033 register_name = "PageMask";
6034 break;
6035 case CP0_REG05__PAGEGRAIN:
6036 check_insn(ctx, ISA_MIPS_R2);
6037 gen_helper_mtc0_pagegrain(tcg_env, arg);
6038 register_name = "PageGrain";
6039 ctx->base.is_jmp = DISAS_STOP;
6040 break;
6041 case CP0_REG05__SEGCTL0:
6042 CP0_CHECK(ctx->sc);
6043 gen_helper_mtc0_segctl0(tcg_env, arg);
6044 register_name = "SegCtl0";
6045 break;
6046 case CP0_REG05__SEGCTL1:
6047 CP0_CHECK(ctx->sc);
6048 gen_helper_mtc0_segctl1(tcg_env, arg);
6049 register_name = "SegCtl1";
6050 break;
6051 case CP0_REG05__SEGCTL2:
6052 CP0_CHECK(ctx->sc);
6053 gen_helper_mtc0_segctl2(tcg_env, arg);
6054 register_name = "SegCtl2";
6055 break;
6056 case CP0_REG05__PWBASE:
6057 check_pw(ctx);
6058 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6059 register_name = "PWBase";
6060 break;
6061 case CP0_REG05__PWFIELD:
6062 check_pw(ctx);
6063 gen_helper_mtc0_pwfield(tcg_env, arg);
6064 register_name = "PWField";
6065 break;
6066 case CP0_REG05__PWSIZE:
6067 check_pw(ctx);
6068 gen_helper_mtc0_pwsize(tcg_env, arg);
6069 register_name = "PWSize";
6070 break;
6071 default:
6072 goto cp0_unimplemented;
6073 }
6074 break;
6075 case CP0_REGISTER_06:
6076 switch (sel) {
6077 case CP0_REG06__WIRED:
6078 gen_helper_mtc0_wired(tcg_env, arg);
6079 register_name = "Wired";
6080 break;
6081 case CP0_REG06__SRSCONF0:
6082 check_insn(ctx, ISA_MIPS_R2);
6083 gen_helper_mtc0_srsconf0(tcg_env, arg);
6084 register_name = "SRSConf0";
6085 break;
6086 case CP0_REG06__SRSCONF1:
6087 check_insn(ctx, ISA_MIPS_R2);
6088 gen_helper_mtc0_srsconf1(tcg_env, arg);
6089 register_name = "SRSConf1";
6090 break;
6091 case CP0_REG06__SRSCONF2:
6092 check_insn(ctx, ISA_MIPS_R2);
6093 gen_helper_mtc0_srsconf2(tcg_env, arg);
6094 register_name = "SRSConf2";
6095 break;
6096 case CP0_REG06__SRSCONF3:
6097 check_insn(ctx, ISA_MIPS_R2);
6098 gen_helper_mtc0_srsconf3(tcg_env, arg);
6099 register_name = "SRSConf3";
6100 break;
6101 case CP0_REG06__SRSCONF4:
6102 check_insn(ctx, ISA_MIPS_R2);
6103 gen_helper_mtc0_srsconf4(tcg_env, arg);
6104 register_name = "SRSConf4";
6105 break;
6106 case CP0_REG06__PWCTL:
6107 check_pw(ctx);
6108 gen_helper_mtc0_pwctl(tcg_env, arg);
6109 register_name = "PWCtl";
6110 break;
6111 default:
6112 goto cp0_unimplemented;
6113 }
6114 break;
6115 case CP0_REGISTER_07:
6116 switch (sel) {
6117 case CP0_REG07__HWRENA:
6118 check_insn(ctx, ISA_MIPS_R2);
6119 gen_helper_mtc0_hwrena(tcg_env, arg);
6120 ctx->base.is_jmp = DISAS_STOP;
6121 register_name = "HWREna";
6122 break;
6123 default:
6124 goto cp0_unimplemented;
6125 }
6126 break;
6127 case CP0_REGISTER_08:
6128 switch (sel) {
6129 case CP0_REG08__BADVADDR:
6130 /* ignored */
6131 register_name = "BadVAddr";
6132 break;
6133 case CP0_REG08__BADINSTR:
6134 /* ignored */
6135 register_name = "BadInstr";
6136 break;
6137 case CP0_REG08__BADINSTRP:
6138 /* ignored */
6139 register_name = "BadInstrP";
6140 break;
6141 case CP0_REG08__BADINSTRX:
6142 /* ignored */
6143 register_name = "BadInstrX";
6144 break;
6145 default:
6146 goto cp0_unimplemented;
6147 }
6148 break;
6149 case CP0_REGISTER_09:
6150 switch (sel) {
6151 case CP0_REG09__COUNT:
6152 gen_helper_mtc0_count(tcg_env, arg);
6153 register_name = "Count";
6154 break;
6155 default:
6156 goto cp0_unimplemented;
6157 }
6158 break;
6159 case CP0_REGISTER_10:
6160 switch (sel) {
6161 case CP0_REG10__ENTRYHI:
6162 gen_helper_mtc0_entryhi(tcg_env, arg);
6163 register_name = "EntryHi";
6164 break;
6165 default:
6166 goto cp0_unimplemented;
6167 }
6168 break;
6169 case CP0_REGISTER_11:
6170 switch (sel) {
6171 case CP0_REG11__COMPARE:
6172 gen_helper_mtc0_compare(tcg_env, arg);
6173 register_name = "Compare";
6174 break;
6175 /* 6,7 are implementation dependent */
6176 default:
6177 goto cp0_unimplemented;
6178 }
6179 break;
6180 case CP0_REGISTER_12:
6181 switch (sel) {
6182 case CP0_REG12__STATUS:
6183 save_cpu_state(ctx, 1);
6184 gen_helper_mtc0_status(tcg_env, arg);
6185 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6186 gen_save_pc(ctx->base.pc_next + 4);
6187 ctx->base.is_jmp = DISAS_EXIT;
6188 register_name = "Status";
6189 break;
6190 case CP0_REG12__INTCTL:
6191 check_insn(ctx, ISA_MIPS_R2);
6192 gen_helper_mtc0_intctl(tcg_env, arg);
6193 /* Stop translation as we may have switched the execution mode */
6194 ctx->base.is_jmp = DISAS_STOP;
6195 register_name = "IntCtl";
6196 break;
6197 case CP0_REG12__SRSCTL:
6198 check_insn(ctx, ISA_MIPS_R2);
6199 gen_helper_mtc0_srsctl(tcg_env, arg);
6200 /* Stop translation as we may have switched the execution mode */
6201 ctx->base.is_jmp = DISAS_STOP;
6202 register_name = "SRSCtl";
6203 break;
6204 case CP0_REG12__SRSMAP:
6205 check_insn(ctx, ISA_MIPS_R2);
6206 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6207 /* Stop translation as we may have switched the execution mode */
6208 ctx->base.is_jmp = DISAS_STOP;
6209 register_name = "SRSMap";
6210 break;
6211 default:
6212 goto cp0_unimplemented;
6213 }
6214 break;
6215 case CP0_REGISTER_13:
6216 switch (sel) {
6217 case CP0_REG13__CAUSE:
6218 save_cpu_state(ctx, 1);
6219 gen_helper_mtc0_cause(tcg_env, arg);
6220 /*
6221 * Stop translation as we may have triggered an interrupt.
6222 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6223 * translated code to check for pending interrupts.
6224 */
6225 gen_save_pc(ctx->base.pc_next + 4);
6226 ctx->base.is_jmp = DISAS_EXIT;
6227 register_name = "Cause";
6228 break;
6229 default:
6230 goto cp0_unimplemented;
6231 }
6232 break;
6233 case CP0_REGISTER_14:
6234 switch (sel) {
6235 case CP0_REG14__EPC:
6236 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
6237 register_name = "EPC";
6238 break;
6239 default:
6240 goto cp0_unimplemented;
6241 }
6242 break;
6243 case CP0_REGISTER_15:
6244 switch (sel) {
6245 case CP0_REG15__PRID:
6246 /* ignored */
6247 register_name = "PRid";
6248 break;
6249 case CP0_REG15__EBASE:
6250 check_insn(ctx, ISA_MIPS_R2);
6251 gen_helper_mtc0_ebase(tcg_env, arg);
6252 register_name = "EBase";
6253 break;
6254 default:
6255 goto cp0_unimplemented;
6256 }
6257 break;
6258 case CP0_REGISTER_16:
6259 switch (sel) {
6260 case CP0_REG16__CONFIG:
6261 gen_helper_mtc0_config0(tcg_env, arg);
6262 register_name = "Config";
6263 /* Stop translation as we may have switched the execution mode */
6264 ctx->base.is_jmp = DISAS_STOP;
6265 break;
6266 case CP0_REG16__CONFIG1:
6267 /* ignored, read only */
6268 register_name = "Config1";
6269 break;
6270 case CP0_REG16__CONFIG2:
6271 gen_helper_mtc0_config2(tcg_env, arg);
6272 register_name = "Config2";
6273 /* Stop translation as we may have switched the execution mode */
6274 ctx->base.is_jmp = DISAS_STOP;
6275 break;
6276 case CP0_REG16__CONFIG3:
6277 gen_helper_mtc0_config3(tcg_env, arg);
6278 register_name = "Config3";
6279 /* Stop translation as we may have switched the execution mode */
6280 ctx->base.is_jmp = DISAS_STOP;
6281 break;
6282 case CP0_REG16__CONFIG4:
6283 gen_helper_mtc0_config4(tcg_env, arg);
6284 register_name = "Config4";
6285 ctx->base.is_jmp = DISAS_STOP;
6286 break;
6287 case CP0_REG16__CONFIG5:
6288 gen_helper_mtc0_config5(tcg_env, arg);
6289 register_name = "Config5";
6290 /* Stop translation as we may have switched the execution mode */
6291 ctx->base.is_jmp = DISAS_STOP;
6292 break;
6293 /* 6,7 are implementation dependent */
6294 case CP0_REG16__CONFIG6:
6295 /* ignored */
6296 register_name = "Config6";
6297 break;
6298 case CP0_REG16__CONFIG7:
6299 /* ignored */
6300 register_name = "Config7";
6301 break;
6302 default:
6303 register_name = "Invalid config selector";
6304 goto cp0_unimplemented;
6305 }
6306 break;
6307 case CP0_REGISTER_17:
6308 switch (sel) {
6309 case CP0_REG17__LLADDR:
6310 gen_helper_mtc0_lladdr(tcg_env, arg);
6311 register_name = "LLAddr";
6312 break;
6313 case CP0_REG17__MAAR:
6314 CP0_CHECK(ctx->mrp);
6315 gen_helper_mtc0_maar(tcg_env, arg);
6316 register_name = "MAAR";
6317 break;
6318 case CP0_REG17__MAARI:
6319 CP0_CHECK(ctx->mrp);
6320 gen_helper_mtc0_maari(tcg_env, arg);
6321 register_name = "MAARI";
6322 break;
6323 default:
6324 goto cp0_unimplemented;
6325 }
6326 break;
6327 case CP0_REGISTER_18:
6328 switch (sel) {
6329 case CP0_REG18__WATCHLO0:
6330 case CP0_REG18__WATCHLO1:
6331 case CP0_REG18__WATCHLO2:
6332 case CP0_REG18__WATCHLO3:
6333 case CP0_REG18__WATCHLO4:
6334 case CP0_REG18__WATCHLO5:
6335 case CP0_REG18__WATCHLO6:
6336 case CP0_REG18__WATCHLO7:
6337 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6338 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6339 register_name = "WatchLo";
6340 break;
6341 default:
6342 goto cp0_unimplemented;
6343 }
6344 break;
6345 case CP0_REGISTER_19:
6346 switch (sel) {
6347 case CP0_REG19__WATCHHI0:
6348 case CP0_REG19__WATCHHI1:
6349 case CP0_REG19__WATCHHI2:
6350 case CP0_REG19__WATCHHI3:
6351 case CP0_REG19__WATCHHI4:
6352 case CP0_REG19__WATCHHI5:
6353 case CP0_REG19__WATCHHI6:
6354 case CP0_REG19__WATCHHI7:
6355 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6356 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6357 register_name = "WatchHi";
6358 break;
6359 default:
6360 goto cp0_unimplemented;
6361 }
6362 break;
6363 case CP0_REGISTER_20:
6364 switch (sel) {
6365 case CP0_REG20__XCONTEXT:
6366 #if defined(TARGET_MIPS64)
6367 check_insn(ctx, ISA_MIPS3);
6368 gen_helper_mtc0_xcontext(tcg_env, arg);
6369 register_name = "XContext";
6370 break;
6371 #endif
6372 default:
6373 goto cp0_unimplemented;
6374 }
6375 break;
6376 case CP0_REGISTER_21:
6377 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6378 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6379 switch (sel) {
6380 case 0:
6381 gen_helper_mtc0_framemask(tcg_env, arg);
6382 register_name = "Framemask";
6383 break;
6384 default:
6385 goto cp0_unimplemented;
6386 }
6387 break;
6388 case CP0_REGISTER_22:
6389 /* ignored */
6390 register_name = "Diagnostic"; /* implementation dependent */
6391 break;
6392 case CP0_REGISTER_23:
6393 switch (sel) {
6394 case CP0_REG23__DEBUG:
6395 gen_helper_mtc0_debug(tcg_env, arg); /* EJTAG support */
6396 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6397 gen_save_pc(ctx->base.pc_next + 4);
6398 ctx->base.is_jmp = DISAS_EXIT;
6399 register_name = "Debug";
6400 break;
6401 case CP0_REG23__TRACECONTROL:
6402 /* PDtrace support */
6403 /* gen_helper_mtc0_tracecontrol(tcg_env, arg); */
6404 register_name = "TraceControl";
6405 /* Stop translation as we may have switched the execution mode */
6406 ctx->base.is_jmp = DISAS_STOP;
6407 goto cp0_unimplemented;
6408 case CP0_REG23__TRACECONTROL2:
6409 /* PDtrace support */
6410 /* gen_helper_mtc0_tracecontrol2(tcg_env, arg); */
6411 register_name = "TraceControl2";
6412 /* Stop translation as we may have switched the execution mode */
6413 ctx->base.is_jmp = DISAS_STOP;
6414 goto cp0_unimplemented;
6415 case CP0_REG23__USERTRACEDATA1:
6416 /* Stop translation as we may have switched the execution mode */
6417 ctx->base.is_jmp = DISAS_STOP;
6418 /* PDtrace support */
6419 /* gen_helper_mtc0_usertracedata1(tcg_env, arg);*/
6420 register_name = "UserTraceData";
6421 /* Stop translation as we may have switched the execution mode */
6422 ctx->base.is_jmp = DISAS_STOP;
6423 goto cp0_unimplemented;
6424 case CP0_REG23__TRACEIBPC:
6425 /* PDtrace support */
6426 /* gen_helper_mtc0_traceibpc(tcg_env, arg); */
6427 /* Stop translation as we may have switched the execution mode */
6428 ctx->base.is_jmp = DISAS_STOP;
6429 register_name = "TraceIBPC";
6430 goto cp0_unimplemented;
6431 case CP0_REG23__TRACEDBPC:
6432 /* PDtrace support */
6433 /* gen_helper_mtc0_tracedbpc(tcg_env, arg); */
6434 /* Stop translation as we may have switched the execution mode */
6435 ctx->base.is_jmp = DISAS_STOP;
6436 register_name = "TraceDBPC";
6437 goto cp0_unimplemented;
6438 default:
6439 goto cp0_unimplemented;
6440 }
6441 break;
6442 case CP0_REGISTER_24:
6443 switch (sel) {
6444 case CP0_REG24__DEPC:
6445 /* EJTAG support */
6446 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
6447 register_name = "DEPC";
6448 break;
6449 default:
6450 goto cp0_unimplemented;
6451 }
6452 break;
6453 case CP0_REGISTER_25:
6454 switch (sel) {
6455 case CP0_REG25__PERFCTL0:
6456 gen_helper_mtc0_performance0(tcg_env, arg);
6457 register_name = "Performance0";
6458 break;
6459 case CP0_REG25__PERFCNT0:
6460 /* gen_helper_mtc0_performance1(arg); */
6461 register_name = "Performance1";
6462 goto cp0_unimplemented;
6463 case CP0_REG25__PERFCTL1:
6464 /* gen_helper_mtc0_performance2(arg); */
6465 register_name = "Performance2";
6466 goto cp0_unimplemented;
6467 case CP0_REG25__PERFCNT1:
6468 /* gen_helper_mtc0_performance3(arg); */
6469 register_name = "Performance3";
6470 goto cp0_unimplemented;
6471 case CP0_REG25__PERFCTL2:
6472 /* gen_helper_mtc0_performance4(arg); */
6473 register_name = "Performance4";
6474 goto cp0_unimplemented;
6475 case CP0_REG25__PERFCNT2:
6476 /* gen_helper_mtc0_performance5(arg); */
6477 register_name = "Performance5";
6478 goto cp0_unimplemented;
6479 case CP0_REG25__PERFCTL3:
6480 /* gen_helper_mtc0_performance6(arg); */
6481 register_name = "Performance6";
6482 goto cp0_unimplemented;
6483 case CP0_REG25__PERFCNT3:
6484 /* gen_helper_mtc0_performance7(arg); */
6485 register_name = "Performance7";
6486 goto cp0_unimplemented;
6487 default:
6488 goto cp0_unimplemented;
6489 }
6490 break;
6491 case CP0_REGISTER_26:
6492 switch (sel) {
6493 case CP0_REG26__ERRCTL:
6494 gen_helper_mtc0_errctl(tcg_env, arg);
6495 ctx->base.is_jmp = DISAS_STOP;
6496 register_name = "ErrCtl";
6497 break;
6498 default:
6499 goto cp0_unimplemented;
6500 }
6501 break;
6502 case CP0_REGISTER_27:
6503 switch (sel) {
6504 case CP0_REG27__CACHERR:
6505 /* ignored */
6506 register_name = "CacheErr";
6507 break;
6508 default:
6509 goto cp0_unimplemented;
6510 }
6511 break;
6512 case CP0_REGISTER_28:
6513 switch (sel) {
6514 case CP0_REG28__TAGLO:
6515 case CP0_REG28__TAGLO1:
6516 case CP0_REG28__TAGLO2:
6517 case CP0_REG28__TAGLO3:
6518 gen_helper_mtc0_taglo(tcg_env, arg);
6519 register_name = "TagLo";
6520 break;
6521 case CP0_REG28__DATALO:
6522 case CP0_REG28__DATALO1:
6523 case CP0_REG28__DATALO2:
6524 case CP0_REG28__DATALO3:
6525 gen_helper_mtc0_datalo(tcg_env, arg);
6526 register_name = "DataLo";
6527 break;
6528 default:
6529 goto cp0_unimplemented;
6530 }
6531 break;
6532 case CP0_REGISTER_29:
6533 switch (sel) {
6534 case CP0_REG29__TAGHI:
6535 case CP0_REG29__TAGHI1:
6536 case CP0_REG29__TAGHI2:
6537 case CP0_REG29__TAGHI3:
6538 gen_helper_mtc0_taghi(tcg_env, arg);
6539 register_name = "TagHi";
6540 break;
6541 case CP0_REG29__DATAHI:
6542 case CP0_REG29__DATAHI1:
6543 case CP0_REG29__DATAHI2:
6544 case CP0_REG29__DATAHI3:
6545 gen_helper_mtc0_datahi(tcg_env, arg);
6546 register_name = "DataHi";
6547 break;
6548 default:
6549 register_name = "invalid sel";
6550 goto cp0_unimplemented;
6551 }
6552 break;
6553 case CP0_REGISTER_30:
6554 switch (sel) {
6555 case CP0_REG30__ERROREPC:
6556 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6557 register_name = "ErrorEPC";
6558 break;
6559 default:
6560 goto cp0_unimplemented;
6561 }
6562 break;
6563 case CP0_REGISTER_31:
6564 switch (sel) {
6565 case CP0_REG31__DESAVE:
6566 /* EJTAG support */
6567 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6568 register_name = "DESAVE";
6569 break;
6570 case CP0_REG31__KSCRATCH1:
6571 case CP0_REG31__KSCRATCH2:
6572 case CP0_REG31__KSCRATCH3:
6573 case CP0_REG31__KSCRATCH4:
6574 case CP0_REG31__KSCRATCH5:
6575 case CP0_REG31__KSCRATCH6:
6576 CP0_CHECK(ctx->kscrexist & (1 << sel));
6577 tcg_gen_st_tl(arg, tcg_env,
6578 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6579 register_name = "KScratch";
6580 break;
6581 default:
6582 goto cp0_unimplemented;
6583 }
6584 break;
6585 default:
6586 goto cp0_unimplemented;
6587 }
6588 trace_mips_translate_c0("mtc0", register_name, reg, sel);
6589
6590 /* For simplicity assume that all writes can cause interrupts. */
6591 if (icount) {
6592 /*
6593 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6594 * translated code to check for pending interrupts.
6595 */
6596 gen_save_pc(ctx->base.pc_next + 4);
6597 ctx->base.is_jmp = DISAS_EXIT;
6598 }
6599 return;
6600
6601 cp0_unimplemented:
6602 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
6603 register_name, reg, sel);
6604 }
6605
6606 #if defined(TARGET_MIPS64)
gen_dmfc0(DisasContext * ctx,TCGv arg,int reg,int sel)6607 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6608 {
6609 const char *register_name = "invalid";
6610
6611 if (sel != 0) {
6612 check_insn(ctx, ISA_MIPS_R1);
6613 }
6614
6615 switch (reg) {
6616 case CP0_REGISTER_00:
6617 switch (sel) {
6618 case CP0_REG00__INDEX:
6619 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6620 register_name = "Index";
6621 break;
6622 case CP0_REG00__MVPCONTROL:
6623 CP0_CHECK(disas_mt_available(ctx));
6624 gen_helper_mfc0_mvpcontrol(arg, tcg_env);
6625 register_name = "MVPControl";
6626 break;
6627 case CP0_REG00__MVPCONF0:
6628 CP0_CHECK(disas_mt_available(ctx));
6629 gen_helper_mfc0_mvpconf0(arg, tcg_env);
6630 register_name = "MVPConf0";
6631 break;
6632 case CP0_REG00__MVPCONF1:
6633 CP0_CHECK(disas_mt_available(ctx));
6634 gen_helper_mfc0_mvpconf1(arg, tcg_env);
6635 register_name = "MVPConf1";
6636 break;
6637 case CP0_REG00__VPCONTROL:
6638 CP0_CHECK(ctx->vp);
6639 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6640 register_name = "VPControl";
6641 break;
6642 default:
6643 goto cp0_unimplemented;
6644 }
6645 break;
6646 case CP0_REGISTER_01:
6647 switch (sel) {
6648 case CP0_REG01__RANDOM:
6649 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6650 gen_helper_mfc0_random(arg, tcg_env);
6651 register_name = "Random";
6652 break;
6653 case CP0_REG01__VPECONTROL:
6654 CP0_CHECK(disas_mt_available(ctx));
6655 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6656 register_name = "VPEControl";
6657 break;
6658 case CP0_REG01__VPECONF0:
6659 CP0_CHECK(disas_mt_available(ctx));
6660 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6661 register_name = "VPEConf0";
6662 break;
6663 case CP0_REG01__VPECONF1:
6664 CP0_CHECK(disas_mt_available(ctx));
6665 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6666 register_name = "VPEConf1";
6667 break;
6668 case CP0_REG01__YQMASK:
6669 CP0_CHECK(disas_mt_available(ctx));
6670 tcg_gen_ld_tl(arg, tcg_env,
6671 offsetof(CPUMIPSState, CP0_YQMask));
6672 register_name = "YQMask";
6673 break;
6674 case CP0_REG01__VPESCHEDULE:
6675 CP0_CHECK(disas_mt_available(ctx));
6676 tcg_gen_ld_tl(arg, tcg_env,
6677 offsetof(CPUMIPSState, CP0_VPESchedule));
6678 register_name = "VPESchedule";
6679 break;
6680 case CP0_REG01__VPESCHEFBACK:
6681 CP0_CHECK(disas_mt_available(ctx));
6682 tcg_gen_ld_tl(arg, tcg_env,
6683 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6684 register_name = "VPEScheFBack";
6685 break;
6686 case CP0_REG01__VPEOPT:
6687 CP0_CHECK(disas_mt_available(ctx));
6688 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6689 register_name = "VPEOpt";
6690 break;
6691 default:
6692 goto cp0_unimplemented;
6693 }
6694 break;
6695 case CP0_REGISTER_02:
6696 switch (sel) {
6697 case CP0_REG02__ENTRYLO0:
6698 tcg_gen_ld_tl(arg, tcg_env,
6699 offsetof(CPUMIPSState, CP0_EntryLo0));
6700 register_name = "EntryLo0";
6701 break;
6702 case CP0_REG02__TCSTATUS:
6703 CP0_CHECK(disas_mt_available(ctx));
6704 gen_helper_mfc0_tcstatus(arg, tcg_env);
6705 register_name = "TCStatus";
6706 break;
6707 case CP0_REG02__TCBIND:
6708 CP0_CHECK(disas_mt_available(ctx));
6709 gen_helper_mfc0_tcbind(arg, tcg_env);
6710 register_name = "TCBind";
6711 break;
6712 case CP0_REG02__TCRESTART:
6713 CP0_CHECK(disas_mt_available(ctx));
6714 gen_helper_dmfc0_tcrestart(arg, tcg_env);
6715 register_name = "TCRestart";
6716 break;
6717 case CP0_REG02__TCHALT:
6718 CP0_CHECK(disas_mt_available(ctx));
6719 gen_helper_dmfc0_tchalt(arg, tcg_env);
6720 register_name = "TCHalt";
6721 break;
6722 case CP0_REG02__TCCONTEXT:
6723 CP0_CHECK(disas_mt_available(ctx));
6724 gen_helper_dmfc0_tccontext(arg, tcg_env);
6725 register_name = "TCContext";
6726 break;
6727 case CP0_REG02__TCSCHEDULE:
6728 CP0_CHECK(disas_mt_available(ctx));
6729 gen_helper_dmfc0_tcschedule(arg, tcg_env);
6730 register_name = "TCSchedule";
6731 break;
6732 case CP0_REG02__TCSCHEFBACK:
6733 CP0_CHECK(disas_mt_available(ctx));
6734 gen_helper_dmfc0_tcschefback(arg, tcg_env);
6735 register_name = "TCScheFBack";
6736 break;
6737 default:
6738 goto cp0_unimplemented;
6739 }
6740 break;
6741 case CP0_REGISTER_03:
6742 switch (sel) {
6743 case CP0_REG03__ENTRYLO1:
6744 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6745 register_name = "EntryLo1";
6746 break;
6747 case CP0_REG03__GLOBALNUM:
6748 CP0_CHECK(ctx->vp);
6749 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6750 register_name = "GlobalNumber";
6751 break;
6752 default:
6753 goto cp0_unimplemented;
6754 }
6755 break;
6756 case CP0_REGISTER_04:
6757 switch (sel) {
6758 case CP0_REG04__CONTEXT:
6759 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_Context));
6760 register_name = "Context";
6761 break;
6762 case CP0_REG04__CONTEXTCONFIG:
6763 /* SmartMIPS ASE */
6764 /* gen_helper_dmfc0_contextconfig(arg); */
6765 register_name = "ContextConfig";
6766 goto cp0_unimplemented;
6767 case CP0_REG04__USERLOCAL:
6768 CP0_CHECK(ctx->ulri);
6769 tcg_gen_ld_tl(arg, tcg_env,
6770 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6771 register_name = "UserLocal";
6772 break;
6773 case CP0_REG04__MMID:
6774 CP0_CHECK(ctx->mi);
6775 gen_helper_mtc0_memorymapid(tcg_env, arg);
6776 register_name = "MMID";
6777 break;
6778 default:
6779 goto cp0_unimplemented;
6780 }
6781 break;
6782 case CP0_REGISTER_05:
6783 switch (sel) {
6784 case CP0_REG05__PAGEMASK:
6785 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6786 register_name = "PageMask";
6787 break;
6788 case CP0_REG05__PAGEGRAIN:
6789 check_insn(ctx, ISA_MIPS_R2);
6790 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6791 register_name = "PageGrain";
6792 break;
6793 case CP0_REG05__SEGCTL0:
6794 CP0_CHECK(ctx->sc);
6795 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6796 register_name = "SegCtl0";
6797 break;
6798 case CP0_REG05__SEGCTL1:
6799 CP0_CHECK(ctx->sc);
6800 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6801 register_name = "SegCtl1";
6802 break;
6803 case CP0_REG05__SEGCTL2:
6804 CP0_CHECK(ctx->sc);
6805 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6806 register_name = "SegCtl2";
6807 break;
6808 case CP0_REG05__PWBASE:
6809 check_pw(ctx);
6810 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWBase));
6811 register_name = "PWBase";
6812 break;
6813 case CP0_REG05__PWFIELD:
6814 check_pw(ctx);
6815 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWField));
6816 register_name = "PWField";
6817 break;
6818 case CP0_REG05__PWSIZE:
6819 check_pw(ctx);
6820 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWSize));
6821 register_name = "PWSize";
6822 break;
6823 default:
6824 goto cp0_unimplemented;
6825 }
6826 break;
6827 case CP0_REGISTER_06:
6828 switch (sel) {
6829 case CP0_REG06__WIRED:
6830 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6831 register_name = "Wired";
6832 break;
6833 case CP0_REG06__SRSCONF0:
6834 check_insn(ctx, ISA_MIPS_R2);
6835 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6836 register_name = "SRSConf0";
6837 break;
6838 case CP0_REG06__SRSCONF1:
6839 check_insn(ctx, ISA_MIPS_R2);
6840 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6841 register_name = "SRSConf1";
6842 break;
6843 case CP0_REG06__SRSCONF2:
6844 check_insn(ctx, ISA_MIPS_R2);
6845 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6846 register_name = "SRSConf2";
6847 break;
6848 case CP0_REG06__SRSCONF3:
6849 check_insn(ctx, ISA_MIPS_R2);
6850 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6851 register_name = "SRSConf3";
6852 break;
6853 case CP0_REG06__SRSCONF4:
6854 check_insn(ctx, ISA_MIPS_R2);
6855 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6856 register_name = "SRSConf4";
6857 break;
6858 case CP0_REG06__PWCTL:
6859 check_pw(ctx);
6860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6861 register_name = "PWCtl";
6862 break;
6863 default:
6864 goto cp0_unimplemented;
6865 }
6866 break;
6867 case CP0_REGISTER_07:
6868 switch (sel) {
6869 case CP0_REG07__HWRENA:
6870 check_insn(ctx, ISA_MIPS_R2);
6871 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6872 register_name = "HWREna";
6873 break;
6874 default:
6875 goto cp0_unimplemented;
6876 }
6877 break;
6878 case CP0_REGISTER_08:
6879 switch (sel) {
6880 case CP0_REG08__BADVADDR:
6881 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6882 register_name = "BadVAddr";
6883 break;
6884 case CP0_REG08__BADINSTR:
6885 CP0_CHECK(ctx->bi);
6886 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6887 register_name = "BadInstr";
6888 break;
6889 case CP0_REG08__BADINSTRP:
6890 CP0_CHECK(ctx->bp);
6891 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6892 register_name = "BadInstrP";
6893 break;
6894 case CP0_REG08__BADINSTRX:
6895 CP0_CHECK(ctx->bi);
6896 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6897 tcg_gen_andi_tl(arg, arg, ~0xffff);
6898 register_name = "BadInstrX";
6899 break;
6900 default:
6901 goto cp0_unimplemented;
6902 }
6903 break;
6904 case CP0_REGISTER_09:
6905 switch (sel) {
6906 case CP0_REG09__COUNT:
6907 /* Mark as an IO operation because we read the time. */
6908 translator_io_start(&ctx->base);
6909 gen_helper_mfc0_count(arg, tcg_env);
6910 /*
6911 * Break the TB to be able to take timer interrupts immediately
6912 * after reading count. DISAS_STOP isn't sufficient, we need to
6913 * ensure we break completely out of translated code.
6914 */
6915 gen_save_pc(ctx->base.pc_next + 4);
6916 ctx->base.is_jmp = DISAS_EXIT;
6917 register_name = "Count";
6918 break;
6919 default:
6920 goto cp0_unimplemented;
6921 }
6922 break;
6923 case CP0_REGISTER_10:
6924 switch (sel) {
6925 case CP0_REG10__ENTRYHI:
6926 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryHi));
6927 register_name = "EntryHi";
6928 break;
6929 default:
6930 goto cp0_unimplemented;
6931 }
6932 break;
6933 case CP0_REGISTER_11:
6934 switch (sel) {
6935 case CP0_REG11__COMPARE:
6936 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6937 register_name = "Compare";
6938 break;
6939 /* 6,7 are implementation dependent */
6940 default:
6941 goto cp0_unimplemented;
6942 }
6943 break;
6944 case CP0_REGISTER_12:
6945 switch (sel) {
6946 case CP0_REG12__STATUS:
6947 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6948 register_name = "Status";
6949 break;
6950 case CP0_REG12__INTCTL:
6951 check_insn(ctx, ISA_MIPS_R2);
6952 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6953 register_name = "IntCtl";
6954 break;
6955 case CP0_REG12__SRSCTL:
6956 check_insn(ctx, ISA_MIPS_R2);
6957 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6958 register_name = "SRSCtl";
6959 break;
6960 case CP0_REG12__SRSMAP:
6961 check_insn(ctx, ISA_MIPS_R2);
6962 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6963 register_name = "SRSMap";
6964 break;
6965 default:
6966 goto cp0_unimplemented;
6967 }
6968 break;
6969 case CP0_REGISTER_13:
6970 switch (sel) {
6971 case CP0_REG13__CAUSE:
6972 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6973 register_name = "Cause";
6974 break;
6975 default:
6976 goto cp0_unimplemented;
6977 }
6978 break;
6979 case CP0_REGISTER_14:
6980 switch (sel) {
6981 case CP0_REG14__EPC:
6982 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
6983 register_name = "EPC";
6984 break;
6985 default:
6986 goto cp0_unimplemented;
6987 }
6988 break;
6989 case CP0_REGISTER_15:
6990 switch (sel) {
6991 case CP0_REG15__PRID:
6992 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6993 register_name = "PRid";
6994 break;
6995 case CP0_REG15__EBASE:
6996 check_insn(ctx, ISA_MIPS_R2);
6997 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EBase));
6998 register_name = "EBase";
6999 break;
7000 case CP0_REG15__CMGCRBASE:
7001 check_insn(ctx, ISA_MIPS_R2);
7002 CP0_CHECK(ctx->cmgcr);
7003 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7004 register_name = "CMGCRBase";
7005 break;
7006 default:
7007 goto cp0_unimplemented;
7008 }
7009 break;
7010 case CP0_REGISTER_16:
7011 switch (sel) {
7012 case CP0_REG16__CONFIG:
7013 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7014 register_name = "Config";
7015 break;
7016 case CP0_REG16__CONFIG1:
7017 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7018 register_name = "Config1";
7019 break;
7020 case CP0_REG16__CONFIG2:
7021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7022 register_name = "Config2";
7023 break;
7024 case CP0_REG16__CONFIG3:
7025 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7026 register_name = "Config3";
7027 break;
7028 case CP0_REG16__CONFIG4:
7029 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7030 register_name = "Config4";
7031 break;
7032 case CP0_REG16__CONFIG5:
7033 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7034 register_name = "Config5";
7035 break;
7036 /* 6,7 are implementation dependent */
7037 case CP0_REG16__CONFIG6:
7038 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7039 register_name = "Config6";
7040 break;
7041 case CP0_REG16__CONFIG7:
7042 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7043 register_name = "Config7";
7044 break;
7045 default:
7046 goto cp0_unimplemented;
7047 }
7048 break;
7049 case CP0_REGISTER_17:
7050 switch (sel) {
7051 case CP0_REG17__LLADDR:
7052 gen_helper_dmfc0_lladdr(arg, tcg_env);
7053 register_name = "LLAddr";
7054 break;
7055 case CP0_REG17__MAAR:
7056 CP0_CHECK(ctx->mrp);
7057 gen_helper_dmfc0_maar(arg, tcg_env);
7058 register_name = "MAAR";
7059 break;
7060 case CP0_REG17__MAARI:
7061 CP0_CHECK(ctx->mrp);
7062 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7063 register_name = "MAARI";
7064 break;
7065 default:
7066 goto cp0_unimplemented;
7067 }
7068 break;
7069 case CP0_REGISTER_18:
7070 switch (sel) {
7071 case CP0_REG18__WATCHLO0:
7072 case CP0_REG18__WATCHLO1:
7073 case CP0_REG18__WATCHLO2:
7074 case CP0_REG18__WATCHLO3:
7075 case CP0_REG18__WATCHLO4:
7076 case CP0_REG18__WATCHLO5:
7077 case CP0_REG18__WATCHLO6:
7078 case CP0_REG18__WATCHLO7:
7079 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7080 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7081 register_name = "WatchLo";
7082 break;
7083 default:
7084 goto cp0_unimplemented;
7085 }
7086 break;
7087 case CP0_REGISTER_19:
7088 switch (sel) {
7089 case CP0_REG19__WATCHHI0:
7090 case CP0_REG19__WATCHHI1:
7091 case CP0_REG19__WATCHHI2:
7092 case CP0_REG19__WATCHHI3:
7093 case CP0_REG19__WATCHHI4:
7094 case CP0_REG19__WATCHHI5:
7095 case CP0_REG19__WATCHHI6:
7096 case CP0_REG19__WATCHHI7:
7097 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7098 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
7099 register_name = "WatchHi";
7100 break;
7101 default:
7102 goto cp0_unimplemented;
7103 }
7104 break;
7105 case CP0_REGISTER_20:
7106 switch (sel) {
7107 case CP0_REG20__XCONTEXT:
7108 check_insn(ctx, ISA_MIPS3);
7109 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_XContext));
7110 register_name = "XContext";
7111 break;
7112 default:
7113 goto cp0_unimplemented;
7114 }
7115 break;
7116 case CP0_REGISTER_21:
7117 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7118 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7119 switch (sel) {
7120 case 0:
7121 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7122 register_name = "Framemask";
7123 break;
7124 default:
7125 goto cp0_unimplemented;
7126 }
7127 break;
7128 case CP0_REGISTER_22:
7129 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7130 register_name = "'Diagnostic"; /* implementation dependent */
7131 break;
7132 case CP0_REGISTER_23:
7133 switch (sel) {
7134 case CP0_REG23__DEBUG:
7135 gen_helper_mfc0_debug(arg, tcg_env); /* EJTAG support */
7136 register_name = "Debug";
7137 break;
7138 case CP0_REG23__TRACECONTROL:
7139 /* PDtrace support */
7140 /* gen_helper_dmfc0_tracecontrol(arg, tcg_env); */
7141 register_name = "TraceControl";
7142 goto cp0_unimplemented;
7143 case CP0_REG23__TRACECONTROL2:
7144 /* PDtrace support */
7145 /* gen_helper_dmfc0_tracecontrol2(arg, tcg_env); */
7146 register_name = "TraceControl2";
7147 goto cp0_unimplemented;
7148 case CP0_REG23__USERTRACEDATA1:
7149 /* PDtrace support */
7150 /* gen_helper_dmfc0_usertracedata1(arg, tcg_env);*/
7151 register_name = "UserTraceData1";
7152 goto cp0_unimplemented;
7153 case CP0_REG23__TRACEIBPC:
7154 /* PDtrace support */
7155 /* gen_helper_dmfc0_traceibpc(arg, tcg_env); */
7156 register_name = "TraceIBPC";
7157 goto cp0_unimplemented;
7158 case CP0_REG23__TRACEDBPC:
7159 /* PDtrace support */
7160 /* gen_helper_dmfc0_tracedbpc(arg, tcg_env); */
7161 register_name = "TraceDBPC";
7162 goto cp0_unimplemented;
7163 default:
7164 goto cp0_unimplemented;
7165 }
7166 break;
7167 case CP0_REGISTER_24:
7168 switch (sel) {
7169 case CP0_REG24__DEPC:
7170 /* EJTAG support */
7171 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
7172 register_name = "DEPC";
7173 break;
7174 default:
7175 goto cp0_unimplemented;
7176 }
7177 break;
7178 case CP0_REGISTER_25:
7179 switch (sel) {
7180 case CP0_REG25__PERFCTL0:
7181 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7182 register_name = "Performance0";
7183 break;
7184 case CP0_REG25__PERFCNT0:
7185 /* gen_helper_dmfc0_performance1(arg); */
7186 register_name = "Performance1";
7187 goto cp0_unimplemented;
7188 case CP0_REG25__PERFCTL1:
7189 /* gen_helper_dmfc0_performance2(arg); */
7190 register_name = "Performance2";
7191 goto cp0_unimplemented;
7192 case CP0_REG25__PERFCNT1:
7193 /* gen_helper_dmfc0_performance3(arg); */
7194 register_name = "Performance3";
7195 goto cp0_unimplemented;
7196 case CP0_REG25__PERFCTL2:
7197 /* gen_helper_dmfc0_performance4(arg); */
7198 register_name = "Performance4";
7199 goto cp0_unimplemented;
7200 case CP0_REG25__PERFCNT2:
7201 /* gen_helper_dmfc0_performance5(arg); */
7202 register_name = "Performance5";
7203 goto cp0_unimplemented;
7204 case CP0_REG25__PERFCTL3:
7205 /* gen_helper_dmfc0_performance6(arg); */
7206 register_name = "Performance6";
7207 goto cp0_unimplemented;
7208 case CP0_REG25__PERFCNT3:
7209 /* gen_helper_dmfc0_performance7(arg); */
7210 register_name = "Performance7";
7211 goto cp0_unimplemented;
7212 default:
7213 goto cp0_unimplemented;
7214 }
7215 break;
7216 case CP0_REGISTER_26:
7217 switch (sel) {
7218 case CP0_REG26__ERRCTL:
7219 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7220 register_name = "ErrCtl";
7221 break;
7222 default:
7223 goto cp0_unimplemented;
7224 }
7225 break;
7226 case CP0_REGISTER_27:
7227 switch (sel) {
7228 /* ignored */
7229 case CP0_REG27__CACHERR:
7230 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7231 register_name = "CacheErr";
7232 break;
7233 default:
7234 goto cp0_unimplemented;
7235 }
7236 break;
7237 case CP0_REGISTER_28:
7238 switch (sel) {
7239 case CP0_REG28__TAGLO:
7240 case CP0_REG28__TAGLO1:
7241 case CP0_REG28__TAGLO2:
7242 case CP0_REG28__TAGLO3:
7243 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7244 register_name = "TagLo";
7245 break;
7246 case CP0_REG28__DATALO:
7247 case CP0_REG28__DATALO1:
7248 case CP0_REG28__DATALO2:
7249 case CP0_REG28__DATALO3:
7250 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7251 register_name = "DataLo";
7252 break;
7253 default:
7254 goto cp0_unimplemented;
7255 }
7256 break;
7257 case CP0_REGISTER_29:
7258 switch (sel) {
7259 case CP0_REG29__TAGHI:
7260 case CP0_REG29__TAGHI1:
7261 case CP0_REG29__TAGHI2:
7262 case CP0_REG29__TAGHI3:
7263 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7264 register_name = "TagHi";
7265 break;
7266 case CP0_REG29__DATAHI:
7267 case CP0_REG29__DATAHI1:
7268 case CP0_REG29__DATAHI2:
7269 case CP0_REG29__DATAHI3:
7270 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7271 register_name = "DataHi";
7272 break;
7273 default:
7274 goto cp0_unimplemented;
7275 }
7276 break;
7277 case CP0_REGISTER_30:
7278 switch (sel) {
7279 case CP0_REG30__ERROREPC:
7280 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7281 register_name = "ErrorEPC";
7282 break;
7283 default:
7284 goto cp0_unimplemented;
7285 }
7286 break;
7287 case CP0_REGISTER_31:
7288 switch (sel) {
7289 case CP0_REG31__DESAVE:
7290 /* EJTAG support */
7291 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7292 register_name = "DESAVE";
7293 break;
7294 case CP0_REG31__KSCRATCH1:
7295 case CP0_REG31__KSCRATCH2:
7296 case CP0_REG31__KSCRATCH3:
7297 case CP0_REG31__KSCRATCH4:
7298 case CP0_REG31__KSCRATCH5:
7299 case CP0_REG31__KSCRATCH6:
7300 CP0_CHECK(ctx->kscrexist & (1 << sel));
7301 tcg_gen_ld_tl(arg, tcg_env,
7302 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7303 register_name = "KScratch";
7304 break;
7305 default:
7306 goto cp0_unimplemented;
7307 }
7308 break;
7309 default:
7310 goto cp0_unimplemented;
7311 }
7312 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
7313 return;
7314
7315 cp0_unimplemented:
7316 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
7317 register_name, reg, sel);
7318 gen_mfc0_unimplemented(ctx, arg);
7319 }
7320
gen_dmtc0(DisasContext * ctx,TCGv arg,int reg,int sel)7321 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7322 {
7323 const char *register_name = "invalid";
7324 bool icount;
7325
7326 if (sel != 0) {
7327 check_insn(ctx, ISA_MIPS_R1);
7328 }
7329
7330 icount = translator_io_start(&ctx->base);
7331
7332 switch (reg) {
7333 case CP0_REGISTER_00:
7334 switch (sel) {
7335 case CP0_REG00__INDEX:
7336 gen_helper_mtc0_index(tcg_env, arg);
7337 register_name = "Index";
7338 break;
7339 case CP0_REG00__MVPCONTROL:
7340 CP0_CHECK(disas_mt_available(ctx));
7341 gen_helper_mtc0_mvpcontrol(tcg_env, arg);
7342 register_name = "MVPControl";
7343 break;
7344 case CP0_REG00__MVPCONF0:
7345 CP0_CHECK(disas_mt_available(ctx));
7346 /* ignored */
7347 register_name = "MVPConf0";
7348 break;
7349 case CP0_REG00__MVPCONF1:
7350 CP0_CHECK(disas_mt_available(ctx));
7351 /* ignored */
7352 register_name = "MVPConf1";
7353 break;
7354 case CP0_REG00__VPCONTROL:
7355 CP0_CHECK(ctx->vp);
7356 /* ignored */
7357 register_name = "VPControl";
7358 break;
7359 default:
7360 goto cp0_unimplemented;
7361 }
7362 break;
7363 case CP0_REGISTER_01:
7364 switch (sel) {
7365 case CP0_REG01__RANDOM:
7366 /* ignored */
7367 register_name = "Random";
7368 break;
7369 case CP0_REG01__VPECONTROL:
7370 CP0_CHECK(disas_mt_available(ctx));
7371 gen_helper_mtc0_vpecontrol(tcg_env, arg);
7372 register_name = "VPEControl";
7373 break;
7374 case CP0_REG01__VPECONF0:
7375 CP0_CHECK(disas_mt_available(ctx));
7376 gen_helper_mtc0_vpeconf0(tcg_env, arg);
7377 register_name = "VPEConf0";
7378 break;
7379 case CP0_REG01__VPECONF1:
7380 CP0_CHECK(disas_mt_available(ctx));
7381 gen_helper_mtc0_vpeconf1(tcg_env, arg);
7382 register_name = "VPEConf1";
7383 break;
7384 case CP0_REG01__YQMASK:
7385 CP0_CHECK(disas_mt_available(ctx));
7386 gen_helper_mtc0_yqmask(tcg_env, arg);
7387 register_name = "YQMask";
7388 break;
7389 case CP0_REG01__VPESCHEDULE:
7390 CP0_CHECK(disas_mt_available(ctx));
7391 tcg_gen_st_tl(arg, tcg_env,
7392 offsetof(CPUMIPSState, CP0_VPESchedule));
7393 register_name = "VPESchedule";
7394 break;
7395 case CP0_REG01__VPESCHEFBACK:
7396 CP0_CHECK(disas_mt_available(ctx));
7397 tcg_gen_st_tl(arg, tcg_env,
7398 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7399 register_name = "VPEScheFBack";
7400 break;
7401 case CP0_REG01__VPEOPT:
7402 CP0_CHECK(disas_mt_available(ctx));
7403 gen_helper_mtc0_vpeopt(tcg_env, arg);
7404 register_name = "VPEOpt";
7405 break;
7406 default:
7407 goto cp0_unimplemented;
7408 }
7409 break;
7410 case CP0_REGISTER_02:
7411 switch (sel) {
7412 case CP0_REG02__ENTRYLO0:
7413 gen_helper_dmtc0_entrylo0(tcg_env, arg);
7414 register_name = "EntryLo0";
7415 break;
7416 case CP0_REG02__TCSTATUS:
7417 CP0_CHECK(disas_mt_available(ctx));
7418 gen_helper_mtc0_tcstatus(tcg_env, arg);
7419 register_name = "TCStatus";
7420 break;
7421 case CP0_REG02__TCBIND:
7422 CP0_CHECK(disas_mt_available(ctx));
7423 gen_helper_mtc0_tcbind(tcg_env, arg);
7424 register_name = "TCBind";
7425 break;
7426 case CP0_REG02__TCRESTART:
7427 CP0_CHECK(disas_mt_available(ctx));
7428 gen_helper_mtc0_tcrestart(tcg_env, arg);
7429 register_name = "TCRestart";
7430 break;
7431 case CP0_REG02__TCHALT:
7432 CP0_CHECK(disas_mt_available(ctx));
7433 gen_helper_mtc0_tchalt(tcg_env, arg);
7434 register_name = "TCHalt";
7435 break;
7436 case CP0_REG02__TCCONTEXT:
7437 CP0_CHECK(disas_mt_available(ctx));
7438 gen_helper_mtc0_tccontext(tcg_env, arg);
7439 register_name = "TCContext";
7440 break;
7441 case CP0_REG02__TCSCHEDULE:
7442 CP0_CHECK(disas_mt_available(ctx));
7443 gen_helper_mtc0_tcschedule(tcg_env, arg);
7444 register_name = "TCSchedule";
7445 break;
7446 case CP0_REG02__TCSCHEFBACK:
7447 CP0_CHECK(disas_mt_available(ctx));
7448 gen_helper_mtc0_tcschefback(tcg_env, arg);
7449 register_name = "TCScheFBack";
7450 break;
7451 default:
7452 goto cp0_unimplemented;
7453 }
7454 break;
7455 case CP0_REGISTER_03:
7456 switch (sel) {
7457 case CP0_REG03__ENTRYLO1:
7458 gen_helper_dmtc0_entrylo1(tcg_env, arg);
7459 register_name = "EntryLo1";
7460 break;
7461 case CP0_REG03__GLOBALNUM:
7462 CP0_CHECK(ctx->vp);
7463 /* ignored */
7464 register_name = "GlobalNumber";
7465 break;
7466 default:
7467 goto cp0_unimplemented;
7468 }
7469 break;
7470 case CP0_REGISTER_04:
7471 switch (sel) {
7472 case CP0_REG04__CONTEXT:
7473 gen_helper_mtc0_context(tcg_env, arg);
7474 register_name = "Context";
7475 break;
7476 case CP0_REG04__CONTEXTCONFIG:
7477 /* SmartMIPS ASE */
7478 /* gen_helper_dmtc0_contextconfig(arg); */
7479 register_name = "ContextConfig";
7480 goto cp0_unimplemented;
7481 case CP0_REG04__USERLOCAL:
7482 CP0_CHECK(ctx->ulri);
7483 tcg_gen_st_tl(arg, tcg_env,
7484 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7485 register_name = "UserLocal";
7486 break;
7487 case CP0_REG04__MMID:
7488 CP0_CHECK(ctx->mi);
7489 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7490 register_name = "MMID";
7491 break;
7492 default:
7493 goto cp0_unimplemented;
7494 }
7495 break;
7496 case CP0_REGISTER_05:
7497 switch (sel) {
7498 case CP0_REG05__PAGEMASK:
7499 gen_helper_mtc0_pagemask(tcg_env, arg);
7500 register_name = "PageMask";
7501 break;
7502 case CP0_REG05__PAGEGRAIN:
7503 check_insn(ctx, ISA_MIPS_R2);
7504 gen_helper_mtc0_pagegrain(tcg_env, arg);
7505 register_name = "PageGrain";
7506 break;
7507 case CP0_REG05__SEGCTL0:
7508 CP0_CHECK(ctx->sc);
7509 gen_helper_mtc0_segctl0(tcg_env, arg);
7510 register_name = "SegCtl0";
7511 break;
7512 case CP0_REG05__SEGCTL1:
7513 CP0_CHECK(ctx->sc);
7514 gen_helper_mtc0_segctl1(tcg_env, arg);
7515 register_name = "SegCtl1";
7516 break;
7517 case CP0_REG05__SEGCTL2:
7518 CP0_CHECK(ctx->sc);
7519 gen_helper_mtc0_segctl2(tcg_env, arg);
7520 register_name = "SegCtl2";
7521 break;
7522 case CP0_REG05__PWBASE:
7523 check_pw(ctx);
7524 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWBase));
7525 register_name = "PWBase";
7526 break;
7527 case CP0_REG05__PWFIELD:
7528 check_pw(ctx);
7529 gen_helper_mtc0_pwfield(tcg_env, arg);
7530 register_name = "PWField";
7531 break;
7532 case CP0_REG05__PWSIZE:
7533 check_pw(ctx);
7534 gen_helper_mtc0_pwsize(tcg_env, arg);
7535 register_name = "PWSize";
7536 break;
7537 default:
7538 goto cp0_unimplemented;
7539 }
7540 break;
7541 case CP0_REGISTER_06:
7542 switch (sel) {
7543 case CP0_REG06__WIRED:
7544 gen_helper_mtc0_wired(tcg_env, arg);
7545 register_name = "Wired";
7546 break;
7547 case CP0_REG06__SRSCONF0:
7548 check_insn(ctx, ISA_MIPS_R2);
7549 gen_helper_mtc0_srsconf0(tcg_env, arg);
7550 register_name = "SRSConf0";
7551 break;
7552 case CP0_REG06__SRSCONF1:
7553 check_insn(ctx, ISA_MIPS_R2);
7554 gen_helper_mtc0_srsconf1(tcg_env, arg);
7555 register_name = "SRSConf1";
7556 break;
7557 case CP0_REG06__SRSCONF2:
7558 check_insn(ctx, ISA_MIPS_R2);
7559 gen_helper_mtc0_srsconf2(tcg_env, arg);
7560 register_name = "SRSConf2";
7561 break;
7562 case CP0_REG06__SRSCONF3:
7563 check_insn(ctx, ISA_MIPS_R2);
7564 gen_helper_mtc0_srsconf3(tcg_env, arg);
7565 register_name = "SRSConf3";
7566 break;
7567 case CP0_REG06__SRSCONF4:
7568 check_insn(ctx, ISA_MIPS_R2);
7569 gen_helper_mtc0_srsconf4(tcg_env, arg);
7570 register_name = "SRSConf4";
7571 break;
7572 case CP0_REG06__PWCTL:
7573 check_pw(ctx);
7574 gen_helper_mtc0_pwctl(tcg_env, arg);
7575 register_name = "PWCtl";
7576 break;
7577 default:
7578 goto cp0_unimplemented;
7579 }
7580 break;
7581 case CP0_REGISTER_07:
7582 switch (sel) {
7583 case CP0_REG07__HWRENA:
7584 check_insn(ctx, ISA_MIPS_R2);
7585 gen_helper_mtc0_hwrena(tcg_env, arg);
7586 ctx->base.is_jmp = DISAS_STOP;
7587 register_name = "HWREna";
7588 break;
7589 default:
7590 goto cp0_unimplemented;
7591 }
7592 break;
7593 case CP0_REGISTER_08:
7594 switch (sel) {
7595 case CP0_REG08__BADVADDR:
7596 /* ignored */
7597 register_name = "BadVAddr";
7598 break;
7599 case CP0_REG08__BADINSTR:
7600 /* ignored */
7601 register_name = "BadInstr";
7602 break;
7603 case CP0_REG08__BADINSTRP:
7604 /* ignored */
7605 register_name = "BadInstrP";
7606 break;
7607 case CP0_REG08__BADINSTRX:
7608 /* ignored */
7609 register_name = "BadInstrX";
7610 break;
7611 default:
7612 goto cp0_unimplemented;
7613 }
7614 break;
7615 case CP0_REGISTER_09:
7616 switch (sel) {
7617 case CP0_REG09__COUNT:
7618 gen_helper_mtc0_count(tcg_env, arg);
7619 register_name = "Count";
7620 break;
7621 default:
7622 goto cp0_unimplemented;
7623 }
7624 /* Stop translation as we may have switched the execution mode */
7625 ctx->base.is_jmp = DISAS_STOP;
7626 break;
7627 case CP0_REGISTER_10:
7628 switch (sel) {
7629 case CP0_REG10__ENTRYHI:
7630 gen_helper_mtc0_entryhi(tcg_env, arg);
7631 register_name = "EntryHi";
7632 break;
7633 default:
7634 goto cp0_unimplemented;
7635 }
7636 break;
7637 case CP0_REGISTER_11:
7638 switch (sel) {
7639 case CP0_REG11__COMPARE:
7640 gen_helper_mtc0_compare(tcg_env, arg);
7641 register_name = "Compare";
7642 break;
7643 /* 6,7 are implementation dependent */
7644 default:
7645 goto cp0_unimplemented;
7646 }
7647 /* Stop translation as we may have switched the execution mode */
7648 ctx->base.is_jmp = DISAS_STOP;
7649 break;
7650 case CP0_REGISTER_12:
7651 switch (sel) {
7652 case CP0_REG12__STATUS:
7653 save_cpu_state(ctx, 1);
7654 gen_helper_mtc0_status(tcg_env, arg);
7655 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7656 gen_save_pc(ctx->base.pc_next + 4);
7657 ctx->base.is_jmp = DISAS_EXIT;
7658 register_name = "Status";
7659 break;
7660 case CP0_REG12__INTCTL:
7661 check_insn(ctx, ISA_MIPS_R2);
7662 gen_helper_mtc0_intctl(tcg_env, arg);
7663 /* Stop translation as we may have switched the execution mode */
7664 ctx->base.is_jmp = DISAS_STOP;
7665 register_name = "IntCtl";
7666 break;
7667 case CP0_REG12__SRSCTL:
7668 check_insn(ctx, ISA_MIPS_R2);
7669 gen_helper_mtc0_srsctl(tcg_env, arg);
7670 /* Stop translation as we may have switched the execution mode */
7671 ctx->base.is_jmp = DISAS_STOP;
7672 register_name = "SRSCtl";
7673 break;
7674 case CP0_REG12__SRSMAP:
7675 check_insn(ctx, ISA_MIPS_R2);
7676 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7677 /* Stop translation as we may have switched the execution mode */
7678 ctx->base.is_jmp = DISAS_STOP;
7679 register_name = "SRSMap";
7680 break;
7681 default:
7682 goto cp0_unimplemented;
7683 }
7684 break;
7685 case CP0_REGISTER_13:
7686 switch (sel) {
7687 case CP0_REG13__CAUSE:
7688 save_cpu_state(ctx, 1);
7689 gen_helper_mtc0_cause(tcg_env, arg);
7690 /*
7691 * Stop translation as we may have triggered an interrupt.
7692 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7693 * translated code to check for pending interrupts.
7694 */
7695 gen_save_pc(ctx->base.pc_next + 4);
7696 ctx->base.is_jmp = DISAS_EXIT;
7697 register_name = "Cause";
7698 break;
7699 default:
7700 goto cp0_unimplemented;
7701 }
7702 break;
7703 case CP0_REGISTER_14:
7704 switch (sel) {
7705 case CP0_REG14__EPC:
7706 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
7707 register_name = "EPC";
7708 break;
7709 default:
7710 goto cp0_unimplemented;
7711 }
7712 break;
7713 case CP0_REGISTER_15:
7714 switch (sel) {
7715 case CP0_REG15__PRID:
7716 /* ignored */
7717 register_name = "PRid";
7718 break;
7719 case CP0_REG15__EBASE:
7720 check_insn(ctx, ISA_MIPS_R2);
7721 gen_helper_mtc0_ebase(tcg_env, arg);
7722 register_name = "EBase";
7723 break;
7724 default:
7725 goto cp0_unimplemented;
7726 }
7727 break;
7728 case CP0_REGISTER_16:
7729 switch (sel) {
7730 case CP0_REG16__CONFIG:
7731 gen_helper_mtc0_config0(tcg_env, arg);
7732 register_name = "Config";
7733 /* Stop translation as we may have switched the execution mode */
7734 ctx->base.is_jmp = DISAS_STOP;
7735 break;
7736 case CP0_REG16__CONFIG1:
7737 /* ignored, read only */
7738 register_name = "Config1";
7739 break;
7740 case CP0_REG16__CONFIG2:
7741 gen_helper_mtc0_config2(tcg_env, arg);
7742 register_name = "Config2";
7743 /* Stop translation as we may have switched the execution mode */
7744 ctx->base.is_jmp = DISAS_STOP;
7745 break;
7746 case CP0_REG16__CONFIG3:
7747 gen_helper_mtc0_config3(tcg_env, arg);
7748 register_name = "Config3";
7749 /* Stop translation as we may have switched the execution mode */
7750 ctx->base.is_jmp = DISAS_STOP;
7751 break;
7752 case CP0_REG16__CONFIG4:
7753 /* currently ignored */
7754 register_name = "Config4";
7755 break;
7756 case CP0_REG16__CONFIG5:
7757 gen_helper_mtc0_config5(tcg_env, arg);
7758 register_name = "Config5";
7759 /* Stop translation as we may have switched the execution mode */
7760 ctx->base.is_jmp = DISAS_STOP;
7761 break;
7762 /* 6,7 are implementation dependent */
7763 default:
7764 register_name = "Invalid config selector";
7765 goto cp0_unimplemented;
7766 }
7767 break;
7768 case CP0_REGISTER_17:
7769 switch (sel) {
7770 case CP0_REG17__LLADDR:
7771 gen_helper_mtc0_lladdr(tcg_env, arg);
7772 register_name = "LLAddr";
7773 break;
7774 case CP0_REG17__MAAR:
7775 CP0_CHECK(ctx->mrp);
7776 gen_helper_mtc0_maar(tcg_env, arg);
7777 register_name = "MAAR";
7778 break;
7779 case CP0_REG17__MAARI:
7780 CP0_CHECK(ctx->mrp);
7781 gen_helper_mtc0_maari(tcg_env, arg);
7782 register_name = "MAARI";
7783 break;
7784 default:
7785 goto cp0_unimplemented;
7786 }
7787 break;
7788 case CP0_REGISTER_18:
7789 switch (sel) {
7790 case CP0_REG18__WATCHLO0:
7791 case CP0_REG18__WATCHLO1:
7792 case CP0_REG18__WATCHLO2:
7793 case CP0_REG18__WATCHLO3:
7794 case CP0_REG18__WATCHLO4:
7795 case CP0_REG18__WATCHLO5:
7796 case CP0_REG18__WATCHLO6:
7797 case CP0_REG18__WATCHLO7:
7798 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7799 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7800 register_name = "WatchLo";
7801 break;
7802 default:
7803 goto cp0_unimplemented;
7804 }
7805 break;
7806 case CP0_REGISTER_19:
7807 switch (sel) {
7808 case CP0_REG19__WATCHHI0:
7809 case CP0_REG19__WATCHHI1:
7810 case CP0_REG19__WATCHHI2:
7811 case CP0_REG19__WATCHHI3:
7812 case CP0_REG19__WATCHHI4:
7813 case CP0_REG19__WATCHHI5:
7814 case CP0_REG19__WATCHHI6:
7815 case CP0_REG19__WATCHHI7:
7816 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7817 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7818 register_name = "WatchHi";
7819 break;
7820 default:
7821 goto cp0_unimplemented;
7822 }
7823 break;
7824 case CP0_REGISTER_20:
7825 switch (sel) {
7826 case CP0_REG20__XCONTEXT:
7827 check_insn(ctx, ISA_MIPS3);
7828 gen_helper_mtc0_xcontext(tcg_env, arg);
7829 register_name = "XContext";
7830 break;
7831 default:
7832 goto cp0_unimplemented;
7833 }
7834 break;
7835 case CP0_REGISTER_21:
7836 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7837 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7838 switch (sel) {
7839 case 0:
7840 gen_helper_mtc0_framemask(tcg_env, arg);
7841 register_name = "Framemask";
7842 break;
7843 default:
7844 goto cp0_unimplemented;
7845 }
7846 break;
7847 case CP0_REGISTER_22:
7848 /* ignored */
7849 register_name = "Diagnostic"; /* implementation dependent */
7850 break;
7851 case CP0_REGISTER_23:
7852 switch (sel) {
7853 case CP0_REG23__DEBUG:
7854 gen_helper_mtc0_debug(tcg_env, arg); /* EJTAG support */
7855 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7856 gen_save_pc(ctx->base.pc_next + 4);
7857 ctx->base.is_jmp = DISAS_EXIT;
7858 register_name = "Debug";
7859 break;
7860 case CP0_REG23__TRACECONTROL:
7861 /* PDtrace support */
7862 /* gen_helper_mtc0_tracecontrol(tcg_env, arg); */
7863 /* Stop translation as we may have switched the execution mode */
7864 ctx->base.is_jmp = DISAS_STOP;
7865 register_name = "TraceControl";
7866 goto cp0_unimplemented;
7867 case CP0_REG23__TRACECONTROL2:
7868 /* PDtrace support */
7869 /* gen_helper_mtc0_tracecontrol2(tcg_env, arg); */
7870 /* Stop translation as we may have switched the execution mode */
7871 ctx->base.is_jmp = DISAS_STOP;
7872 register_name = "TraceControl2";
7873 goto cp0_unimplemented;
7874 case CP0_REG23__USERTRACEDATA1:
7875 /* PDtrace support */
7876 /* gen_helper_mtc0_usertracedata1(tcg_env, arg);*/
7877 /* Stop translation as we may have switched the execution mode */
7878 ctx->base.is_jmp = DISAS_STOP;
7879 register_name = "UserTraceData1";
7880 goto cp0_unimplemented;
7881 case CP0_REG23__TRACEIBPC:
7882 /* PDtrace support */
7883 /* gen_helper_mtc0_traceibpc(tcg_env, arg); */
7884 /* Stop translation as we may have switched the execution mode */
7885 ctx->base.is_jmp = DISAS_STOP;
7886 register_name = "TraceIBPC";
7887 goto cp0_unimplemented;
7888 case CP0_REG23__TRACEDBPC:
7889 /* PDtrace support */
7890 /* gen_helper_mtc0_tracedbpc(tcg_env, arg); */
7891 /* Stop translation as we may have switched the execution mode */
7892 ctx->base.is_jmp = DISAS_STOP;
7893 register_name = "TraceDBPC";
7894 goto cp0_unimplemented;
7895 default:
7896 goto cp0_unimplemented;
7897 }
7898 break;
7899 case CP0_REGISTER_24:
7900 switch (sel) {
7901 case CP0_REG24__DEPC:
7902 /* EJTAG support */
7903 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
7904 register_name = "DEPC";
7905 break;
7906 default:
7907 goto cp0_unimplemented;
7908 }
7909 break;
7910 case CP0_REGISTER_25:
7911 switch (sel) {
7912 case CP0_REG25__PERFCTL0:
7913 gen_helper_mtc0_performance0(tcg_env, arg);
7914 register_name = "Performance0";
7915 break;
7916 case CP0_REG25__PERFCNT0:
7917 /* gen_helper_mtc0_performance1(tcg_env, arg); */
7918 register_name = "Performance1";
7919 goto cp0_unimplemented;
7920 case CP0_REG25__PERFCTL1:
7921 /* gen_helper_mtc0_performance2(tcg_env, arg); */
7922 register_name = "Performance2";
7923 goto cp0_unimplemented;
7924 case CP0_REG25__PERFCNT1:
7925 /* gen_helper_mtc0_performance3(tcg_env, arg); */
7926 register_name = "Performance3";
7927 goto cp0_unimplemented;
7928 case CP0_REG25__PERFCTL2:
7929 /* gen_helper_mtc0_performance4(tcg_env, arg); */
7930 register_name = "Performance4";
7931 goto cp0_unimplemented;
7932 case CP0_REG25__PERFCNT2:
7933 /* gen_helper_mtc0_performance5(tcg_env, arg); */
7934 register_name = "Performance5";
7935 goto cp0_unimplemented;
7936 case CP0_REG25__PERFCTL3:
7937 /* gen_helper_mtc0_performance6(tcg_env, arg); */
7938 register_name = "Performance6";
7939 goto cp0_unimplemented;
7940 case CP0_REG25__PERFCNT3:
7941 /* gen_helper_mtc0_performance7(tcg_env, arg); */
7942 register_name = "Performance7";
7943 goto cp0_unimplemented;
7944 default:
7945 goto cp0_unimplemented;
7946 }
7947 break;
7948 case CP0_REGISTER_26:
7949 switch (sel) {
7950 case CP0_REG26__ERRCTL:
7951 gen_helper_mtc0_errctl(tcg_env, arg);
7952 ctx->base.is_jmp = DISAS_STOP;
7953 register_name = "ErrCtl";
7954 break;
7955 default:
7956 goto cp0_unimplemented;
7957 }
7958 break;
7959 case CP0_REGISTER_27:
7960 switch (sel) {
7961 case CP0_REG27__CACHERR:
7962 /* ignored */
7963 register_name = "CacheErr";
7964 break;
7965 default:
7966 goto cp0_unimplemented;
7967 }
7968 break;
7969 case CP0_REGISTER_28:
7970 switch (sel) {
7971 case CP0_REG28__TAGLO:
7972 case CP0_REG28__TAGLO1:
7973 case CP0_REG28__TAGLO2:
7974 case CP0_REG28__TAGLO3:
7975 gen_helper_mtc0_taglo(tcg_env, arg);
7976 register_name = "TagLo";
7977 break;
7978 case CP0_REG28__DATALO:
7979 case CP0_REG28__DATALO1:
7980 case CP0_REG28__DATALO2:
7981 case CP0_REG28__DATALO3:
7982 gen_helper_mtc0_datalo(tcg_env, arg);
7983 register_name = "DataLo";
7984 break;
7985 default:
7986 goto cp0_unimplemented;
7987 }
7988 break;
7989 case CP0_REGISTER_29:
7990 switch (sel) {
7991 case CP0_REG29__TAGHI:
7992 case CP0_REG29__TAGHI1:
7993 case CP0_REG29__TAGHI2:
7994 case CP0_REG29__TAGHI3:
7995 gen_helper_mtc0_taghi(tcg_env, arg);
7996 register_name = "TagHi";
7997 break;
7998 case CP0_REG29__DATAHI:
7999 case CP0_REG29__DATAHI1:
8000 case CP0_REG29__DATAHI2:
8001 case CP0_REG29__DATAHI3:
8002 gen_helper_mtc0_datahi(tcg_env, arg);
8003 register_name = "DataHi";
8004 break;
8005 default:
8006 register_name = "invalid sel";
8007 goto cp0_unimplemented;
8008 }
8009 break;
8010 case CP0_REGISTER_30:
8011 switch (sel) {
8012 case CP0_REG30__ERROREPC:
8013 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8014 register_name = "ErrorEPC";
8015 break;
8016 default:
8017 goto cp0_unimplemented;
8018 }
8019 break;
8020 case CP0_REGISTER_31:
8021 switch (sel) {
8022 case CP0_REG31__DESAVE:
8023 /* EJTAG support */
8024 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8025 register_name = "DESAVE";
8026 break;
8027 case CP0_REG31__KSCRATCH1:
8028 case CP0_REG31__KSCRATCH2:
8029 case CP0_REG31__KSCRATCH3:
8030 case CP0_REG31__KSCRATCH4:
8031 case CP0_REG31__KSCRATCH5:
8032 case CP0_REG31__KSCRATCH6:
8033 CP0_CHECK(ctx->kscrexist & (1 << sel));
8034 tcg_gen_st_tl(arg, tcg_env,
8035 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8036 register_name = "KScratch";
8037 break;
8038 default:
8039 goto cp0_unimplemented;
8040 }
8041 break;
8042 default:
8043 goto cp0_unimplemented;
8044 }
8045 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
8046
8047 /* For simplicity assume that all writes can cause interrupts. */
8048 if (icount) {
8049 /*
8050 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8051 * translated code to check for pending interrupts.
8052 */
8053 gen_save_pc(ctx->base.pc_next + 4);
8054 ctx->base.is_jmp = DISAS_EXIT;
8055 }
8056 return;
8057
8058 cp0_unimplemented:
8059 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8060 register_name, reg, sel);
8061 }
8062 #endif /* TARGET_MIPS64 */
8063
gen_mftr(CPUMIPSState * env,DisasContext * ctx,int rt,int rd,int u,int sel,int h)8064 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8065 int u, int sel, int h)
8066 {
8067 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8068 TCGv t0 = tcg_temp_new();
8069
8070 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8071 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8072 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8073 tcg_gen_movi_tl(t0, -1);
8074 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8075 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8076 tcg_gen_movi_tl(t0, -1);
8077 } else if (u == 0) {
8078 switch (rt) {
8079 case 1:
8080 switch (sel) {
8081 case 1:
8082 gen_helper_mftc0_vpecontrol(t0, tcg_env);
8083 break;
8084 case 2:
8085 gen_helper_mftc0_vpeconf0(t0, tcg_env);
8086 break;
8087 default:
8088 goto die;
8089 break;
8090 }
8091 break;
8092 case 2:
8093 switch (sel) {
8094 case 1:
8095 gen_helper_mftc0_tcstatus(t0, tcg_env);
8096 break;
8097 case 2:
8098 gen_helper_mftc0_tcbind(t0, tcg_env);
8099 break;
8100 case 3:
8101 gen_helper_mftc0_tcrestart(t0, tcg_env);
8102 break;
8103 case 4:
8104 gen_helper_mftc0_tchalt(t0, tcg_env);
8105 break;
8106 case 5:
8107 gen_helper_mftc0_tccontext(t0, tcg_env);
8108 break;
8109 case 6:
8110 gen_helper_mftc0_tcschedule(t0, tcg_env);
8111 break;
8112 case 7:
8113 gen_helper_mftc0_tcschefback(t0, tcg_env);
8114 break;
8115 default:
8116 gen_mfc0(ctx, t0, rt, sel);
8117 break;
8118 }
8119 break;
8120 case 10:
8121 switch (sel) {
8122 case 0:
8123 gen_helper_mftc0_entryhi(t0, tcg_env);
8124 break;
8125 default:
8126 gen_mfc0(ctx, t0, rt, sel);
8127 break;
8128 }
8129 break;
8130 case 12:
8131 switch (sel) {
8132 case 0:
8133 gen_helper_mftc0_status(t0, tcg_env);
8134 break;
8135 default:
8136 gen_mfc0(ctx, t0, rt, sel);
8137 break;
8138 }
8139 break;
8140 case 13:
8141 switch (sel) {
8142 case 0:
8143 gen_helper_mftc0_cause(t0, tcg_env);
8144 break;
8145 default:
8146 goto die;
8147 break;
8148 }
8149 break;
8150 case 14:
8151 switch (sel) {
8152 case 0:
8153 gen_helper_mftc0_epc(t0, tcg_env);
8154 break;
8155 default:
8156 goto die;
8157 break;
8158 }
8159 break;
8160 case 15:
8161 switch (sel) {
8162 case 1:
8163 gen_helper_mftc0_ebase(t0, tcg_env);
8164 break;
8165 default:
8166 goto die;
8167 break;
8168 }
8169 break;
8170 case 16:
8171 switch (sel) {
8172 case 0:
8173 case 1:
8174 case 2:
8175 case 3:
8176 case 4:
8177 case 5:
8178 case 6:
8179 case 7:
8180 gen_helper_mftc0_configx(t0, tcg_env, tcg_constant_tl(sel));
8181 break;
8182 default:
8183 goto die;
8184 break;
8185 }
8186 break;
8187 case 23:
8188 switch (sel) {
8189 case 0:
8190 gen_helper_mftc0_debug(t0, tcg_env);
8191 break;
8192 default:
8193 gen_mfc0(ctx, t0, rt, sel);
8194 break;
8195 }
8196 break;
8197 default:
8198 gen_mfc0(ctx, t0, rt, sel);
8199 }
8200 } else {
8201 switch (sel) {
8202 /* GPR registers. */
8203 case 0:
8204 gen_helper_1e0i(mftgpr, t0, rt);
8205 break;
8206 /* Auxiliary CPU registers */
8207 case 1:
8208 switch (rt) {
8209 case 0:
8210 gen_helper_1e0i(mftlo, t0, 0);
8211 break;
8212 case 1:
8213 gen_helper_1e0i(mfthi, t0, 0);
8214 break;
8215 case 2:
8216 gen_helper_1e0i(mftacx, t0, 0);
8217 break;
8218 case 4:
8219 gen_helper_1e0i(mftlo, t0, 1);
8220 break;
8221 case 5:
8222 gen_helper_1e0i(mfthi, t0, 1);
8223 break;
8224 case 6:
8225 gen_helper_1e0i(mftacx, t0, 1);
8226 break;
8227 case 8:
8228 gen_helper_1e0i(mftlo, t0, 2);
8229 break;
8230 case 9:
8231 gen_helper_1e0i(mfthi, t0, 2);
8232 break;
8233 case 10:
8234 gen_helper_1e0i(mftacx, t0, 2);
8235 break;
8236 case 12:
8237 gen_helper_1e0i(mftlo, t0, 3);
8238 break;
8239 case 13:
8240 gen_helper_1e0i(mfthi, t0, 3);
8241 break;
8242 case 14:
8243 gen_helper_1e0i(mftacx, t0, 3);
8244 break;
8245 case 16:
8246 gen_helper_mftdsp(t0, tcg_env);
8247 break;
8248 default:
8249 goto die;
8250 }
8251 break;
8252 /* Floating point (COP1). */
8253 case 2:
8254 /* XXX: For now we support only a single FPU context. */
8255 if (h == 0) {
8256 TCGv_i32 fp0 = tcg_temp_new_i32();
8257
8258 gen_load_fpr32(ctx, fp0, rt);
8259 tcg_gen_ext_i32_tl(t0, fp0);
8260 } else {
8261 TCGv_i32 fp0 = tcg_temp_new_i32();
8262
8263 gen_load_fpr32h(ctx, fp0, rt);
8264 tcg_gen_ext_i32_tl(t0, fp0);
8265 }
8266 break;
8267 case 3:
8268 /* XXX: For now we support only a single FPU context. */
8269 gen_helper_1e0i(cfc1, t0, rt);
8270 break;
8271 /* COP2: Not implemented. */
8272 case 4:
8273 case 5:
8274 /* fall through */
8275 default:
8276 goto die;
8277 }
8278 }
8279 trace_mips_translate_tr("mftr", rt, u, sel, h);
8280 gen_store_gpr(t0, rd);
8281 return;
8282
8283 die:
8284 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
8285 gen_reserved_instruction(ctx);
8286 }
8287
gen_mttr(CPUMIPSState * env,DisasContext * ctx,int rd,int rt,int u,int sel,int h)8288 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
8289 int u, int sel, int h)
8290 {
8291 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8292 TCGv t0 = tcg_temp_new();
8293
8294 gen_load_gpr(t0, rt);
8295 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8296 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8297 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8298 /* NOP */
8299 ;
8300 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8301 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8302 /* NOP */
8303 ;
8304 } else if (u == 0) {
8305 switch (rd) {
8306 case 1:
8307 switch (sel) {
8308 case 1:
8309 gen_helper_mttc0_vpecontrol(tcg_env, t0);
8310 break;
8311 case 2:
8312 gen_helper_mttc0_vpeconf0(tcg_env, t0);
8313 break;
8314 default:
8315 goto die;
8316 break;
8317 }
8318 break;
8319 case 2:
8320 switch (sel) {
8321 case 1:
8322 gen_helper_mttc0_tcstatus(tcg_env, t0);
8323 break;
8324 case 2:
8325 gen_helper_mttc0_tcbind(tcg_env, t0);
8326 break;
8327 case 3:
8328 gen_helper_mttc0_tcrestart(tcg_env, t0);
8329 break;
8330 case 4:
8331 gen_helper_mttc0_tchalt(tcg_env, t0);
8332 break;
8333 case 5:
8334 gen_helper_mttc0_tccontext(tcg_env, t0);
8335 break;
8336 case 6:
8337 gen_helper_mttc0_tcschedule(tcg_env, t0);
8338 break;
8339 case 7:
8340 gen_helper_mttc0_tcschefback(tcg_env, t0);
8341 break;
8342 default:
8343 gen_mtc0(ctx, t0, rd, sel);
8344 break;
8345 }
8346 break;
8347 case 10:
8348 switch (sel) {
8349 case 0:
8350 gen_helper_mttc0_entryhi(tcg_env, t0);
8351 break;
8352 default:
8353 gen_mtc0(ctx, t0, rd, sel);
8354 break;
8355 }
8356 break;
8357 case 12:
8358 switch (sel) {
8359 case 0:
8360 gen_helper_mttc0_status(tcg_env, t0);
8361 break;
8362 default:
8363 gen_mtc0(ctx, t0, rd, sel);
8364 break;
8365 }
8366 break;
8367 case 13:
8368 switch (sel) {
8369 case 0:
8370 gen_helper_mttc0_cause(tcg_env, t0);
8371 break;
8372 default:
8373 goto die;
8374 break;
8375 }
8376 break;
8377 case 15:
8378 switch (sel) {
8379 case 1:
8380 gen_helper_mttc0_ebase(tcg_env, t0);
8381 break;
8382 default:
8383 goto die;
8384 break;
8385 }
8386 break;
8387 case 23:
8388 switch (sel) {
8389 case 0:
8390 gen_helper_mttc0_debug(tcg_env, t0);
8391 break;
8392 default:
8393 gen_mtc0(ctx, t0, rd, sel);
8394 break;
8395 }
8396 break;
8397 default:
8398 gen_mtc0(ctx, t0, rd, sel);
8399 }
8400 } else {
8401 switch (sel) {
8402 /* GPR registers. */
8403 case 0:
8404 gen_helper_0e1i(mttgpr, t0, rd);
8405 break;
8406 /* Auxiliary CPU registers */
8407 case 1:
8408 switch (rd) {
8409 case 0:
8410 gen_helper_0e1i(mttlo, t0, 0);
8411 break;
8412 case 1:
8413 gen_helper_0e1i(mtthi, t0, 0);
8414 break;
8415 case 2:
8416 gen_helper_0e1i(mttacx, t0, 0);
8417 break;
8418 case 4:
8419 gen_helper_0e1i(mttlo, t0, 1);
8420 break;
8421 case 5:
8422 gen_helper_0e1i(mtthi, t0, 1);
8423 break;
8424 case 6:
8425 gen_helper_0e1i(mttacx, t0, 1);
8426 break;
8427 case 8:
8428 gen_helper_0e1i(mttlo, t0, 2);
8429 break;
8430 case 9:
8431 gen_helper_0e1i(mtthi, t0, 2);
8432 break;
8433 case 10:
8434 gen_helper_0e1i(mttacx, t0, 2);
8435 break;
8436 case 12:
8437 gen_helper_0e1i(mttlo, t0, 3);
8438 break;
8439 case 13:
8440 gen_helper_0e1i(mtthi, t0, 3);
8441 break;
8442 case 14:
8443 gen_helper_0e1i(mttacx, t0, 3);
8444 break;
8445 case 16:
8446 gen_helper_mttdsp(tcg_env, t0);
8447 break;
8448 default:
8449 goto die;
8450 }
8451 break;
8452 /* Floating point (COP1). */
8453 case 2:
8454 /* XXX: For now we support only a single FPU context. */
8455 if (h == 0) {
8456 TCGv_i32 fp0 = tcg_temp_new_i32();
8457
8458 tcg_gen_trunc_tl_i32(fp0, t0);
8459 gen_store_fpr32(ctx, fp0, rd);
8460 } else {
8461 TCGv_i32 fp0 = tcg_temp_new_i32();
8462
8463 tcg_gen_trunc_tl_i32(fp0, t0);
8464 gen_store_fpr32h(ctx, fp0, rd);
8465 }
8466 break;
8467 case 3:
8468 /* XXX: For now we support only a single FPU context. */
8469 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(rd), rt);
8470 /* Stop translation as we may have changed hflags */
8471 ctx->base.is_jmp = DISAS_STOP;
8472 break;
8473 /* COP2: Not implemented. */
8474 case 4:
8475 case 5:
8476 /* fall through */
8477 default:
8478 goto die;
8479 }
8480 }
8481 trace_mips_translate_tr("mttr", rd, u, sel, h);
8482 return;
8483
8484 die:
8485 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8486 gen_reserved_instruction(ctx);
8487 }
8488
gen_cp0(CPUMIPSState * env,DisasContext * ctx,uint32_t opc,int rt,int rd)8489 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
8490 int rt, int rd)
8491 {
8492 const char *opn = "ldst";
8493
8494 check_cp0_enabled(ctx);
8495 switch (opc) {
8496 case OPC_MFC0:
8497 if (rt == 0) {
8498 /* Treat as NOP. */
8499 return;
8500 }
8501 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8502 opn = "mfc0";
8503 break;
8504 case OPC_MTC0:
8505 {
8506 TCGv t0 = tcg_temp_new();
8507
8508 gen_load_gpr(t0, rt);
8509 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8510 }
8511 opn = "mtc0";
8512 break;
8513 #if defined(TARGET_MIPS64)
8514 case OPC_DMFC0:
8515 check_insn(ctx, ISA_MIPS3);
8516 if (rt == 0) {
8517 /* Treat as NOP. */
8518 return;
8519 }
8520 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8521 opn = "dmfc0";
8522 break;
8523 case OPC_DMTC0:
8524 check_insn(ctx, ISA_MIPS3);
8525 {
8526 TCGv t0 = tcg_temp_new();
8527
8528 gen_load_gpr(t0, rt);
8529 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8530 }
8531 opn = "dmtc0";
8532 break;
8533 #endif
8534 case OPC_MFHC0:
8535 check_mvh(ctx);
8536 if (rt == 0) {
8537 /* Treat as NOP. */
8538 return;
8539 }
8540 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8541 opn = "mfhc0";
8542 break;
8543 case OPC_MTHC0:
8544 check_mvh(ctx);
8545 {
8546 TCGv t0 = tcg_temp_new();
8547 gen_load_gpr(t0, rt);
8548 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8549 }
8550 opn = "mthc0";
8551 break;
8552 case OPC_MFTR:
8553 check_cp0_enabled(ctx);
8554 if (rd == 0) {
8555 /* Treat as NOP. */
8556 return;
8557 }
8558 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8559 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8560 opn = "mftr";
8561 break;
8562 case OPC_MTTR:
8563 check_cp0_enabled(ctx);
8564 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8565 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8566 opn = "mttr";
8567 break;
8568 case OPC_TLBWI:
8569 opn = "tlbwi";
8570 if (!env->tlb->helper_tlbwi) {
8571 goto die;
8572 }
8573 gen_helper_tlbwi(tcg_env);
8574 break;
8575 case OPC_TLBINV:
8576 opn = "tlbinv";
8577 if (ctx->ie >= 2) {
8578 if (!env->tlb->helper_tlbinv) {
8579 goto die;
8580 }
8581 gen_helper_tlbinv(tcg_env);
8582 } /* treat as nop if TLBINV not supported */
8583 break;
8584 case OPC_TLBINVF:
8585 opn = "tlbinvf";
8586 if (ctx->ie >= 2) {
8587 if (!env->tlb->helper_tlbinvf) {
8588 goto die;
8589 }
8590 gen_helper_tlbinvf(tcg_env);
8591 } /* treat as nop if TLBINV not supported */
8592 break;
8593 case OPC_TLBWR:
8594 opn = "tlbwr";
8595 if (!env->tlb->helper_tlbwr) {
8596 goto die;
8597 }
8598 gen_helper_tlbwr(tcg_env);
8599 break;
8600 case OPC_TLBP:
8601 opn = "tlbp";
8602 if (!env->tlb->helper_tlbp) {
8603 goto die;
8604 }
8605 gen_helper_tlbp(tcg_env);
8606 break;
8607 case OPC_TLBR:
8608 opn = "tlbr";
8609 if (!env->tlb->helper_tlbr) {
8610 goto die;
8611 }
8612 gen_helper_tlbr(tcg_env);
8613 break;
8614 case OPC_ERET: /* OPC_ERETNC */
8615 if ((ctx->insn_flags & ISA_MIPS_R6) &&
8616 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8617 goto die;
8618 } else {
8619 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8620 if (ctx->opcode & (1 << bit_shift)) {
8621 /* OPC_ERETNC */
8622 opn = "eretnc";
8623 check_insn(ctx, ISA_MIPS_R5);
8624 gen_helper_eretnc(tcg_env);
8625 } else {
8626 /* OPC_ERET */
8627 opn = "eret";
8628 check_insn(ctx, ISA_MIPS2);
8629 gen_helper_eret(tcg_env);
8630 }
8631 ctx->base.is_jmp = DISAS_EXIT;
8632 }
8633 break;
8634 case OPC_DERET:
8635 opn = "deret";
8636 check_insn(ctx, ISA_MIPS_R1);
8637 if ((ctx->insn_flags & ISA_MIPS_R6) &&
8638 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8639 goto die;
8640 }
8641 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8642 MIPS_INVAL(opn);
8643 gen_reserved_instruction(ctx);
8644 } else {
8645 gen_helper_deret(tcg_env);
8646 ctx->base.is_jmp = DISAS_EXIT;
8647 }
8648 break;
8649 case OPC_WAIT:
8650 opn = "wait";
8651 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
8652 if ((ctx->insn_flags & ISA_MIPS_R6) &&
8653 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8654 goto die;
8655 }
8656 /* If we get an exception, we want to restart at next instruction */
8657 ctx->base.pc_next += 4;
8658 save_cpu_state(ctx, 1);
8659 ctx->base.pc_next -= 4;
8660 gen_helper_wait(tcg_env);
8661 ctx->base.is_jmp = DISAS_NORETURN;
8662 break;
8663 default:
8664 die:
8665 MIPS_INVAL(opn);
8666 gen_reserved_instruction(ctx);
8667 return;
8668 }
8669 (void)opn; /* avoid a compiler warning */
8670 }
8671 #endif /* !CONFIG_USER_ONLY */
8672
8673 /* CP1 Branches (before delay slot) */
gen_compute_branch1(DisasContext * ctx,uint32_t op,int32_t cc,int32_t offset)8674 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8675 int32_t cc, int32_t offset)
8676 {
8677 target_ulong btarget;
8678 TCGv_i32 t0 = tcg_temp_new_i32();
8679
8680 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8681 gen_reserved_instruction(ctx);
8682 return;
8683 }
8684
8685 if (cc != 0) {
8686 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
8687 }
8688
8689 btarget = ctx->base.pc_next + 4 + offset;
8690
8691 switch (op) {
8692 case OPC_BC1F:
8693 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8694 tcg_gen_not_i32(t0, t0);
8695 tcg_gen_andi_i32(t0, t0, 1);
8696 tcg_gen_extu_i32_tl(bcond, t0);
8697 goto not_likely;
8698 case OPC_BC1FL:
8699 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8700 tcg_gen_not_i32(t0, t0);
8701 tcg_gen_andi_i32(t0, t0, 1);
8702 tcg_gen_extu_i32_tl(bcond, t0);
8703 goto likely;
8704 case OPC_BC1T:
8705 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8706 tcg_gen_andi_i32(t0, t0, 1);
8707 tcg_gen_extu_i32_tl(bcond, t0);
8708 goto not_likely;
8709 case OPC_BC1TL:
8710 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8711 tcg_gen_andi_i32(t0, t0, 1);
8712 tcg_gen_extu_i32_tl(bcond, t0);
8713 likely:
8714 ctx->hflags |= MIPS_HFLAG_BL;
8715 break;
8716 case OPC_BC1FANY2:
8717 {
8718 TCGv_i32 t1 = tcg_temp_new_i32();
8719 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8720 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8721 tcg_gen_nand_i32(t0, t0, t1);
8722 tcg_gen_andi_i32(t0, t0, 1);
8723 tcg_gen_extu_i32_tl(bcond, t0);
8724 }
8725 goto not_likely;
8726 case OPC_BC1TANY2:
8727 {
8728 TCGv_i32 t1 = tcg_temp_new_i32();
8729 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8730 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8731 tcg_gen_or_i32(t0, t0, t1);
8732 tcg_gen_andi_i32(t0, t0, 1);
8733 tcg_gen_extu_i32_tl(bcond, t0);
8734 }
8735 goto not_likely;
8736 case OPC_BC1FANY4:
8737 {
8738 TCGv_i32 t1 = tcg_temp_new_i32();
8739 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8740 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8741 tcg_gen_and_i32(t0, t0, t1);
8742 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
8743 tcg_gen_and_i32(t0, t0, t1);
8744 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
8745 tcg_gen_nand_i32(t0, t0, t1);
8746 tcg_gen_andi_i32(t0, t0, 1);
8747 tcg_gen_extu_i32_tl(bcond, t0);
8748 }
8749 goto not_likely;
8750 case OPC_BC1TANY4:
8751 {
8752 TCGv_i32 t1 = tcg_temp_new_i32();
8753 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8754 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8755 tcg_gen_or_i32(t0, t0, t1);
8756 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
8757 tcg_gen_or_i32(t0, t0, t1);
8758 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
8759 tcg_gen_or_i32(t0, t0, t1);
8760 tcg_gen_andi_i32(t0, t0, 1);
8761 tcg_gen_extu_i32_tl(bcond, t0);
8762 }
8763 not_likely:
8764 ctx->hflags |= MIPS_HFLAG_BC;
8765 break;
8766 default:
8767 MIPS_INVAL("cp1 cond branch");
8768 gen_reserved_instruction(ctx);
8769 return;
8770 }
8771 ctx->btarget = btarget;
8772 ctx->hflags |= MIPS_HFLAG_BDS32;
8773 }
8774
8775 /* R6 CP1 Branches */
gen_compute_branch1_r6(DisasContext * ctx,uint32_t op,int32_t ft,int32_t offset,int delayslot_size)8776 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8777 int32_t ft, int32_t offset,
8778 int delayslot_size)
8779 {
8780 target_ulong btarget;
8781 TCGv_i64 t0 = tcg_temp_new_i64();
8782
8783 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8784 #ifdef MIPS_DEBUG_DISAS
8785 LOG_DISAS("Branch in delay / forbidden slot at PC 0x%016"
8786 VADDR_PRIx "\n", ctx->base.pc_next);
8787 #endif
8788 gen_reserved_instruction(ctx);
8789 return;
8790 }
8791
8792 gen_load_fpr64(ctx, t0, ft);
8793 tcg_gen_andi_i64(t0, t0, 1);
8794
8795 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
8796
8797 switch (op) {
8798 case OPC_BC1EQZ:
8799 tcg_gen_xori_i64(t0, t0, 1);
8800 ctx->hflags |= MIPS_HFLAG_BC;
8801 break;
8802 case OPC_BC1NEZ:
8803 /* t0 already set */
8804 ctx->hflags |= MIPS_HFLAG_BC;
8805 break;
8806 default:
8807 MIPS_INVAL("cp1 cond branch");
8808 gen_reserved_instruction(ctx);
8809 return;
8810 }
8811
8812 tcg_gen_trunc_i64_tl(bcond, t0);
8813
8814 ctx->btarget = btarget;
8815
8816 switch (delayslot_size) {
8817 case 2:
8818 ctx->hflags |= MIPS_HFLAG_BDS16;
8819 break;
8820 case 4:
8821 ctx->hflags |= MIPS_HFLAG_BDS32;
8822 break;
8823 }
8824 }
8825
8826 /* Coprocessor 1 (FPU) */
8827
8828 #define FOP(func, fmt) (((fmt) << 21) | (func))
8829
8830 enum fopcode {
8831 OPC_ADD_S = FOP(0, FMT_S),
8832 OPC_SUB_S = FOP(1, FMT_S),
8833 OPC_MUL_S = FOP(2, FMT_S),
8834 OPC_DIV_S = FOP(3, FMT_S),
8835 OPC_SQRT_S = FOP(4, FMT_S),
8836 OPC_ABS_S = FOP(5, FMT_S),
8837 OPC_MOV_S = FOP(6, FMT_S),
8838 OPC_NEG_S = FOP(7, FMT_S),
8839 OPC_ROUND_L_S = FOP(8, FMT_S),
8840 OPC_TRUNC_L_S = FOP(9, FMT_S),
8841 OPC_CEIL_L_S = FOP(10, FMT_S),
8842 OPC_FLOOR_L_S = FOP(11, FMT_S),
8843 OPC_ROUND_W_S = FOP(12, FMT_S),
8844 OPC_TRUNC_W_S = FOP(13, FMT_S),
8845 OPC_CEIL_W_S = FOP(14, FMT_S),
8846 OPC_FLOOR_W_S = FOP(15, FMT_S),
8847 OPC_SEL_S = FOP(16, FMT_S),
8848 OPC_MOVCF_S = FOP(17, FMT_S),
8849 OPC_MOVZ_S = FOP(18, FMT_S),
8850 OPC_MOVN_S = FOP(19, FMT_S),
8851 OPC_SELEQZ_S = FOP(20, FMT_S),
8852 OPC_RECIP_S = FOP(21, FMT_S),
8853 OPC_RSQRT_S = FOP(22, FMT_S),
8854 OPC_SELNEZ_S = FOP(23, FMT_S),
8855 OPC_MADDF_S = FOP(24, FMT_S),
8856 OPC_MSUBF_S = FOP(25, FMT_S),
8857 OPC_RINT_S = FOP(26, FMT_S),
8858 OPC_CLASS_S = FOP(27, FMT_S),
8859 OPC_MIN_S = FOP(28, FMT_S),
8860 OPC_RECIP2_S = FOP(28, FMT_S),
8861 OPC_MINA_S = FOP(29, FMT_S),
8862 OPC_RECIP1_S = FOP(29, FMT_S),
8863 OPC_MAX_S = FOP(30, FMT_S),
8864 OPC_RSQRT1_S = FOP(30, FMT_S),
8865 OPC_MAXA_S = FOP(31, FMT_S),
8866 OPC_RSQRT2_S = FOP(31, FMT_S),
8867 OPC_CVT_D_S = FOP(33, FMT_S),
8868 OPC_CVT_W_S = FOP(36, FMT_S),
8869 OPC_CVT_L_S = FOP(37, FMT_S),
8870 OPC_CVT_PS_S = FOP(38, FMT_S),
8871 OPC_CMP_F_S = FOP(48, FMT_S),
8872 OPC_CMP_UN_S = FOP(49, FMT_S),
8873 OPC_CMP_EQ_S = FOP(50, FMT_S),
8874 OPC_CMP_UEQ_S = FOP(51, FMT_S),
8875 OPC_CMP_OLT_S = FOP(52, FMT_S),
8876 OPC_CMP_ULT_S = FOP(53, FMT_S),
8877 OPC_CMP_OLE_S = FOP(54, FMT_S),
8878 OPC_CMP_ULE_S = FOP(55, FMT_S),
8879 OPC_CMP_SF_S = FOP(56, FMT_S),
8880 OPC_CMP_NGLE_S = FOP(57, FMT_S),
8881 OPC_CMP_SEQ_S = FOP(58, FMT_S),
8882 OPC_CMP_NGL_S = FOP(59, FMT_S),
8883 OPC_CMP_LT_S = FOP(60, FMT_S),
8884 OPC_CMP_NGE_S = FOP(61, FMT_S),
8885 OPC_CMP_LE_S = FOP(62, FMT_S),
8886 OPC_CMP_NGT_S = FOP(63, FMT_S),
8887
8888 OPC_ADD_D = FOP(0, FMT_D),
8889 OPC_SUB_D = FOP(1, FMT_D),
8890 OPC_MUL_D = FOP(2, FMT_D),
8891 OPC_DIV_D = FOP(3, FMT_D),
8892 OPC_SQRT_D = FOP(4, FMT_D),
8893 OPC_ABS_D = FOP(5, FMT_D),
8894 OPC_MOV_D = FOP(6, FMT_D),
8895 OPC_NEG_D = FOP(7, FMT_D),
8896 OPC_ROUND_L_D = FOP(8, FMT_D),
8897 OPC_TRUNC_L_D = FOP(9, FMT_D),
8898 OPC_CEIL_L_D = FOP(10, FMT_D),
8899 OPC_FLOOR_L_D = FOP(11, FMT_D),
8900 OPC_ROUND_W_D = FOP(12, FMT_D),
8901 OPC_TRUNC_W_D = FOP(13, FMT_D),
8902 OPC_CEIL_W_D = FOP(14, FMT_D),
8903 OPC_FLOOR_W_D = FOP(15, FMT_D),
8904 OPC_SEL_D = FOP(16, FMT_D),
8905 OPC_MOVCF_D = FOP(17, FMT_D),
8906 OPC_MOVZ_D = FOP(18, FMT_D),
8907 OPC_MOVN_D = FOP(19, FMT_D),
8908 OPC_SELEQZ_D = FOP(20, FMT_D),
8909 OPC_RECIP_D = FOP(21, FMT_D),
8910 OPC_RSQRT_D = FOP(22, FMT_D),
8911 OPC_SELNEZ_D = FOP(23, FMT_D),
8912 OPC_MADDF_D = FOP(24, FMT_D),
8913 OPC_MSUBF_D = FOP(25, FMT_D),
8914 OPC_RINT_D = FOP(26, FMT_D),
8915 OPC_CLASS_D = FOP(27, FMT_D),
8916 OPC_MIN_D = FOP(28, FMT_D),
8917 OPC_RECIP2_D = FOP(28, FMT_D),
8918 OPC_MINA_D = FOP(29, FMT_D),
8919 OPC_RECIP1_D = FOP(29, FMT_D),
8920 OPC_MAX_D = FOP(30, FMT_D),
8921 OPC_RSQRT1_D = FOP(30, FMT_D),
8922 OPC_MAXA_D = FOP(31, FMT_D),
8923 OPC_RSQRT2_D = FOP(31, FMT_D),
8924 OPC_CVT_S_D = FOP(32, FMT_D),
8925 OPC_CVT_W_D = FOP(36, FMT_D),
8926 OPC_CVT_L_D = FOP(37, FMT_D),
8927 OPC_CMP_F_D = FOP(48, FMT_D),
8928 OPC_CMP_UN_D = FOP(49, FMT_D),
8929 OPC_CMP_EQ_D = FOP(50, FMT_D),
8930 OPC_CMP_UEQ_D = FOP(51, FMT_D),
8931 OPC_CMP_OLT_D = FOP(52, FMT_D),
8932 OPC_CMP_ULT_D = FOP(53, FMT_D),
8933 OPC_CMP_OLE_D = FOP(54, FMT_D),
8934 OPC_CMP_ULE_D = FOP(55, FMT_D),
8935 OPC_CMP_SF_D = FOP(56, FMT_D),
8936 OPC_CMP_NGLE_D = FOP(57, FMT_D),
8937 OPC_CMP_SEQ_D = FOP(58, FMT_D),
8938 OPC_CMP_NGL_D = FOP(59, FMT_D),
8939 OPC_CMP_LT_D = FOP(60, FMT_D),
8940 OPC_CMP_NGE_D = FOP(61, FMT_D),
8941 OPC_CMP_LE_D = FOP(62, FMT_D),
8942 OPC_CMP_NGT_D = FOP(63, FMT_D),
8943
8944 OPC_CVT_S_W = FOP(32, FMT_W),
8945 OPC_CVT_D_W = FOP(33, FMT_W),
8946 OPC_CVT_S_L = FOP(32, FMT_L),
8947 OPC_CVT_D_L = FOP(33, FMT_L),
8948 OPC_CVT_PS_PW = FOP(38, FMT_W),
8949
8950 OPC_ADD_PS = FOP(0, FMT_PS),
8951 OPC_SUB_PS = FOP(1, FMT_PS),
8952 OPC_MUL_PS = FOP(2, FMT_PS),
8953 OPC_DIV_PS = FOP(3, FMT_PS),
8954 OPC_ABS_PS = FOP(5, FMT_PS),
8955 OPC_MOV_PS = FOP(6, FMT_PS),
8956 OPC_NEG_PS = FOP(7, FMT_PS),
8957 OPC_MOVCF_PS = FOP(17, FMT_PS),
8958 OPC_MOVZ_PS = FOP(18, FMT_PS),
8959 OPC_MOVN_PS = FOP(19, FMT_PS),
8960 OPC_ADDR_PS = FOP(24, FMT_PS),
8961 OPC_MULR_PS = FOP(26, FMT_PS),
8962 OPC_RECIP2_PS = FOP(28, FMT_PS),
8963 OPC_RECIP1_PS = FOP(29, FMT_PS),
8964 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8965 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8966
8967 OPC_CVT_S_PU = FOP(32, FMT_PS),
8968 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8969 OPC_CVT_S_PL = FOP(40, FMT_PS),
8970 OPC_PLL_PS = FOP(44, FMT_PS),
8971 OPC_PLU_PS = FOP(45, FMT_PS),
8972 OPC_PUL_PS = FOP(46, FMT_PS),
8973 OPC_PUU_PS = FOP(47, FMT_PS),
8974 OPC_CMP_F_PS = FOP(48, FMT_PS),
8975 OPC_CMP_UN_PS = FOP(49, FMT_PS),
8976 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
8977 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
8978 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
8979 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
8980 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
8981 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
8982 OPC_CMP_SF_PS = FOP(56, FMT_PS),
8983 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
8984 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
8985 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
8986 OPC_CMP_LT_PS = FOP(60, FMT_PS),
8987 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
8988 OPC_CMP_LE_PS = FOP(62, FMT_PS),
8989 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
8990 };
8991
8992 enum r6_f_cmp_op {
8993 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8994 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8995 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8996 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8997 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8998 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8999 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
9000 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9001 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9002 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9003 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9004 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9005 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9006 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9007 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9008 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9009 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9010 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9011 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9012 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9013 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9014 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9015
9016 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9017 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9018 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9019 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9020 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9021 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9022 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9023 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9024 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9025 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9026 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9027 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9028 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9029 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9030 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9031 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9032 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9033 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9034 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9035 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9036 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9037 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9038 };
9039
gen_cp1(DisasContext * ctx,uint32_t opc,int rt,int fs)9040 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
9041 {
9042 TCGv t0 = tcg_temp_new();
9043
9044 switch (opc) {
9045 case OPC_MFC1:
9046 {
9047 TCGv_i32 fp0 = tcg_temp_new_i32();
9048
9049 gen_load_fpr32(ctx, fp0, fs);
9050 tcg_gen_ext_i32_tl(t0, fp0);
9051 }
9052 gen_store_gpr(t0, rt);
9053 break;
9054 case OPC_MTC1:
9055 gen_load_gpr(t0, rt);
9056 {
9057 TCGv_i32 fp0 = tcg_temp_new_i32();
9058
9059 tcg_gen_trunc_tl_i32(fp0, t0);
9060 gen_store_fpr32(ctx, fp0, fs);
9061 }
9062 break;
9063 case OPC_CFC1:
9064 gen_helper_1e0i(cfc1, t0, fs);
9065 gen_store_gpr(t0, rt);
9066 break;
9067 case OPC_CTC1:
9068 gen_load_gpr(t0, rt);
9069 save_cpu_state(ctx, 0);
9070 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(fs), rt);
9071 /* Stop translation as we may have changed hflags */
9072 ctx->base.is_jmp = DISAS_STOP;
9073 break;
9074 #if defined(TARGET_MIPS64)
9075 case OPC_DMFC1:
9076 gen_load_fpr64(ctx, t0, fs);
9077 gen_store_gpr(t0, rt);
9078 break;
9079 case OPC_DMTC1:
9080 gen_load_gpr(t0, rt);
9081 gen_store_fpr64(ctx, t0, fs);
9082 break;
9083 #endif
9084 case OPC_MFHC1:
9085 {
9086 TCGv_i32 fp0 = tcg_temp_new_i32();
9087
9088 gen_load_fpr32h(ctx, fp0, fs);
9089 tcg_gen_ext_i32_tl(t0, fp0);
9090 }
9091 gen_store_gpr(t0, rt);
9092 break;
9093 case OPC_MTHC1:
9094 gen_load_gpr(t0, rt);
9095 {
9096 TCGv_i32 fp0 = tcg_temp_new_i32();
9097
9098 tcg_gen_trunc_tl_i32(fp0, t0);
9099 gen_store_fpr32h(ctx, fp0, fs);
9100 }
9101 break;
9102 default:
9103 MIPS_INVAL("cp1 move");
9104 gen_reserved_instruction(ctx);
9105 return;
9106 }
9107 }
9108
gen_movci(DisasContext * ctx,int rd,int rs,int cc,int tf)9109 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
9110 {
9111 TCGLabel *l1;
9112 TCGCond cond;
9113 TCGv_i32 t0;
9114
9115 if (rd == 0) {
9116 /* Treat as NOP. */
9117 return;
9118 }
9119
9120 if (tf) {
9121 cond = TCG_COND_EQ;
9122 } else {
9123 cond = TCG_COND_NE;
9124 }
9125
9126 l1 = gen_new_label();
9127 t0 = tcg_temp_new_i32();
9128 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9129 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9130 gen_load_gpr(cpu_gpr[rd], rs);
9131 gen_set_label(l1);
9132 }
9133
gen_movcf_s(DisasContext * ctx,int fs,int fd,int cc,int tf)9134 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9135 int tf)
9136 {
9137 int cond;
9138 TCGv_i32 t0 = tcg_temp_new_i32();
9139 TCGLabel *l1 = gen_new_label();
9140
9141 if (tf) {
9142 cond = TCG_COND_EQ;
9143 } else {
9144 cond = TCG_COND_NE;
9145 }
9146
9147 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9148 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9149 gen_load_fpr32(ctx, t0, fs);
9150 gen_store_fpr32(ctx, t0, fd);
9151 gen_set_label(l1);
9152 }
9153
gen_movcf_d(DisasContext * ctx,int fs,int fd,int cc,int tf)9154 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
9155 int tf)
9156 {
9157 int cond;
9158 TCGv_i32 t0 = tcg_temp_new_i32();
9159 TCGv_i64 fp0;
9160 TCGLabel *l1 = gen_new_label();
9161
9162 if (tf) {
9163 cond = TCG_COND_EQ;
9164 } else {
9165 cond = TCG_COND_NE;
9166 }
9167
9168 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9169 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9170 fp0 = tcg_temp_new_i64();
9171 gen_load_fpr64(ctx, fp0, fs);
9172 gen_store_fpr64(ctx, fp0, fd);
9173 gen_set_label(l1);
9174 }
9175
gen_movcf_ps(DisasContext * ctx,int fs,int fd,int cc,int tf)9176 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9177 int cc, int tf)
9178 {
9179 int cond;
9180 TCGv_i32 t0 = tcg_temp_new_i32();
9181 TCGLabel *l1 = gen_new_label();
9182 TCGLabel *l2 = gen_new_label();
9183
9184 if (tf) {
9185 cond = TCG_COND_EQ;
9186 } else {
9187 cond = TCG_COND_NE;
9188 }
9189
9190 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9191 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9192 gen_load_fpr32(ctx, t0, fs);
9193 gen_store_fpr32(ctx, t0, fd);
9194 gen_set_label(l1);
9195
9196 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
9197 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9198 gen_load_fpr32h(ctx, t0, fs);
9199 gen_store_fpr32h(ctx, t0, fd);
9200 gen_set_label(l2);
9201 }
9202
gen_sel_s(DisasContext * ctx,enum fopcode op1,int fd,int ft,int fs)9203 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9204 int fs)
9205 {
9206 TCGv_i32 t1 = tcg_constant_i32(0);
9207 TCGv_i32 fp0 = tcg_temp_new_i32();
9208 TCGv_i32 fp1 = tcg_temp_new_i32();
9209 TCGv_i32 fp2 = tcg_temp_new_i32();
9210 gen_load_fpr32(ctx, fp0, fd);
9211 gen_load_fpr32(ctx, fp1, ft);
9212 gen_load_fpr32(ctx, fp2, fs);
9213
9214 switch (op1) {
9215 case OPC_SEL_S:
9216 tcg_gen_andi_i32(fp0, fp0, 1);
9217 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9218 break;
9219 case OPC_SELEQZ_S:
9220 tcg_gen_andi_i32(fp1, fp1, 1);
9221 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9222 break;
9223 case OPC_SELNEZ_S:
9224 tcg_gen_andi_i32(fp1, fp1, 1);
9225 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9226 break;
9227 default:
9228 MIPS_INVAL("gen_sel_s");
9229 gen_reserved_instruction(ctx);
9230 break;
9231 }
9232
9233 gen_store_fpr32(ctx, fp0, fd);
9234 }
9235
gen_sel_d(DisasContext * ctx,enum fopcode op1,int fd,int ft,int fs)9236 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9237 int fs)
9238 {
9239 TCGv_i64 t1 = tcg_constant_i64(0);
9240 TCGv_i64 fp0 = tcg_temp_new_i64();
9241 TCGv_i64 fp1 = tcg_temp_new_i64();
9242 TCGv_i64 fp2 = tcg_temp_new_i64();
9243 gen_load_fpr64(ctx, fp0, fd);
9244 gen_load_fpr64(ctx, fp1, ft);
9245 gen_load_fpr64(ctx, fp2, fs);
9246
9247 switch (op1) {
9248 case OPC_SEL_D:
9249 tcg_gen_andi_i64(fp0, fp0, 1);
9250 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9251 break;
9252 case OPC_SELEQZ_D:
9253 tcg_gen_andi_i64(fp1, fp1, 1);
9254 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9255 break;
9256 case OPC_SELNEZ_D:
9257 tcg_gen_andi_i64(fp1, fp1, 1);
9258 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9259 break;
9260 default:
9261 MIPS_INVAL("gen_sel_d");
9262 gen_reserved_instruction(ctx);
9263 break;
9264 }
9265
9266 gen_store_fpr64(ctx, fp0, fd);
9267 }
9268
gen_farith(DisasContext * ctx,enum fopcode op1,int ft,int fs,int fd,int cc)9269 static void gen_farith(DisasContext *ctx, enum fopcode op1,
9270 int ft, int fs, int fd, int cc)
9271 {
9272 uint32_t func = ctx->opcode & 0x3f;
9273 switch (op1) {
9274 case OPC_ADD_S:
9275 {
9276 TCGv_i32 fp0 = tcg_temp_new_i32();
9277 TCGv_i32 fp1 = tcg_temp_new_i32();
9278
9279 gen_load_fpr32(ctx, fp0, fs);
9280 gen_load_fpr32(ctx, fp1, ft);
9281 gen_helper_float_add_s(fp0, tcg_env, fp0, fp1);
9282 gen_store_fpr32(ctx, fp0, fd);
9283 }
9284 break;
9285 case OPC_SUB_S:
9286 {
9287 TCGv_i32 fp0 = tcg_temp_new_i32();
9288 TCGv_i32 fp1 = tcg_temp_new_i32();
9289
9290 gen_load_fpr32(ctx, fp0, fs);
9291 gen_load_fpr32(ctx, fp1, ft);
9292 gen_helper_float_sub_s(fp0, tcg_env, fp0, fp1);
9293 gen_store_fpr32(ctx, fp0, fd);
9294 }
9295 break;
9296 case OPC_MUL_S:
9297 {
9298 TCGv_i32 fp0 = tcg_temp_new_i32();
9299 TCGv_i32 fp1 = tcg_temp_new_i32();
9300
9301 gen_load_fpr32(ctx, fp0, fs);
9302 gen_load_fpr32(ctx, fp1, ft);
9303 gen_helper_float_mul_s(fp0, tcg_env, fp0, fp1);
9304 gen_store_fpr32(ctx, fp0, fd);
9305 }
9306 break;
9307 case OPC_DIV_S:
9308 {
9309 TCGv_i32 fp0 = tcg_temp_new_i32();
9310 TCGv_i32 fp1 = tcg_temp_new_i32();
9311
9312 gen_load_fpr32(ctx, fp0, fs);
9313 gen_load_fpr32(ctx, fp1, ft);
9314 gen_helper_float_div_s(fp0, tcg_env, fp0, fp1);
9315 gen_store_fpr32(ctx, fp0, fd);
9316 }
9317 break;
9318 case OPC_SQRT_S:
9319 {
9320 TCGv_i32 fp0 = tcg_temp_new_i32();
9321
9322 gen_load_fpr32(ctx, fp0, fs);
9323 gen_helper_float_sqrt_s(fp0, tcg_env, fp0);
9324 gen_store_fpr32(ctx, fp0, fd);
9325 }
9326 break;
9327 case OPC_ABS_S:
9328 {
9329 TCGv_i32 fp0 = tcg_temp_new_i32();
9330
9331 gen_load_fpr32(ctx, fp0, fs);
9332 if (ctx->abs2008) {
9333 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9334 } else {
9335 gen_helper_float_abs_s(fp0, fp0);
9336 }
9337 gen_store_fpr32(ctx, fp0, fd);
9338 }
9339 break;
9340 case OPC_MOV_S:
9341 {
9342 TCGv_i32 fp0 = tcg_temp_new_i32();
9343
9344 gen_load_fpr32(ctx, fp0, fs);
9345 gen_store_fpr32(ctx, fp0, fd);
9346 }
9347 break;
9348 case OPC_NEG_S:
9349 {
9350 TCGv_i32 fp0 = tcg_temp_new_i32();
9351
9352 gen_load_fpr32(ctx, fp0, fs);
9353 if (ctx->abs2008) {
9354 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9355 } else {
9356 gen_helper_float_chs_s(fp0, fp0);
9357 }
9358 gen_store_fpr32(ctx, fp0, fd);
9359 }
9360 break;
9361 case OPC_ROUND_L_S:
9362 check_cp1_64bitmode(ctx);
9363 {
9364 TCGv_i32 fp32 = tcg_temp_new_i32();
9365 TCGv_i64 fp64 = tcg_temp_new_i64();
9366
9367 gen_load_fpr32(ctx, fp32, fs);
9368 if (ctx->nan2008) {
9369 gen_helper_float_round_2008_l_s(fp64, tcg_env, fp32);
9370 } else {
9371 gen_helper_float_round_l_s(fp64, tcg_env, fp32);
9372 }
9373 gen_store_fpr64(ctx, fp64, fd);
9374 }
9375 break;
9376 case OPC_TRUNC_L_S:
9377 check_cp1_64bitmode(ctx);
9378 {
9379 TCGv_i32 fp32 = tcg_temp_new_i32();
9380 TCGv_i64 fp64 = tcg_temp_new_i64();
9381
9382 gen_load_fpr32(ctx, fp32, fs);
9383 if (ctx->nan2008) {
9384 gen_helper_float_trunc_2008_l_s(fp64, tcg_env, fp32);
9385 } else {
9386 gen_helper_float_trunc_l_s(fp64, tcg_env, fp32);
9387 }
9388 gen_store_fpr64(ctx, fp64, fd);
9389 }
9390 break;
9391 case OPC_CEIL_L_S:
9392 check_cp1_64bitmode(ctx);
9393 {
9394 TCGv_i32 fp32 = tcg_temp_new_i32();
9395 TCGv_i64 fp64 = tcg_temp_new_i64();
9396
9397 gen_load_fpr32(ctx, fp32, fs);
9398 if (ctx->nan2008) {
9399 gen_helper_float_ceil_2008_l_s(fp64, tcg_env, fp32);
9400 } else {
9401 gen_helper_float_ceil_l_s(fp64, tcg_env, fp32);
9402 }
9403 gen_store_fpr64(ctx, fp64, fd);
9404 }
9405 break;
9406 case OPC_FLOOR_L_S:
9407 check_cp1_64bitmode(ctx);
9408 {
9409 TCGv_i32 fp32 = tcg_temp_new_i32();
9410 TCGv_i64 fp64 = tcg_temp_new_i64();
9411
9412 gen_load_fpr32(ctx, fp32, fs);
9413 if (ctx->nan2008) {
9414 gen_helper_float_floor_2008_l_s(fp64, tcg_env, fp32);
9415 } else {
9416 gen_helper_float_floor_l_s(fp64, tcg_env, fp32);
9417 }
9418 gen_store_fpr64(ctx, fp64, fd);
9419 }
9420 break;
9421 case OPC_ROUND_W_S:
9422 {
9423 TCGv_i32 fp0 = tcg_temp_new_i32();
9424
9425 gen_load_fpr32(ctx, fp0, fs);
9426 if (ctx->nan2008) {
9427 gen_helper_float_round_2008_w_s(fp0, tcg_env, fp0);
9428 } else {
9429 gen_helper_float_round_w_s(fp0, tcg_env, fp0);
9430 }
9431 gen_store_fpr32(ctx, fp0, fd);
9432 }
9433 break;
9434 case OPC_TRUNC_W_S:
9435 {
9436 TCGv_i32 fp0 = tcg_temp_new_i32();
9437
9438 gen_load_fpr32(ctx, fp0, fs);
9439 if (ctx->nan2008) {
9440 gen_helper_float_trunc_2008_w_s(fp0, tcg_env, fp0);
9441 } else {
9442 gen_helper_float_trunc_w_s(fp0, tcg_env, fp0);
9443 }
9444 gen_store_fpr32(ctx, fp0, fd);
9445 }
9446 break;
9447 case OPC_CEIL_W_S:
9448 {
9449 TCGv_i32 fp0 = tcg_temp_new_i32();
9450
9451 gen_load_fpr32(ctx, fp0, fs);
9452 if (ctx->nan2008) {
9453 gen_helper_float_ceil_2008_w_s(fp0, tcg_env, fp0);
9454 } else {
9455 gen_helper_float_ceil_w_s(fp0, tcg_env, fp0);
9456 }
9457 gen_store_fpr32(ctx, fp0, fd);
9458 }
9459 break;
9460 case OPC_FLOOR_W_S:
9461 {
9462 TCGv_i32 fp0 = tcg_temp_new_i32();
9463
9464 gen_load_fpr32(ctx, fp0, fs);
9465 if (ctx->nan2008) {
9466 gen_helper_float_floor_2008_w_s(fp0, tcg_env, fp0);
9467 } else {
9468 gen_helper_float_floor_w_s(fp0, tcg_env, fp0);
9469 }
9470 gen_store_fpr32(ctx, fp0, fd);
9471 }
9472 break;
9473 case OPC_SEL_S:
9474 check_insn(ctx, ISA_MIPS_R6);
9475 gen_sel_s(ctx, op1, fd, ft, fs);
9476 break;
9477 case OPC_SELEQZ_S:
9478 check_insn(ctx, ISA_MIPS_R6);
9479 gen_sel_s(ctx, op1, fd, ft, fs);
9480 break;
9481 case OPC_SELNEZ_S:
9482 check_insn(ctx, ISA_MIPS_R6);
9483 gen_sel_s(ctx, op1, fd, ft, fs);
9484 break;
9485 case OPC_MOVCF_S:
9486 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9487 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9488 break;
9489 case OPC_MOVZ_S:
9490 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9491 {
9492 TCGLabel *l1 = gen_new_label();
9493 TCGv_i32 fp0;
9494
9495 if (ft != 0) {
9496 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9497 }
9498 fp0 = tcg_temp_new_i32();
9499 gen_load_fpr32(ctx, fp0, fs);
9500 gen_store_fpr32(ctx, fp0, fd);
9501 gen_set_label(l1);
9502 }
9503 break;
9504 case OPC_MOVN_S:
9505 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9506 {
9507 TCGLabel *l1 = gen_new_label();
9508 TCGv_i32 fp0;
9509
9510 if (ft != 0) {
9511 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9512 fp0 = tcg_temp_new_i32();
9513 gen_load_fpr32(ctx, fp0, fs);
9514 gen_store_fpr32(ctx, fp0, fd);
9515 gen_set_label(l1);
9516 }
9517 }
9518 break;
9519 case OPC_RECIP_S:
9520 {
9521 TCGv_i32 fp0 = tcg_temp_new_i32();
9522
9523 gen_load_fpr32(ctx, fp0, fs);
9524 gen_helper_float_recip_s(fp0, tcg_env, fp0);
9525 gen_store_fpr32(ctx, fp0, fd);
9526 }
9527 break;
9528 case OPC_RSQRT_S:
9529 {
9530 TCGv_i32 fp0 = tcg_temp_new_i32();
9531
9532 gen_load_fpr32(ctx, fp0, fs);
9533 gen_helper_float_rsqrt_s(fp0, tcg_env, fp0);
9534 gen_store_fpr32(ctx, fp0, fd);
9535 }
9536 break;
9537 case OPC_MADDF_S:
9538 check_insn(ctx, ISA_MIPS_R6);
9539 {
9540 TCGv_i32 fp0 = tcg_temp_new_i32();
9541 TCGv_i32 fp1 = tcg_temp_new_i32();
9542 TCGv_i32 fp2 = tcg_temp_new_i32();
9543 gen_load_fpr32(ctx, fp0, fs);
9544 gen_load_fpr32(ctx, fp1, ft);
9545 gen_load_fpr32(ctx, fp2, fd);
9546 gen_helper_float_maddf_s(fp2, tcg_env, fp0, fp1, fp2);
9547 gen_store_fpr32(ctx, fp2, fd);
9548 }
9549 break;
9550 case OPC_MSUBF_S:
9551 check_insn(ctx, ISA_MIPS_R6);
9552 {
9553 TCGv_i32 fp0 = tcg_temp_new_i32();
9554 TCGv_i32 fp1 = tcg_temp_new_i32();
9555 TCGv_i32 fp2 = tcg_temp_new_i32();
9556 gen_load_fpr32(ctx, fp0, fs);
9557 gen_load_fpr32(ctx, fp1, ft);
9558 gen_load_fpr32(ctx, fp2, fd);
9559 gen_helper_float_msubf_s(fp2, tcg_env, fp0, fp1, fp2);
9560 gen_store_fpr32(ctx, fp2, fd);
9561 }
9562 break;
9563 case OPC_RINT_S:
9564 check_insn(ctx, ISA_MIPS_R6);
9565 {
9566 TCGv_i32 fp0 = tcg_temp_new_i32();
9567 gen_load_fpr32(ctx, fp0, fs);
9568 gen_helper_float_rint_s(fp0, tcg_env, fp0);
9569 gen_store_fpr32(ctx, fp0, fd);
9570 }
9571 break;
9572 case OPC_CLASS_S:
9573 check_insn(ctx, ISA_MIPS_R6);
9574 {
9575 TCGv_i32 fp0 = tcg_temp_new_i32();
9576 gen_load_fpr32(ctx, fp0, fs);
9577 gen_helper_float_class_s(fp0, tcg_env, fp0);
9578 gen_store_fpr32(ctx, fp0, fd);
9579 }
9580 break;
9581 case OPC_MIN_S: /* OPC_RECIP2_S */
9582 if (ctx->insn_flags & ISA_MIPS_R6) {
9583 /* OPC_MIN_S */
9584 TCGv_i32 fp0 = tcg_temp_new_i32();
9585 TCGv_i32 fp1 = tcg_temp_new_i32();
9586 TCGv_i32 fp2 = tcg_temp_new_i32();
9587 gen_load_fpr32(ctx, fp0, fs);
9588 gen_load_fpr32(ctx, fp1, ft);
9589 gen_helper_float_min_s(fp2, tcg_env, fp0, fp1);
9590 gen_store_fpr32(ctx, fp2, fd);
9591 } else {
9592 /* OPC_RECIP2_S */
9593 check_cp1_64bitmode(ctx);
9594 {
9595 TCGv_i32 fp0 = tcg_temp_new_i32();
9596 TCGv_i32 fp1 = tcg_temp_new_i32();
9597
9598 gen_load_fpr32(ctx, fp0, fs);
9599 gen_load_fpr32(ctx, fp1, ft);
9600 gen_helper_float_recip2_s(fp0, tcg_env, fp0, fp1);
9601 gen_store_fpr32(ctx, fp0, fd);
9602 }
9603 }
9604 break;
9605 case OPC_MINA_S: /* OPC_RECIP1_S */
9606 if (ctx->insn_flags & ISA_MIPS_R6) {
9607 /* OPC_MINA_S */
9608 TCGv_i32 fp0 = tcg_temp_new_i32();
9609 TCGv_i32 fp1 = tcg_temp_new_i32();
9610 TCGv_i32 fp2 = tcg_temp_new_i32();
9611 gen_load_fpr32(ctx, fp0, fs);
9612 gen_load_fpr32(ctx, fp1, ft);
9613 gen_helper_float_mina_s(fp2, tcg_env, fp0, fp1);
9614 gen_store_fpr32(ctx, fp2, fd);
9615 } else {
9616 /* OPC_RECIP1_S */
9617 check_cp1_64bitmode(ctx);
9618 {
9619 TCGv_i32 fp0 = tcg_temp_new_i32();
9620
9621 gen_load_fpr32(ctx, fp0, fs);
9622 gen_helper_float_recip1_s(fp0, tcg_env, fp0);
9623 gen_store_fpr32(ctx, fp0, fd);
9624 }
9625 }
9626 break;
9627 case OPC_MAX_S: /* OPC_RSQRT1_S */
9628 if (ctx->insn_flags & ISA_MIPS_R6) {
9629 /* OPC_MAX_S */
9630 TCGv_i32 fp0 = tcg_temp_new_i32();
9631 TCGv_i32 fp1 = tcg_temp_new_i32();
9632 gen_load_fpr32(ctx, fp0, fs);
9633 gen_load_fpr32(ctx, fp1, ft);
9634 gen_helper_float_max_s(fp1, tcg_env, fp0, fp1);
9635 gen_store_fpr32(ctx, fp1, fd);
9636 } else {
9637 /* OPC_RSQRT1_S */
9638 check_cp1_64bitmode(ctx);
9639 {
9640 TCGv_i32 fp0 = tcg_temp_new_i32();
9641
9642 gen_load_fpr32(ctx, fp0, fs);
9643 gen_helper_float_rsqrt1_s(fp0, tcg_env, fp0);
9644 gen_store_fpr32(ctx, fp0, fd);
9645 }
9646 }
9647 break;
9648 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9649 if (ctx->insn_flags & ISA_MIPS_R6) {
9650 /* OPC_MAXA_S */
9651 TCGv_i32 fp0 = tcg_temp_new_i32();
9652 TCGv_i32 fp1 = tcg_temp_new_i32();
9653 gen_load_fpr32(ctx, fp0, fs);
9654 gen_load_fpr32(ctx, fp1, ft);
9655 gen_helper_float_maxa_s(fp1, tcg_env, fp0, fp1);
9656 gen_store_fpr32(ctx, fp1, fd);
9657 } else {
9658 /* OPC_RSQRT2_S */
9659 check_cp1_64bitmode(ctx);
9660 {
9661 TCGv_i32 fp0 = tcg_temp_new_i32();
9662 TCGv_i32 fp1 = tcg_temp_new_i32();
9663
9664 gen_load_fpr32(ctx, fp0, fs);
9665 gen_load_fpr32(ctx, fp1, ft);
9666 gen_helper_float_rsqrt2_s(fp0, tcg_env, fp0, fp1);
9667 gen_store_fpr32(ctx, fp0, fd);
9668 }
9669 }
9670 break;
9671 case OPC_CVT_D_S:
9672 check_cp1_registers(ctx, fd);
9673 {
9674 TCGv_i32 fp32 = tcg_temp_new_i32();
9675 TCGv_i64 fp64 = tcg_temp_new_i64();
9676
9677 gen_load_fpr32(ctx, fp32, fs);
9678 gen_helper_float_cvtd_s(fp64, tcg_env, fp32);
9679 gen_store_fpr64(ctx, fp64, fd);
9680 }
9681 break;
9682 case OPC_CVT_W_S:
9683 {
9684 TCGv_i32 fp0 = tcg_temp_new_i32();
9685
9686 gen_load_fpr32(ctx, fp0, fs);
9687 if (ctx->nan2008) {
9688 gen_helper_float_cvt_2008_w_s(fp0, tcg_env, fp0);
9689 } else {
9690 gen_helper_float_cvt_w_s(fp0, tcg_env, fp0);
9691 }
9692 gen_store_fpr32(ctx, fp0, fd);
9693 }
9694 break;
9695 case OPC_CVT_L_S:
9696 check_cp1_64bitmode(ctx);
9697 {
9698 TCGv_i32 fp32 = tcg_temp_new_i32();
9699 TCGv_i64 fp64 = tcg_temp_new_i64();
9700
9701 gen_load_fpr32(ctx, fp32, fs);
9702 if (ctx->nan2008) {
9703 gen_helper_float_cvt_2008_l_s(fp64, tcg_env, fp32);
9704 } else {
9705 gen_helper_float_cvt_l_s(fp64, tcg_env, fp32);
9706 }
9707 gen_store_fpr64(ctx, fp64, fd);
9708 }
9709 break;
9710 case OPC_CVT_PS_S:
9711 check_ps(ctx);
9712 {
9713 TCGv_i64 fp64 = tcg_temp_new_i64();
9714 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9715 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9716
9717 gen_load_fpr32(ctx, fp32_0, fs);
9718 gen_load_fpr32(ctx, fp32_1, ft);
9719 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9720 gen_store_fpr64(ctx, fp64, fd);
9721 }
9722 break;
9723 case OPC_CMP_F_S:
9724 case OPC_CMP_UN_S:
9725 case OPC_CMP_EQ_S:
9726 case OPC_CMP_UEQ_S:
9727 case OPC_CMP_OLT_S:
9728 case OPC_CMP_ULT_S:
9729 case OPC_CMP_OLE_S:
9730 case OPC_CMP_ULE_S:
9731 case OPC_CMP_SF_S:
9732 case OPC_CMP_NGLE_S:
9733 case OPC_CMP_SEQ_S:
9734 case OPC_CMP_NGL_S:
9735 case OPC_CMP_LT_S:
9736 case OPC_CMP_NGE_S:
9737 case OPC_CMP_LE_S:
9738 case OPC_CMP_NGT_S:
9739 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9740 if (ctx->opcode & (1 << 6)) {
9741 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
9742 } else {
9743 gen_cmp_s(ctx, func - 48, ft, fs, cc);
9744 }
9745 break;
9746 case OPC_ADD_D:
9747 check_cp1_registers(ctx, fs | ft | fd);
9748 {
9749 TCGv_i64 fp0 = tcg_temp_new_i64();
9750 TCGv_i64 fp1 = tcg_temp_new_i64();
9751
9752 gen_load_fpr64(ctx, fp0, fs);
9753 gen_load_fpr64(ctx, fp1, ft);
9754 gen_helper_float_add_d(fp0, tcg_env, fp0, fp1);
9755 gen_store_fpr64(ctx, fp0, fd);
9756 }
9757 break;
9758 case OPC_SUB_D:
9759 check_cp1_registers(ctx, fs | ft | fd);
9760 {
9761 TCGv_i64 fp0 = tcg_temp_new_i64();
9762 TCGv_i64 fp1 = tcg_temp_new_i64();
9763
9764 gen_load_fpr64(ctx, fp0, fs);
9765 gen_load_fpr64(ctx, fp1, ft);
9766 gen_helper_float_sub_d(fp0, tcg_env, fp0, fp1);
9767 gen_store_fpr64(ctx, fp0, fd);
9768 }
9769 break;
9770 case OPC_MUL_D:
9771 check_cp1_registers(ctx, fs | ft | fd);
9772 {
9773 TCGv_i64 fp0 = tcg_temp_new_i64();
9774 TCGv_i64 fp1 = tcg_temp_new_i64();
9775
9776 gen_load_fpr64(ctx, fp0, fs);
9777 gen_load_fpr64(ctx, fp1, ft);
9778 gen_helper_float_mul_d(fp0, tcg_env, fp0, fp1);
9779 gen_store_fpr64(ctx, fp0, fd);
9780 }
9781 break;
9782 case OPC_DIV_D:
9783 check_cp1_registers(ctx, fs | ft | fd);
9784 {
9785 TCGv_i64 fp0 = tcg_temp_new_i64();
9786 TCGv_i64 fp1 = tcg_temp_new_i64();
9787
9788 gen_load_fpr64(ctx, fp0, fs);
9789 gen_load_fpr64(ctx, fp1, ft);
9790 gen_helper_float_div_d(fp0, tcg_env, fp0, fp1);
9791 gen_store_fpr64(ctx, fp0, fd);
9792 }
9793 break;
9794 case OPC_SQRT_D:
9795 check_cp1_registers(ctx, fs | fd);
9796 {
9797 TCGv_i64 fp0 = tcg_temp_new_i64();
9798
9799 gen_load_fpr64(ctx, fp0, fs);
9800 gen_helper_float_sqrt_d(fp0, tcg_env, fp0);
9801 gen_store_fpr64(ctx, fp0, fd);
9802 }
9803 break;
9804 case OPC_ABS_D:
9805 check_cp1_registers(ctx, fs | fd);
9806 {
9807 TCGv_i64 fp0 = tcg_temp_new_i64();
9808
9809 gen_load_fpr64(ctx, fp0, fs);
9810 if (ctx->abs2008) {
9811 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9812 } else {
9813 gen_helper_float_abs_d(fp0, fp0);
9814 }
9815 gen_store_fpr64(ctx, fp0, fd);
9816 }
9817 break;
9818 case OPC_MOV_D:
9819 check_cp1_registers(ctx, fs | fd);
9820 {
9821 TCGv_i64 fp0 = tcg_temp_new_i64();
9822
9823 gen_load_fpr64(ctx, fp0, fs);
9824 gen_store_fpr64(ctx, fp0, fd);
9825 }
9826 break;
9827 case OPC_NEG_D:
9828 check_cp1_registers(ctx, fs | fd);
9829 {
9830 TCGv_i64 fp0 = tcg_temp_new_i64();
9831
9832 gen_load_fpr64(ctx, fp0, fs);
9833 if (ctx->abs2008) {
9834 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
9835 } else {
9836 gen_helper_float_chs_d(fp0, fp0);
9837 }
9838 gen_store_fpr64(ctx, fp0, fd);
9839 }
9840 break;
9841 case OPC_ROUND_L_D:
9842 check_cp1_64bitmode(ctx);
9843 {
9844 TCGv_i64 fp0 = tcg_temp_new_i64();
9845
9846 gen_load_fpr64(ctx, fp0, fs);
9847 if (ctx->nan2008) {
9848 gen_helper_float_round_2008_l_d(fp0, tcg_env, fp0);
9849 } else {
9850 gen_helper_float_round_l_d(fp0, tcg_env, fp0);
9851 }
9852 gen_store_fpr64(ctx, fp0, fd);
9853 }
9854 break;
9855 case OPC_TRUNC_L_D:
9856 check_cp1_64bitmode(ctx);
9857 {
9858 TCGv_i64 fp0 = tcg_temp_new_i64();
9859
9860 gen_load_fpr64(ctx, fp0, fs);
9861 if (ctx->nan2008) {
9862 gen_helper_float_trunc_2008_l_d(fp0, tcg_env, fp0);
9863 } else {
9864 gen_helper_float_trunc_l_d(fp0, tcg_env, fp0);
9865 }
9866 gen_store_fpr64(ctx, fp0, fd);
9867 }
9868 break;
9869 case OPC_CEIL_L_D:
9870 check_cp1_64bitmode(ctx);
9871 {
9872 TCGv_i64 fp0 = tcg_temp_new_i64();
9873
9874 gen_load_fpr64(ctx, fp0, fs);
9875 if (ctx->nan2008) {
9876 gen_helper_float_ceil_2008_l_d(fp0, tcg_env, fp0);
9877 } else {
9878 gen_helper_float_ceil_l_d(fp0, tcg_env, fp0);
9879 }
9880 gen_store_fpr64(ctx, fp0, fd);
9881 }
9882 break;
9883 case OPC_FLOOR_L_D:
9884 check_cp1_64bitmode(ctx);
9885 {
9886 TCGv_i64 fp0 = tcg_temp_new_i64();
9887
9888 gen_load_fpr64(ctx, fp0, fs);
9889 if (ctx->nan2008) {
9890 gen_helper_float_floor_2008_l_d(fp0, tcg_env, fp0);
9891 } else {
9892 gen_helper_float_floor_l_d(fp0, tcg_env, fp0);
9893 }
9894 gen_store_fpr64(ctx, fp0, fd);
9895 }
9896 break;
9897 case OPC_ROUND_W_D:
9898 check_cp1_registers(ctx, fs);
9899 {
9900 TCGv_i32 fp32 = tcg_temp_new_i32();
9901 TCGv_i64 fp64 = tcg_temp_new_i64();
9902
9903 gen_load_fpr64(ctx, fp64, fs);
9904 if (ctx->nan2008) {
9905 gen_helper_float_round_2008_w_d(fp32, tcg_env, fp64);
9906 } else {
9907 gen_helper_float_round_w_d(fp32, tcg_env, fp64);
9908 }
9909 gen_store_fpr32(ctx, fp32, fd);
9910 }
9911 break;
9912 case OPC_TRUNC_W_D:
9913 check_cp1_registers(ctx, fs);
9914 {
9915 TCGv_i32 fp32 = tcg_temp_new_i32();
9916 TCGv_i64 fp64 = tcg_temp_new_i64();
9917
9918 gen_load_fpr64(ctx, fp64, fs);
9919 if (ctx->nan2008) {
9920 gen_helper_float_trunc_2008_w_d(fp32, tcg_env, fp64);
9921 } else {
9922 gen_helper_float_trunc_w_d(fp32, tcg_env, fp64);
9923 }
9924 gen_store_fpr32(ctx, fp32, fd);
9925 }
9926 break;
9927 case OPC_CEIL_W_D:
9928 check_cp1_registers(ctx, fs);
9929 {
9930 TCGv_i32 fp32 = tcg_temp_new_i32();
9931 TCGv_i64 fp64 = tcg_temp_new_i64();
9932
9933 gen_load_fpr64(ctx, fp64, fs);
9934 if (ctx->nan2008) {
9935 gen_helper_float_ceil_2008_w_d(fp32, tcg_env, fp64);
9936 } else {
9937 gen_helper_float_ceil_w_d(fp32, tcg_env, fp64);
9938 }
9939 gen_store_fpr32(ctx, fp32, fd);
9940 }
9941 break;
9942 case OPC_FLOOR_W_D:
9943 check_cp1_registers(ctx, fs);
9944 {
9945 TCGv_i32 fp32 = tcg_temp_new_i32();
9946 TCGv_i64 fp64 = tcg_temp_new_i64();
9947
9948 gen_load_fpr64(ctx, fp64, fs);
9949 if (ctx->nan2008) {
9950 gen_helper_float_floor_2008_w_d(fp32, tcg_env, fp64);
9951 } else {
9952 gen_helper_float_floor_w_d(fp32, tcg_env, fp64);
9953 }
9954 gen_store_fpr32(ctx, fp32, fd);
9955 }
9956 break;
9957 case OPC_SEL_D:
9958 check_insn(ctx, ISA_MIPS_R6);
9959 gen_sel_d(ctx, op1, fd, ft, fs);
9960 break;
9961 case OPC_SELEQZ_D:
9962 check_insn(ctx, ISA_MIPS_R6);
9963 gen_sel_d(ctx, op1, fd, ft, fs);
9964 break;
9965 case OPC_SELNEZ_D:
9966 check_insn(ctx, ISA_MIPS_R6);
9967 gen_sel_d(ctx, op1, fd, ft, fs);
9968 break;
9969 case OPC_MOVCF_D:
9970 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9971 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9972 break;
9973 case OPC_MOVZ_D:
9974 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9975 {
9976 TCGLabel *l1 = gen_new_label();
9977 TCGv_i64 fp0;
9978
9979 if (ft != 0) {
9980 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9981 }
9982 fp0 = tcg_temp_new_i64();
9983 gen_load_fpr64(ctx, fp0, fs);
9984 gen_store_fpr64(ctx, fp0, fd);
9985 gen_set_label(l1);
9986 }
9987 break;
9988 case OPC_MOVN_D:
9989 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9990 {
9991 TCGLabel *l1 = gen_new_label();
9992 TCGv_i64 fp0;
9993
9994 if (ft != 0) {
9995 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9996 fp0 = tcg_temp_new_i64();
9997 gen_load_fpr64(ctx, fp0, fs);
9998 gen_store_fpr64(ctx, fp0, fd);
9999 gen_set_label(l1);
10000 }
10001 }
10002 break;
10003 case OPC_RECIP_D:
10004 check_cp1_registers(ctx, fs | fd);
10005 {
10006 TCGv_i64 fp0 = tcg_temp_new_i64();
10007
10008 gen_load_fpr64(ctx, fp0, fs);
10009 gen_helper_float_recip_d(fp0, tcg_env, fp0);
10010 gen_store_fpr64(ctx, fp0, fd);
10011 }
10012 break;
10013 case OPC_RSQRT_D:
10014 check_cp1_registers(ctx, fs | fd);
10015 {
10016 TCGv_i64 fp0 = tcg_temp_new_i64();
10017
10018 gen_load_fpr64(ctx, fp0, fs);
10019 gen_helper_float_rsqrt_d(fp0, tcg_env, fp0);
10020 gen_store_fpr64(ctx, fp0, fd);
10021 }
10022 break;
10023 case OPC_MADDF_D:
10024 check_insn(ctx, ISA_MIPS_R6);
10025 {
10026 TCGv_i64 fp0 = tcg_temp_new_i64();
10027 TCGv_i64 fp1 = tcg_temp_new_i64();
10028 TCGv_i64 fp2 = tcg_temp_new_i64();
10029 gen_load_fpr64(ctx, fp0, fs);
10030 gen_load_fpr64(ctx, fp1, ft);
10031 gen_load_fpr64(ctx, fp2, fd);
10032 gen_helper_float_maddf_d(fp2, tcg_env, fp0, fp1, fp2);
10033 gen_store_fpr64(ctx, fp2, fd);
10034 }
10035 break;
10036 case OPC_MSUBF_D:
10037 check_insn(ctx, ISA_MIPS_R6);
10038 {
10039 TCGv_i64 fp0 = tcg_temp_new_i64();
10040 TCGv_i64 fp1 = tcg_temp_new_i64();
10041 TCGv_i64 fp2 = tcg_temp_new_i64();
10042 gen_load_fpr64(ctx, fp0, fs);
10043 gen_load_fpr64(ctx, fp1, ft);
10044 gen_load_fpr64(ctx, fp2, fd);
10045 gen_helper_float_msubf_d(fp2, tcg_env, fp0, fp1, fp2);
10046 gen_store_fpr64(ctx, fp2, fd);
10047 }
10048 break;
10049 case OPC_RINT_D:
10050 check_insn(ctx, ISA_MIPS_R6);
10051 {
10052 TCGv_i64 fp0 = tcg_temp_new_i64();
10053 gen_load_fpr64(ctx, fp0, fs);
10054 gen_helper_float_rint_d(fp0, tcg_env, fp0);
10055 gen_store_fpr64(ctx, fp0, fd);
10056 }
10057 break;
10058 case OPC_CLASS_D:
10059 check_insn(ctx, ISA_MIPS_R6);
10060 {
10061 TCGv_i64 fp0 = tcg_temp_new_i64();
10062 gen_load_fpr64(ctx, fp0, fs);
10063 gen_helper_float_class_d(fp0, tcg_env, fp0);
10064 gen_store_fpr64(ctx, fp0, fd);
10065 }
10066 break;
10067 case OPC_MIN_D: /* OPC_RECIP2_D */
10068 if (ctx->insn_flags & ISA_MIPS_R6) {
10069 /* OPC_MIN_D */
10070 TCGv_i64 fp0 = tcg_temp_new_i64();
10071 TCGv_i64 fp1 = tcg_temp_new_i64();
10072 gen_load_fpr64(ctx, fp0, fs);
10073 gen_load_fpr64(ctx, fp1, ft);
10074 gen_helper_float_min_d(fp1, tcg_env, fp0, fp1);
10075 gen_store_fpr64(ctx, fp1, fd);
10076 } else {
10077 /* OPC_RECIP2_D */
10078 check_cp1_64bitmode(ctx);
10079 {
10080 TCGv_i64 fp0 = tcg_temp_new_i64();
10081 TCGv_i64 fp1 = tcg_temp_new_i64();
10082
10083 gen_load_fpr64(ctx, fp0, fs);
10084 gen_load_fpr64(ctx, fp1, ft);
10085 gen_helper_float_recip2_d(fp0, tcg_env, fp0, fp1);
10086 gen_store_fpr64(ctx, fp0, fd);
10087 }
10088 }
10089 break;
10090 case OPC_MINA_D: /* OPC_RECIP1_D */
10091 if (ctx->insn_flags & ISA_MIPS_R6) {
10092 /* OPC_MINA_D */
10093 TCGv_i64 fp0 = tcg_temp_new_i64();
10094 TCGv_i64 fp1 = tcg_temp_new_i64();
10095 gen_load_fpr64(ctx, fp0, fs);
10096 gen_load_fpr64(ctx, fp1, ft);
10097 gen_helper_float_mina_d(fp1, tcg_env, fp0, fp1);
10098 gen_store_fpr64(ctx, fp1, fd);
10099 } else {
10100 /* OPC_RECIP1_D */
10101 check_cp1_64bitmode(ctx);
10102 {
10103 TCGv_i64 fp0 = tcg_temp_new_i64();
10104
10105 gen_load_fpr64(ctx, fp0, fs);
10106 gen_helper_float_recip1_d(fp0, tcg_env, fp0);
10107 gen_store_fpr64(ctx, fp0, fd);
10108 }
10109 }
10110 break;
10111 case OPC_MAX_D: /* OPC_RSQRT1_D */
10112 if (ctx->insn_flags & ISA_MIPS_R6) {
10113 /* OPC_MAX_D */
10114 TCGv_i64 fp0 = tcg_temp_new_i64();
10115 TCGv_i64 fp1 = tcg_temp_new_i64();
10116 gen_load_fpr64(ctx, fp0, fs);
10117 gen_load_fpr64(ctx, fp1, ft);
10118 gen_helper_float_max_d(fp1, tcg_env, fp0, fp1);
10119 gen_store_fpr64(ctx, fp1, fd);
10120 } else {
10121 /* OPC_RSQRT1_D */
10122 check_cp1_64bitmode(ctx);
10123 {
10124 TCGv_i64 fp0 = tcg_temp_new_i64();
10125
10126 gen_load_fpr64(ctx, fp0, fs);
10127 gen_helper_float_rsqrt1_d(fp0, tcg_env, fp0);
10128 gen_store_fpr64(ctx, fp0, fd);
10129 }
10130 }
10131 break;
10132 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10133 if (ctx->insn_flags & ISA_MIPS_R6) {
10134 /* OPC_MAXA_D */
10135 TCGv_i64 fp0 = tcg_temp_new_i64();
10136 TCGv_i64 fp1 = tcg_temp_new_i64();
10137 gen_load_fpr64(ctx, fp0, fs);
10138 gen_load_fpr64(ctx, fp1, ft);
10139 gen_helper_float_maxa_d(fp1, tcg_env, fp0, fp1);
10140 gen_store_fpr64(ctx, fp1, fd);
10141 } else {
10142 /* OPC_RSQRT2_D */
10143 check_cp1_64bitmode(ctx);
10144 {
10145 TCGv_i64 fp0 = tcg_temp_new_i64();
10146 TCGv_i64 fp1 = tcg_temp_new_i64();
10147
10148 gen_load_fpr64(ctx, fp0, fs);
10149 gen_load_fpr64(ctx, fp1, ft);
10150 gen_helper_float_rsqrt2_d(fp0, tcg_env, fp0, fp1);
10151 gen_store_fpr64(ctx, fp0, fd);
10152 }
10153 }
10154 break;
10155 case OPC_CMP_F_D:
10156 case OPC_CMP_UN_D:
10157 case OPC_CMP_EQ_D:
10158 case OPC_CMP_UEQ_D:
10159 case OPC_CMP_OLT_D:
10160 case OPC_CMP_ULT_D:
10161 case OPC_CMP_OLE_D:
10162 case OPC_CMP_ULE_D:
10163 case OPC_CMP_SF_D:
10164 case OPC_CMP_NGLE_D:
10165 case OPC_CMP_SEQ_D:
10166 case OPC_CMP_NGL_D:
10167 case OPC_CMP_LT_D:
10168 case OPC_CMP_NGE_D:
10169 case OPC_CMP_LE_D:
10170 case OPC_CMP_NGT_D:
10171 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10172 if (ctx->opcode & (1 << 6)) {
10173 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
10174 } else {
10175 gen_cmp_d(ctx, func - 48, ft, fs, cc);
10176 }
10177 break;
10178 case OPC_CVT_S_D:
10179 check_cp1_registers(ctx, fs);
10180 {
10181 TCGv_i32 fp32 = tcg_temp_new_i32();
10182 TCGv_i64 fp64 = tcg_temp_new_i64();
10183
10184 gen_load_fpr64(ctx, fp64, fs);
10185 gen_helper_float_cvts_d(fp32, tcg_env, fp64);
10186 gen_store_fpr32(ctx, fp32, fd);
10187 }
10188 break;
10189 case OPC_CVT_W_D:
10190 check_cp1_registers(ctx, fs);
10191 {
10192 TCGv_i32 fp32 = tcg_temp_new_i32();
10193 TCGv_i64 fp64 = tcg_temp_new_i64();
10194
10195 gen_load_fpr64(ctx, fp64, fs);
10196 if (ctx->nan2008) {
10197 gen_helper_float_cvt_2008_w_d(fp32, tcg_env, fp64);
10198 } else {
10199 gen_helper_float_cvt_w_d(fp32, tcg_env, fp64);
10200 }
10201 gen_store_fpr32(ctx, fp32, fd);
10202 }
10203 break;
10204 case OPC_CVT_L_D:
10205 check_cp1_64bitmode(ctx);
10206 {
10207 TCGv_i64 fp0 = tcg_temp_new_i64();
10208
10209 gen_load_fpr64(ctx, fp0, fs);
10210 if (ctx->nan2008) {
10211 gen_helper_float_cvt_2008_l_d(fp0, tcg_env, fp0);
10212 } else {
10213 gen_helper_float_cvt_l_d(fp0, tcg_env, fp0);
10214 }
10215 gen_store_fpr64(ctx, fp0, fd);
10216 }
10217 break;
10218 case OPC_CVT_S_W:
10219 {
10220 TCGv_i32 fp0 = tcg_temp_new_i32();
10221
10222 gen_load_fpr32(ctx, fp0, fs);
10223 gen_helper_float_cvts_w(fp0, tcg_env, fp0);
10224 gen_store_fpr32(ctx, fp0, fd);
10225 }
10226 break;
10227 case OPC_CVT_D_W:
10228 check_cp1_registers(ctx, fd);
10229 {
10230 TCGv_i32 fp32 = tcg_temp_new_i32();
10231 TCGv_i64 fp64 = tcg_temp_new_i64();
10232
10233 gen_load_fpr32(ctx, fp32, fs);
10234 gen_helper_float_cvtd_w(fp64, tcg_env, fp32);
10235 gen_store_fpr64(ctx, fp64, fd);
10236 }
10237 break;
10238 case OPC_CVT_S_L:
10239 check_cp1_64bitmode(ctx);
10240 {
10241 TCGv_i32 fp32 = tcg_temp_new_i32();
10242 TCGv_i64 fp64 = tcg_temp_new_i64();
10243
10244 gen_load_fpr64(ctx, fp64, fs);
10245 gen_helper_float_cvts_l(fp32, tcg_env, fp64);
10246 gen_store_fpr32(ctx, fp32, fd);
10247 }
10248 break;
10249 case OPC_CVT_D_L:
10250 check_cp1_64bitmode(ctx);
10251 {
10252 TCGv_i64 fp0 = tcg_temp_new_i64();
10253
10254 gen_load_fpr64(ctx, fp0, fs);
10255 gen_helper_float_cvtd_l(fp0, tcg_env, fp0);
10256 gen_store_fpr64(ctx, fp0, fd);
10257 }
10258 break;
10259 case OPC_CVT_PS_PW:
10260 check_ps(ctx);
10261 {
10262 TCGv_i64 fp0 = tcg_temp_new_i64();
10263
10264 gen_load_fpr64(ctx, fp0, fs);
10265 gen_helper_float_cvtps_pw(fp0, tcg_env, fp0);
10266 gen_store_fpr64(ctx, fp0, fd);
10267 }
10268 break;
10269 case OPC_ADD_PS:
10270 check_ps(ctx);
10271 {
10272 TCGv_i64 fp0 = tcg_temp_new_i64();
10273 TCGv_i64 fp1 = tcg_temp_new_i64();
10274
10275 gen_load_fpr64(ctx, fp0, fs);
10276 gen_load_fpr64(ctx, fp1, ft);
10277 gen_helper_float_add_ps(fp0, tcg_env, fp0, fp1);
10278 gen_store_fpr64(ctx, fp0, fd);
10279 }
10280 break;
10281 case OPC_SUB_PS:
10282 check_ps(ctx);
10283 {
10284 TCGv_i64 fp0 = tcg_temp_new_i64();
10285 TCGv_i64 fp1 = tcg_temp_new_i64();
10286
10287 gen_load_fpr64(ctx, fp0, fs);
10288 gen_load_fpr64(ctx, fp1, ft);
10289 gen_helper_float_sub_ps(fp0, tcg_env, fp0, fp1);
10290 gen_store_fpr64(ctx, fp0, fd);
10291 }
10292 break;
10293 case OPC_MUL_PS:
10294 check_ps(ctx);
10295 {
10296 TCGv_i64 fp0 = tcg_temp_new_i64();
10297 TCGv_i64 fp1 = tcg_temp_new_i64();
10298
10299 gen_load_fpr64(ctx, fp0, fs);
10300 gen_load_fpr64(ctx, fp1, ft);
10301 gen_helper_float_mul_ps(fp0, tcg_env, fp0, fp1);
10302 gen_store_fpr64(ctx, fp0, fd);
10303 }
10304 break;
10305 case OPC_ABS_PS:
10306 check_ps(ctx);
10307 {
10308 TCGv_i64 fp0 = tcg_temp_new_i64();
10309
10310 gen_load_fpr64(ctx, fp0, fs);
10311 gen_helper_float_abs_ps(fp0, fp0);
10312 gen_store_fpr64(ctx, fp0, fd);
10313 }
10314 break;
10315 case OPC_MOV_PS:
10316 check_ps(ctx);
10317 {
10318 TCGv_i64 fp0 = tcg_temp_new_i64();
10319
10320 gen_load_fpr64(ctx, fp0, fs);
10321 gen_store_fpr64(ctx, fp0, fd);
10322 }
10323 break;
10324 case OPC_NEG_PS:
10325 check_ps(ctx);
10326 {
10327 TCGv_i64 fp0 = tcg_temp_new_i64();
10328
10329 gen_load_fpr64(ctx, fp0, fs);
10330 gen_helper_float_chs_ps(fp0, fp0);
10331 gen_store_fpr64(ctx, fp0, fd);
10332 }
10333 break;
10334 case OPC_MOVCF_PS:
10335 check_ps(ctx);
10336 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10337 break;
10338 case OPC_MOVZ_PS:
10339 check_ps(ctx);
10340 {
10341 TCGLabel *l1 = gen_new_label();
10342 TCGv_i64 fp0;
10343
10344 if (ft != 0) {
10345 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10346 }
10347 fp0 = tcg_temp_new_i64();
10348 gen_load_fpr64(ctx, fp0, fs);
10349 gen_store_fpr64(ctx, fp0, fd);
10350 gen_set_label(l1);
10351 }
10352 break;
10353 case OPC_MOVN_PS:
10354 check_ps(ctx);
10355 {
10356 TCGLabel *l1 = gen_new_label();
10357 TCGv_i64 fp0;
10358
10359 if (ft != 0) {
10360 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10361 fp0 = tcg_temp_new_i64();
10362 gen_load_fpr64(ctx, fp0, fs);
10363 gen_store_fpr64(ctx, fp0, fd);
10364 gen_set_label(l1);
10365 }
10366 }
10367 break;
10368 case OPC_ADDR_PS:
10369 check_ps(ctx);
10370 {
10371 TCGv_i64 fp0 = tcg_temp_new_i64();
10372 TCGv_i64 fp1 = tcg_temp_new_i64();
10373
10374 gen_load_fpr64(ctx, fp0, ft);
10375 gen_load_fpr64(ctx, fp1, fs);
10376 gen_helper_float_addr_ps(fp0, tcg_env, fp0, fp1);
10377 gen_store_fpr64(ctx, fp0, fd);
10378 }
10379 break;
10380 case OPC_MULR_PS:
10381 check_ps(ctx);
10382 {
10383 TCGv_i64 fp0 = tcg_temp_new_i64();
10384 TCGv_i64 fp1 = tcg_temp_new_i64();
10385
10386 gen_load_fpr64(ctx, fp0, ft);
10387 gen_load_fpr64(ctx, fp1, fs);
10388 gen_helper_float_mulr_ps(fp0, tcg_env, fp0, fp1);
10389 gen_store_fpr64(ctx, fp0, fd);
10390 }
10391 break;
10392 case OPC_RECIP2_PS:
10393 check_ps(ctx);
10394 {
10395 TCGv_i64 fp0 = tcg_temp_new_i64();
10396 TCGv_i64 fp1 = tcg_temp_new_i64();
10397
10398 gen_load_fpr64(ctx, fp0, fs);
10399 gen_load_fpr64(ctx, fp1, ft);
10400 gen_helper_float_recip2_ps(fp0, tcg_env, fp0, fp1);
10401 gen_store_fpr64(ctx, fp0, fd);
10402 }
10403 break;
10404 case OPC_RECIP1_PS:
10405 check_ps(ctx);
10406 {
10407 TCGv_i64 fp0 = tcg_temp_new_i64();
10408
10409 gen_load_fpr64(ctx, fp0, fs);
10410 gen_helper_float_recip1_ps(fp0, tcg_env, fp0);
10411 gen_store_fpr64(ctx, fp0, fd);
10412 }
10413 break;
10414 case OPC_RSQRT1_PS:
10415 check_ps(ctx);
10416 {
10417 TCGv_i64 fp0 = tcg_temp_new_i64();
10418
10419 gen_load_fpr64(ctx, fp0, fs);
10420 gen_helper_float_rsqrt1_ps(fp0, tcg_env, fp0);
10421 gen_store_fpr64(ctx, fp0, fd);
10422 }
10423 break;
10424 case OPC_RSQRT2_PS:
10425 check_ps(ctx);
10426 {
10427 TCGv_i64 fp0 = tcg_temp_new_i64();
10428 TCGv_i64 fp1 = tcg_temp_new_i64();
10429
10430 gen_load_fpr64(ctx, fp0, fs);
10431 gen_load_fpr64(ctx, fp1, ft);
10432 gen_helper_float_rsqrt2_ps(fp0, tcg_env, fp0, fp1);
10433 gen_store_fpr64(ctx, fp0, fd);
10434 }
10435 break;
10436 case OPC_CVT_S_PU:
10437 check_cp1_64bitmode(ctx);
10438 {
10439 TCGv_i32 fp0 = tcg_temp_new_i32();
10440
10441 gen_load_fpr32h(ctx, fp0, fs);
10442 gen_helper_float_cvts_pu(fp0, tcg_env, fp0);
10443 gen_store_fpr32(ctx, fp0, fd);
10444 }
10445 break;
10446 case OPC_CVT_PW_PS:
10447 check_ps(ctx);
10448 {
10449 TCGv_i64 fp0 = tcg_temp_new_i64();
10450
10451 gen_load_fpr64(ctx, fp0, fs);
10452 gen_helper_float_cvtpw_ps(fp0, tcg_env, fp0);
10453 gen_store_fpr64(ctx, fp0, fd);
10454 }
10455 break;
10456 case OPC_CVT_S_PL:
10457 check_cp1_64bitmode(ctx);
10458 {
10459 TCGv_i32 fp0 = tcg_temp_new_i32();
10460
10461 gen_load_fpr32(ctx, fp0, fs);
10462 gen_helper_float_cvts_pl(fp0, tcg_env, fp0);
10463 gen_store_fpr32(ctx, fp0, fd);
10464 }
10465 break;
10466 case OPC_PLL_PS:
10467 check_ps(ctx);
10468 {
10469 TCGv_i32 fp0 = tcg_temp_new_i32();
10470 TCGv_i32 fp1 = tcg_temp_new_i32();
10471
10472 gen_load_fpr32(ctx, fp0, fs);
10473 gen_load_fpr32(ctx, fp1, ft);
10474 gen_store_fpr32h(ctx, fp0, fd);
10475 gen_store_fpr32(ctx, fp1, fd);
10476 }
10477 break;
10478 case OPC_PLU_PS:
10479 check_ps(ctx);
10480 {
10481 TCGv_i32 fp0 = tcg_temp_new_i32();
10482 TCGv_i32 fp1 = tcg_temp_new_i32();
10483
10484 gen_load_fpr32(ctx, fp0, fs);
10485 gen_load_fpr32h(ctx, fp1, ft);
10486 gen_store_fpr32(ctx, fp1, fd);
10487 gen_store_fpr32h(ctx, fp0, fd);
10488 }
10489 break;
10490 case OPC_PUL_PS:
10491 check_ps(ctx);
10492 {
10493 TCGv_i32 fp0 = tcg_temp_new_i32();
10494 TCGv_i32 fp1 = tcg_temp_new_i32();
10495
10496 gen_load_fpr32h(ctx, fp0, fs);
10497 gen_load_fpr32(ctx, fp1, ft);
10498 gen_store_fpr32(ctx, fp1, fd);
10499 gen_store_fpr32h(ctx, fp0, fd);
10500 }
10501 break;
10502 case OPC_PUU_PS:
10503 check_ps(ctx);
10504 {
10505 TCGv_i32 fp0 = tcg_temp_new_i32();
10506 TCGv_i32 fp1 = tcg_temp_new_i32();
10507
10508 gen_load_fpr32h(ctx, fp0, fs);
10509 gen_load_fpr32h(ctx, fp1, ft);
10510 gen_store_fpr32(ctx, fp1, fd);
10511 gen_store_fpr32h(ctx, fp0, fd);
10512 }
10513 break;
10514 case OPC_CMP_F_PS:
10515 case OPC_CMP_UN_PS:
10516 case OPC_CMP_EQ_PS:
10517 case OPC_CMP_UEQ_PS:
10518 case OPC_CMP_OLT_PS:
10519 case OPC_CMP_ULT_PS:
10520 case OPC_CMP_OLE_PS:
10521 case OPC_CMP_ULE_PS:
10522 case OPC_CMP_SF_PS:
10523 case OPC_CMP_NGLE_PS:
10524 case OPC_CMP_SEQ_PS:
10525 case OPC_CMP_NGL_PS:
10526 case OPC_CMP_LT_PS:
10527 case OPC_CMP_NGE_PS:
10528 case OPC_CMP_LE_PS:
10529 case OPC_CMP_NGT_PS:
10530 if (ctx->opcode & (1 << 6)) {
10531 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
10532 } else {
10533 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
10534 }
10535 break;
10536 default:
10537 MIPS_INVAL("farith");
10538 gen_reserved_instruction(ctx);
10539 return;
10540 }
10541 }
10542
10543 /* Coprocessor 3 (FPU) */
gen_flt3_ldst(DisasContext * ctx,uint32_t opc,int fd,int fs,int base,int index)10544 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
10545 int fd, int fs, int base, int index)
10546 {
10547 TCGv t0 = tcg_temp_new();
10548
10549 if (base == 0) {
10550 gen_load_gpr(t0, index);
10551 } else if (index == 0) {
10552 gen_load_gpr(t0, base);
10553 } else {
10554 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10555 }
10556 /*
10557 * Don't do NOP if destination is zero: we must perform the actual
10558 * memory access.
10559 */
10560 switch (opc) {
10561 case OPC_LWXC1:
10562 check_cop1x(ctx);
10563 {
10564 TCGv_i32 fp0 = tcg_temp_new_i32();
10565
10566 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
10567 tcg_gen_trunc_tl_i32(fp0, t0);
10568 gen_store_fpr32(ctx, fp0, fd);
10569 }
10570 break;
10571 case OPC_LDXC1:
10572 check_cop1x(ctx);
10573 check_cp1_registers(ctx, fd);
10574 {
10575 TCGv_i64 fp0 = tcg_temp_new_i64();
10576 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10577 gen_store_fpr64(ctx, fp0, fd);
10578 }
10579 break;
10580 case OPC_LUXC1:
10581 check_cp1_64bitmode(ctx);
10582 tcg_gen_andi_tl(t0, t0, ~0x7);
10583 {
10584 TCGv_i64 fp0 = tcg_temp_new_i64();
10585
10586 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10587 gen_store_fpr64(ctx, fp0, fd);
10588 }
10589 break;
10590 case OPC_SWXC1:
10591 check_cop1x(ctx);
10592 {
10593 TCGv_i32 fp0 = tcg_temp_new_i32();
10594 gen_load_fpr32(ctx, fp0, fs);
10595 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
10596 }
10597 break;
10598 case OPC_SDXC1:
10599 check_cop1x(ctx);
10600 check_cp1_registers(ctx, fs);
10601 {
10602 TCGv_i64 fp0 = tcg_temp_new_i64();
10603 gen_load_fpr64(ctx, fp0, fs);
10604 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10605 }
10606 break;
10607 case OPC_SUXC1:
10608 check_cp1_64bitmode(ctx);
10609 tcg_gen_andi_tl(t0, t0, ~0x7);
10610 {
10611 TCGv_i64 fp0 = tcg_temp_new_i64();
10612 gen_load_fpr64(ctx, fp0, fs);
10613 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10614 }
10615 break;
10616 }
10617 }
10618
gen_flt3_arith(DisasContext * ctx,uint32_t opc,int fd,int fr,int fs,int ft)10619 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
10620 int fd, int fr, int fs, int ft)
10621 {
10622 switch (opc) {
10623 case OPC_ALNV_PS:
10624 check_ps(ctx);
10625 {
10626 TCGv t0 = tcg_temp_new();
10627 TCGv_i32 fp = tcg_temp_new_i32();
10628 TCGv_i32 fph = tcg_temp_new_i32();
10629 TCGLabel *l1 = gen_new_label();
10630 TCGLabel *l2 = gen_new_label();
10631
10632 gen_load_gpr(t0, fr);
10633 tcg_gen_andi_tl(t0, t0, 0x7);
10634
10635 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10636 gen_load_fpr32(ctx, fp, fs);
10637 gen_load_fpr32h(ctx, fph, fs);
10638 gen_store_fpr32(ctx, fp, fd);
10639 gen_store_fpr32h(ctx, fph, fd);
10640 tcg_gen_br(l2);
10641 gen_set_label(l1);
10642 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10643 if (disas_is_bigendian(ctx)) {
10644 gen_load_fpr32(ctx, fp, fs);
10645 gen_load_fpr32h(ctx, fph, ft);
10646 gen_store_fpr32h(ctx, fp, fd);
10647 gen_store_fpr32(ctx, fph, fd);
10648 } else {
10649 gen_load_fpr32h(ctx, fph, fs);
10650 gen_load_fpr32(ctx, fp, ft);
10651 gen_store_fpr32(ctx, fph, fd);
10652 gen_store_fpr32h(ctx, fp, fd);
10653 }
10654 gen_set_label(l2);
10655 }
10656 break;
10657 case OPC_MADD_S:
10658 check_cop1x(ctx);
10659 {
10660 TCGv_i32 fp0 = tcg_temp_new_i32();
10661 TCGv_i32 fp1 = tcg_temp_new_i32();
10662 TCGv_i32 fp2 = tcg_temp_new_i32();
10663
10664 gen_load_fpr32(ctx, fp0, fs);
10665 gen_load_fpr32(ctx, fp1, ft);
10666 gen_load_fpr32(ctx, fp2, fr);
10667 gen_helper_float_madd_s(fp2, tcg_env, fp0, fp1, fp2);
10668 gen_store_fpr32(ctx, fp2, fd);
10669 }
10670 break;
10671 case OPC_MADD_D:
10672 check_cop1x(ctx);
10673 check_cp1_registers(ctx, fd | fs | ft | fr);
10674 {
10675 TCGv_i64 fp0 = tcg_temp_new_i64();
10676 TCGv_i64 fp1 = tcg_temp_new_i64();
10677 TCGv_i64 fp2 = tcg_temp_new_i64();
10678
10679 gen_load_fpr64(ctx, fp0, fs);
10680 gen_load_fpr64(ctx, fp1, ft);
10681 gen_load_fpr64(ctx, fp2, fr);
10682 gen_helper_float_madd_d(fp2, tcg_env, fp0, fp1, fp2);
10683 gen_store_fpr64(ctx, fp2, fd);
10684 }
10685 break;
10686 case OPC_MADD_PS:
10687 check_ps(ctx);
10688 {
10689 TCGv_i64 fp0 = tcg_temp_new_i64();
10690 TCGv_i64 fp1 = tcg_temp_new_i64();
10691 TCGv_i64 fp2 = tcg_temp_new_i64();
10692
10693 gen_load_fpr64(ctx, fp0, fs);
10694 gen_load_fpr64(ctx, fp1, ft);
10695 gen_load_fpr64(ctx, fp2, fr);
10696 gen_helper_float_madd_ps(fp2, tcg_env, fp0, fp1, fp2);
10697 gen_store_fpr64(ctx, fp2, fd);
10698 }
10699 break;
10700 case OPC_MSUB_S:
10701 check_cop1x(ctx);
10702 {
10703 TCGv_i32 fp0 = tcg_temp_new_i32();
10704 TCGv_i32 fp1 = tcg_temp_new_i32();
10705 TCGv_i32 fp2 = tcg_temp_new_i32();
10706
10707 gen_load_fpr32(ctx, fp0, fs);
10708 gen_load_fpr32(ctx, fp1, ft);
10709 gen_load_fpr32(ctx, fp2, fr);
10710 gen_helper_float_msub_s(fp2, tcg_env, fp0, fp1, fp2);
10711 gen_store_fpr32(ctx, fp2, fd);
10712 }
10713 break;
10714 case OPC_MSUB_D:
10715 check_cop1x(ctx);
10716 check_cp1_registers(ctx, fd | fs | ft | fr);
10717 {
10718 TCGv_i64 fp0 = tcg_temp_new_i64();
10719 TCGv_i64 fp1 = tcg_temp_new_i64();
10720 TCGv_i64 fp2 = tcg_temp_new_i64();
10721
10722 gen_load_fpr64(ctx, fp0, fs);
10723 gen_load_fpr64(ctx, fp1, ft);
10724 gen_load_fpr64(ctx, fp2, fr);
10725 gen_helper_float_msub_d(fp2, tcg_env, fp0, fp1, fp2);
10726 gen_store_fpr64(ctx, fp2, fd);
10727 }
10728 break;
10729 case OPC_MSUB_PS:
10730 check_ps(ctx);
10731 {
10732 TCGv_i64 fp0 = tcg_temp_new_i64();
10733 TCGv_i64 fp1 = tcg_temp_new_i64();
10734 TCGv_i64 fp2 = tcg_temp_new_i64();
10735
10736 gen_load_fpr64(ctx, fp0, fs);
10737 gen_load_fpr64(ctx, fp1, ft);
10738 gen_load_fpr64(ctx, fp2, fr);
10739 gen_helper_float_msub_ps(fp2, tcg_env, fp0, fp1, fp2);
10740 gen_store_fpr64(ctx, fp2, fd);
10741 }
10742 break;
10743 case OPC_NMADD_S:
10744 check_cop1x(ctx);
10745 {
10746 TCGv_i32 fp0 = tcg_temp_new_i32();
10747 TCGv_i32 fp1 = tcg_temp_new_i32();
10748 TCGv_i32 fp2 = tcg_temp_new_i32();
10749
10750 gen_load_fpr32(ctx, fp0, fs);
10751 gen_load_fpr32(ctx, fp1, ft);
10752 gen_load_fpr32(ctx, fp2, fr);
10753 gen_helper_float_nmadd_s(fp2, tcg_env, fp0, fp1, fp2);
10754 gen_store_fpr32(ctx, fp2, fd);
10755 }
10756 break;
10757 case OPC_NMADD_D:
10758 check_cop1x(ctx);
10759 check_cp1_registers(ctx, fd | fs | ft | fr);
10760 {
10761 TCGv_i64 fp0 = tcg_temp_new_i64();
10762 TCGv_i64 fp1 = tcg_temp_new_i64();
10763 TCGv_i64 fp2 = tcg_temp_new_i64();
10764
10765 gen_load_fpr64(ctx, fp0, fs);
10766 gen_load_fpr64(ctx, fp1, ft);
10767 gen_load_fpr64(ctx, fp2, fr);
10768 gen_helper_float_nmadd_d(fp2, tcg_env, fp0, fp1, fp2);
10769 gen_store_fpr64(ctx, fp2, fd);
10770 }
10771 break;
10772 case OPC_NMADD_PS:
10773 check_ps(ctx);
10774 {
10775 TCGv_i64 fp0 = tcg_temp_new_i64();
10776 TCGv_i64 fp1 = tcg_temp_new_i64();
10777 TCGv_i64 fp2 = tcg_temp_new_i64();
10778
10779 gen_load_fpr64(ctx, fp0, fs);
10780 gen_load_fpr64(ctx, fp1, ft);
10781 gen_load_fpr64(ctx, fp2, fr);
10782 gen_helper_float_nmadd_ps(fp2, tcg_env, fp0, fp1, fp2);
10783 gen_store_fpr64(ctx, fp2, fd);
10784 }
10785 break;
10786 case OPC_NMSUB_S:
10787 check_cop1x(ctx);
10788 {
10789 TCGv_i32 fp0 = tcg_temp_new_i32();
10790 TCGv_i32 fp1 = tcg_temp_new_i32();
10791 TCGv_i32 fp2 = tcg_temp_new_i32();
10792
10793 gen_load_fpr32(ctx, fp0, fs);
10794 gen_load_fpr32(ctx, fp1, ft);
10795 gen_load_fpr32(ctx, fp2, fr);
10796 gen_helper_float_nmsub_s(fp2, tcg_env, fp0, fp1, fp2);
10797 gen_store_fpr32(ctx, fp2, fd);
10798 }
10799 break;
10800 case OPC_NMSUB_D:
10801 check_cop1x(ctx);
10802 check_cp1_registers(ctx, fd | fs | ft | fr);
10803 {
10804 TCGv_i64 fp0 = tcg_temp_new_i64();
10805 TCGv_i64 fp1 = tcg_temp_new_i64();
10806 TCGv_i64 fp2 = tcg_temp_new_i64();
10807
10808 gen_load_fpr64(ctx, fp0, fs);
10809 gen_load_fpr64(ctx, fp1, ft);
10810 gen_load_fpr64(ctx, fp2, fr);
10811 gen_helper_float_nmsub_d(fp2, tcg_env, fp0, fp1, fp2);
10812 gen_store_fpr64(ctx, fp2, fd);
10813 }
10814 break;
10815 case OPC_NMSUB_PS:
10816 check_ps(ctx);
10817 {
10818 TCGv_i64 fp0 = tcg_temp_new_i64();
10819 TCGv_i64 fp1 = tcg_temp_new_i64();
10820 TCGv_i64 fp2 = tcg_temp_new_i64();
10821
10822 gen_load_fpr64(ctx, fp0, fs);
10823 gen_load_fpr64(ctx, fp1, ft);
10824 gen_load_fpr64(ctx, fp2, fr);
10825 gen_helper_float_nmsub_ps(fp2, tcg_env, fp0, fp1, fp2);
10826 gen_store_fpr64(ctx, fp2, fd);
10827 }
10828 break;
10829 default:
10830 MIPS_INVAL("flt3_arith");
10831 gen_reserved_instruction(ctx);
10832 return;
10833 }
10834 }
10835
gen_rdhwr(DisasContext * ctx,int rt,int rd,int sel)10836 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10837 {
10838 TCGv t0;
10839
10840 #if !defined(CONFIG_USER_ONLY)
10841 /*
10842 * The Linux kernel will emulate rdhwr if it's not supported natively.
10843 * Therefore only check the ISA in system mode.
10844 */
10845 check_insn(ctx, ISA_MIPS_R2);
10846 #endif
10847 t0 = tcg_temp_new();
10848
10849 switch (rd) {
10850 case 0:
10851 gen_helper_rdhwr_cpunum(t0, tcg_env);
10852 gen_store_gpr(t0, rt);
10853 break;
10854 case 1:
10855 gen_helper_rdhwr_synci_step(t0, tcg_env);
10856 gen_store_gpr(t0, rt);
10857 break;
10858 case 2:
10859 translator_io_start(&ctx->base);
10860 gen_helper_rdhwr_cc(t0, tcg_env);
10861 gen_store_gpr(t0, rt);
10862 /*
10863 * Break the TB to be able to take timer interrupts immediately
10864 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
10865 * we break completely out of translated code.
10866 */
10867 gen_save_pc(ctx->base.pc_next + 4);
10868 ctx->base.is_jmp = DISAS_EXIT;
10869 break;
10870 case 3:
10871 gen_helper_rdhwr_ccres(t0, tcg_env);
10872 gen_store_gpr(t0, rt);
10873 break;
10874 case 4:
10875 check_insn(ctx, ISA_MIPS_R6);
10876 if (sel != 0) {
10877 /*
10878 * Performance counter registers are not implemented other than
10879 * control register 0.
10880 */
10881 generate_exception(ctx, EXCP_RI);
10882 }
10883 gen_helper_rdhwr_performance(t0, tcg_env);
10884 gen_store_gpr(t0, rt);
10885 break;
10886 case 5:
10887 check_insn(ctx, ISA_MIPS_R6);
10888 gen_helper_rdhwr_xnp(t0, tcg_env);
10889 gen_store_gpr(t0, rt);
10890 break;
10891 case 29:
10892 #if defined(CONFIG_USER_ONLY)
10893 tcg_gen_ld_tl(t0, tcg_env,
10894 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10895 gen_store_gpr(t0, rt);
10896 break;
10897 #else
10898 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10899 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10900 tcg_gen_ld_tl(t0, tcg_env,
10901 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10902 gen_store_gpr(t0, rt);
10903 } else {
10904 gen_reserved_instruction(ctx);
10905 }
10906 break;
10907 #endif
10908 default: /* Invalid */
10909 MIPS_INVAL("rdhwr");
10910 gen_reserved_instruction(ctx);
10911 break;
10912 }
10913 }
10914
clear_branch_hflags(DisasContext * ctx)10915 static inline void clear_branch_hflags(DisasContext *ctx)
10916 {
10917 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10918 if (ctx->base.is_jmp == DISAS_NEXT) {
10919 save_cpu_state(ctx, 0);
10920 } else {
10921 /*
10922 * It is not safe to save ctx->hflags as hflags may be changed
10923 * in execution time by the instruction in delay / forbidden slot.
10924 */
10925 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10926 }
10927 }
10928
gen_branch(DisasContext * ctx,int insn_bytes)10929 static void gen_branch(DisasContext *ctx, int insn_bytes)
10930 {
10931 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10932 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10933 /* Branches completion */
10934 clear_branch_hflags(ctx);
10935 ctx->base.is_jmp = DISAS_NORETURN;
10936 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10937 case MIPS_HFLAG_FBNSLOT:
10938 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
10939 break;
10940 case MIPS_HFLAG_B:
10941 /* unconditional branch */
10942 if (proc_hflags & MIPS_HFLAG_BX) {
10943 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10944 }
10945 gen_goto_tb(ctx, 0, ctx->btarget);
10946 break;
10947 case MIPS_HFLAG_BL:
10948 /* blikely taken case */
10949 gen_goto_tb(ctx, 0, ctx->btarget);
10950 break;
10951 case MIPS_HFLAG_BC:
10952 /* Conditional branch */
10953 {
10954 TCGLabel *l1 = gen_new_label();
10955
10956 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10957 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
10958 gen_set_label(l1);
10959 gen_goto_tb(ctx, 0, ctx->btarget);
10960 }
10961 break;
10962 case MIPS_HFLAG_BR:
10963 /* unconditional branch to register */
10964 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10965 TCGv t0 = tcg_temp_new();
10966 TCGv_i32 t1 = tcg_temp_new_i32();
10967
10968 tcg_gen_andi_tl(t0, btarget, 0x1);
10969 tcg_gen_trunc_tl_i32(t1, t0);
10970 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10971 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10972 tcg_gen_or_i32(hflags, hflags, t1);
10973
10974 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10975 } else {
10976 tcg_gen_mov_tl(cpu_PC, btarget);
10977 }
10978 tcg_gen_lookup_and_goto_ptr();
10979 break;
10980 default:
10981 LOG_DISAS("unknown branch 0x%x\n", proc_hflags);
10982 gen_reserved_instruction(ctx);
10983 }
10984 }
10985 }
10986
10987 /* Compact Branches */
gen_compute_compact_branch(DisasContext * ctx,uint32_t opc,int rs,int rt,int32_t offset)10988 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10989 int rs, int rt, int32_t offset)
10990 {
10991 int bcond_compute = 0;
10992 TCGv t0 = tcg_temp_new();
10993 TCGv t1 = tcg_temp_new();
10994 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10995
10996 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10997 #ifdef MIPS_DEBUG_DISAS
10998 LOG_DISAS("Branch in delay / forbidden slot at PC 0x%016"
10999 VADDR_PRIx "\n", ctx->base.pc_next);
11000 #endif
11001 gen_reserved_instruction(ctx);
11002 return;
11003 }
11004
11005 /* Load needed operands and calculate btarget */
11006 switch (opc) {
11007 /* compact branch */
11008 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11009 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11010 gen_load_gpr(t0, rs);
11011 gen_load_gpr(t1, rt);
11012 bcond_compute = 1;
11013 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11014 if (rs <= rt && rs == 0) {
11015 /* OPC_BEQZALC, OPC_BNEZALC */
11016 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11017 }
11018 break;
11019 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11020 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11021 gen_load_gpr(t0, rs);
11022 gen_load_gpr(t1, rt);
11023 bcond_compute = 1;
11024 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11025 break;
11026 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11027 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11028 if (rs == 0 || rs == rt) {
11029 /* OPC_BLEZALC, OPC_BGEZALC */
11030 /* OPC_BGTZALC, OPC_BLTZALC */
11031 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11032 }
11033 gen_load_gpr(t0, rs);
11034 gen_load_gpr(t1, rt);
11035 bcond_compute = 1;
11036 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11037 break;
11038 case OPC_BC:
11039 case OPC_BALC:
11040 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11041 break;
11042 case OPC_BEQZC:
11043 case OPC_BNEZC:
11044 if (rs != 0) {
11045 /* OPC_BEQZC, OPC_BNEZC */
11046 gen_load_gpr(t0, rs);
11047 bcond_compute = 1;
11048 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11049 } else {
11050 /* OPC_JIC, OPC_JIALC */
11051 TCGv tbase = tcg_temp_new();
11052
11053 gen_load_gpr(tbase, rt);
11054 gen_op_addr_addi(ctx, btarget, tbase, offset);
11055 }
11056 break;
11057 default:
11058 MIPS_INVAL("Compact branch/jump");
11059 gen_reserved_instruction(ctx);
11060 return;
11061 }
11062
11063 if (bcond_compute == 0) {
11064 /* Unconditional compact branch */
11065 switch (opc) {
11066 case OPC_JIALC:
11067 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11068 /* Fallthrough */
11069 case OPC_JIC:
11070 ctx->hflags |= MIPS_HFLAG_BR;
11071 break;
11072 case OPC_BALC:
11073 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11074 /* Fallthrough */
11075 case OPC_BC:
11076 ctx->hflags |= MIPS_HFLAG_B;
11077 break;
11078 default:
11079 MIPS_INVAL("Compact branch/jump");
11080 gen_reserved_instruction(ctx);
11081 return;
11082 }
11083
11084 /* Generating branch here as compact branches don't have delay slot */
11085 gen_branch(ctx, 4);
11086 } else {
11087 /* Conditional compact branch */
11088 TCGLabel *fs = gen_new_label();
11089 save_cpu_state(ctx, 0);
11090
11091 switch (opc) {
11092 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11093 if (rs == 0 && rt != 0) {
11094 /* OPC_BLEZALC */
11095 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11096 } else if (rs != 0 && rt != 0 && rs == rt) {
11097 /* OPC_BGEZALC */
11098 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11099 } else {
11100 /* OPC_BGEUC */
11101 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11102 }
11103 break;
11104 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11105 if (rs == 0 && rt != 0) {
11106 /* OPC_BGTZALC */
11107 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11108 } else if (rs != 0 && rt != 0 && rs == rt) {
11109 /* OPC_BLTZALC */
11110 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11111 } else {
11112 /* OPC_BLTUC */
11113 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11114 }
11115 break;
11116 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11117 if (rs == 0 && rt != 0) {
11118 /* OPC_BLEZC */
11119 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11120 } else if (rs != 0 && rt != 0 && rs == rt) {
11121 /* OPC_BGEZC */
11122 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11123 } else {
11124 /* OPC_BGEC */
11125 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11126 }
11127 break;
11128 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11129 if (rs == 0 && rt != 0) {
11130 /* OPC_BGTZC */
11131 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11132 } else if (rs != 0 && rt != 0 && rs == rt) {
11133 /* OPC_BLTZC */
11134 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11135 } else {
11136 /* OPC_BLTC */
11137 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11138 }
11139 break;
11140 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11141 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11142 if (rs >= rt) {
11143 /* OPC_BOVC, OPC_BNVC */
11144 TCGv t2 = tcg_temp_new();
11145 TCGv t3 = tcg_temp_new();
11146 TCGv t4 = tcg_temp_new();
11147 TCGv input_overflow = tcg_temp_new();
11148
11149 gen_load_gpr(t0, rs);
11150 gen_load_gpr(t1, rt);
11151 tcg_gen_ext32s_tl(t2, t0);
11152 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11153 tcg_gen_ext32s_tl(t3, t1);
11154 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11155 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11156
11157 tcg_gen_add_tl(t4, t2, t3);
11158 tcg_gen_ext32s_tl(t4, t4);
11159 tcg_gen_xor_tl(t2, t2, t3);
11160 tcg_gen_xor_tl(t3, t4, t3);
11161 tcg_gen_andc_tl(t2, t3, t2);
11162 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11163 tcg_gen_or_tl(t4, t4, input_overflow);
11164 if (opc == OPC_BOVC) {
11165 /* OPC_BOVC */
11166 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11167 } else {
11168 /* OPC_BNVC */
11169 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11170 }
11171 } else if (rs < rt && rs == 0) {
11172 /* OPC_BEQZALC, OPC_BNEZALC */
11173 if (opc == OPC_BEQZALC) {
11174 /* OPC_BEQZALC */
11175 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11176 } else {
11177 /* OPC_BNEZALC */
11178 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11179 }
11180 } else {
11181 /* OPC_BEQC, OPC_BNEC */
11182 if (opc == OPC_BEQC) {
11183 /* OPC_BEQC */
11184 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11185 } else {
11186 /* OPC_BNEC */
11187 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11188 }
11189 }
11190 break;
11191 case OPC_BEQZC:
11192 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11193 break;
11194 case OPC_BNEZC:
11195 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11196 break;
11197 default:
11198 MIPS_INVAL("Compact conditional branch/jump");
11199 gen_reserved_instruction(ctx);
11200 return;
11201 }
11202
11203 /* Generating branch here as compact branches don't have delay slot */
11204 gen_goto_tb(ctx, 1, ctx->btarget);
11205 gen_set_label(fs);
11206
11207 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11208 }
11209 }
11210
gen_addiupc(DisasContext * ctx,int rx,int imm,int is_64_bit,int extended)11211 void gen_addiupc(DisasContext *ctx, int rx, int imm,
11212 int is_64_bit, int extended)
11213 {
11214 target_ulong npc;
11215
11216 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11217 gen_reserved_instruction(ctx);
11218 return;
11219 }
11220
11221 npc = pc_relative_pc(ctx) + imm;
11222 if (!is_64_bit) {
11223 npc = (int32_t)npc;
11224 }
11225 tcg_gen_movi_tl(cpu_gpr[rx], npc);
11226 }
11227
gen_cache_operation(DisasContext * ctx,uint32_t op,int base,int16_t offset)11228 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11229 int16_t offset)
11230 {
11231 TCGv_i32 t0 = tcg_constant_i32(op);
11232 TCGv t1 = tcg_temp_new();
11233 gen_base_offset_addr(ctx, t1, base, offset);
11234 gen_helper_cache(tcg_env, t1, t0);
11235 }
11236
is_uhi(DisasContext * ctx,int sdbbp_code)11237 static inline bool is_uhi(DisasContext *ctx, int sdbbp_code)
11238 {
11239 #ifdef CONFIG_USER_ONLY
11240 return false;
11241 #else
11242 bool is_user = (ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM;
11243 return semihosting_enabled(is_user) && sdbbp_code == 1;
11244 #endif
11245 }
11246
gen_ldxs(DisasContext * ctx,int base,int index,int rd)11247 void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
11248 {
11249 TCGv t0 = tcg_temp_new();
11250 TCGv t1 = tcg_temp_new();
11251
11252 gen_load_gpr(t0, base);
11253
11254 if (index != 0) {
11255 gen_load_gpr(t1, index);
11256 tcg_gen_shli_tl(t1, t1, 2);
11257 gen_op_addr_add(ctx, t0, t1, t0);
11258 }
11259
11260 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
11261 gen_store_gpr(t1, rd);
11262 }
11263
gen_sync(int stype)11264 static void gen_sync(int stype)
11265 {
11266 TCGBar tcg_mo = TCG_BAR_SC;
11267
11268 switch (stype) {
11269 case 0x4: /* SYNC_WMB */
11270 tcg_mo |= TCG_MO_ST_ST;
11271 break;
11272 case 0x10: /* SYNC_MB */
11273 tcg_mo |= TCG_MO_ALL;
11274 break;
11275 case 0x11: /* SYNC_ACQUIRE */
11276 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
11277 break;
11278 case 0x12: /* SYNC_RELEASE */
11279 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
11280 break;
11281 case 0x13: /* SYNC_RMB */
11282 tcg_mo |= TCG_MO_LD_LD;
11283 break;
11284 default:
11285 tcg_mo |= TCG_MO_ALL;
11286 break;
11287 }
11288
11289 tcg_gen_mb(tcg_mo);
11290 }
11291
11292 /* ISA extensions (ASEs) */
11293
11294 /* MIPS16 extension to MIPS32 */
11295 #include "mips16e_translate.c.inc"
11296
11297 /* microMIPS extension to MIPS32/MIPS64 */
11298
11299 /*
11300 * Values for microMIPS fmt field. Variable-width, depending on which
11301 * formats the instruction supports.
11302 */
11303 enum {
11304 FMT_SD_S = 0,
11305 FMT_SD_D = 1,
11306
11307 FMT_SDPS_S = 0,
11308 FMT_SDPS_D = 1,
11309 FMT_SDPS_PS = 2,
11310
11311 FMT_SWL_S = 0,
11312 FMT_SWL_W = 1,
11313 FMT_SWL_L = 2,
11314
11315 FMT_DWL_D = 0,
11316 FMT_DWL_W = 1,
11317 FMT_DWL_L = 2
11318 };
11319
11320 #include "micromips_translate.c.inc"
11321
11322 #include "nanomips_translate.c.inc"
11323
11324 /* MIPSDSP functions. */
11325
11326 /* Indexed load is not for DSP only */
gen_mips_lx(DisasContext * ctx,uint32_t opc,int rd,int base,int offset)11327 static void gen_mips_lx(DisasContext *ctx, uint32_t opc,
11328 int rd, int base, int offset)
11329 {
11330 TCGv t0;
11331
11332 if (!(ctx->insn_flags & INSN_OCTEON)) {
11333 check_dsp(ctx);
11334 }
11335 t0 = tcg_temp_new();
11336
11337 if (base == 0) {
11338 gen_load_gpr(t0, offset);
11339 } else if (offset == 0) {
11340 gen_load_gpr(t0, base);
11341 } else {
11342 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
11343 }
11344
11345 switch (opc) {
11346 case OPC_LBUX:
11347 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
11348 gen_store_gpr(t0, rd);
11349 break;
11350 case OPC_LHX:
11351 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SW);
11352 gen_store_gpr(t0, rd);
11353 break;
11354 case OPC_LWX:
11355 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
11356 gen_store_gpr(t0, rd);
11357 break;
11358 #if defined(TARGET_MIPS64)
11359 case OPC_LDX:
11360 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
11361 gen_store_gpr(t0, rd);
11362 break;
11363 #endif
11364 }
11365 }
11366
gen_mipsdsp_arith(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2)11367 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
11368 int ret, int v1, int v2)
11369 {
11370 TCGv v1_t;
11371 TCGv v2_t;
11372
11373 if (ret == 0) {
11374 /* Treat as NOP. */
11375 return;
11376 }
11377
11378 v1_t = tcg_temp_new();
11379 v2_t = tcg_temp_new();
11380
11381 gen_load_gpr(v1_t, v1);
11382 gen_load_gpr(v2_t, v2);
11383
11384 switch (op1) {
11385 case OPC_ADDUH_QB_DSP:
11386 check_dsp_r2(ctx);
11387 switch (op2) {
11388 case OPC_ADDUH_QB:
11389 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
11390 break;
11391 case OPC_ADDUH_R_QB:
11392 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
11393 break;
11394 case OPC_ADDQH_PH:
11395 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
11396 break;
11397 case OPC_ADDQH_R_PH:
11398 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
11399 break;
11400 case OPC_ADDQH_W:
11401 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
11402 break;
11403 case OPC_ADDQH_R_W:
11404 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
11405 break;
11406 case OPC_SUBUH_QB:
11407 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
11408 break;
11409 case OPC_SUBUH_R_QB:
11410 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
11411 break;
11412 case OPC_SUBQH_PH:
11413 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
11414 break;
11415 case OPC_SUBQH_R_PH:
11416 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
11417 break;
11418 case OPC_SUBQH_W:
11419 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
11420 break;
11421 case OPC_SUBQH_R_W:
11422 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
11423 break;
11424 }
11425 break;
11426 case OPC_ABSQ_S_PH_DSP:
11427 switch (op2) {
11428 case OPC_ABSQ_S_QB:
11429 check_dsp_r2(ctx);
11430 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, tcg_env);
11431 break;
11432 case OPC_ABSQ_S_PH:
11433 check_dsp(ctx);
11434 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, tcg_env);
11435 break;
11436 case OPC_ABSQ_S_W:
11437 check_dsp(ctx);
11438 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, tcg_env);
11439 break;
11440 case OPC_PRECEQ_W_PHL:
11441 check_dsp(ctx);
11442 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
11443 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
11444 break;
11445 case OPC_PRECEQ_W_PHR:
11446 check_dsp(ctx);
11447 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
11448 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
11449 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
11450 break;
11451 case OPC_PRECEQU_PH_QBL:
11452 check_dsp(ctx);
11453 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
11454 break;
11455 case OPC_PRECEQU_PH_QBR:
11456 check_dsp(ctx);
11457 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
11458 break;
11459 case OPC_PRECEQU_PH_QBLA:
11460 check_dsp(ctx);
11461 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
11462 break;
11463 case OPC_PRECEQU_PH_QBRA:
11464 check_dsp(ctx);
11465 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
11466 break;
11467 case OPC_PRECEU_PH_QBL:
11468 check_dsp(ctx);
11469 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
11470 break;
11471 case OPC_PRECEU_PH_QBR:
11472 check_dsp(ctx);
11473 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
11474 break;
11475 case OPC_PRECEU_PH_QBLA:
11476 check_dsp(ctx);
11477 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
11478 break;
11479 case OPC_PRECEU_PH_QBRA:
11480 check_dsp(ctx);
11481 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
11482 break;
11483 }
11484 break;
11485 case OPC_ADDU_QB_DSP:
11486 switch (op2) {
11487 case OPC_ADDQ_PH:
11488 check_dsp(ctx);
11489 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11490 break;
11491 case OPC_ADDQ_S_PH:
11492 check_dsp(ctx);
11493 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11494 break;
11495 case OPC_ADDQ_S_W:
11496 check_dsp(ctx);
11497 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11498 break;
11499 case OPC_ADDU_QB:
11500 check_dsp(ctx);
11501 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11502 break;
11503 case OPC_ADDU_S_QB:
11504 check_dsp(ctx);
11505 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11506 break;
11507 case OPC_ADDU_PH:
11508 check_dsp_r2(ctx);
11509 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11510 break;
11511 case OPC_ADDU_S_PH:
11512 check_dsp_r2(ctx);
11513 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11514 break;
11515 case OPC_SUBQ_PH:
11516 check_dsp(ctx);
11517 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11518 break;
11519 case OPC_SUBQ_S_PH:
11520 check_dsp(ctx);
11521 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11522 break;
11523 case OPC_SUBQ_S_W:
11524 check_dsp(ctx);
11525 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11526 break;
11527 case OPC_SUBU_QB:
11528 check_dsp(ctx);
11529 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11530 break;
11531 case OPC_SUBU_S_QB:
11532 check_dsp(ctx);
11533 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11534 break;
11535 case OPC_SUBU_PH:
11536 check_dsp_r2(ctx);
11537 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11538 break;
11539 case OPC_SUBU_S_PH:
11540 check_dsp_r2(ctx);
11541 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11542 break;
11543 case OPC_ADDSC:
11544 check_dsp(ctx);
11545 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11546 break;
11547 case OPC_ADDWC:
11548 check_dsp(ctx);
11549 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11550 break;
11551 case OPC_MODSUB:
11552 check_dsp(ctx);
11553 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
11554 break;
11555 case OPC_RADDU_W_QB:
11556 check_dsp(ctx);
11557 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
11558 break;
11559 }
11560 break;
11561 case OPC_CMPU_EQ_QB_DSP:
11562 switch (op2) {
11563 case OPC_PRECR_QB_PH:
11564 check_dsp_r2(ctx);
11565 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
11566 break;
11567 case OPC_PRECRQ_QB_PH:
11568 check_dsp(ctx);
11569 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
11570 break;
11571 case OPC_PRECR_SRA_PH_W:
11572 check_dsp_r2(ctx);
11573 {
11574 TCGv_i32 sa_t = tcg_constant_i32(v2);
11575 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
11576 cpu_gpr[ret]);
11577 break;
11578 }
11579 case OPC_PRECR_SRA_R_PH_W:
11580 check_dsp_r2(ctx);
11581 {
11582 TCGv_i32 sa_t = tcg_constant_i32(v2);
11583 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
11584 cpu_gpr[ret]);
11585 break;
11586 }
11587 case OPC_PRECRQ_PH_W:
11588 check_dsp(ctx);
11589 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
11590 break;
11591 case OPC_PRECRQ_RS_PH_W:
11592 check_dsp(ctx);
11593 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11594 break;
11595 case OPC_PRECRQU_S_QB_PH:
11596 check_dsp(ctx);
11597 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11598 break;
11599 }
11600 break;
11601 #ifdef TARGET_MIPS64
11602 case OPC_ABSQ_S_QH_DSP:
11603 switch (op2) {
11604 case OPC_PRECEQ_L_PWL:
11605 check_dsp(ctx);
11606 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
11607 break;
11608 case OPC_PRECEQ_L_PWR:
11609 check_dsp(ctx);
11610 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
11611 break;
11612 case OPC_PRECEQ_PW_QHL:
11613 check_dsp(ctx);
11614 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
11615 break;
11616 case OPC_PRECEQ_PW_QHR:
11617 check_dsp(ctx);
11618 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
11619 break;
11620 case OPC_PRECEQ_PW_QHLA:
11621 check_dsp(ctx);
11622 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
11623 break;
11624 case OPC_PRECEQ_PW_QHRA:
11625 check_dsp(ctx);
11626 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
11627 break;
11628 case OPC_PRECEQU_QH_OBL:
11629 check_dsp(ctx);
11630 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
11631 break;
11632 case OPC_PRECEQU_QH_OBR:
11633 check_dsp(ctx);
11634 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
11635 break;
11636 case OPC_PRECEQU_QH_OBLA:
11637 check_dsp(ctx);
11638 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
11639 break;
11640 case OPC_PRECEQU_QH_OBRA:
11641 check_dsp(ctx);
11642 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
11643 break;
11644 case OPC_PRECEU_QH_OBL:
11645 check_dsp(ctx);
11646 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
11647 break;
11648 case OPC_PRECEU_QH_OBR:
11649 check_dsp(ctx);
11650 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
11651 break;
11652 case OPC_PRECEU_QH_OBLA:
11653 check_dsp(ctx);
11654 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
11655 break;
11656 case OPC_PRECEU_QH_OBRA:
11657 check_dsp(ctx);
11658 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
11659 break;
11660 case OPC_ABSQ_S_OB:
11661 check_dsp_r2(ctx);
11662 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, tcg_env);
11663 break;
11664 case OPC_ABSQ_S_PW:
11665 check_dsp(ctx);
11666 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, tcg_env);
11667 break;
11668 case OPC_ABSQ_S_QH:
11669 check_dsp(ctx);
11670 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, tcg_env);
11671 break;
11672 }
11673 break;
11674 case OPC_ADDU_OB_DSP:
11675 switch (op2) {
11676 case OPC_RADDU_L_OB:
11677 check_dsp(ctx);
11678 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
11679 break;
11680 case OPC_SUBQ_PW:
11681 check_dsp(ctx);
11682 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11683 break;
11684 case OPC_SUBQ_S_PW:
11685 check_dsp(ctx);
11686 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11687 break;
11688 case OPC_SUBQ_QH:
11689 check_dsp(ctx);
11690 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11691 break;
11692 case OPC_SUBQ_S_QH:
11693 check_dsp(ctx);
11694 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11695 break;
11696 case OPC_SUBU_OB:
11697 check_dsp(ctx);
11698 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11699 break;
11700 case OPC_SUBU_S_OB:
11701 check_dsp(ctx);
11702 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11703 break;
11704 case OPC_SUBU_QH:
11705 check_dsp_r2(ctx);
11706 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11707 break;
11708 case OPC_SUBU_S_QH:
11709 check_dsp_r2(ctx);
11710 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11711 break;
11712 case OPC_SUBUH_OB:
11713 check_dsp_r2(ctx);
11714 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
11715 break;
11716 case OPC_SUBUH_R_OB:
11717 check_dsp_r2(ctx);
11718 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
11719 break;
11720 case OPC_ADDQ_PW:
11721 check_dsp(ctx);
11722 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11723 break;
11724 case OPC_ADDQ_S_PW:
11725 check_dsp(ctx);
11726 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11727 break;
11728 case OPC_ADDQ_QH:
11729 check_dsp(ctx);
11730 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11731 break;
11732 case OPC_ADDQ_S_QH:
11733 check_dsp(ctx);
11734 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11735 break;
11736 case OPC_ADDU_OB:
11737 check_dsp(ctx);
11738 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11739 break;
11740 case OPC_ADDU_S_OB:
11741 check_dsp(ctx);
11742 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11743 break;
11744 case OPC_ADDU_QH:
11745 check_dsp_r2(ctx);
11746 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11747 break;
11748 case OPC_ADDU_S_QH:
11749 check_dsp_r2(ctx);
11750 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11751 break;
11752 case OPC_ADDUH_OB:
11753 check_dsp_r2(ctx);
11754 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
11755 break;
11756 case OPC_ADDUH_R_OB:
11757 check_dsp_r2(ctx);
11758 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
11759 break;
11760 }
11761 break;
11762 case OPC_CMPU_EQ_OB_DSP:
11763 switch (op2) {
11764 case OPC_PRECR_OB_QH:
11765 check_dsp_r2(ctx);
11766 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
11767 break;
11768 case OPC_PRECR_SRA_QH_PW:
11769 check_dsp_r2(ctx);
11770 {
11771 TCGv_i32 ret_t = tcg_constant_i32(ret);
11772 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
11773 break;
11774 }
11775 case OPC_PRECR_SRA_R_QH_PW:
11776 check_dsp_r2(ctx);
11777 {
11778 TCGv_i32 sa_v = tcg_constant_i32(ret);
11779 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
11780 break;
11781 }
11782 case OPC_PRECRQ_OB_QH:
11783 check_dsp(ctx);
11784 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
11785 break;
11786 case OPC_PRECRQ_PW_L:
11787 check_dsp(ctx);
11788 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
11789 break;
11790 case OPC_PRECRQ_QH_PW:
11791 check_dsp(ctx);
11792 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
11793 break;
11794 case OPC_PRECRQ_RS_QH_PW:
11795 check_dsp(ctx);
11796 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11797 break;
11798 case OPC_PRECRQU_S_OB_QH:
11799 check_dsp(ctx);
11800 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11801 break;
11802 }
11803 break;
11804 #endif
11805 }
11806 }
11807
gen_mipsdsp_shift(DisasContext * ctx,uint32_t opc,int ret,int v1,int v2)11808 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
11809 int ret, int v1, int v2)
11810 {
11811 uint32_t op2;
11812 TCGv t0;
11813 TCGv v1_t;
11814 TCGv v2_t;
11815
11816 if (ret == 0) {
11817 /* Treat as NOP. */
11818 return;
11819 }
11820
11821 t0 = tcg_temp_new();
11822 v1_t = tcg_temp_new();
11823 v2_t = tcg_temp_new();
11824
11825 tcg_gen_movi_tl(t0, v1);
11826 gen_load_gpr(v1_t, v1);
11827 gen_load_gpr(v2_t, v2);
11828
11829 switch (opc) {
11830 case OPC_SHLL_QB_DSP:
11831 {
11832 op2 = MASK_SHLL_QB(ctx->opcode);
11833 switch (op2) {
11834 case OPC_SHLL_QB:
11835 check_dsp(ctx);
11836 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, tcg_env);
11837 break;
11838 case OPC_SHLLV_QB:
11839 check_dsp(ctx);
11840 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11841 break;
11842 case OPC_SHLL_PH:
11843 check_dsp(ctx);
11844 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, tcg_env);
11845 break;
11846 case OPC_SHLLV_PH:
11847 check_dsp(ctx);
11848 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11849 break;
11850 case OPC_SHLL_S_PH:
11851 check_dsp(ctx);
11852 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, tcg_env);
11853 break;
11854 case OPC_SHLLV_S_PH:
11855 check_dsp(ctx);
11856 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11857 break;
11858 case OPC_SHLL_S_W:
11859 check_dsp(ctx);
11860 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, tcg_env);
11861 break;
11862 case OPC_SHLLV_S_W:
11863 check_dsp(ctx);
11864 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11865 break;
11866 case OPC_SHRL_QB:
11867 check_dsp(ctx);
11868 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
11869 break;
11870 case OPC_SHRLV_QB:
11871 check_dsp(ctx);
11872 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
11873 break;
11874 case OPC_SHRL_PH:
11875 check_dsp_r2(ctx);
11876 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
11877 break;
11878 case OPC_SHRLV_PH:
11879 check_dsp_r2(ctx);
11880 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
11881 break;
11882 case OPC_SHRA_QB:
11883 check_dsp_r2(ctx);
11884 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
11885 break;
11886 case OPC_SHRA_R_QB:
11887 check_dsp_r2(ctx);
11888 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
11889 break;
11890 case OPC_SHRAV_QB:
11891 check_dsp_r2(ctx);
11892 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
11893 break;
11894 case OPC_SHRAV_R_QB:
11895 check_dsp_r2(ctx);
11896 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
11897 break;
11898 case OPC_SHRA_PH:
11899 check_dsp(ctx);
11900 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
11901 break;
11902 case OPC_SHRA_R_PH:
11903 check_dsp(ctx);
11904 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
11905 break;
11906 case OPC_SHRAV_PH:
11907 check_dsp(ctx);
11908 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
11909 break;
11910 case OPC_SHRAV_R_PH:
11911 check_dsp(ctx);
11912 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
11913 break;
11914 case OPC_SHRA_R_W:
11915 check_dsp(ctx);
11916 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
11917 break;
11918 case OPC_SHRAV_R_W:
11919 check_dsp(ctx);
11920 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
11921 break;
11922 default: /* Invalid */
11923 MIPS_INVAL("MASK SHLL.QB");
11924 gen_reserved_instruction(ctx);
11925 break;
11926 }
11927 break;
11928 }
11929 #ifdef TARGET_MIPS64
11930 case OPC_SHLL_OB_DSP:
11931 op2 = MASK_SHLL_OB(ctx->opcode);
11932 switch (op2) {
11933 case OPC_SHLL_PW:
11934 check_dsp(ctx);
11935 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, tcg_env);
11936 break;
11937 case OPC_SHLLV_PW:
11938 check_dsp(ctx);
11939 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11940 break;
11941 case OPC_SHLL_S_PW:
11942 check_dsp(ctx);
11943 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, tcg_env);
11944 break;
11945 case OPC_SHLLV_S_PW:
11946 check_dsp(ctx);
11947 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11948 break;
11949 case OPC_SHLL_OB:
11950 check_dsp(ctx);
11951 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, tcg_env);
11952 break;
11953 case OPC_SHLLV_OB:
11954 check_dsp(ctx);
11955 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11956 break;
11957 case OPC_SHLL_QH:
11958 check_dsp(ctx);
11959 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, tcg_env);
11960 break;
11961 case OPC_SHLLV_QH:
11962 check_dsp(ctx);
11963 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11964 break;
11965 case OPC_SHLL_S_QH:
11966 check_dsp(ctx);
11967 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, tcg_env);
11968 break;
11969 case OPC_SHLLV_S_QH:
11970 check_dsp(ctx);
11971 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11972 break;
11973 case OPC_SHRA_OB:
11974 check_dsp_r2(ctx);
11975 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
11976 break;
11977 case OPC_SHRAV_OB:
11978 check_dsp_r2(ctx);
11979 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
11980 break;
11981 case OPC_SHRA_R_OB:
11982 check_dsp_r2(ctx);
11983 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
11984 break;
11985 case OPC_SHRAV_R_OB:
11986 check_dsp_r2(ctx);
11987 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
11988 break;
11989 case OPC_SHRA_PW:
11990 check_dsp(ctx);
11991 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
11992 break;
11993 case OPC_SHRAV_PW:
11994 check_dsp(ctx);
11995 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
11996 break;
11997 case OPC_SHRA_R_PW:
11998 check_dsp(ctx);
11999 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
12000 break;
12001 case OPC_SHRAV_R_PW:
12002 check_dsp(ctx);
12003 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
12004 break;
12005 case OPC_SHRA_QH:
12006 check_dsp(ctx);
12007 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
12008 break;
12009 case OPC_SHRAV_QH:
12010 check_dsp(ctx);
12011 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
12012 break;
12013 case OPC_SHRA_R_QH:
12014 check_dsp(ctx);
12015 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
12016 break;
12017 case OPC_SHRAV_R_QH:
12018 check_dsp(ctx);
12019 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
12020 break;
12021 case OPC_SHRL_OB:
12022 check_dsp(ctx);
12023 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
12024 break;
12025 case OPC_SHRLV_OB:
12026 check_dsp(ctx);
12027 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
12028 break;
12029 case OPC_SHRL_QH:
12030 check_dsp_r2(ctx);
12031 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
12032 break;
12033 case OPC_SHRLV_QH:
12034 check_dsp_r2(ctx);
12035 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
12036 break;
12037 default: /* Invalid */
12038 MIPS_INVAL("MASK SHLL.OB");
12039 gen_reserved_instruction(ctx);
12040 break;
12041 }
12042 break;
12043 #endif
12044 }
12045 }
12046
gen_mipsdsp_multiply(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2,int check_ret)12047 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
12048 int ret, int v1, int v2, int check_ret)
12049 {
12050 TCGv_i32 t0;
12051 TCGv v1_t;
12052 TCGv v2_t;
12053
12054 if ((ret == 0) && (check_ret == 1)) {
12055 /* Treat as NOP. */
12056 return;
12057 }
12058
12059 t0 = tcg_temp_new_i32();
12060 v1_t = tcg_temp_new();
12061 v2_t = tcg_temp_new();
12062
12063 tcg_gen_movi_i32(t0, ret);
12064 gen_load_gpr(v1_t, v1);
12065 gen_load_gpr(v2_t, v2);
12066
12067 switch (op1) {
12068 case OPC_MUL_PH_DSP:
12069 check_dsp_r2(ctx);
12070 switch (op2) {
12071 case OPC_MUL_PH:
12072 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12073 break;
12074 case OPC_MUL_S_PH:
12075 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12076 break;
12077 case OPC_MULQ_S_W:
12078 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12079 break;
12080 case OPC_MULQ_RS_W:
12081 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12082 break;
12083 }
12084 break;
12085 case OPC_DPA_W_PH_DSP:
12086 switch (op2) {
12087 case OPC_DPAU_H_QBL:
12088 check_dsp(ctx);
12089 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, tcg_env);
12090 break;
12091 case OPC_DPAU_H_QBR:
12092 check_dsp(ctx);
12093 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, tcg_env);
12094 break;
12095 case OPC_DPSU_H_QBL:
12096 check_dsp(ctx);
12097 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, tcg_env);
12098 break;
12099 case OPC_DPSU_H_QBR:
12100 check_dsp(ctx);
12101 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, tcg_env);
12102 break;
12103 case OPC_DPA_W_PH:
12104 check_dsp_r2(ctx);
12105 gen_helper_dpa_w_ph(t0, v1_t, v2_t, tcg_env);
12106 break;
12107 case OPC_DPAX_W_PH:
12108 check_dsp_r2(ctx);
12109 gen_helper_dpax_w_ph(t0, v1_t, v2_t, tcg_env);
12110 break;
12111 case OPC_DPAQ_S_W_PH:
12112 check_dsp(ctx);
12113 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, tcg_env);
12114 break;
12115 case OPC_DPAQX_S_W_PH:
12116 check_dsp_r2(ctx);
12117 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, tcg_env);
12118 break;
12119 case OPC_DPAQX_SA_W_PH:
12120 check_dsp_r2(ctx);
12121 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, tcg_env);
12122 break;
12123 case OPC_DPS_W_PH:
12124 check_dsp_r2(ctx);
12125 gen_helper_dps_w_ph(t0, v1_t, v2_t, tcg_env);
12126 break;
12127 case OPC_DPSX_W_PH:
12128 check_dsp_r2(ctx);
12129 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, tcg_env);
12130 break;
12131 case OPC_DPSQ_S_W_PH:
12132 check_dsp(ctx);
12133 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, tcg_env);
12134 break;
12135 case OPC_DPSQX_S_W_PH:
12136 check_dsp_r2(ctx);
12137 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, tcg_env);
12138 break;
12139 case OPC_DPSQX_SA_W_PH:
12140 check_dsp_r2(ctx);
12141 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, tcg_env);
12142 break;
12143 case OPC_MULSAQ_S_W_PH:
12144 check_dsp(ctx);
12145 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, tcg_env);
12146 break;
12147 case OPC_DPAQ_SA_L_W:
12148 check_dsp(ctx);
12149 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, tcg_env);
12150 break;
12151 case OPC_DPSQ_SA_L_W:
12152 check_dsp(ctx);
12153 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, tcg_env);
12154 break;
12155 case OPC_MAQ_S_W_PHL:
12156 check_dsp(ctx);
12157 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, tcg_env);
12158 break;
12159 case OPC_MAQ_S_W_PHR:
12160 check_dsp(ctx);
12161 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, tcg_env);
12162 break;
12163 case OPC_MAQ_SA_W_PHL:
12164 check_dsp(ctx);
12165 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, tcg_env);
12166 break;
12167 case OPC_MAQ_SA_W_PHR:
12168 check_dsp(ctx);
12169 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, tcg_env);
12170 break;
12171 case OPC_MULSA_W_PH:
12172 check_dsp_r2(ctx);
12173 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, tcg_env);
12174 break;
12175 }
12176 break;
12177 #ifdef TARGET_MIPS64
12178 case OPC_DPAQ_W_QH_DSP:
12179 {
12180 int ac = ret & 0x03;
12181 tcg_gen_movi_i32(t0, ac);
12182
12183 switch (op2) {
12184 case OPC_DMADD:
12185 check_dsp(ctx);
12186 gen_helper_dmadd(v1_t, v2_t, t0, tcg_env);
12187 break;
12188 case OPC_DMADDU:
12189 check_dsp(ctx);
12190 gen_helper_dmaddu(v1_t, v2_t, t0, tcg_env);
12191 break;
12192 case OPC_DMSUB:
12193 check_dsp(ctx);
12194 gen_helper_dmsub(v1_t, v2_t, t0, tcg_env);
12195 break;
12196 case OPC_DMSUBU:
12197 check_dsp(ctx);
12198 gen_helper_dmsubu(v1_t, v2_t, t0, tcg_env);
12199 break;
12200 case OPC_DPA_W_QH:
12201 check_dsp_r2(ctx);
12202 gen_helper_dpa_w_qh(v1_t, v2_t, t0, tcg_env);
12203 break;
12204 case OPC_DPAQ_S_W_QH:
12205 check_dsp(ctx);
12206 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, tcg_env);
12207 break;
12208 case OPC_DPAQ_SA_L_PW:
12209 check_dsp(ctx);
12210 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, tcg_env);
12211 break;
12212 case OPC_DPAU_H_OBL:
12213 check_dsp(ctx);
12214 gen_helper_dpau_h_obl(v1_t, v2_t, t0, tcg_env);
12215 break;
12216 case OPC_DPAU_H_OBR:
12217 check_dsp(ctx);
12218 gen_helper_dpau_h_obr(v1_t, v2_t, t0, tcg_env);
12219 break;
12220 case OPC_DPS_W_QH:
12221 check_dsp_r2(ctx);
12222 gen_helper_dps_w_qh(v1_t, v2_t, t0, tcg_env);
12223 break;
12224 case OPC_DPSQ_S_W_QH:
12225 check_dsp(ctx);
12226 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, tcg_env);
12227 break;
12228 case OPC_DPSQ_SA_L_PW:
12229 check_dsp(ctx);
12230 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, tcg_env);
12231 break;
12232 case OPC_DPSU_H_OBL:
12233 check_dsp(ctx);
12234 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, tcg_env);
12235 break;
12236 case OPC_DPSU_H_OBR:
12237 check_dsp(ctx);
12238 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, tcg_env);
12239 break;
12240 case OPC_MAQ_S_L_PWL:
12241 check_dsp(ctx);
12242 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, tcg_env);
12243 break;
12244 case OPC_MAQ_S_L_PWR:
12245 check_dsp(ctx);
12246 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, tcg_env);
12247 break;
12248 case OPC_MAQ_S_W_QHLL:
12249 check_dsp(ctx);
12250 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, tcg_env);
12251 break;
12252 case OPC_MAQ_SA_W_QHLL:
12253 check_dsp(ctx);
12254 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, tcg_env);
12255 break;
12256 case OPC_MAQ_S_W_QHLR:
12257 check_dsp(ctx);
12258 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, tcg_env);
12259 break;
12260 case OPC_MAQ_SA_W_QHLR:
12261 check_dsp(ctx);
12262 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, tcg_env);
12263 break;
12264 case OPC_MAQ_S_W_QHRL:
12265 check_dsp(ctx);
12266 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, tcg_env);
12267 break;
12268 case OPC_MAQ_SA_W_QHRL:
12269 check_dsp(ctx);
12270 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, tcg_env);
12271 break;
12272 case OPC_MAQ_S_W_QHRR:
12273 check_dsp(ctx);
12274 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, tcg_env);
12275 break;
12276 case OPC_MAQ_SA_W_QHRR:
12277 check_dsp(ctx);
12278 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, tcg_env);
12279 break;
12280 case OPC_MULSAQ_S_L_PW:
12281 check_dsp(ctx);
12282 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, tcg_env);
12283 break;
12284 case OPC_MULSAQ_S_W_QH:
12285 check_dsp(ctx);
12286 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, tcg_env);
12287 break;
12288 }
12289 }
12290 break;
12291 #endif
12292 case OPC_ADDU_QB_DSP:
12293 switch (op2) {
12294 case OPC_MULEU_S_PH_QBL:
12295 check_dsp(ctx);
12296 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12297 break;
12298 case OPC_MULEU_S_PH_QBR:
12299 check_dsp(ctx);
12300 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12301 break;
12302 case OPC_MULQ_RS_PH:
12303 check_dsp(ctx);
12304 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12305 break;
12306 case OPC_MULEQ_S_W_PHL:
12307 check_dsp(ctx);
12308 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12309 break;
12310 case OPC_MULEQ_S_W_PHR:
12311 check_dsp(ctx);
12312 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12313 break;
12314 case OPC_MULQ_S_PH:
12315 check_dsp_r2(ctx);
12316 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12317 break;
12318 }
12319 break;
12320 #ifdef TARGET_MIPS64
12321 case OPC_ADDU_OB_DSP:
12322 switch (op2) {
12323 case OPC_MULEQ_S_PW_QHL:
12324 check_dsp(ctx);
12325 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12326 break;
12327 case OPC_MULEQ_S_PW_QHR:
12328 check_dsp(ctx);
12329 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12330 break;
12331 case OPC_MULEU_S_QH_OBL:
12332 check_dsp(ctx);
12333 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12334 break;
12335 case OPC_MULEU_S_QH_OBR:
12336 check_dsp(ctx);
12337 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12338 break;
12339 case OPC_MULQ_RS_QH:
12340 check_dsp(ctx);
12341 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12342 break;
12343 }
12344 break;
12345 #endif
12346 }
12347 }
12348
gen_mipsdsp_bitinsn(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int val)12349 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
12350 int ret, int val)
12351 {
12352 int16_t imm;
12353 TCGv t0;
12354 TCGv val_t;
12355
12356 if (ret == 0) {
12357 /* Treat as NOP. */
12358 return;
12359 }
12360
12361 t0 = tcg_temp_new();
12362 val_t = tcg_temp_new();
12363 gen_load_gpr(val_t, val);
12364
12365 switch (op1) {
12366 case OPC_ABSQ_S_PH_DSP:
12367 switch (op2) {
12368 case OPC_BITREV:
12369 check_dsp(ctx);
12370 gen_helper_bitrev(cpu_gpr[ret], val_t);
12371 break;
12372 case OPC_REPL_QB:
12373 check_dsp(ctx);
12374 {
12375 target_long result;
12376 imm = (ctx->opcode >> 16) & 0xFF;
12377 result = (uint32_t)imm << 24 |
12378 (uint32_t)imm << 16 |
12379 (uint32_t)imm << 8 |
12380 (uint32_t)imm;
12381 result = (int32_t)result;
12382 tcg_gen_movi_tl(cpu_gpr[ret], result);
12383 }
12384 break;
12385 case OPC_REPLV_QB:
12386 check_dsp(ctx);
12387 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
12388 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
12389 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12390 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12391 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12392 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12393 break;
12394 case OPC_REPL_PH:
12395 check_dsp(ctx);
12396 {
12397 imm = (ctx->opcode >> 16) & 0x03FF;
12398 imm = (int16_t)(imm << 6) >> 6;
12399 tcg_gen_movi_tl(cpu_gpr[ret], \
12400 (target_long)((int32_t)imm << 16 | \
12401 (uint16_t)imm));
12402 }
12403 break;
12404 case OPC_REPLV_PH:
12405 check_dsp(ctx);
12406 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
12407 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12408 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12409 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12410 break;
12411 }
12412 break;
12413 #ifdef TARGET_MIPS64
12414 case OPC_ABSQ_S_QH_DSP:
12415 switch (op2) {
12416 case OPC_REPL_OB:
12417 check_dsp(ctx);
12418 {
12419 target_long temp;
12420
12421 imm = (ctx->opcode >> 16) & 0xFF;
12422 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
12423 temp = (temp << 16) | temp;
12424 temp = (temp << 32) | temp;
12425 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12426 break;
12427 }
12428 case OPC_REPL_PW:
12429 check_dsp(ctx);
12430 {
12431 target_long temp;
12432
12433 imm = (ctx->opcode >> 16) & 0x03FF;
12434 imm = (int16_t)(imm << 6) >> 6;
12435 temp = ((target_long)imm << 32) \
12436 | ((target_long)imm & 0xFFFFFFFF);
12437 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12438 break;
12439 }
12440 case OPC_REPL_QH:
12441 check_dsp(ctx);
12442 {
12443 target_long temp;
12444
12445 imm = (ctx->opcode >> 16) & 0x03FF;
12446 imm = (int16_t)(imm << 6) >> 6;
12447
12448 temp = ((uint64_t)(uint16_t)imm << 48) |
12449 ((uint64_t)(uint16_t)imm << 32) |
12450 ((uint64_t)(uint16_t)imm << 16) |
12451 (uint64_t)(uint16_t)imm;
12452 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12453 break;
12454 }
12455 case OPC_REPLV_OB:
12456 check_dsp(ctx);
12457 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
12458 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
12459 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12460 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12461 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12462 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12463 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12464 break;
12465 case OPC_REPLV_PW:
12466 check_dsp(ctx);
12467 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
12468 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12469 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12470 break;
12471 case OPC_REPLV_QH:
12472 check_dsp(ctx);
12473 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
12474 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12475 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12476 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12477 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12478 break;
12479 }
12480 break;
12481 #endif
12482 }
12483 }
12484
gen_mipsdsp_add_cmp_pick(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2,int check_ret)12485 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
12486 uint32_t op1, uint32_t op2,
12487 int ret, int v1, int v2, int check_ret)
12488 {
12489 TCGv t1;
12490 TCGv v1_t;
12491 TCGv v2_t;
12492
12493 if ((ret == 0) && (check_ret == 1)) {
12494 /* Treat as NOP. */
12495 return;
12496 }
12497
12498 t1 = tcg_temp_new();
12499 v1_t = tcg_temp_new();
12500 v2_t = tcg_temp_new();
12501
12502 gen_load_gpr(v1_t, v1);
12503 gen_load_gpr(v2_t, v2);
12504
12505 switch (op1) {
12506 case OPC_CMPU_EQ_QB_DSP:
12507 switch (op2) {
12508 case OPC_CMPU_EQ_QB:
12509 check_dsp(ctx);
12510 gen_helper_cmpu_eq_qb(v1_t, v2_t, tcg_env);
12511 break;
12512 case OPC_CMPU_LT_QB:
12513 check_dsp(ctx);
12514 gen_helper_cmpu_lt_qb(v1_t, v2_t, tcg_env);
12515 break;
12516 case OPC_CMPU_LE_QB:
12517 check_dsp(ctx);
12518 gen_helper_cmpu_le_qb(v1_t, v2_t, tcg_env);
12519 break;
12520 case OPC_CMPGU_EQ_QB:
12521 check_dsp(ctx);
12522 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
12523 break;
12524 case OPC_CMPGU_LT_QB:
12525 check_dsp(ctx);
12526 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
12527 break;
12528 case OPC_CMPGU_LE_QB:
12529 check_dsp(ctx);
12530 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
12531 break;
12532 case OPC_CMPGDU_EQ_QB:
12533 check_dsp_r2(ctx);
12534 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
12535 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12536 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12537 tcg_gen_shli_tl(t1, t1, 24);
12538 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12539 break;
12540 case OPC_CMPGDU_LT_QB:
12541 check_dsp_r2(ctx);
12542 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
12543 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12544 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12545 tcg_gen_shli_tl(t1, t1, 24);
12546 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12547 break;
12548 case OPC_CMPGDU_LE_QB:
12549 check_dsp_r2(ctx);
12550 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
12551 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12552 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12553 tcg_gen_shli_tl(t1, t1, 24);
12554 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12555 break;
12556 case OPC_CMP_EQ_PH:
12557 check_dsp(ctx);
12558 gen_helper_cmp_eq_ph(v1_t, v2_t, tcg_env);
12559 break;
12560 case OPC_CMP_LT_PH:
12561 check_dsp(ctx);
12562 gen_helper_cmp_lt_ph(v1_t, v2_t, tcg_env);
12563 break;
12564 case OPC_CMP_LE_PH:
12565 check_dsp(ctx);
12566 gen_helper_cmp_le_ph(v1_t, v2_t, tcg_env);
12567 break;
12568 case OPC_PICK_QB:
12569 check_dsp(ctx);
12570 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12571 break;
12572 case OPC_PICK_PH:
12573 check_dsp(ctx);
12574 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12575 break;
12576 case OPC_PACKRL_PH:
12577 check_dsp(ctx);
12578 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
12579 break;
12580 }
12581 break;
12582 #ifdef TARGET_MIPS64
12583 case OPC_CMPU_EQ_OB_DSP:
12584 switch (op2) {
12585 case OPC_CMP_EQ_PW:
12586 check_dsp(ctx);
12587 gen_helper_cmp_eq_pw(v1_t, v2_t, tcg_env);
12588 break;
12589 case OPC_CMP_LT_PW:
12590 check_dsp(ctx);
12591 gen_helper_cmp_lt_pw(v1_t, v2_t, tcg_env);
12592 break;
12593 case OPC_CMP_LE_PW:
12594 check_dsp(ctx);
12595 gen_helper_cmp_le_pw(v1_t, v2_t, tcg_env);
12596 break;
12597 case OPC_CMP_EQ_QH:
12598 check_dsp(ctx);
12599 gen_helper_cmp_eq_qh(v1_t, v2_t, tcg_env);
12600 break;
12601 case OPC_CMP_LT_QH:
12602 check_dsp(ctx);
12603 gen_helper_cmp_lt_qh(v1_t, v2_t, tcg_env);
12604 break;
12605 case OPC_CMP_LE_QH:
12606 check_dsp(ctx);
12607 gen_helper_cmp_le_qh(v1_t, v2_t, tcg_env);
12608 break;
12609 case OPC_CMPGDU_EQ_OB:
12610 check_dsp_r2(ctx);
12611 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12612 break;
12613 case OPC_CMPGDU_LT_OB:
12614 check_dsp_r2(ctx);
12615 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12616 break;
12617 case OPC_CMPGDU_LE_OB:
12618 check_dsp_r2(ctx);
12619 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12620 break;
12621 case OPC_CMPGU_EQ_OB:
12622 check_dsp(ctx);
12623 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
12624 break;
12625 case OPC_CMPGU_LT_OB:
12626 check_dsp(ctx);
12627 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
12628 break;
12629 case OPC_CMPGU_LE_OB:
12630 check_dsp(ctx);
12631 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
12632 break;
12633 case OPC_CMPU_EQ_OB:
12634 check_dsp(ctx);
12635 gen_helper_cmpu_eq_ob(v1_t, v2_t, tcg_env);
12636 break;
12637 case OPC_CMPU_LT_OB:
12638 check_dsp(ctx);
12639 gen_helper_cmpu_lt_ob(v1_t, v2_t, tcg_env);
12640 break;
12641 case OPC_CMPU_LE_OB:
12642 check_dsp(ctx);
12643 gen_helper_cmpu_le_ob(v1_t, v2_t, tcg_env);
12644 break;
12645 case OPC_PACKRL_PW:
12646 check_dsp(ctx);
12647 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
12648 break;
12649 case OPC_PICK_OB:
12650 check_dsp(ctx);
12651 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12652 break;
12653 case OPC_PICK_PW:
12654 check_dsp(ctx);
12655 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12656 break;
12657 case OPC_PICK_QH:
12658 check_dsp(ctx);
12659 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12660 break;
12661 }
12662 break;
12663 #endif
12664 }
12665 }
12666
gen_mipsdsp_append(CPUMIPSState * env,DisasContext * ctx,uint32_t op1,int rt,int rs,int sa)12667 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
12668 uint32_t op1, int rt, int rs, int sa)
12669 {
12670 TCGv t0;
12671
12672 check_dsp_r2(ctx);
12673
12674 if (rt == 0) {
12675 /* Treat as NOP. */
12676 return;
12677 }
12678
12679 t0 = tcg_temp_new();
12680 gen_load_gpr(t0, rs);
12681
12682 switch (op1) {
12683 case OPC_APPEND_DSP:
12684 switch (MASK_APPEND(ctx->opcode)) {
12685 case OPC_APPEND:
12686 if (sa != 0) {
12687 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
12688 }
12689 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12690 break;
12691 case OPC_PREPEND:
12692 if (sa != 0) {
12693 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
12694 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
12695 tcg_gen_shli_tl(t0, t0, 32 - sa);
12696 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12697 }
12698 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12699 break;
12700 case OPC_BALIGN:
12701 sa &= 3;
12702 if (sa != 0 && sa != 2) {
12703 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
12704 tcg_gen_ext32u_tl(t0, t0);
12705 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
12706 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12707 }
12708 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12709 break;
12710 default: /* Invalid */
12711 MIPS_INVAL("MASK APPEND");
12712 gen_reserved_instruction(ctx);
12713 break;
12714 }
12715 break;
12716 #ifdef TARGET_MIPS64
12717 case OPC_DAPPEND_DSP:
12718 switch (MASK_DAPPEND(ctx->opcode)) {
12719 case OPC_DAPPEND:
12720 if (sa != 0) {
12721 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
12722 }
12723 break;
12724 case OPC_PREPENDD:
12725 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
12726 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
12727 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
12728 break;
12729 case OPC_PREPENDW:
12730 if (sa != 0) {
12731 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
12732 tcg_gen_shli_tl(t0, t0, 64 - sa);
12733 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12734 }
12735 break;
12736 case OPC_DBALIGN:
12737 sa &= 7;
12738 if (sa != 0 && sa != 2 && sa != 4) {
12739 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
12740 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
12741 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12742 }
12743 break;
12744 default: /* Invalid */
12745 MIPS_INVAL("MASK DAPPEND");
12746 gen_reserved_instruction(ctx);
12747 break;
12748 }
12749 break;
12750 #endif
12751 }
12752 }
12753
gen_mipsdsp_accinsn(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2,int check_ret)12754 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
12755 int ret, int v1, int v2, int check_ret)
12756
12757 {
12758 TCGv t0;
12759 TCGv t1;
12760 TCGv v1_t;
12761 int16_t imm;
12762
12763 if ((ret == 0) && (check_ret == 1)) {
12764 /* Treat as NOP. */
12765 return;
12766 }
12767
12768 t0 = tcg_temp_new();
12769 t1 = tcg_temp_new();
12770 v1_t = tcg_temp_new();
12771
12772 gen_load_gpr(v1_t, v1);
12773
12774 switch (op1) {
12775 case OPC_EXTR_W_DSP:
12776 check_dsp(ctx);
12777 switch (op2) {
12778 case OPC_EXTR_W:
12779 tcg_gen_movi_tl(t0, v2);
12780 tcg_gen_movi_tl(t1, v1);
12781 gen_helper_extr_w(cpu_gpr[ret], t0, t1, tcg_env);
12782 break;
12783 case OPC_EXTR_R_W:
12784 tcg_gen_movi_tl(t0, v2);
12785 tcg_gen_movi_tl(t1, v1);
12786 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, tcg_env);
12787 break;
12788 case OPC_EXTR_RS_W:
12789 tcg_gen_movi_tl(t0, v2);
12790 tcg_gen_movi_tl(t1, v1);
12791 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, tcg_env);
12792 break;
12793 case OPC_EXTR_S_H:
12794 tcg_gen_movi_tl(t0, v2);
12795 tcg_gen_movi_tl(t1, v1);
12796 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, tcg_env);
12797 break;
12798 case OPC_EXTRV_S_H:
12799 tcg_gen_movi_tl(t0, v2);
12800 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, tcg_env);
12801 break;
12802 case OPC_EXTRV_W:
12803 tcg_gen_movi_tl(t0, v2);
12804 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12805 break;
12806 case OPC_EXTRV_R_W:
12807 tcg_gen_movi_tl(t0, v2);
12808 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12809 break;
12810 case OPC_EXTRV_RS_W:
12811 tcg_gen_movi_tl(t0, v2);
12812 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12813 break;
12814 case OPC_EXTP:
12815 tcg_gen_movi_tl(t0, v2);
12816 tcg_gen_movi_tl(t1, v1);
12817 gen_helper_extp(cpu_gpr[ret], t0, t1, tcg_env);
12818 break;
12819 case OPC_EXTPV:
12820 tcg_gen_movi_tl(t0, v2);
12821 gen_helper_extp(cpu_gpr[ret], t0, v1_t, tcg_env);
12822 break;
12823 case OPC_EXTPDP:
12824 tcg_gen_movi_tl(t0, v2);
12825 tcg_gen_movi_tl(t1, v1);
12826 gen_helper_extpdp(cpu_gpr[ret], t0, t1, tcg_env);
12827 break;
12828 case OPC_EXTPDPV:
12829 tcg_gen_movi_tl(t0, v2);
12830 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, tcg_env);
12831 break;
12832 case OPC_SHILO:
12833 imm = (ctx->opcode >> 20) & 0x3F;
12834 tcg_gen_movi_tl(t0, ret);
12835 tcg_gen_movi_tl(t1, imm);
12836 gen_helper_shilo(t0, t1, tcg_env);
12837 break;
12838 case OPC_SHILOV:
12839 tcg_gen_movi_tl(t0, ret);
12840 gen_helper_shilo(t0, v1_t, tcg_env);
12841 break;
12842 case OPC_MTHLIP:
12843 tcg_gen_movi_tl(t0, ret);
12844 gen_helper_mthlip(t0, v1_t, tcg_env);
12845 break;
12846 case OPC_WRDSP:
12847 imm = (ctx->opcode >> 11) & 0x3FF;
12848 tcg_gen_movi_tl(t0, imm);
12849 gen_helper_wrdsp(v1_t, t0, tcg_env);
12850 break;
12851 case OPC_RDDSP:
12852 imm = (ctx->opcode >> 16) & 0x03FF;
12853 tcg_gen_movi_tl(t0, imm);
12854 gen_helper_rddsp(cpu_gpr[ret], t0, tcg_env);
12855 break;
12856 }
12857 break;
12858 #ifdef TARGET_MIPS64
12859 case OPC_DEXTR_W_DSP:
12860 check_dsp(ctx);
12861 switch (op2) {
12862 case OPC_DMTHLIP:
12863 tcg_gen_movi_tl(t0, ret);
12864 gen_helper_dmthlip(v1_t, t0, tcg_env);
12865 break;
12866 case OPC_DSHILO:
12867 {
12868 int shift = (ctx->opcode >> 19) & 0x7F;
12869 int ac = (ctx->opcode >> 11) & 0x03;
12870 tcg_gen_movi_tl(t0, shift);
12871 tcg_gen_movi_tl(t1, ac);
12872 gen_helper_dshilo(t0, t1, tcg_env);
12873 break;
12874 }
12875 case OPC_DSHILOV:
12876 {
12877 int ac = (ctx->opcode >> 11) & 0x03;
12878 tcg_gen_movi_tl(t0, ac);
12879 gen_helper_dshilo(v1_t, t0, tcg_env);
12880 break;
12881 }
12882 case OPC_DEXTP:
12883 tcg_gen_movi_tl(t0, v2);
12884 tcg_gen_movi_tl(t1, v1);
12885
12886 gen_helper_dextp(cpu_gpr[ret], t0, t1, tcg_env);
12887 break;
12888 case OPC_DEXTPV:
12889 tcg_gen_movi_tl(t0, v2);
12890 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, tcg_env);
12891 break;
12892 case OPC_DEXTPDP:
12893 tcg_gen_movi_tl(t0, v2);
12894 tcg_gen_movi_tl(t1, v1);
12895 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, tcg_env);
12896 break;
12897 case OPC_DEXTPDPV:
12898 tcg_gen_movi_tl(t0, v2);
12899 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, tcg_env);
12900 break;
12901 case OPC_DEXTR_L:
12902 tcg_gen_movi_tl(t0, v2);
12903 tcg_gen_movi_tl(t1, v1);
12904 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, tcg_env);
12905 break;
12906 case OPC_DEXTR_R_L:
12907 tcg_gen_movi_tl(t0, v2);
12908 tcg_gen_movi_tl(t1, v1);
12909 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, tcg_env);
12910 break;
12911 case OPC_DEXTR_RS_L:
12912 tcg_gen_movi_tl(t0, v2);
12913 tcg_gen_movi_tl(t1, v1);
12914 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, tcg_env);
12915 break;
12916 case OPC_DEXTR_W:
12917 tcg_gen_movi_tl(t0, v2);
12918 tcg_gen_movi_tl(t1, v1);
12919 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, tcg_env);
12920 break;
12921 case OPC_DEXTR_R_W:
12922 tcg_gen_movi_tl(t0, v2);
12923 tcg_gen_movi_tl(t1, v1);
12924 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, tcg_env);
12925 break;
12926 case OPC_DEXTR_RS_W:
12927 tcg_gen_movi_tl(t0, v2);
12928 tcg_gen_movi_tl(t1, v1);
12929 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, tcg_env);
12930 break;
12931 case OPC_DEXTR_S_H:
12932 tcg_gen_movi_tl(t0, v2);
12933 tcg_gen_movi_tl(t1, v1);
12934 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, tcg_env);
12935 break;
12936 case OPC_DEXTRV_S_H:
12937 tcg_gen_movi_tl(t0, v2);
12938 gen_helper_dextr_s_h(cpu_gpr[ret], t0, v1_t, tcg_env);
12939 break;
12940 case OPC_DEXTRV_L:
12941 tcg_gen_movi_tl(t0, v2);
12942 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, tcg_env);
12943 break;
12944 case OPC_DEXTRV_R_L:
12945 tcg_gen_movi_tl(t0, v2);
12946 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, tcg_env);
12947 break;
12948 case OPC_DEXTRV_RS_L:
12949 tcg_gen_movi_tl(t0, v2);
12950 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, tcg_env);
12951 break;
12952 case OPC_DEXTRV_W:
12953 tcg_gen_movi_tl(t0, v2);
12954 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12955 break;
12956 case OPC_DEXTRV_R_W:
12957 tcg_gen_movi_tl(t0, v2);
12958 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12959 break;
12960 case OPC_DEXTRV_RS_W:
12961 tcg_gen_movi_tl(t0, v2);
12962 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12963 break;
12964 }
12965 break;
12966 #endif
12967 }
12968 }
12969
12970 /* End MIPSDSP functions. */
12971
decode_opc_special_r6(CPUMIPSState * env,DisasContext * ctx)12972 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
12973 {
12974 int rs, rt, rd, sa;
12975 uint32_t op1, op2;
12976
12977 rs = (ctx->opcode >> 21) & 0x1f;
12978 rt = (ctx->opcode >> 16) & 0x1f;
12979 rd = (ctx->opcode >> 11) & 0x1f;
12980 sa = (ctx->opcode >> 6) & 0x1f;
12981
12982 op1 = MASK_SPECIAL(ctx->opcode);
12983 switch (op1) {
12984 case OPC_MULT:
12985 case OPC_MULTU:
12986 case OPC_DIV:
12987 case OPC_DIVU:
12988 op2 = MASK_R6_MULDIV(ctx->opcode);
12989 switch (op2) {
12990 case R6_OPC_MUL:
12991 case R6_OPC_MUH:
12992 case R6_OPC_MULU:
12993 case R6_OPC_MUHU:
12994 case R6_OPC_DIV:
12995 case R6_OPC_MOD:
12996 case R6_OPC_DIVU:
12997 case R6_OPC_MODU:
12998 gen_r6_muldiv(ctx, op2, rd, rs, rt);
12999 break;
13000 default:
13001 MIPS_INVAL("special_r6 muldiv");
13002 gen_reserved_instruction(ctx);
13003 break;
13004 }
13005 break;
13006 case OPC_SELEQZ:
13007 case OPC_SELNEZ:
13008 gen_cond_move(ctx, op1, rd, rs, rt);
13009 break;
13010 case R6_OPC_CLO:
13011 case R6_OPC_CLZ:
13012 if (rt == 0 && sa == 1) {
13013 /*
13014 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13015 * We need additionally to check other fields.
13016 */
13017 gen_cl(ctx, op1, rd, rs);
13018 } else {
13019 gen_reserved_instruction(ctx);
13020 }
13021 break;
13022 case R6_OPC_SDBBP:
13023 if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) {
13024 ctx->base.is_jmp = DISAS_SEMIHOST;
13025 } else {
13026 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13027 gen_reserved_instruction(ctx);
13028 } else {
13029 generate_exception_end(ctx, EXCP_DBp);
13030 }
13031 }
13032 break;
13033 #if defined(TARGET_MIPS64)
13034 case R6_OPC_DCLO:
13035 case R6_OPC_DCLZ:
13036 if (rt == 0 && sa == 1) {
13037 /*
13038 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13039 * We need additionally to check other fields.
13040 */
13041 check_mips_64(ctx);
13042 gen_cl(ctx, op1, rd, rs);
13043 } else {
13044 gen_reserved_instruction(ctx);
13045 }
13046 break;
13047 case OPC_DMULT:
13048 case OPC_DMULTU:
13049 case OPC_DDIV:
13050 case OPC_DDIVU:
13051
13052 op2 = MASK_R6_MULDIV(ctx->opcode);
13053 switch (op2) {
13054 case R6_OPC_DMUL:
13055 case R6_OPC_DMUH:
13056 case R6_OPC_DMULU:
13057 case R6_OPC_DMUHU:
13058 case R6_OPC_DDIV:
13059 case R6_OPC_DMOD:
13060 case R6_OPC_DDIVU:
13061 case R6_OPC_DMODU:
13062 check_mips_64(ctx);
13063 gen_r6_muldiv(ctx, op2, rd, rs, rt);
13064 break;
13065 default:
13066 MIPS_INVAL("special_r6 muldiv");
13067 gen_reserved_instruction(ctx);
13068 break;
13069 }
13070 break;
13071 #endif
13072 default: /* Invalid */
13073 MIPS_INVAL("special_r6");
13074 gen_reserved_instruction(ctx);
13075 break;
13076 }
13077 }
13078
decode_opc_special_tx79(CPUMIPSState * env,DisasContext * ctx)13079 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
13080 {
13081 int rs = extract32(ctx->opcode, 21, 5);
13082 int rt = extract32(ctx->opcode, 16, 5);
13083 int rd = extract32(ctx->opcode, 11, 5);
13084 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
13085
13086 switch (op1) {
13087 case OPC_MOVN: /* Conditional move */
13088 case OPC_MOVZ:
13089 gen_cond_move(ctx, op1, rd, rs, rt);
13090 break;
13091 case OPC_MFHI: /* Move from HI/LO */
13092 case OPC_MFLO:
13093 gen_HILO(ctx, op1, 0, rd);
13094 break;
13095 case OPC_MTHI:
13096 case OPC_MTLO: /* Move to HI/LO */
13097 gen_HILO(ctx, op1, 0, rs);
13098 break;
13099 case OPC_MULT:
13100 case OPC_MULTU:
13101 gen_mul_txx9(ctx, op1, rd, rs, rt);
13102 break;
13103 case OPC_DIV:
13104 case OPC_DIVU:
13105 gen_muldiv(ctx, op1, 0, rs, rt);
13106 break;
13107 #if defined(TARGET_MIPS64)
13108 case OPC_DMULT:
13109 case OPC_DMULTU:
13110 case OPC_DDIV:
13111 case OPC_DDIVU:
13112 check_insn_opc_user_only(ctx, INSN_R5900);
13113 gen_muldiv(ctx, op1, 0, rs, rt);
13114 break;
13115 #endif
13116 case OPC_JR:
13117 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
13118 break;
13119 default: /* Invalid */
13120 MIPS_INVAL("special_tx79");
13121 gen_reserved_instruction(ctx);
13122 break;
13123 }
13124 }
13125
decode_opc_special_legacy(CPUMIPSState * env,DisasContext * ctx)13126 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
13127 {
13128 int rs, rt, rd;
13129 uint32_t op1;
13130
13131 rs = (ctx->opcode >> 21) & 0x1f;
13132 rt = (ctx->opcode >> 16) & 0x1f;
13133 rd = (ctx->opcode >> 11) & 0x1f;
13134
13135 op1 = MASK_SPECIAL(ctx->opcode);
13136 switch (op1) {
13137 case OPC_MOVN: /* Conditional move */
13138 case OPC_MOVZ:
13139 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
13140 INSN_LOONGSON2E | INSN_LOONGSON2F);
13141 gen_cond_move(ctx, op1, rd, rs, rt);
13142 break;
13143 case OPC_MFHI: /* Move from HI/LO */
13144 case OPC_MFLO:
13145 gen_HILO(ctx, op1, rs & 3, rd);
13146 break;
13147 case OPC_MTHI:
13148 case OPC_MTLO: /* Move to HI/LO */
13149 gen_HILO(ctx, op1, rd & 3, rs);
13150 break;
13151 case OPC_MOVCI:
13152 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
13153 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
13154 check_cp1_enabled(ctx);
13155 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
13156 (ctx->opcode >> 16) & 1);
13157 } else {
13158 generate_exception_err(ctx, EXCP_CpU, 1);
13159 }
13160 break;
13161 case OPC_MULT:
13162 case OPC_MULTU:
13163 gen_muldiv(ctx, op1, rd & 3, rs, rt);
13164 break;
13165 case OPC_DIV:
13166 case OPC_DIVU:
13167 gen_muldiv(ctx, op1, 0, rs, rt);
13168 break;
13169 #if defined(TARGET_MIPS64)
13170 case OPC_DMULT:
13171 case OPC_DMULTU:
13172 case OPC_DDIV:
13173 case OPC_DDIVU:
13174 check_insn(ctx, ISA_MIPS3);
13175 check_mips_64(ctx);
13176 gen_muldiv(ctx, op1, 0, rs, rt);
13177 break;
13178 #endif
13179 case OPC_JR:
13180 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
13181 break;
13182 case OPC_SPIM:
13183 #ifdef MIPS_STRICT_STANDARD
13184 MIPS_INVAL("SPIM");
13185 gen_reserved_instruction(ctx);
13186 #else
13187 /* Implemented as RI exception for now. */
13188 MIPS_INVAL("spim (unofficial)");
13189 gen_reserved_instruction(ctx);
13190 #endif
13191 break;
13192 default: /* Invalid */
13193 MIPS_INVAL("special_legacy");
13194 gen_reserved_instruction(ctx);
13195 break;
13196 }
13197 }
13198
decode_opc_special(CPUMIPSState * env,DisasContext * ctx)13199 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
13200 {
13201 int rs, rt, rd, sa;
13202 uint32_t op1;
13203
13204 rs = (ctx->opcode >> 21) & 0x1f;
13205 rt = (ctx->opcode >> 16) & 0x1f;
13206 rd = (ctx->opcode >> 11) & 0x1f;
13207 sa = (ctx->opcode >> 6) & 0x1f;
13208
13209 op1 = MASK_SPECIAL(ctx->opcode);
13210 switch (op1) {
13211 case OPC_SLL: /* Shift with immediate */
13212 if (sa == 5 && rd == 0 &&
13213 rs == 0 && rt == 0) { /* PAUSE */
13214 if ((ctx->insn_flags & ISA_MIPS_R6) &&
13215 (ctx->hflags & MIPS_HFLAG_BMASK)) {
13216 gen_reserved_instruction(ctx);
13217 break;
13218 }
13219 }
13220 /* Fallthrough */
13221 case OPC_SRA:
13222 gen_shift_imm(ctx, op1, rd, rt, sa);
13223 break;
13224 case OPC_SRL:
13225 switch ((ctx->opcode >> 21) & 0x1f) {
13226 case 1:
13227 /* rotr is decoded as srl on non-R2 CPUs */
13228 if (ctx->insn_flags & ISA_MIPS_R2) {
13229 op1 = OPC_ROTR;
13230 }
13231 /* Fallthrough */
13232 case 0:
13233 gen_shift_imm(ctx, op1, rd, rt, sa);
13234 break;
13235 default:
13236 gen_reserved_instruction(ctx);
13237 break;
13238 }
13239 break;
13240 case OPC_ADD:
13241 case OPC_ADDU:
13242 case OPC_SUB:
13243 case OPC_SUBU:
13244 gen_arith(ctx, op1, rd, rs, rt);
13245 break;
13246 case OPC_SLLV: /* Shifts */
13247 case OPC_SRAV:
13248 gen_shift(ctx, op1, rd, rs, rt);
13249 break;
13250 case OPC_SRLV:
13251 switch ((ctx->opcode >> 6) & 0x1f) {
13252 case 1:
13253 /* rotrv is decoded as srlv on non-R2 CPUs */
13254 if (ctx->insn_flags & ISA_MIPS_R2) {
13255 op1 = OPC_ROTRV;
13256 }
13257 /* Fallthrough */
13258 case 0:
13259 gen_shift(ctx, op1, rd, rs, rt);
13260 break;
13261 default:
13262 gen_reserved_instruction(ctx);
13263 break;
13264 }
13265 break;
13266 case OPC_SLT: /* Set on less than */
13267 case OPC_SLTU:
13268 gen_slt(ctx, op1, rd, rs, rt);
13269 break;
13270 case OPC_AND: /* Logic*/
13271 case OPC_OR:
13272 case OPC_NOR:
13273 case OPC_XOR:
13274 gen_logic(ctx, op1, rd, rs, rt);
13275 break;
13276 case OPC_JALR:
13277 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
13278 break;
13279 case OPC_TGE: /* Traps */
13280 case OPC_TGEU:
13281 case OPC_TLT:
13282 case OPC_TLTU:
13283 case OPC_TEQ:
13284 case OPC_TNE:
13285 check_insn(ctx, ISA_MIPS2);
13286 gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10));
13287 break;
13288 case OPC_PMON:
13289 /* Pmon entry point, also R4010 selsl */
13290 #ifdef MIPS_STRICT_STANDARD
13291 MIPS_INVAL("PMON / selsl");
13292 gen_reserved_instruction(ctx);
13293 #else
13294 gen_helper_pmon(tcg_env, tcg_constant_i32(sa));
13295 #endif
13296 break;
13297 case OPC_SYSCALL:
13298 generate_exception_end(ctx, EXCP_SYSCALL);
13299 break;
13300 case OPC_BREAK:
13301 generate_exception_break(ctx, extract32(ctx->opcode, 6, 20));
13302 break;
13303 case OPC_SYNC:
13304 check_insn(ctx, ISA_MIPS2);
13305 gen_sync(extract32(ctx->opcode, 6, 5));
13306 break;
13307
13308 #if defined(TARGET_MIPS64)
13309 /* MIPS64 specific opcodes */
13310 case OPC_DSLL:
13311 case OPC_DSRA:
13312 case OPC_DSLL32:
13313 case OPC_DSRA32:
13314 check_insn(ctx, ISA_MIPS3);
13315 check_mips_64(ctx);
13316 gen_shift_imm(ctx, op1, rd, rt, sa);
13317 break;
13318 case OPC_DSRL:
13319 switch ((ctx->opcode >> 21) & 0x1f) {
13320 case 1:
13321 /* drotr is decoded as dsrl on non-R2 CPUs */
13322 if (ctx->insn_flags & ISA_MIPS_R2) {
13323 op1 = OPC_DROTR;
13324 }
13325 /* Fallthrough */
13326 case 0:
13327 check_insn(ctx, ISA_MIPS3);
13328 check_mips_64(ctx);
13329 gen_shift_imm(ctx, op1, rd, rt, sa);
13330 break;
13331 default:
13332 gen_reserved_instruction(ctx);
13333 break;
13334 }
13335 break;
13336 case OPC_DSRL32:
13337 switch ((ctx->opcode >> 21) & 0x1f) {
13338 case 1:
13339 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
13340 if (ctx->insn_flags & ISA_MIPS_R2) {
13341 op1 = OPC_DROTR32;
13342 }
13343 /* Fallthrough */
13344 case 0:
13345 check_insn(ctx, ISA_MIPS3);
13346 check_mips_64(ctx);
13347 gen_shift_imm(ctx, op1, rd, rt, sa);
13348 break;
13349 default:
13350 gen_reserved_instruction(ctx);
13351 break;
13352 }
13353 break;
13354 case OPC_DADD:
13355 case OPC_DADDU:
13356 case OPC_DSUB:
13357 case OPC_DSUBU:
13358 check_insn(ctx, ISA_MIPS3);
13359 check_mips_64(ctx);
13360 gen_arith(ctx, op1, rd, rs, rt);
13361 break;
13362 case OPC_DSLLV:
13363 case OPC_DSRAV:
13364 check_insn(ctx, ISA_MIPS3);
13365 check_mips_64(ctx);
13366 gen_shift(ctx, op1, rd, rs, rt);
13367 break;
13368 case OPC_DSRLV:
13369 switch ((ctx->opcode >> 6) & 0x1f) {
13370 case 1:
13371 /* drotrv is decoded as dsrlv on non-R2 CPUs */
13372 if (ctx->insn_flags & ISA_MIPS_R2) {
13373 op1 = OPC_DROTRV;
13374 }
13375 /* Fallthrough */
13376 case 0:
13377 check_insn(ctx, ISA_MIPS3);
13378 check_mips_64(ctx);
13379 gen_shift(ctx, op1, rd, rs, rt);
13380 break;
13381 default:
13382 gen_reserved_instruction(ctx);
13383 break;
13384 }
13385 break;
13386 #endif
13387 default:
13388 if (ctx->insn_flags & ISA_MIPS_R6) {
13389 decode_opc_special_r6(env, ctx);
13390 } else if (ctx->insn_flags & INSN_R5900) {
13391 decode_opc_special_tx79(env, ctx);
13392 } else {
13393 decode_opc_special_legacy(env, ctx);
13394 }
13395 }
13396 }
13397
13398
decode_opc_special2_legacy(CPUMIPSState * env,DisasContext * ctx)13399 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
13400 {
13401 int rs, rt, rd;
13402 uint32_t op1;
13403
13404 rs = (ctx->opcode >> 21) & 0x1f;
13405 rt = (ctx->opcode >> 16) & 0x1f;
13406 rd = (ctx->opcode >> 11) & 0x1f;
13407
13408 op1 = MASK_SPECIAL2(ctx->opcode);
13409 switch (op1) {
13410 case OPC_MADD: /* Multiply and add/sub */
13411 case OPC_MADDU:
13412 case OPC_MSUB:
13413 case OPC_MSUBU:
13414 check_insn(ctx, ISA_MIPS_R1);
13415 gen_muldiv(ctx, op1, rd & 3, rs, rt);
13416 break;
13417 case OPC_MUL:
13418 gen_arith(ctx, op1, rd, rs, rt);
13419 break;
13420 case OPC_CLO:
13421 case OPC_CLZ:
13422 check_insn(ctx, ISA_MIPS_R1);
13423 gen_cl(ctx, op1, rd, rs);
13424 break;
13425 case OPC_SDBBP:
13426 if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) {
13427 ctx->base.is_jmp = DISAS_SEMIHOST;
13428 } else {
13429 /*
13430 * XXX: not clear which exception should be raised
13431 * when in debug mode...
13432 */
13433 check_insn(ctx, ISA_MIPS_R1);
13434 generate_exception_end(ctx, EXCP_DBp);
13435 }
13436 break;
13437 #if defined(TARGET_MIPS64)
13438 case OPC_DCLO:
13439 case OPC_DCLZ:
13440 check_insn(ctx, ISA_MIPS_R1);
13441 check_mips_64(ctx);
13442 gen_cl(ctx, op1, rd, rs);
13443 break;
13444 #endif
13445 default: /* Invalid */
13446 MIPS_INVAL("special2_legacy");
13447 gen_reserved_instruction(ctx);
13448 break;
13449 }
13450 }
13451
decode_opc_special3_r6(CPUMIPSState * env,DisasContext * ctx)13452 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
13453 {
13454 int rs, rt, rd, sa;
13455 uint32_t op1, op2;
13456 int16_t imm;
13457
13458 rs = (ctx->opcode >> 21) & 0x1f;
13459 rt = (ctx->opcode >> 16) & 0x1f;
13460 rd = (ctx->opcode >> 11) & 0x1f;
13461 sa = (ctx->opcode >> 6) & 0x1f;
13462 imm = (int16_t)ctx->opcode >> 7;
13463
13464 op1 = MASK_SPECIAL3(ctx->opcode);
13465 switch (op1) {
13466 case R6_OPC_PREF:
13467 if (rt >= 24) {
13468 /* hint codes 24-31 are reserved and signal RI */
13469 gen_reserved_instruction(ctx);
13470 }
13471 /* Treat as NOP. */
13472 break;
13473 case R6_OPC_CACHE:
13474 check_cp0_enabled(ctx);
13475 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13476 gen_cache_operation(ctx, rt, rs, imm);
13477 }
13478 break;
13479 case R6_OPC_SC:
13480 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, false);
13481 break;
13482 case R6_OPC_LL:
13483 gen_ld(ctx, op1, rt, rs, imm);
13484 break;
13485 case OPC_BSHFL:
13486 {
13487 if (rd == 0) {
13488 /* Treat as NOP. */
13489 break;
13490 }
13491 op2 = MASK_BSHFL(ctx->opcode);
13492 switch (op2) {
13493 case OPC_ALIGN:
13494 case OPC_ALIGN_1:
13495 case OPC_ALIGN_2:
13496 case OPC_ALIGN_3:
13497 gen_align(ctx, 32, rd, rs, rt, sa & 3);
13498 break;
13499 case OPC_BITSWAP:
13500 gen_bitswap(ctx, op2, rd, rt);
13501 break;
13502 }
13503 }
13504 break;
13505 #ifndef CONFIG_USER_ONLY
13506 case OPC_GINV:
13507 if (unlikely(ctx->gi <= 1)) {
13508 gen_reserved_instruction(ctx);
13509 }
13510 check_cp0_enabled(ctx);
13511 switch ((ctx->opcode >> 6) & 3) {
13512 case 0: /* GINVI */
13513 /* Treat as NOP. */
13514 break;
13515 case 2: /* GINVT */
13516 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
13517 break;
13518 default:
13519 gen_reserved_instruction(ctx);
13520 break;
13521 }
13522 break;
13523 #endif
13524 #if defined(TARGET_MIPS64)
13525 case R6_OPC_SCD:
13526 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_UQ, false);
13527 break;
13528 case R6_OPC_LLD:
13529 gen_ld(ctx, op1, rt, rs, imm);
13530 break;
13531 case OPC_DBSHFL:
13532 check_mips_64(ctx);
13533 {
13534 if (rd == 0) {
13535 /* Treat as NOP. */
13536 break;
13537 }
13538 op2 = MASK_DBSHFL(ctx->opcode);
13539 switch (op2) {
13540 case OPC_DALIGN:
13541 case OPC_DALIGN_1:
13542 case OPC_DALIGN_2:
13543 case OPC_DALIGN_3:
13544 case OPC_DALIGN_4:
13545 case OPC_DALIGN_5:
13546 case OPC_DALIGN_6:
13547 case OPC_DALIGN_7:
13548 gen_align(ctx, 64, rd, rs, rt, sa & 7);
13549 break;
13550 case OPC_DBITSWAP:
13551 gen_bitswap(ctx, op2, rd, rt);
13552 break;
13553 }
13554
13555 }
13556 break;
13557 #endif
13558 default: /* Invalid */
13559 MIPS_INVAL("special3_r6");
13560 gen_reserved_instruction(ctx);
13561 break;
13562 }
13563 }
13564
decode_opc_special3_legacy(CPUMIPSState * env,DisasContext * ctx)13565 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
13566 {
13567 int rs, rt, rd;
13568 uint32_t op1, op2;
13569
13570 rs = (ctx->opcode >> 21) & 0x1f;
13571 rt = (ctx->opcode >> 16) & 0x1f;
13572 rd = (ctx->opcode >> 11) & 0x1f;
13573
13574 op1 = MASK_SPECIAL3(ctx->opcode);
13575 switch (op1) {
13576 case OPC_MUL_PH_DSP:
13577 /*
13578 * OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13579 * the same mask and op1.
13580 */
13581 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MUL_PH_DSP)) {
13582 op2 = MASK_ADDUH_QB(ctx->opcode);
13583 switch (op2) {
13584 case OPC_ADDUH_QB:
13585 case OPC_ADDUH_R_QB:
13586 case OPC_ADDQH_PH:
13587 case OPC_ADDQH_R_PH:
13588 case OPC_ADDQH_W:
13589 case OPC_ADDQH_R_W:
13590 case OPC_SUBUH_QB:
13591 case OPC_SUBUH_R_QB:
13592 case OPC_SUBQH_PH:
13593 case OPC_SUBQH_R_PH:
13594 case OPC_SUBQH_W:
13595 case OPC_SUBQH_R_W:
13596 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13597 break;
13598 case OPC_MUL_PH:
13599 case OPC_MUL_S_PH:
13600 case OPC_MULQ_S_W:
13601 case OPC_MULQ_RS_W:
13602 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
13603 break;
13604 default:
13605 MIPS_INVAL("MASK ADDUH.QB");
13606 gen_reserved_instruction(ctx);
13607 break;
13608 }
13609 } else {
13610 gen_reserved_instruction(ctx);
13611 }
13612 break;
13613 case OPC_LX_DSP:
13614 op2 = MASK_LX(ctx->opcode);
13615 switch (op2) {
13616 #if defined(TARGET_MIPS64)
13617 case OPC_LDX:
13618 #endif
13619 case OPC_LBUX:
13620 case OPC_LHX:
13621 case OPC_LWX:
13622 gen_mips_lx(ctx, op2, rd, rs, rt);
13623 break;
13624 default: /* Invalid */
13625 MIPS_INVAL("MASK LX");
13626 gen_reserved_instruction(ctx);
13627 break;
13628 }
13629 break;
13630 case OPC_ABSQ_S_PH_DSP:
13631 op2 = MASK_ABSQ_S_PH(ctx->opcode);
13632 switch (op2) {
13633 case OPC_ABSQ_S_QB:
13634 case OPC_ABSQ_S_PH:
13635 case OPC_ABSQ_S_W:
13636 case OPC_PRECEQ_W_PHL:
13637 case OPC_PRECEQ_W_PHR:
13638 case OPC_PRECEQU_PH_QBL:
13639 case OPC_PRECEQU_PH_QBR:
13640 case OPC_PRECEQU_PH_QBLA:
13641 case OPC_PRECEQU_PH_QBRA:
13642 case OPC_PRECEU_PH_QBL:
13643 case OPC_PRECEU_PH_QBR:
13644 case OPC_PRECEU_PH_QBLA:
13645 case OPC_PRECEU_PH_QBRA:
13646 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13647 break;
13648 case OPC_BITREV:
13649 case OPC_REPL_QB:
13650 case OPC_REPLV_QB:
13651 case OPC_REPL_PH:
13652 case OPC_REPLV_PH:
13653 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
13654 break;
13655 default:
13656 MIPS_INVAL("MASK ABSQ_S.PH");
13657 gen_reserved_instruction(ctx);
13658 break;
13659 }
13660 break;
13661 case OPC_ADDU_QB_DSP:
13662 op2 = MASK_ADDU_QB(ctx->opcode);
13663 switch (op2) {
13664 case OPC_ADDQ_PH:
13665 case OPC_ADDQ_S_PH:
13666 case OPC_ADDQ_S_W:
13667 case OPC_ADDU_QB:
13668 case OPC_ADDU_S_QB:
13669 case OPC_ADDU_PH:
13670 case OPC_ADDU_S_PH:
13671 case OPC_SUBQ_PH:
13672 case OPC_SUBQ_S_PH:
13673 case OPC_SUBQ_S_W:
13674 case OPC_SUBU_QB:
13675 case OPC_SUBU_S_QB:
13676 case OPC_SUBU_PH:
13677 case OPC_SUBU_S_PH:
13678 case OPC_ADDSC:
13679 case OPC_ADDWC:
13680 case OPC_MODSUB:
13681 case OPC_RADDU_W_QB:
13682 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13683 break;
13684 case OPC_MULEU_S_PH_QBL:
13685 case OPC_MULEU_S_PH_QBR:
13686 case OPC_MULQ_RS_PH:
13687 case OPC_MULEQ_S_W_PHL:
13688 case OPC_MULEQ_S_W_PHR:
13689 case OPC_MULQ_S_PH:
13690 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
13691 break;
13692 default: /* Invalid */
13693 MIPS_INVAL("MASK ADDU.QB");
13694 gen_reserved_instruction(ctx);
13695 break;
13696
13697 }
13698 break;
13699 case OPC_CMPU_EQ_QB_DSP:
13700 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
13701 switch (op2) {
13702 case OPC_PRECR_SRA_PH_W:
13703 case OPC_PRECR_SRA_R_PH_W:
13704 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
13705 break;
13706 case OPC_PRECR_QB_PH:
13707 case OPC_PRECRQ_QB_PH:
13708 case OPC_PRECRQ_PH_W:
13709 case OPC_PRECRQ_RS_PH_W:
13710 case OPC_PRECRQU_S_QB_PH:
13711 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13712 break;
13713 case OPC_CMPU_EQ_QB:
13714 case OPC_CMPU_LT_QB:
13715 case OPC_CMPU_LE_QB:
13716 case OPC_CMP_EQ_PH:
13717 case OPC_CMP_LT_PH:
13718 case OPC_CMP_LE_PH:
13719 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
13720 break;
13721 case OPC_CMPGU_EQ_QB:
13722 case OPC_CMPGU_LT_QB:
13723 case OPC_CMPGU_LE_QB:
13724 case OPC_CMPGDU_EQ_QB:
13725 case OPC_CMPGDU_LT_QB:
13726 case OPC_CMPGDU_LE_QB:
13727 case OPC_PICK_QB:
13728 case OPC_PICK_PH:
13729 case OPC_PACKRL_PH:
13730 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
13731 break;
13732 default: /* Invalid */
13733 MIPS_INVAL("MASK CMPU.EQ.QB");
13734 gen_reserved_instruction(ctx);
13735 break;
13736 }
13737 break;
13738 case OPC_SHLL_QB_DSP:
13739 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
13740 break;
13741 case OPC_DPA_W_PH_DSP:
13742 op2 = MASK_DPA_W_PH(ctx->opcode);
13743 switch (op2) {
13744 case OPC_DPAU_H_QBL:
13745 case OPC_DPAU_H_QBR:
13746 case OPC_DPSU_H_QBL:
13747 case OPC_DPSU_H_QBR:
13748 case OPC_DPA_W_PH:
13749 case OPC_DPAX_W_PH:
13750 case OPC_DPAQ_S_W_PH:
13751 case OPC_DPAQX_S_W_PH:
13752 case OPC_DPAQX_SA_W_PH:
13753 case OPC_DPS_W_PH:
13754 case OPC_DPSX_W_PH:
13755 case OPC_DPSQ_S_W_PH:
13756 case OPC_DPSQX_S_W_PH:
13757 case OPC_DPSQX_SA_W_PH:
13758 case OPC_MULSAQ_S_W_PH:
13759 case OPC_DPAQ_SA_L_W:
13760 case OPC_DPSQ_SA_L_W:
13761 case OPC_MAQ_S_W_PHL:
13762 case OPC_MAQ_S_W_PHR:
13763 case OPC_MAQ_SA_W_PHL:
13764 case OPC_MAQ_SA_W_PHR:
13765 case OPC_MULSA_W_PH:
13766 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
13767 break;
13768 default: /* Invalid */
13769 MIPS_INVAL("MASK DPAW.PH");
13770 gen_reserved_instruction(ctx);
13771 break;
13772 }
13773 break;
13774 case OPC_INSV_DSP:
13775 op2 = MASK_INSV(ctx->opcode);
13776 switch (op2) {
13777 case OPC_INSV:
13778 check_dsp(ctx);
13779 {
13780 TCGv t0, t1;
13781
13782 if (rt == 0) {
13783 break;
13784 }
13785
13786 t0 = tcg_temp_new();
13787 t1 = tcg_temp_new();
13788
13789 gen_load_gpr(t0, rt);
13790 gen_load_gpr(t1, rs);
13791
13792 gen_helper_insv(cpu_gpr[rt], tcg_env, t1, t0);
13793 break;
13794 }
13795 default: /* Invalid */
13796 MIPS_INVAL("MASK INSV");
13797 gen_reserved_instruction(ctx);
13798 break;
13799 }
13800 break;
13801 case OPC_APPEND_DSP:
13802 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
13803 break;
13804 case OPC_EXTR_W_DSP:
13805 op2 = MASK_EXTR_W(ctx->opcode);
13806 switch (op2) {
13807 case OPC_EXTR_W:
13808 case OPC_EXTR_R_W:
13809 case OPC_EXTR_RS_W:
13810 case OPC_EXTR_S_H:
13811 case OPC_EXTRV_S_H:
13812 case OPC_EXTRV_W:
13813 case OPC_EXTRV_R_W:
13814 case OPC_EXTRV_RS_W:
13815 case OPC_EXTP:
13816 case OPC_EXTPV:
13817 case OPC_EXTPDP:
13818 case OPC_EXTPDPV:
13819 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
13820 break;
13821 case OPC_RDDSP:
13822 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
13823 break;
13824 case OPC_SHILO:
13825 case OPC_SHILOV:
13826 case OPC_MTHLIP:
13827 case OPC_WRDSP:
13828 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
13829 break;
13830 default: /* Invalid */
13831 MIPS_INVAL("MASK EXTR.W");
13832 gen_reserved_instruction(ctx);
13833 break;
13834 }
13835 break;
13836 #if defined(TARGET_MIPS64)
13837 case OPC_ABSQ_S_QH_DSP:
13838 op2 = MASK_ABSQ_S_QH(ctx->opcode);
13839 switch (op2) {
13840 case OPC_PRECEQ_L_PWL:
13841 case OPC_PRECEQ_L_PWR:
13842 case OPC_PRECEQ_PW_QHL:
13843 case OPC_PRECEQ_PW_QHR:
13844 case OPC_PRECEQ_PW_QHLA:
13845 case OPC_PRECEQ_PW_QHRA:
13846 case OPC_PRECEQU_QH_OBL:
13847 case OPC_PRECEQU_QH_OBR:
13848 case OPC_PRECEQU_QH_OBLA:
13849 case OPC_PRECEQU_QH_OBRA:
13850 case OPC_PRECEU_QH_OBL:
13851 case OPC_PRECEU_QH_OBR:
13852 case OPC_PRECEU_QH_OBLA:
13853 case OPC_PRECEU_QH_OBRA:
13854 case OPC_ABSQ_S_OB:
13855 case OPC_ABSQ_S_PW:
13856 case OPC_ABSQ_S_QH:
13857 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13858 break;
13859 case OPC_REPL_OB:
13860 case OPC_REPL_PW:
13861 case OPC_REPL_QH:
13862 case OPC_REPLV_OB:
13863 case OPC_REPLV_PW:
13864 case OPC_REPLV_QH:
13865 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
13866 break;
13867 default: /* Invalid */
13868 MIPS_INVAL("MASK ABSQ_S.QH");
13869 gen_reserved_instruction(ctx);
13870 break;
13871 }
13872 break;
13873 case OPC_ADDU_OB_DSP:
13874 op2 = MASK_ADDU_OB(ctx->opcode);
13875 switch (op2) {
13876 case OPC_RADDU_L_OB:
13877 case OPC_SUBQ_PW:
13878 case OPC_SUBQ_S_PW:
13879 case OPC_SUBQ_QH:
13880 case OPC_SUBQ_S_QH:
13881 case OPC_SUBU_OB:
13882 case OPC_SUBU_S_OB:
13883 case OPC_SUBU_QH:
13884 case OPC_SUBU_S_QH:
13885 case OPC_SUBUH_OB:
13886 case OPC_SUBUH_R_OB:
13887 case OPC_ADDQ_PW:
13888 case OPC_ADDQ_S_PW:
13889 case OPC_ADDQ_QH:
13890 case OPC_ADDQ_S_QH:
13891 case OPC_ADDU_OB:
13892 case OPC_ADDU_S_OB:
13893 case OPC_ADDU_QH:
13894 case OPC_ADDU_S_QH:
13895 case OPC_ADDUH_OB:
13896 case OPC_ADDUH_R_OB:
13897 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13898 break;
13899 case OPC_MULEQ_S_PW_QHL:
13900 case OPC_MULEQ_S_PW_QHR:
13901 case OPC_MULEU_S_QH_OBL:
13902 case OPC_MULEU_S_QH_OBR:
13903 case OPC_MULQ_RS_QH:
13904 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
13905 break;
13906 default: /* Invalid */
13907 MIPS_INVAL("MASK ADDU.OB");
13908 gen_reserved_instruction(ctx);
13909 break;
13910 }
13911 break;
13912 case OPC_CMPU_EQ_OB_DSP:
13913 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
13914 switch (op2) {
13915 case OPC_PRECR_SRA_QH_PW:
13916 case OPC_PRECR_SRA_R_QH_PW:
13917 /* Return value is rt. */
13918 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
13919 break;
13920 case OPC_PRECR_OB_QH:
13921 case OPC_PRECRQ_OB_QH:
13922 case OPC_PRECRQ_PW_L:
13923 case OPC_PRECRQ_QH_PW:
13924 case OPC_PRECRQ_RS_QH_PW:
13925 case OPC_PRECRQU_S_OB_QH:
13926 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13927 break;
13928 case OPC_CMPU_EQ_OB:
13929 case OPC_CMPU_LT_OB:
13930 case OPC_CMPU_LE_OB:
13931 case OPC_CMP_EQ_QH:
13932 case OPC_CMP_LT_QH:
13933 case OPC_CMP_LE_QH:
13934 case OPC_CMP_EQ_PW:
13935 case OPC_CMP_LT_PW:
13936 case OPC_CMP_LE_PW:
13937 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
13938 break;
13939 case OPC_CMPGDU_EQ_OB:
13940 case OPC_CMPGDU_LT_OB:
13941 case OPC_CMPGDU_LE_OB:
13942 case OPC_CMPGU_EQ_OB:
13943 case OPC_CMPGU_LT_OB:
13944 case OPC_CMPGU_LE_OB:
13945 case OPC_PACKRL_PW:
13946 case OPC_PICK_OB:
13947 case OPC_PICK_PW:
13948 case OPC_PICK_QH:
13949 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
13950 break;
13951 default: /* Invalid */
13952 MIPS_INVAL("MASK CMPU_EQ.OB");
13953 gen_reserved_instruction(ctx);
13954 break;
13955 }
13956 break;
13957 case OPC_DAPPEND_DSP:
13958 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
13959 break;
13960 case OPC_DEXTR_W_DSP:
13961 op2 = MASK_DEXTR_W(ctx->opcode);
13962 switch (op2) {
13963 case OPC_DEXTP:
13964 case OPC_DEXTPDP:
13965 case OPC_DEXTPDPV:
13966 case OPC_DEXTPV:
13967 case OPC_DEXTR_L:
13968 case OPC_DEXTR_R_L:
13969 case OPC_DEXTR_RS_L:
13970 case OPC_DEXTR_W:
13971 case OPC_DEXTR_R_W:
13972 case OPC_DEXTR_RS_W:
13973 case OPC_DEXTR_S_H:
13974 case OPC_DEXTRV_L:
13975 case OPC_DEXTRV_R_L:
13976 case OPC_DEXTRV_RS_L:
13977 case OPC_DEXTRV_S_H:
13978 case OPC_DEXTRV_W:
13979 case OPC_DEXTRV_R_W:
13980 case OPC_DEXTRV_RS_W:
13981 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
13982 break;
13983 case OPC_DMTHLIP:
13984 case OPC_DSHILO:
13985 case OPC_DSHILOV:
13986 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
13987 break;
13988 default: /* Invalid */
13989 MIPS_INVAL("MASK EXTR.W");
13990 gen_reserved_instruction(ctx);
13991 break;
13992 }
13993 break;
13994 case OPC_DPAQ_W_QH_DSP:
13995 op2 = MASK_DPAQ_W_QH(ctx->opcode);
13996 switch (op2) {
13997 case OPC_DPAU_H_OBL:
13998 case OPC_DPAU_H_OBR:
13999 case OPC_DPSU_H_OBL:
14000 case OPC_DPSU_H_OBR:
14001 case OPC_DPA_W_QH:
14002 case OPC_DPAQ_S_W_QH:
14003 case OPC_DPS_W_QH:
14004 case OPC_DPSQ_S_W_QH:
14005 case OPC_MULSAQ_S_W_QH:
14006 case OPC_DPAQ_SA_L_PW:
14007 case OPC_DPSQ_SA_L_PW:
14008 case OPC_MULSAQ_S_L_PW:
14009 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14010 break;
14011 case OPC_MAQ_S_W_QHLL:
14012 case OPC_MAQ_S_W_QHLR:
14013 case OPC_MAQ_S_W_QHRL:
14014 case OPC_MAQ_S_W_QHRR:
14015 case OPC_MAQ_SA_W_QHLL:
14016 case OPC_MAQ_SA_W_QHLR:
14017 case OPC_MAQ_SA_W_QHRL:
14018 case OPC_MAQ_SA_W_QHRR:
14019 case OPC_MAQ_S_L_PWL:
14020 case OPC_MAQ_S_L_PWR:
14021 case OPC_DMADD:
14022 case OPC_DMADDU:
14023 case OPC_DMSUB:
14024 case OPC_DMSUBU:
14025 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14026 break;
14027 default: /* Invalid */
14028 MIPS_INVAL("MASK DPAQ.W.QH");
14029 gen_reserved_instruction(ctx);
14030 break;
14031 }
14032 break;
14033 case OPC_DINSV_DSP:
14034 op2 = MASK_INSV(ctx->opcode);
14035 switch (op2) {
14036 case OPC_DINSV:
14037 {
14038 TCGv t0, t1;
14039
14040 check_dsp(ctx);
14041
14042 if (rt == 0) {
14043 break;
14044 }
14045
14046 t0 = tcg_temp_new();
14047 t1 = tcg_temp_new();
14048
14049 gen_load_gpr(t0, rt);
14050 gen_load_gpr(t1, rs);
14051
14052 gen_helper_dinsv(cpu_gpr[rt], tcg_env, t1, t0);
14053 break;
14054 }
14055 default: /* Invalid */
14056 MIPS_INVAL("MASK DINSV");
14057 gen_reserved_instruction(ctx);
14058 break;
14059 }
14060 break;
14061 case OPC_SHLL_OB_DSP:
14062 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14063 break;
14064 #endif
14065 default: /* Invalid */
14066 MIPS_INVAL("special3_legacy");
14067 gen_reserved_instruction(ctx);
14068 break;
14069 }
14070 }
14071
14072
14073 #if defined(TARGET_MIPS64)
14074
decode_mmi(CPUMIPSState * env,DisasContext * ctx)14075 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
14076 {
14077 uint32_t opc = MASK_MMI(ctx->opcode);
14078 int rs = extract32(ctx->opcode, 21, 5);
14079 int rt = extract32(ctx->opcode, 16, 5);
14080 int rd = extract32(ctx->opcode, 11, 5);
14081
14082 switch (opc) {
14083 case MMI_OPC_MULT1:
14084 case MMI_OPC_MULTU1:
14085 case MMI_OPC_MADD:
14086 case MMI_OPC_MADDU:
14087 case MMI_OPC_MADD1:
14088 case MMI_OPC_MADDU1:
14089 gen_mul_txx9(ctx, opc, rd, rs, rt);
14090 break;
14091 case MMI_OPC_DIV1:
14092 case MMI_OPC_DIVU1:
14093 gen_div1_tx79(ctx, opc, rs, rt);
14094 break;
14095 default:
14096 MIPS_INVAL("TX79 MMI class");
14097 gen_reserved_instruction(ctx);
14098 break;
14099 }
14100 }
14101
gen_mmi_sq(DisasContext * ctx,int base,int rt,int offset)14102 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
14103 {
14104 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
14105 }
14106
14107 /*
14108 * The TX79-specific instruction Store Quadword
14109 *
14110 * +--------+-------+-------+------------------------+
14111 * | 011111 | base | rt | offset | SQ
14112 * +--------+-------+-------+------------------------+
14113 * 6 5 5 16
14114 *
14115 * has the same opcode as the Read Hardware Register instruction
14116 *
14117 * +--------+-------+-------+-------+-------+--------+
14118 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
14119 * +--------+-------+-------+-------+-------+--------+
14120 * 6 5 5 5 5 6
14121 *
14122 * that is required, trapped and emulated by the Linux kernel. However, all
14123 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
14124 * offset is odd. Therefore all valid SQ instructions can execute normally.
14125 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
14126 * between SQ and RDHWR, as the Linux kernel does.
14127 */
decode_mmi_sq(CPUMIPSState * env,DisasContext * ctx)14128 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
14129 {
14130 int base = extract32(ctx->opcode, 21, 5);
14131 int rt = extract32(ctx->opcode, 16, 5);
14132 int offset = extract32(ctx->opcode, 0, 16);
14133
14134 #ifdef CONFIG_USER_ONLY
14135 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
14136 uint32_t op2 = extract32(ctx->opcode, 6, 5);
14137
14138 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
14139 int rd = extract32(ctx->opcode, 11, 5);
14140
14141 gen_rdhwr(ctx, rt, rd, 0);
14142 return;
14143 }
14144 #endif
14145
14146 gen_mmi_sq(ctx, base, rt, offset);
14147 }
14148
14149 #endif
14150
decode_opc_special3(CPUMIPSState * env,DisasContext * ctx)14151 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
14152 {
14153 int rs, rt, rd, sa;
14154 uint32_t op1, op2;
14155 int16_t imm;
14156
14157 rs = (ctx->opcode >> 21) & 0x1f;
14158 rt = (ctx->opcode >> 16) & 0x1f;
14159 rd = (ctx->opcode >> 11) & 0x1f;
14160 sa = (ctx->opcode >> 6) & 0x1f;
14161 imm = sextract32(ctx->opcode, 7, 9);
14162
14163 op1 = MASK_SPECIAL3(ctx->opcode);
14164
14165 /*
14166 * EVA loads and stores overlap Loongson 2E instructions decoded by
14167 * decode_opc_special3_legacy(), so be careful to allow their decoding when
14168 * EVA is absent.
14169 */
14170 if (ctx->eva) {
14171 switch (op1) {
14172 case OPC_LWLE:
14173 case OPC_LWRE:
14174 case OPC_LBUE:
14175 case OPC_LHUE:
14176 case OPC_LBE:
14177 case OPC_LHE:
14178 case OPC_LLE:
14179 case OPC_LWE:
14180 check_cp0_enabled(ctx);
14181 gen_ld(ctx, op1, rt, rs, imm);
14182 return;
14183 case OPC_SWLE:
14184 case OPC_SWRE:
14185 case OPC_SBE:
14186 case OPC_SHE:
14187 case OPC_SWE:
14188 check_cp0_enabled(ctx);
14189 gen_st(ctx, op1, rt, rs, imm);
14190 return;
14191 case OPC_SCE:
14192 check_cp0_enabled(ctx);
14193 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, true);
14194 return;
14195 case OPC_CACHEE:
14196 check_eva(ctx);
14197 check_cp0_enabled(ctx);
14198 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14199 gen_cache_operation(ctx, rt, rs, imm);
14200 }
14201 return;
14202 case OPC_PREFE:
14203 check_cp0_enabled(ctx);
14204 /* Treat as NOP. */
14205 return;
14206 }
14207 }
14208
14209 switch (op1) {
14210 case OPC_EXT:
14211 case OPC_INS:
14212 check_insn(ctx, ISA_MIPS_R2);
14213 gen_bitops(ctx, op1, rt, rs, sa, rd);
14214 break;
14215 case OPC_BSHFL:
14216 op2 = MASK_BSHFL(ctx->opcode);
14217 switch (op2) {
14218 case OPC_ALIGN:
14219 case OPC_ALIGN_1:
14220 case OPC_ALIGN_2:
14221 case OPC_ALIGN_3:
14222 case OPC_BITSWAP:
14223 check_insn(ctx, ISA_MIPS_R6);
14224 decode_opc_special3_r6(env, ctx);
14225 break;
14226 default:
14227 check_insn(ctx, ISA_MIPS_R2);
14228 gen_bshfl(ctx, op2, rt, rd);
14229 break;
14230 }
14231 break;
14232 #if defined(TARGET_MIPS64)
14233 case OPC_DEXTM:
14234 case OPC_DEXTU:
14235 case OPC_DEXT:
14236 case OPC_DINSM:
14237 case OPC_DINSU:
14238 case OPC_DINS:
14239 check_insn(ctx, ISA_MIPS_R2);
14240 check_mips_64(ctx);
14241 gen_bitops(ctx, op1, rt, rs, sa, rd);
14242 break;
14243 case OPC_DBSHFL:
14244 op2 = MASK_DBSHFL(ctx->opcode);
14245 switch (op2) {
14246 case OPC_DALIGN:
14247 case OPC_DALIGN_1:
14248 case OPC_DALIGN_2:
14249 case OPC_DALIGN_3:
14250 case OPC_DALIGN_4:
14251 case OPC_DALIGN_5:
14252 case OPC_DALIGN_6:
14253 case OPC_DALIGN_7:
14254 case OPC_DBITSWAP:
14255 check_insn(ctx, ISA_MIPS_R6);
14256 decode_opc_special3_r6(env, ctx);
14257 break;
14258 default:
14259 check_insn(ctx, ISA_MIPS_R2);
14260 check_mips_64(ctx);
14261 op2 = MASK_DBSHFL(ctx->opcode);
14262 gen_bshfl(ctx, op2, rt, rd);
14263 break;
14264 }
14265 break;
14266 #endif
14267 case OPC_RDHWR:
14268 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
14269 break;
14270 case OPC_FORK:
14271 check_mt(ctx);
14272 {
14273 TCGv t0 = tcg_temp_new();
14274 TCGv t1 = tcg_temp_new();
14275
14276 gen_load_gpr(t0, rt);
14277 gen_load_gpr(t1, rs);
14278 gen_helper_fork(t0, t1);
14279 }
14280 break;
14281 case OPC_YIELD:
14282 check_mt(ctx);
14283 {
14284 TCGv t0 = tcg_temp_new();
14285
14286 gen_load_gpr(t0, rs);
14287 gen_helper_yield(t0, tcg_env, t0);
14288 gen_store_gpr(t0, rd);
14289 }
14290 break;
14291 default:
14292 if (ctx->insn_flags & ISA_MIPS_R6) {
14293 decode_opc_special3_r6(env, ctx);
14294 } else {
14295 decode_opc_special3_legacy(env, ctx);
14296 }
14297 }
14298 }
14299
decode_opc_legacy(CPUMIPSState * env,DisasContext * ctx)14300 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
14301 {
14302 int32_t offset;
14303 int rs, rt, rd, sa;
14304 uint32_t op, op1;
14305 int16_t imm;
14306
14307 op = MASK_OP_MAJOR(ctx->opcode);
14308 rs = (ctx->opcode >> 21) & 0x1f;
14309 rt = (ctx->opcode >> 16) & 0x1f;
14310 rd = (ctx->opcode >> 11) & 0x1f;
14311 sa = (ctx->opcode >> 6) & 0x1f;
14312 imm = (int16_t)ctx->opcode;
14313 switch (op) {
14314 case OPC_SPECIAL:
14315 decode_opc_special(env, ctx);
14316 break;
14317 case OPC_SPECIAL2:
14318 #if defined(TARGET_MIPS64)
14319 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
14320 decode_mmi(env, ctx);
14321 break;
14322 }
14323 #endif
14324 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
14325 if (decode_ase_mxu(ctx, ctx->opcode)) {
14326 break;
14327 }
14328 }
14329 decode_opc_special2_legacy(env, ctx);
14330 break;
14331 case OPC_SPECIAL3:
14332 #if defined(TARGET_MIPS64)
14333 if (ctx->insn_flags & INSN_R5900) {
14334 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
14335 } else {
14336 decode_opc_special3(env, ctx);
14337 }
14338 #else
14339 decode_opc_special3(env, ctx);
14340 #endif
14341 break;
14342 case OPC_REGIMM:
14343 op1 = MASK_REGIMM(ctx->opcode);
14344 switch (op1) {
14345 case OPC_BLTZL: /* REGIMM branches */
14346 case OPC_BGEZL:
14347 case OPC_BLTZALL:
14348 case OPC_BGEZALL:
14349 check_insn(ctx, ISA_MIPS2);
14350 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14351 /* Fallthrough */
14352 case OPC_BLTZ:
14353 case OPC_BGEZ:
14354 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
14355 break;
14356 case OPC_BLTZAL:
14357 case OPC_BGEZAL:
14358 if (ctx->insn_flags & ISA_MIPS_R6) {
14359 if (rs == 0) {
14360 /* OPC_NAL, OPC_BAL */
14361 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
14362 } else {
14363 gen_reserved_instruction(ctx);
14364 }
14365 } else {
14366 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
14367 }
14368 break;
14369 case OPC_TGEI: /* REGIMM traps */
14370 case OPC_TGEIU:
14371 case OPC_TLTI:
14372 case OPC_TLTIU:
14373 case OPC_TEQI:
14374 case OPC_TNEI:
14375 check_insn(ctx, ISA_MIPS2);
14376 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14377 gen_trap(ctx, op1, rs, -1, imm, 0);
14378 break;
14379 case OPC_SIGRIE:
14380 check_insn(ctx, ISA_MIPS_R6);
14381 gen_reserved_instruction(ctx);
14382 break;
14383 case OPC_SYNCI:
14384 check_insn(ctx, ISA_MIPS_R2);
14385 /*
14386 * Break the TB to be able to sync copied instructions
14387 * immediately.
14388 */
14389 ctx->base.is_jmp = DISAS_STOP;
14390 break;
14391 case OPC_BPOSGE32: /* MIPS DSP branch */
14392 #if defined(TARGET_MIPS64)
14393 case OPC_BPOSGE64:
14394 #endif
14395 check_dsp(ctx);
14396 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
14397 break;
14398 #if defined(TARGET_MIPS64)
14399 case OPC_DAHI:
14400 check_insn(ctx, ISA_MIPS_R6);
14401 check_mips_64(ctx);
14402 if (rs != 0) {
14403 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
14404 }
14405 break;
14406 case OPC_DATI:
14407 check_insn(ctx, ISA_MIPS_R6);
14408 check_mips_64(ctx);
14409 if (rs != 0) {
14410 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
14411 }
14412 break;
14413 #endif
14414 default: /* Invalid */
14415 MIPS_INVAL("regimm");
14416 gen_reserved_instruction(ctx);
14417 break;
14418 }
14419 break;
14420 case OPC_CP0:
14421 check_cp0_enabled(ctx);
14422 op1 = MASK_CP0(ctx->opcode);
14423 switch (op1) {
14424 case OPC_MFC0:
14425 case OPC_MTC0:
14426 case OPC_MFTR:
14427 case OPC_MTTR:
14428 case OPC_MFHC0:
14429 case OPC_MTHC0:
14430 #if defined(TARGET_MIPS64)
14431 case OPC_DMFC0:
14432 case OPC_DMTC0:
14433 #endif
14434 #ifndef CONFIG_USER_ONLY
14435 gen_cp0(env, ctx, op1, rt, rd);
14436 #endif /* !CONFIG_USER_ONLY */
14437 break;
14438 case OPC_C0:
14439 case OPC_C0_1:
14440 case OPC_C0_2:
14441 case OPC_C0_3:
14442 case OPC_C0_4:
14443 case OPC_C0_5:
14444 case OPC_C0_6:
14445 case OPC_C0_7:
14446 case OPC_C0_8:
14447 case OPC_C0_9:
14448 case OPC_C0_A:
14449 case OPC_C0_B:
14450 case OPC_C0_C:
14451 case OPC_C0_D:
14452 case OPC_C0_E:
14453 case OPC_C0_F:
14454 #ifndef CONFIG_USER_ONLY
14455 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
14456 #endif /* !CONFIG_USER_ONLY */
14457 break;
14458 case OPC_MFMC0:
14459 #ifndef CONFIG_USER_ONLY
14460 {
14461 uint32_t op2;
14462 TCGv t0 = tcg_temp_new();
14463
14464 op2 = MASK_MFMC0(ctx->opcode);
14465 switch (op2) {
14466 case OPC_DMT:
14467 check_cp0_mt(ctx);
14468 gen_helper_dmt(t0);
14469 gen_store_gpr(t0, rt);
14470 break;
14471 case OPC_EMT:
14472 check_cp0_mt(ctx);
14473 gen_helper_emt(t0);
14474 gen_store_gpr(t0, rt);
14475 break;
14476 case OPC_DVPE:
14477 check_cp0_mt(ctx);
14478 gen_helper_dvpe(t0, tcg_env);
14479 gen_store_gpr(t0, rt);
14480 break;
14481 case OPC_EVPE:
14482 check_cp0_mt(ctx);
14483 gen_helper_evpe(t0, tcg_env);
14484 gen_store_gpr(t0, rt);
14485 break;
14486 case OPC_DVP:
14487 check_insn(ctx, ISA_MIPS_R6);
14488 if (ctx->vp) {
14489 gen_helper_dvp(t0, tcg_env);
14490 gen_store_gpr(t0, rt);
14491 }
14492 break;
14493 case OPC_EVP:
14494 check_insn(ctx, ISA_MIPS_R6);
14495 if (ctx->vp) {
14496 gen_helper_evp(t0, tcg_env);
14497 gen_store_gpr(t0, rt);
14498 }
14499 break;
14500 case OPC_DI:
14501 check_insn(ctx, ISA_MIPS_R2);
14502 save_cpu_state(ctx, 1);
14503 gen_helper_di(t0, tcg_env);
14504 gen_store_gpr(t0, rt);
14505 /*
14506 * Stop translation as we may have switched
14507 * the execution mode.
14508 */
14509 ctx->base.is_jmp = DISAS_STOP;
14510 break;
14511 case OPC_EI:
14512 check_insn(ctx, ISA_MIPS_R2);
14513 save_cpu_state(ctx, 1);
14514 gen_helper_ei(t0, tcg_env);
14515 gen_store_gpr(t0, rt);
14516 /*
14517 * DISAS_STOP isn't sufficient, we need to ensure we break
14518 * out of translated code to check for pending interrupts.
14519 */
14520 gen_save_pc(ctx->base.pc_next + 4);
14521 ctx->base.is_jmp = DISAS_EXIT;
14522 break;
14523 default: /* Invalid */
14524 MIPS_INVAL("mfmc0");
14525 gen_reserved_instruction(ctx);
14526 break;
14527 }
14528 }
14529 #endif /* !CONFIG_USER_ONLY */
14530 break;
14531 case OPC_RDPGPR:
14532 check_insn(ctx, ISA_MIPS_R2);
14533 gen_load_srsgpr(rt, rd);
14534 break;
14535 case OPC_WRPGPR:
14536 check_insn(ctx, ISA_MIPS_R2);
14537 gen_store_srsgpr(rt, rd);
14538 break;
14539 default:
14540 MIPS_INVAL("cp0");
14541 gen_reserved_instruction(ctx);
14542 break;
14543 }
14544 break;
14545 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
14546 if (ctx->insn_flags & ISA_MIPS_R6) {
14547 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
14548 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14549 } else {
14550 /* OPC_ADDI */
14551 /* Arithmetic with immediate opcode */
14552 gen_arith_imm(ctx, op, rt, rs, imm);
14553 }
14554 break;
14555 case OPC_ADDIU:
14556 gen_arith_imm(ctx, op, rt, rs, imm);
14557 break;
14558 case OPC_SLTI: /* Set on less than with immediate opcode */
14559 case OPC_SLTIU:
14560 gen_slt_imm(ctx, op, rt, rs, imm);
14561 break;
14562 case OPC_ANDI: /* Arithmetic with immediate opcode */
14563 case OPC_LUI: /* OPC_AUI */
14564 case OPC_ORI:
14565 case OPC_XORI:
14566 gen_logic_imm(ctx, op, rt, rs, imm);
14567 break;
14568 case OPC_J: /* Jump */
14569 case OPC_JAL:
14570 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14571 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
14572 break;
14573 /* Branch */
14574 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
14575 if (ctx->insn_flags & ISA_MIPS_R6) {
14576 if (rt == 0) {
14577 gen_reserved_instruction(ctx);
14578 break;
14579 }
14580 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
14581 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14582 } else {
14583 /* OPC_BLEZL */
14584 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14585 }
14586 break;
14587 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
14588 if (ctx->insn_flags & ISA_MIPS_R6) {
14589 if (rt == 0) {
14590 gen_reserved_instruction(ctx);
14591 break;
14592 }
14593 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
14594 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14595 } else {
14596 /* OPC_BGTZL */
14597 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14598 }
14599 break;
14600 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
14601 if (rt == 0) {
14602 /* OPC_BLEZ */
14603 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14604 } else {
14605 check_insn(ctx, ISA_MIPS_R6);
14606 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
14607 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14608 }
14609 break;
14610 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
14611 if (rt == 0) {
14612 /* OPC_BGTZ */
14613 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14614 } else {
14615 check_insn(ctx, ISA_MIPS_R6);
14616 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
14617 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14618 }
14619 break;
14620 case OPC_BEQL:
14621 case OPC_BNEL:
14622 check_insn(ctx, ISA_MIPS2);
14623 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14624 /* Fallthrough */
14625 case OPC_BEQ:
14626 case OPC_BNE:
14627 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14628 break;
14629 case OPC_LL: /* Load and stores */
14630 check_insn(ctx, ISA_MIPS2);
14631 if (ctx->insn_flags & INSN_R5900) {
14632 check_insn_opc_user_only(ctx, INSN_R5900);
14633 }
14634 /* Fallthrough */
14635 case OPC_LWL:
14636 case OPC_LWR:
14637 case OPC_LB:
14638 case OPC_LH:
14639 case OPC_LW:
14640 case OPC_LWPC:
14641 case OPC_LBU:
14642 case OPC_LHU:
14643 gen_ld(ctx, op, rt, rs, imm);
14644 break;
14645 case OPC_SWL:
14646 case OPC_SWR:
14647 case OPC_SB:
14648 case OPC_SH:
14649 case OPC_SW:
14650 gen_st(ctx, op, rt, rs, imm);
14651 break;
14652 case OPC_SC:
14653 check_insn(ctx, ISA_MIPS2);
14654 if (ctx->insn_flags & INSN_R5900) {
14655 check_insn_opc_user_only(ctx, INSN_R5900);
14656 }
14657 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, false);
14658 break;
14659 case OPC_CACHE:
14660 check_cp0_enabled(ctx);
14661 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
14662 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14663 gen_cache_operation(ctx, rt, rs, imm);
14664 }
14665 /* Treat as NOP. */
14666 break;
14667 case OPC_PREF:
14668 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 | INSN_R5900);
14669 /* Treat as NOP. */
14670 break;
14671
14672 /* Floating point (COP1). */
14673 case OPC_LWC1:
14674 case OPC_LDC1:
14675 case OPC_SWC1:
14676 case OPC_SDC1:
14677 gen_cop1_ldst(ctx, op, rt, rs, imm);
14678 break;
14679
14680 case OPC_CP1:
14681 op1 = MASK_CP1(ctx->opcode);
14682
14683 switch (op1) {
14684 case OPC_MFHC1:
14685 case OPC_MTHC1:
14686 check_cp1_enabled(ctx);
14687 check_insn(ctx, ISA_MIPS_R2);
14688 /* fall through */
14689 case OPC_MFC1:
14690 case OPC_CFC1:
14691 case OPC_MTC1:
14692 case OPC_CTC1:
14693 check_cp1_enabled(ctx);
14694 gen_cp1(ctx, op1, rt, rd);
14695 break;
14696 #if defined(TARGET_MIPS64)
14697 case OPC_DMFC1:
14698 case OPC_DMTC1:
14699 check_cp1_enabled(ctx);
14700 check_insn(ctx, ISA_MIPS3);
14701 check_mips_64(ctx);
14702 gen_cp1(ctx, op1, rt, rd);
14703 break;
14704 #endif
14705 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
14706 check_cp1_enabled(ctx);
14707 if (ctx->insn_flags & ISA_MIPS_R6) {
14708 /* OPC_BC1EQZ */
14709 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
14710 rt, imm << 2, 4);
14711 } else {
14712 /* OPC_BC1ANY2 */
14713 check_cop1x(ctx);
14714 if (!ase_3d_available(env)) {
14715 return false;
14716 }
14717 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
14718 (rt >> 2) & 0x7, imm << 2);
14719 }
14720 break;
14721 case OPC_BC1NEZ:
14722 check_cp1_enabled(ctx);
14723 check_insn(ctx, ISA_MIPS_R6);
14724 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
14725 rt, imm << 2, 4);
14726 break;
14727 case OPC_BC1ANY4:
14728 check_cp1_enabled(ctx);
14729 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14730 check_cop1x(ctx);
14731 if (!ase_3d_available(env)) {
14732 return false;
14733 }
14734 /* fall through */
14735 case OPC_BC1:
14736 check_cp1_enabled(ctx);
14737 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14738 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
14739 (rt >> 2) & 0x7, imm << 2);
14740 break;
14741 case OPC_PS_FMT:
14742 check_ps(ctx);
14743 /* fall through */
14744 case OPC_S_FMT:
14745 case OPC_D_FMT:
14746 check_cp1_enabled(ctx);
14747 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
14748 (imm >> 8) & 0x7);
14749 break;
14750 case OPC_W_FMT:
14751 case OPC_L_FMT:
14752 {
14753 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
14754 check_cp1_enabled(ctx);
14755 if (ctx->insn_flags & ISA_MIPS_R6) {
14756 switch (r6_op) {
14757 case R6_OPC_CMP_AF_S:
14758 case R6_OPC_CMP_UN_S:
14759 case R6_OPC_CMP_EQ_S:
14760 case R6_OPC_CMP_UEQ_S:
14761 case R6_OPC_CMP_LT_S:
14762 case R6_OPC_CMP_ULT_S:
14763 case R6_OPC_CMP_LE_S:
14764 case R6_OPC_CMP_ULE_S:
14765 case R6_OPC_CMP_SAF_S:
14766 case R6_OPC_CMP_SUN_S:
14767 case R6_OPC_CMP_SEQ_S:
14768 case R6_OPC_CMP_SEUQ_S:
14769 case R6_OPC_CMP_SLT_S:
14770 case R6_OPC_CMP_SULT_S:
14771 case R6_OPC_CMP_SLE_S:
14772 case R6_OPC_CMP_SULE_S:
14773 case R6_OPC_CMP_OR_S:
14774 case R6_OPC_CMP_UNE_S:
14775 case R6_OPC_CMP_NE_S:
14776 case R6_OPC_CMP_SOR_S:
14777 case R6_OPC_CMP_SUNE_S:
14778 case R6_OPC_CMP_SNE_S:
14779 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
14780 break;
14781 case R6_OPC_CMP_AF_D:
14782 case R6_OPC_CMP_UN_D:
14783 case R6_OPC_CMP_EQ_D:
14784 case R6_OPC_CMP_UEQ_D:
14785 case R6_OPC_CMP_LT_D:
14786 case R6_OPC_CMP_ULT_D:
14787 case R6_OPC_CMP_LE_D:
14788 case R6_OPC_CMP_ULE_D:
14789 case R6_OPC_CMP_SAF_D:
14790 case R6_OPC_CMP_SUN_D:
14791 case R6_OPC_CMP_SEQ_D:
14792 case R6_OPC_CMP_SEUQ_D:
14793 case R6_OPC_CMP_SLT_D:
14794 case R6_OPC_CMP_SULT_D:
14795 case R6_OPC_CMP_SLE_D:
14796 case R6_OPC_CMP_SULE_D:
14797 case R6_OPC_CMP_OR_D:
14798 case R6_OPC_CMP_UNE_D:
14799 case R6_OPC_CMP_NE_D:
14800 case R6_OPC_CMP_SOR_D:
14801 case R6_OPC_CMP_SUNE_D:
14802 case R6_OPC_CMP_SNE_D:
14803 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
14804 break;
14805 default:
14806 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
14807 rt, rd, sa, (imm >> 8) & 0x7);
14808
14809 break;
14810 }
14811 } else {
14812 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
14813 (imm >> 8) & 0x7);
14814 }
14815 break;
14816 }
14817 default:
14818 MIPS_INVAL("cp1");
14819 gen_reserved_instruction(ctx);
14820 break;
14821 }
14822 break;
14823
14824 /* Compact branches [R6] and COP2 [non-R6] */
14825 case OPC_BC: /* OPC_LWC2 */
14826 case OPC_BALC: /* OPC_SWC2 */
14827 if (ctx->insn_flags & ISA_MIPS_R6) {
14828 /* OPC_BC, OPC_BALC */
14829 gen_compute_compact_branch(ctx, op, 0, 0,
14830 sextract32(ctx->opcode << 2, 0, 28));
14831 } else if (ctx->insn_flags & ASE_LEXT) {
14832 gen_loongson_lswc2(ctx, rt, rs, rd);
14833 } else {
14834 /* OPC_LWC2, OPC_SWC2 */
14835 /* COP2: Not implemented. */
14836 generate_exception_err(ctx, EXCP_CpU, 2);
14837 }
14838 break;
14839 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
14840 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
14841 if (ctx->insn_flags & ISA_MIPS_R6) {
14842 if (rs != 0) {
14843 /* OPC_BEQZC, OPC_BNEZC */
14844 gen_compute_compact_branch(ctx, op, rs, 0,
14845 sextract32(ctx->opcode << 2, 0, 23));
14846 } else {
14847 /* OPC_JIC, OPC_JIALC */
14848 gen_compute_compact_branch(ctx, op, 0, rt, imm);
14849 }
14850 } else if (ctx->insn_flags & ASE_LEXT) {
14851 gen_loongson_lsdc2(ctx, rt, rs, rd);
14852 } else {
14853 /* OPC_LWC2, OPC_SWC2 */
14854 /* COP2: Not implemented. */
14855 generate_exception_err(ctx, EXCP_CpU, 2);
14856 }
14857 break;
14858 case OPC_CP2:
14859 check_insn(ctx, ASE_LMMI);
14860 /* Note that these instructions use different fields. */
14861 gen_loongson_multimedia(ctx, sa, rd, rt);
14862 break;
14863
14864 case OPC_CP3:
14865 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14866 check_cp1_enabled(ctx);
14867 op1 = MASK_CP3(ctx->opcode);
14868 switch (op1) {
14869 case OPC_LUXC1:
14870 case OPC_SUXC1:
14871 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
14872 /* Fallthrough */
14873 case OPC_LWXC1:
14874 case OPC_LDXC1:
14875 case OPC_SWXC1:
14876 case OPC_SDXC1:
14877 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
14878 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
14879 break;
14880 case OPC_PREFX:
14881 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
14882 /* Treat as NOP. */
14883 break;
14884 case OPC_ALNV_PS:
14885 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
14886 /* Fallthrough */
14887 case OPC_MADD_S:
14888 case OPC_MADD_D:
14889 case OPC_MADD_PS:
14890 case OPC_MSUB_S:
14891 case OPC_MSUB_D:
14892 case OPC_MSUB_PS:
14893 case OPC_NMADD_S:
14894 case OPC_NMADD_D:
14895 case OPC_NMADD_PS:
14896 case OPC_NMSUB_S:
14897 case OPC_NMSUB_D:
14898 case OPC_NMSUB_PS:
14899 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
14900 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
14901 break;
14902 default:
14903 MIPS_INVAL("cp3");
14904 gen_reserved_instruction(ctx);
14905 break;
14906 }
14907 } else {
14908 generate_exception_err(ctx, EXCP_CpU, 1);
14909 }
14910 break;
14911
14912 #if defined(TARGET_MIPS64)
14913 /* MIPS64 opcodes */
14914 case OPC_LLD:
14915 if (ctx->insn_flags & INSN_R5900) {
14916 check_insn_opc_user_only(ctx, INSN_R5900);
14917 }
14918 /* fall through */
14919 case OPC_LDL:
14920 case OPC_LDR:
14921 case OPC_LWU:
14922 case OPC_LD:
14923 check_insn(ctx, ISA_MIPS3);
14924 check_mips_64(ctx);
14925 gen_ld(ctx, op, rt, rs, imm);
14926 break;
14927 case OPC_SDL:
14928 case OPC_SDR:
14929 case OPC_SD:
14930 check_insn(ctx, ISA_MIPS3);
14931 check_mips_64(ctx);
14932 gen_st(ctx, op, rt, rs, imm);
14933 break;
14934 case OPC_SCD:
14935 check_insn(ctx, ISA_MIPS3);
14936 if (ctx->insn_flags & INSN_R5900) {
14937 check_insn_opc_user_only(ctx, INSN_R5900);
14938 }
14939 check_mips_64(ctx);
14940 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_UQ, false);
14941 break;
14942 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
14943 if (ctx->insn_flags & ISA_MIPS_R6) {
14944 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
14945 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14946 } else {
14947 /* OPC_DADDI */
14948 check_insn(ctx, ISA_MIPS3);
14949 check_mips_64(ctx);
14950 gen_arith_imm(ctx, op, rt, rs, imm);
14951 }
14952 break;
14953 case OPC_DADDIU:
14954 check_insn(ctx, ISA_MIPS3);
14955 check_mips_64(ctx);
14956 gen_arith_imm(ctx, op, rt, rs, imm);
14957 break;
14958 #else
14959 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
14960 if (ctx->insn_flags & ISA_MIPS_R6) {
14961 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14962 } else {
14963 MIPS_INVAL("major opcode");
14964 gen_reserved_instruction(ctx);
14965 }
14966 break;
14967 #endif
14968 case OPC_DAUI: /* OPC_JALX */
14969 if (ctx->insn_flags & ISA_MIPS_R6) {
14970 #if defined(TARGET_MIPS64)
14971 /* OPC_DAUI */
14972 check_mips_64(ctx);
14973 if (rs == 0) {
14974 generate_exception(ctx, EXCP_RI);
14975 } else if (rt != 0) {
14976 TCGv t0 = tcg_temp_new();
14977 gen_load_gpr(t0, rs);
14978 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
14979 }
14980 #else
14981 gen_reserved_instruction(ctx);
14982 MIPS_INVAL("major opcode");
14983 #endif
14984 } else {
14985 /* OPC_JALX */
14986 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
14987 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14988 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
14989 }
14990 break;
14991 case OPC_MDMX:
14992 /* MDMX: Not implemented. */
14993 break;
14994 case OPC_PCREL:
14995 check_insn(ctx, ISA_MIPS_R6);
14996 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
14997 break;
14998 default: /* Invalid */
14999 MIPS_INVAL("major opcode");
15000 return false;
15001 }
15002 return true;
15003 }
15004
decode_opc(CPUMIPSState * env,DisasContext * ctx)15005 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
15006 {
15007 /* make sure instructions are on a word boundary */
15008 if (ctx->base.pc_next & 0x3) {
15009 env->CP0_BadVAddr = ctx->base.pc_next;
15010 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
15011 return;
15012 }
15013
15014 /* Handle blikely not taken case */
15015 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
15016 TCGLabel *l1 = gen_new_label();
15017
15018 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
15019 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
15020 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
15021 gen_set_label(l1);
15022 }
15023
15024 /* Transition to the auto-generated decoder. */
15025
15026 /* Vendor specific extensions */
15027 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
15028 return;
15029 }
15030 if (cpu_supports_isa(env, INSN_VR54XX) && decode_ext_vr54xx(ctx, ctx->opcode)) {
15031 return;
15032 }
15033 if (TARGET_LONG_BITS == 64 && decode_ext_loongson(ctx, ctx->opcode)) {
15034 return;
15035 }
15036 #if defined(TARGET_MIPS64)
15037 if (ase_lcsr_available(env) && decode_ase_lcsr(ctx, ctx->opcode)) {
15038 return;
15039 }
15040 if (cpu_supports_isa(env, INSN_OCTEON) && decode_ext_octeon(ctx, ctx->opcode)) {
15041 return;
15042 }
15043 #endif
15044
15045 /* ISA extensions */
15046 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
15047 return;
15048 }
15049
15050 /* ISA (from latest to oldest) */
15051 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
15052 return;
15053 }
15054
15055 if (decode_opc_legacy(env, ctx)) {
15056 return;
15057 }
15058
15059 gen_reserved_instruction(ctx);
15060 }
15061
mips_tr_init_disas_context(DisasContextBase * dcbase,CPUState * cs)15062 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
15063 {
15064 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15065 CPUMIPSState *env = cpu_env(cs);
15066
15067 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
15068 ctx->saved_pc = -1;
15069 ctx->insn_flags = env->insn_flags;
15070 ctx->CP0_Config0 = env->CP0_Config0;
15071 ctx->CP0_Config1 = env->CP0_Config1;
15072 ctx->CP0_Config2 = env->CP0_Config2;
15073 ctx->CP0_Config3 = env->CP0_Config3;
15074 ctx->CP0_Config5 = env->CP0_Config5;
15075 ctx->btarget = 0;
15076 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
15077 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
15078 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
15079 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
15080 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
15081 ctx->PAMask = env->PAMask;
15082 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
15083 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
15084 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
15085 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
15086 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
15087 /* Restore delay slot state from the tb context. */
15088 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
15089 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
15090 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
15091 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
15092 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
15093 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
15094 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
15095 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
15096 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
15097 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
15098 restore_cpu_state(env, ctx);
15099 #ifdef CONFIG_USER_ONLY
15100 ctx->mem_idx = MIPS_HFLAG_UM;
15101 #else
15102 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
15103 #endif
15104 ctx->default_tcg_memop_mask = (!(ctx->insn_flags & ISA_NANOMIPS32) &&
15105 (ctx->insn_flags & (ISA_MIPS_R6 |
15106 INSN_LOONGSON3A))) ? MO_UNALN : MO_ALIGN;
15107
15108 /*
15109 * Execute a branch and its delay slot as a single instruction.
15110 * This is what GDB expects and is consistent with what the
15111 * hardware does (e.g. if a delay slot instruction faults, the
15112 * reported PC is the PC of the branch).
15113 */
15114 if ((tb_cflags(ctx->base.tb) & CF_SINGLE_STEP) &&
15115 (ctx->hflags & MIPS_HFLAG_BMASK)) {
15116 ctx->base.max_insns = 2;
15117 }
15118
15119 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
15120 ctx->hflags);
15121 }
15122
mips_tr_tb_start(DisasContextBase * dcbase,CPUState * cs)15123 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
15124 {
15125 }
15126
mips_tr_insn_start(DisasContextBase * dcbase,CPUState * cs)15127 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
15128 {
15129 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15130
15131 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
15132 ctx->btarget);
15133 }
15134
mips_tr_translate_insn(DisasContextBase * dcbase,CPUState * cs)15135 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
15136 {
15137 CPUMIPSState *env = cpu_env(cs);
15138 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15139 int insn_bytes;
15140 int is_slot;
15141
15142 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
15143 if (ctx->insn_flags & ISA_NANOMIPS32) {
15144 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
15145 insn_bytes = decode_isa_nanomips(env, ctx);
15146 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
15147 ctx->opcode = translator_ldl(env, &ctx->base, ctx->base.pc_next);
15148 insn_bytes = 4;
15149 decode_opc(env, ctx);
15150 } else if (ctx->insn_flags & ASE_MICROMIPS) {
15151 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
15152 insn_bytes = decode_isa_micromips(env, ctx);
15153 } else if (ctx->insn_flags & ASE_MIPS16) {
15154 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
15155 insn_bytes = decode_ase_mips16e(env, ctx);
15156 } else {
15157 gen_reserved_instruction(ctx);
15158 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
15159 return;
15160 }
15161
15162 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15163 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
15164 MIPS_HFLAG_FBNSLOT))) {
15165 /*
15166 * Force to generate branch as there is neither delay nor
15167 * forbidden slot.
15168 */
15169 is_slot = 1;
15170 }
15171 if ((ctx->hflags & MIPS_HFLAG_M16) &&
15172 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
15173 /*
15174 * Force to generate branch as microMIPS R6 doesn't restrict
15175 * branches in the forbidden slot.
15176 */
15177 is_slot = 1;
15178 }
15179 }
15180 if (is_slot) {
15181 gen_branch(ctx, insn_bytes);
15182 }
15183 if (ctx->base.is_jmp == DISAS_SEMIHOST) {
15184 generate_exception_err(ctx, EXCP_SEMIHOST, insn_bytes);
15185 }
15186 ctx->base.pc_next += insn_bytes;
15187
15188 if (ctx->base.is_jmp != DISAS_NEXT) {
15189 return;
15190 }
15191
15192 /*
15193 * End the TB on (most) page crossings.
15194 * See mips_tr_init_disas_context about single-stepping a branch
15195 * together with its delay slot.
15196 */
15197 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE
15198 && !(tb_cflags(ctx->base.tb) & CF_SINGLE_STEP)) {
15199 ctx->base.is_jmp = DISAS_TOO_MANY;
15200 }
15201 }
15202
mips_tr_tb_stop(DisasContextBase * dcbase,CPUState * cs)15203 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
15204 {
15205 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15206
15207 switch (ctx->base.is_jmp) {
15208 case DISAS_STOP:
15209 gen_save_pc(ctx->base.pc_next);
15210 tcg_gen_lookup_and_goto_ptr();
15211 break;
15212 case DISAS_NEXT:
15213 case DISAS_TOO_MANY:
15214 save_cpu_state(ctx, 0);
15215 gen_goto_tb(ctx, 0, ctx->base.pc_next);
15216 break;
15217 case DISAS_EXIT:
15218 tcg_gen_exit_tb(NULL, 0);
15219 break;
15220 case DISAS_NORETURN:
15221 break;
15222 default:
15223 g_assert_not_reached();
15224 }
15225 }
15226
15227 static const TranslatorOps mips_tr_ops = {
15228 .init_disas_context = mips_tr_init_disas_context,
15229 .tb_start = mips_tr_tb_start,
15230 .insn_start = mips_tr_insn_start,
15231 .translate_insn = mips_tr_translate_insn,
15232 .tb_stop = mips_tr_tb_stop,
15233 };
15234
mips_translate_code(CPUState * cs,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)15235 void mips_translate_code(CPUState *cs, TranslationBlock *tb,
15236 int *max_insns, vaddr pc, void *host_pc)
15237 {
15238 DisasContext ctx;
15239
15240 translator_loop(cs, tb, max_insns, pc, host_pc, &mips_tr_ops, &ctx.base);
15241 }
15242
mips_tcg_init(void)15243 void mips_tcg_init(void)
15244 {
15245 cpu_gpr[0] = NULL;
15246 for (unsigned i = 1; i < 32; i++)
15247 cpu_gpr[i] = tcg_global_mem_new(tcg_env,
15248 offsetof(CPUMIPSState,
15249 active_tc.gpr[i]),
15250 regnames[i]);
15251 #if defined(TARGET_MIPS64)
15252 cpu_gpr_hi[0] = NULL;
15253
15254 for (unsigned i = 1; i < 32; i++) {
15255 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
15256
15257 cpu_gpr_hi[i] = tcg_global_mem_new_i64(tcg_env,
15258 offsetof(CPUMIPSState,
15259 active_tc.gpr_hi[i]),
15260 rname);
15261 }
15262 #endif /* !TARGET_MIPS64 */
15263 for (unsigned i = 0; i < 32; i++) {
15264 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
15265
15266 fpu_f64[i] = tcg_global_mem_new_i64(tcg_env, off, fregnames[i]);
15267 }
15268 msa_translate_init();
15269 cpu_PC = tcg_global_mem_new(tcg_env,
15270 offsetof(CPUMIPSState, active_tc.PC), "PC");
15271 for (unsigned i = 0; i < MIPS_DSP_ACC; i++) {
15272 cpu_HI[i] = tcg_global_mem_new(tcg_env,
15273 offsetof(CPUMIPSState, active_tc.HI[i]),
15274 regnames_HI[i]);
15275 cpu_LO[i] = tcg_global_mem_new(tcg_env,
15276 offsetof(CPUMIPSState, active_tc.LO[i]),
15277 regnames_LO[i]);
15278 }
15279 cpu_dspctrl = tcg_global_mem_new(tcg_env,
15280 offsetof(CPUMIPSState,
15281 active_tc.DSPControl),
15282 "DSPControl");
15283 bcond = tcg_global_mem_new(tcg_env,
15284 offsetof(CPUMIPSState, bcond), "bcond");
15285 btarget = tcg_global_mem_new(tcg_env,
15286 offsetof(CPUMIPSState, btarget), "btarget");
15287 hflags = tcg_global_mem_new_i32(tcg_env,
15288 offsetof(CPUMIPSState, hflags), "hflags");
15289
15290 fpu_fcr0 = tcg_global_mem_new_i32(tcg_env,
15291 offsetof(CPUMIPSState, active_fpu.fcr0),
15292 "fcr0");
15293 fpu_fcr31 = tcg_global_mem_new_i32(tcg_env,
15294 offsetof(CPUMIPSState, active_fpu.fcr31),
15295 "fcr31");
15296 cpu_lladdr = tcg_global_mem_new(tcg_env, offsetof(CPUMIPSState, lladdr),
15297 "lladdr");
15298 cpu_llval = tcg_global_mem_new(tcg_env, offsetof(CPUMIPSState, llval),
15299 "llval");
15300
15301 if (TARGET_LONG_BITS == 32) {
15302 mxu_translate_init();
15303 }
15304 }
15305
mips_restore_state_to_opc(CPUState * cs,const TranslationBlock * tb,const uint64_t * data)15306 void mips_restore_state_to_opc(CPUState *cs,
15307 const TranslationBlock *tb,
15308 const uint64_t *data)
15309 {
15310 CPUMIPSState *env = cpu_env(cs);
15311
15312 env->active_tc.PC = data[0];
15313 env->hflags &= ~MIPS_HFLAG_BMASK;
15314 env->hflags |= data[1];
15315 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
15316 case MIPS_HFLAG_BR:
15317 break;
15318 case MIPS_HFLAG_BC:
15319 case MIPS_HFLAG_BL:
15320 case MIPS_HFLAG_B:
15321 env->btarget = data[2];
15322 break;
15323 }
15324 }
15325