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 "semihosting/semihost.h"
31 #include "trace.h"
32 #include "fpu_helper.h"
33
34 #define HELPER_H "helper.h"
35 #include "exec/helper-info.c.inc"
36 #undef HELPER_H
37
38
39 /*
40 * Many sysemu-only helpers are not reachable for user-only.
41 * Define stub generators here, so that we need not either sprinkle
42 * ifdefs through the translator, nor provide the helper function.
43 */
44 #define STUB_HELPER(NAME, ...) \
45 static inline void gen_helper_##NAME(__VA_ARGS__) \
46 { g_assert_not_reached(); }
47
48 #ifdef CONFIG_USER_ONLY
49 STUB_HELPER(cache, TCGv_env env, TCGv val, TCGv_i32 reg)
50 #endif
51
52 enum {
53 /* indirect opcode tables */
54 OPC_SPECIAL = (0x00 << 26),
55 OPC_REGIMM = (0x01 << 26),
56 OPC_CP0 = (0x10 << 26),
57 OPC_CP2 = (0x12 << 26),
58 OPC_CP3 = (0x13 << 26),
59 OPC_SPECIAL2 = (0x1C << 26),
60 OPC_SPECIAL3 = (0x1F << 26),
61 /* arithmetic with immediate */
62 OPC_ADDI = (0x08 << 26),
63 OPC_ADDIU = (0x09 << 26),
64 OPC_SLTI = (0x0A << 26),
65 OPC_SLTIU = (0x0B << 26),
66 /* logic with immediate */
67 OPC_ANDI = (0x0C << 26),
68 OPC_ORI = (0x0D << 26),
69 OPC_XORI = (0x0E << 26),
70 OPC_LUI = (0x0F << 26),
71 /* arithmetic with immediate */
72 OPC_DADDI = (0x18 << 26),
73 OPC_DADDIU = (0x19 << 26),
74 /* Jump and branches */
75 OPC_J = (0x02 << 26),
76 OPC_JAL = (0x03 << 26),
77 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
78 OPC_BEQL = (0x14 << 26),
79 OPC_BNE = (0x05 << 26),
80 OPC_BNEL = (0x15 << 26),
81 OPC_BLEZ = (0x06 << 26),
82 OPC_BLEZL = (0x16 << 26),
83 OPC_BGTZ = (0x07 << 26),
84 OPC_BGTZL = (0x17 << 26),
85 OPC_JALX = (0x1D << 26),
86 OPC_DAUI = (0x1D << 26),
87 /* Load and stores */
88 OPC_LDL = (0x1A << 26),
89 OPC_LDR = (0x1B << 26),
90 OPC_LB = (0x20 << 26),
91 OPC_LH = (0x21 << 26),
92 OPC_LWL = (0x22 << 26),
93 OPC_LW = (0x23 << 26),
94 OPC_LWPC = OPC_LW | 0x5,
95 OPC_LBU = (0x24 << 26),
96 OPC_LHU = (0x25 << 26),
97 OPC_LWR = (0x26 << 26),
98 OPC_LWU = (0x27 << 26),
99 OPC_SB = (0x28 << 26),
100 OPC_SH = (0x29 << 26),
101 OPC_SWL = (0x2A << 26),
102 OPC_SW = (0x2B << 26),
103 OPC_SDL = (0x2C << 26),
104 OPC_SDR = (0x2D << 26),
105 OPC_SWR = (0x2E << 26),
106 OPC_LL = (0x30 << 26),
107 OPC_LLD = (0x34 << 26),
108 OPC_LD = (0x37 << 26),
109 OPC_LDPC = OPC_LD | 0x5,
110 OPC_SC = (0x38 << 26),
111 OPC_SCD = (0x3C << 26),
112 OPC_SD = (0x3F << 26),
113 /* Floating point load/store */
114 OPC_LWC1 = (0x31 << 26),
115 OPC_LWC2 = (0x32 << 26),
116 OPC_LDC1 = (0x35 << 26),
117 OPC_LDC2 = (0x36 << 26),
118 OPC_SWC1 = (0x39 << 26),
119 OPC_SWC2 = (0x3A << 26),
120 OPC_SDC1 = (0x3D << 26),
121 OPC_SDC2 = (0x3E << 26),
122 /* Compact Branches */
123 OPC_BLEZALC = (0x06 << 26),
124 OPC_BGEZALC = (0x06 << 26),
125 OPC_BGEUC = (0x06 << 26),
126 OPC_BGTZALC = (0x07 << 26),
127 OPC_BLTZALC = (0x07 << 26),
128 OPC_BLTUC = (0x07 << 26),
129 OPC_BOVC = (0x08 << 26),
130 OPC_BEQZALC = (0x08 << 26),
131 OPC_BEQC = (0x08 << 26),
132 OPC_BLEZC = (0x16 << 26),
133 OPC_BGEZC = (0x16 << 26),
134 OPC_BGEC = (0x16 << 26),
135 OPC_BGTZC = (0x17 << 26),
136 OPC_BLTZC = (0x17 << 26),
137 OPC_BLTC = (0x17 << 26),
138 OPC_BNVC = (0x18 << 26),
139 OPC_BNEZALC = (0x18 << 26),
140 OPC_BNEC = (0x18 << 26),
141 OPC_BC = (0x32 << 26),
142 OPC_BEQZC = (0x36 << 26),
143 OPC_JIC = (0x36 << 26),
144 OPC_BALC = (0x3A << 26),
145 OPC_BNEZC = (0x3E << 26),
146 OPC_JIALC = (0x3E << 26),
147 /* MDMX ASE specific */
148 OPC_MDMX = (0x1E << 26),
149 /* Cache and prefetch */
150 OPC_CACHE = (0x2F << 26),
151 OPC_PREF = (0x33 << 26),
152 /* PC-relative address computation / loads */
153 OPC_PCREL = (0x3B << 26),
154 };
155
156 /* PC-relative address computation / loads */
157 #define MASK_OPC_PCREL_TOP2BITS(op) (MASK_OP_MAJOR(op) | (op & (3 << 19)))
158 #define MASK_OPC_PCREL_TOP5BITS(op) (MASK_OP_MAJOR(op) | (op & (0x1f << 16)))
159 enum {
160 /* Instructions determined by bits 19 and 20 */
161 OPC_ADDIUPC = OPC_PCREL | (0 << 19),
162 R6_OPC_LWPC = OPC_PCREL | (1 << 19),
163 OPC_LWUPC = OPC_PCREL | (2 << 19),
164
165 /* Instructions determined by bits 16 ... 20 */
166 OPC_AUIPC = OPC_PCREL | (0x1e << 16),
167 OPC_ALUIPC = OPC_PCREL | (0x1f << 16),
168
169 /* Other */
170 R6_OPC_LDPC = OPC_PCREL | (6 << 18),
171 };
172
173 /* MIPS special opcodes */
174 #define MASK_SPECIAL(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
175
176 enum {
177 /* Shifts */
178 OPC_SLL = 0x00 | OPC_SPECIAL,
179 /* NOP is SLL r0, r0, 0 */
180 /* SSNOP is SLL r0, r0, 1 */
181 /* EHB is SLL r0, r0, 3 */
182 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
183 OPC_ROTR = OPC_SRL | (1 << 21),
184 OPC_SRA = 0x03 | OPC_SPECIAL,
185 OPC_SLLV = 0x04 | OPC_SPECIAL,
186 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
187 OPC_ROTRV = OPC_SRLV | (1 << 6),
188 OPC_SRAV = 0x07 | OPC_SPECIAL,
189 OPC_DSLLV = 0x14 | OPC_SPECIAL,
190 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
191 OPC_DROTRV = OPC_DSRLV | (1 << 6),
192 OPC_DSRAV = 0x17 | OPC_SPECIAL,
193 OPC_DSLL = 0x38 | OPC_SPECIAL,
194 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
195 OPC_DROTR = OPC_DSRL | (1 << 21),
196 OPC_DSRA = 0x3B | OPC_SPECIAL,
197 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
198 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
199 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
200 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
201 /* Multiplication / division */
202 OPC_MULT = 0x18 | OPC_SPECIAL,
203 OPC_MULTU = 0x19 | OPC_SPECIAL,
204 OPC_DIV = 0x1A | OPC_SPECIAL,
205 OPC_DIVU = 0x1B | OPC_SPECIAL,
206 OPC_DMULT = 0x1C | OPC_SPECIAL,
207 OPC_DMULTU = 0x1D | OPC_SPECIAL,
208 OPC_DDIV = 0x1E | OPC_SPECIAL,
209 OPC_DDIVU = 0x1F | OPC_SPECIAL,
210
211 /* 2 registers arithmetic / logic */
212 OPC_ADD = 0x20 | OPC_SPECIAL,
213 OPC_ADDU = 0x21 | OPC_SPECIAL,
214 OPC_SUB = 0x22 | OPC_SPECIAL,
215 OPC_SUBU = 0x23 | OPC_SPECIAL,
216 OPC_AND = 0x24 | OPC_SPECIAL,
217 OPC_OR = 0x25 | OPC_SPECIAL,
218 OPC_XOR = 0x26 | OPC_SPECIAL,
219 OPC_NOR = 0x27 | OPC_SPECIAL,
220 OPC_SLT = 0x2A | OPC_SPECIAL,
221 OPC_SLTU = 0x2B | OPC_SPECIAL,
222 OPC_DADD = 0x2C | OPC_SPECIAL,
223 OPC_DADDU = 0x2D | OPC_SPECIAL,
224 OPC_DSUB = 0x2E | OPC_SPECIAL,
225 OPC_DSUBU = 0x2F | OPC_SPECIAL,
226 /* Jumps */
227 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
228 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
229 /* Traps */
230 OPC_TGE = 0x30 | OPC_SPECIAL,
231 OPC_TGEU = 0x31 | OPC_SPECIAL,
232 OPC_TLT = 0x32 | OPC_SPECIAL,
233 OPC_TLTU = 0x33 | OPC_SPECIAL,
234 OPC_TEQ = 0x34 | OPC_SPECIAL,
235 OPC_TNE = 0x36 | OPC_SPECIAL,
236 /* HI / LO registers load & stores */
237 OPC_MFHI = 0x10 | OPC_SPECIAL,
238 OPC_MTHI = 0x11 | OPC_SPECIAL,
239 OPC_MFLO = 0x12 | OPC_SPECIAL,
240 OPC_MTLO = 0x13 | OPC_SPECIAL,
241 /* Conditional moves */
242 OPC_MOVZ = 0x0A | OPC_SPECIAL,
243 OPC_MOVN = 0x0B | OPC_SPECIAL,
244
245 OPC_SELEQZ = 0x35 | OPC_SPECIAL,
246 OPC_SELNEZ = 0x37 | OPC_SPECIAL,
247
248 OPC_MOVCI = 0x01 | OPC_SPECIAL,
249
250 /* Special */
251 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
252 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
253 OPC_BREAK = 0x0D | OPC_SPECIAL,
254 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
255 OPC_SYNC = 0x0F | OPC_SPECIAL,
256
257 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
258 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
259 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
260 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
261 };
262
263 /*
264 * R6 Multiply and Divide instructions have the same opcode
265 * and function field as legacy OPC_MULT[U]/OPC_DIV[U]
266 */
267 #define MASK_R6_MULDIV(op) (MASK_SPECIAL(op) | (op & (0x7ff)))
268
269 enum {
270 R6_OPC_MUL = OPC_MULT | (2 << 6),
271 R6_OPC_MUH = OPC_MULT | (3 << 6),
272 R6_OPC_MULU = OPC_MULTU | (2 << 6),
273 R6_OPC_MUHU = OPC_MULTU | (3 << 6),
274 R6_OPC_DIV = OPC_DIV | (2 << 6),
275 R6_OPC_MOD = OPC_DIV | (3 << 6),
276 R6_OPC_DIVU = OPC_DIVU | (2 << 6),
277 R6_OPC_MODU = OPC_DIVU | (3 << 6),
278
279 R6_OPC_DMUL = OPC_DMULT | (2 << 6),
280 R6_OPC_DMUH = OPC_DMULT | (3 << 6),
281 R6_OPC_DMULU = OPC_DMULTU | (2 << 6),
282 R6_OPC_DMUHU = OPC_DMULTU | (3 << 6),
283 R6_OPC_DDIV = OPC_DDIV | (2 << 6),
284 R6_OPC_DMOD = OPC_DDIV | (3 << 6),
285 R6_OPC_DDIVU = OPC_DDIVU | (2 << 6),
286 R6_OPC_DMODU = OPC_DDIVU | (3 << 6),
287
288 R6_OPC_CLZ = 0x10 | OPC_SPECIAL,
289 R6_OPC_CLO = 0x11 | OPC_SPECIAL,
290 R6_OPC_DCLZ = 0x12 | OPC_SPECIAL,
291 R6_OPC_DCLO = 0x13 | OPC_SPECIAL,
292 R6_OPC_SDBBP = 0x0e | OPC_SPECIAL,
293 };
294
295 /* REGIMM (rt field) opcodes */
296 #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16)))
297
298 enum {
299 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
300 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
301 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
302 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
303 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
304 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
305 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
306 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
307 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
308 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
309 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
310 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
311 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
312 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
313 OPC_SIGRIE = (0x17 << 16) | OPC_REGIMM,
314 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
315
316 OPC_DAHI = (0x06 << 16) | OPC_REGIMM,
317 OPC_DATI = (0x1e << 16) | OPC_REGIMM,
318 };
319
320 /* Special2 opcodes */
321 #define MASK_SPECIAL2(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
322
323 enum {
324 /* Multiply & xxx operations */
325 OPC_MADD = 0x00 | OPC_SPECIAL2,
326 OPC_MADDU = 0x01 | OPC_SPECIAL2,
327 OPC_MUL = 0x02 | OPC_SPECIAL2,
328 OPC_MSUB = 0x04 | OPC_SPECIAL2,
329 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
330 /* Misc */
331 OPC_CLZ = 0x20 | OPC_SPECIAL2,
332 OPC_CLO = 0x21 | OPC_SPECIAL2,
333 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
334 OPC_DCLO = 0x25 | OPC_SPECIAL2,
335 /* Special */
336 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
337 };
338
339 /* Special3 opcodes */
340 #define MASK_SPECIAL3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
341
342 enum {
343 OPC_EXT = 0x00 | OPC_SPECIAL3,
344 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
345 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
346 OPC_DEXT = 0x03 | OPC_SPECIAL3,
347 OPC_INS = 0x04 | OPC_SPECIAL3,
348 OPC_DINSM = 0x05 | OPC_SPECIAL3,
349 OPC_DINSU = 0x06 | OPC_SPECIAL3,
350 OPC_DINS = 0x07 | OPC_SPECIAL3,
351 OPC_FORK = 0x08 | OPC_SPECIAL3,
352 OPC_YIELD = 0x09 | OPC_SPECIAL3,
353 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
354 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
355 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
356 OPC_GINV = 0x3D | OPC_SPECIAL3,
357
358 /* MIPS DSP Load */
359 OPC_LX_DSP = 0x0A | OPC_SPECIAL3,
360 /* MIPS DSP Arithmetic */
361 OPC_ADDU_QB_DSP = 0x10 | OPC_SPECIAL3,
362 OPC_ADDU_OB_DSP = 0x14 | OPC_SPECIAL3,
363 OPC_ABSQ_S_PH_DSP = 0x12 | OPC_SPECIAL3,
364 OPC_ABSQ_S_QH_DSP = 0x16 | OPC_SPECIAL3,
365 OPC_ADDUH_QB_DSP = 0x18 | OPC_SPECIAL3,
366 OPC_CMPU_EQ_QB_DSP = 0x11 | OPC_SPECIAL3,
367 OPC_CMPU_EQ_OB_DSP = 0x15 | OPC_SPECIAL3,
368 /* MIPS DSP GPR-Based Shift Sub-class */
369 OPC_SHLL_QB_DSP = 0x13 | OPC_SPECIAL3,
370 OPC_SHLL_OB_DSP = 0x17 | OPC_SPECIAL3,
371 /* MIPS DSP Multiply Sub-class insns */
372 OPC_MUL_PH_DSP = 0x18 | OPC_SPECIAL3,
373 OPC_DPA_W_PH_DSP = 0x30 | OPC_SPECIAL3,
374 OPC_DPAQ_W_QH_DSP = 0x34 | OPC_SPECIAL3,
375 /* DSP Bit/Manipulation Sub-class */
376 OPC_INSV_DSP = 0x0C | OPC_SPECIAL3,
377 OPC_DINSV_DSP = 0x0D | OPC_SPECIAL3,
378 /* MIPS DSP Append Sub-class */
379 OPC_APPEND_DSP = 0x31 | OPC_SPECIAL3,
380 OPC_DAPPEND_DSP = 0x35 | OPC_SPECIAL3,
381 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
382 OPC_EXTR_W_DSP = 0x38 | OPC_SPECIAL3,
383 OPC_DEXTR_W_DSP = 0x3C | OPC_SPECIAL3,
384
385 /* EVA */
386 OPC_LWLE = 0x19 | OPC_SPECIAL3,
387 OPC_LWRE = 0x1A | OPC_SPECIAL3,
388 OPC_CACHEE = 0x1B | OPC_SPECIAL3,
389 OPC_SBE = 0x1C | OPC_SPECIAL3,
390 OPC_SHE = 0x1D | OPC_SPECIAL3,
391 OPC_SCE = 0x1E | OPC_SPECIAL3,
392 OPC_SWE = 0x1F | OPC_SPECIAL3,
393 OPC_SWLE = 0x21 | OPC_SPECIAL3,
394 OPC_SWRE = 0x22 | OPC_SPECIAL3,
395 OPC_PREFE = 0x23 | OPC_SPECIAL3,
396 OPC_LBUE = 0x28 | OPC_SPECIAL3,
397 OPC_LHUE = 0x29 | OPC_SPECIAL3,
398 OPC_LBE = 0x2C | OPC_SPECIAL3,
399 OPC_LHE = 0x2D | OPC_SPECIAL3,
400 OPC_LLE = 0x2E | OPC_SPECIAL3,
401 OPC_LWE = 0x2F | OPC_SPECIAL3,
402
403 /* R6 */
404 R6_OPC_PREF = 0x35 | OPC_SPECIAL3,
405 R6_OPC_CACHE = 0x25 | OPC_SPECIAL3,
406 R6_OPC_LL = 0x36 | OPC_SPECIAL3,
407 R6_OPC_SC = 0x26 | OPC_SPECIAL3,
408 R6_OPC_LLD = 0x37 | OPC_SPECIAL3,
409 R6_OPC_SCD = 0x27 | OPC_SPECIAL3,
410 };
411
412 /* Loongson EXT load/store quad word opcodes */
413 #define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020))
414 enum {
415 OPC_GSLQ = 0x0020 | OPC_LWC2,
416 OPC_GSLQC1 = 0x8020 | OPC_LWC2,
417 OPC_GSSHFL = OPC_LWC2,
418 OPC_GSSQ = 0x0020 | OPC_SWC2,
419 OPC_GSSQC1 = 0x8020 | OPC_SWC2,
420 OPC_GSSHFS = OPC_SWC2,
421 };
422
423 /* Loongson EXT shifted load/store opcodes */
424 #define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f))
425 enum {
426 OPC_GSLWLC1 = 0x4 | OPC_GSSHFL,
427 OPC_GSLWRC1 = 0x5 | OPC_GSSHFL,
428 OPC_GSLDLC1 = 0x6 | OPC_GSSHFL,
429 OPC_GSLDRC1 = 0x7 | OPC_GSSHFL,
430 OPC_GSSWLC1 = 0x4 | OPC_GSSHFS,
431 OPC_GSSWRC1 = 0x5 | OPC_GSSHFS,
432 OPC_GSSDLC1 = 0x6 | OPC_GSSHFS,
433 OPC_GSSDRC1 = 0x7 | OPC_GSSHFS,
434 };
435
436 /* Loongson EXT LDC2/SDC2 opcodes */
437 #define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7))
438
439 enum {
440 OPC_GSLBX = 0x0 | OPC_LDC2,
441 OPC_GSLHX = 0x1 | OPC_LDC2,
442 OPC_GSLWX = 0x2 | OPC_LDC2,
443 OPC_GSLDX = 0x3 | OPC_LDC2,
444 OPC_GSLWXC1 = 0x6 | OPC_LDC2,
445 OPC_GSLDXC1 = 0x7 | OPC_LDC2,
446 OPC_GSSBX = 0x0 | OPC_SDC2,
447 OPC_GSSHX = 0x1 | OPC_SDC2,
448 OPC_GSSWX = 0x2 | OPC_SDC2,
449 OPC_GSSDX = 0x3 | OPC_SDC2,
450 OPC_GSSWXC1 = 0x6 | OPC_SDC2,
451 OPC_GSSDXC1 = 0x7 | OPC_SDC2,
452 };
453
454 /* BSHFL opcodes */
455 #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
456
457 enum {
458 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
459 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
460 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
461 OPC_ALIGN = (0x08 << 6) | OPC_BSHFL, /* 010.bp (010.00 to 010.11) */
462 OPC_ALIGN_1 = (0x09 << 6) | OPC_BSHFL,
463 OPC_ALIGN_2 = (0x0A << 6) | OPC_BSHFL,
464 OPC_ALIGN_3 = (0x0B << 6) | OPC_BSHFL,
465 OPC_BITSWAP = (0x00 << 6) | OPC_BSHFL /* 00000 */
466 };
467
468 /* DBSHFL opcodes */
469 #define MASK_DBSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
470
471 enum {
472 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
473 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
474 OPC_DALIGN = (0x08 << 6) | OPC_DBSHFL, /* 01.bp (01.000 to 01.111) */
475 OPC_DALIGN_1 = (0x09 << 6) | OPC_DBSHFL,
476 OPC_DALIGN_2 = (0x0A << 6) | OPC_DBSHFL,
477 OPC_DALIGN_3 = (0x0B << 6) | OPC_DBSHFL,
478 OPC_DALIGN_4 = (0x0C << 6) | OPC_DBSHFL,
479 OPC_DALIGN_5 = (0x0D << 6) | OPC_DBSHFL,
480 OPC_DALIGN_6 = (0x0E << 6) | OPC_DBSHFL,
481 OPC_DALIGN_7 = (0x0F << 6) | OPC_DBSHFL,
482 OPC_DBITSWAP = (0x00 << 6) | OPC_DBSHFL, /* 00000 */
483 };
484
485 /* MIPS DSP REGIMM opcodes */
486 enum {
487 OPC_BPOSGE32 = (0x1C << 16) | OPC_REGIMM,
488 OPC_BPOSGE64 = (0x1D << 16) | OPC_REGIMM,
489 };
490
491 #define MASK_LX(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
492 /* MIPS DSP Load */
493 enum {
494 OPC_LBUX = (0x06 << 6) | OPC_LX_DSP,
495 OPC_LHX = (0x04 << 6) | OPC_LX_DSP,
496 OPC_LWX = (0x00 << 6) | OPC_LX_DSP,
497 OPC_LDX = (0x08 << 6) | OPC_LX_DSP,
498 };
499
500 #define MASK_ADDU_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
501 enum {
502 /* MIPS DSP Arithmetic Sub-class */
503 OPC_ADDQ_PH = (0x0A << 6) | OPC_ADDU_QB_DSP,
504 OPC_ADDQ_S_PH = (0x0E << 6) | OPC_ADDU_QB_DSP,
505 OPC_ADDQ_S_W = (0x16 << 6) | OPC_ADDU_QB_DSP,
506 OPC_ADDU_QB = (0x00 << 6) | OPC_ADDU_QB_DSP,
507 OPC_ADDU_S_QB = (0x04 << 6) | OPC_ADDU_QB_DSP,
508 OPC_ADDU_PH = (0x08 << 6) | OPC_ADDU_QB_DSP,
509 OPC_ADDU_S_PH = (0x0C << 6) | OPC_ADDU_QB_DSP,
510 OPC_SUBQ_PH = (0x0B << 6) | OPC_ADDU_QB_DSP,
511 OPC_SUBQ_S_PH = (0x0F << 6) | OPC_ADDU_QB_DSP,
512 OPC_SUBQ_S_W = (0x17 << 6) | OPC_ADDU_QB_DSP,
513 OPC_SUBU_QB = (0x01 << 6) | OPC_ADDU_QB_DSP,
514 OPC_SUBU_S_QB = (0x05 << 6) | OPC_ADDU_QB_DSP,
515 OPC_SUBU_PH = (0x09 << 6) | OPC_ADDU_QB_DSP,
516 OPC_SUBU_S_PH = (0x0D << 6) | OPC_ADDU_QB_DSP,
517 OPC_ADDSC = (0x10 << 6) | OPC_ADDU_QB_DSP,
518 OPC_ADDWC = (0x11 << 6) | OPC_ADDU_QB_DSP,
519 OPC_MODSUB = (0x12 << 6) | OPC_ADDU_QB_DSP,
520 OPC_RADDU_W_QB = (0x14 << 6) | OPC_ADDU_QB_DSP,
521 /* MIPS DSP Multiply Sub-class insns */
522 OPC_MULEU_S_PH_QBL = (0x06 << 6) | OPC_ADDU_QB_DSP,
523 OPC_MULEU_S_PH_QBR = (0x07 << 6) | OPC_ADDU_QB_DSP,
524 OPC_MULQ_RS_PH = (0x1F << 6) | OPC_ADDU_QB_DSP,
525 OPC_MULEQ_S_W_PHL = (0x1C << 6) | OPC_ADDU_QB_DSP,
526 OPC_MULEQ_S_W_PHR = (0x1D << 6) | OPC_ADDU_QB_DSP,
527 OPC_MULQ_S_PH = (0x1E << 6) | OPC_ADDU_QB_DSP,
528 };
529
530 #define MASK_ADDUH_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
531 enum {
532 /* MIPS DSP Arithmetic Sub-class */
533 OPC_ADDUH_QB = (0x00 << 6) | OPC_ADDUH_QB_DSP,
534 OPC_ADDUH_R_QB = (0x02 << 6) | OPC_ADDUH_QB_DSP,
535 OPC_ADDQH_PH = (0x08 << 6) | OPC_ADDUH_QB_DSP,
536 OPC_ADDQH_R_PH = (0x0A << 6) | OPC_ADDUH_QB_DSP,
537 OPC_ADDQH_W = (0x10 << 6) | OPC_ADDUH_QB_DSP,
538 OPC_ADDQH_R_W = (0x12 << 6) | OPC_ADDUH_QB_DSP,
539 OPC_SUBUH_QB = (0x01 << 6) | OPC_ADDUH_QB_DSP,
540 OPC_SUBUH_R_QB = (0x03 << 6) | OPC_ADDUH_QB_DSP,
541 OPC_SUBQH_PH = (0x09 << 6) | OPC_ADDUH_QB_DSP,
542 OPC_SUBQH_R_PH = (0x0B << 6) | OPC_ADDUH_QB_DSP,
543 OPC_SUBQH_W = (0x11 << 6) | OPC_ADDUH_QB_DSP,
544 OPC_SUBQH_R_W = (0x13 << 6) | OPC_ADDUH_QB_DSP,
545 /* MIPS DSP Multiply Sub-class insns */
546 OPC_MUL_PH = (0x0C << 6) | OPC_ADDUH_QB_DSP,
547 OPC_MUL_S_PH = (0x0E << 6) | OPC_ADDUH_QB_DSP,
548 OPC_MULQ_S_W = (0x16 << 6) | OPC_ADDUH_QB_DSP,
549 OPC_MULQ_RS_W = (0x17 << 6) | OPC_ADDUH_QB_DSP,
550 };
551
552 #define MASK_ABSQ_S_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
553 enum {
554 /* MIPS DSP Arithmetic Sub-class */
555 OPC_ABSQ_S_QB = (0x01 << 6) | OPC_ABSQ_S_PH_DSP,
556 OPC_ABSQ_S_PH = (0x09 << 6) | OPC_ABSQ_S_PH_DSP,
557 OPC_ABSQ_S_W = (0x11 << 6) | OPC_ABSQ_S_PH_DSP,
558 OPC_PRECEQ_W_PHL = (0x0C << 6) | OPC_ABSQ_S_PH_DSP,
559 OPC_PRECEQ_W_PHR = (0x0D << 6) | OPC_ABSQ_S_PH_DSP,
560 OPC_PRECEQU_PH_QBL = (0x04 << 6) | OPC_ABSQ_S_PH_DSP,
561 OPC_PRECEQU_PH_QBR = (0x05 << 6) | OPC_ABSQ_S_PH_DSP,
562 OPC_PRECEQU_PH_QBLA = (0x06 << 6) | OPC_ABSQ_S_PH_DSP,
563 OPC_PRECEQU_PH_QBRA = (0x07 << 6) | OPC_ABSQ_S_PH_DSP,
564 OPC_PRECEU_PH_QBL = (0x1C << 6) | OPC_ABSQ_S_PH_DSP,
565 OPC_PRECEU_PH_QBR = (0x1D << 6) | OPC_ABSQ_S_PH_DSP,
566 OPC_PRECEU_PH_QBLA = (0x1E << 6) | OPC_ABSQ_S_PH_DSP,
567 OPC_PRECEU_PH_QBRA = (0x1F << 6) | OPC_ABSQ_S_PH_DSP,
568 /* DSP Bit/Manipulation Sub-class */
569 OPC_BITREV = (0x1B << 6) | OPC_ABSQ_S_PH_DSP,
570 OPC_REPL_QB = (0x02 << 6) | OPC_ABSQ_S_PH_DSP,
571 OPC_REPLV_QB = (0x03 << 6) | OPC_ABSQ_S_PH_DSP,
572 OPC_REPL_PH = (0x0A << 6) | OPC_ABSQ_S_PH_DSP,
573 OPC_REPLV_PH = (0x0B << 6) | OPC_ABSQ_S_PH_DSP,
574 };
575
576 #define MASK_CMPU_EQ_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
577 enum {
578 /* MIPS DSP Arithmetic Sub-class */
579 OPC_PRECR_QB_PH = (0x0D << 6) | OPC_CMPU_EQ_QB_DSP,
580 OPC_PRECRQ_QB_PH = (0x0C << 6) | OPC_CMPU_EQ_QB_DSP,
581 OPC_PRECR_SRA_PH_W = (0x1E << 6) | OPC_CMPU_EQ_QB_DSP,
582 OPC_PRECR_SRA_R_PH_W = (0x1F << 6) | OPC_CMPU_EQ_QB_DSP,
583 OPC_PRECRQ_PH_W = (0x14 << 6) | OPC_CMPU_EQ_QB_DSP,
584 OPC_PRECRQ_RS_PH_W = (0x15 << 6) | OPC_CMPU_EQ_QB_DSP,
585 OPC_PRECRQU_S_QB_PH = (0x0F << 6) | OPC_CMPU_EQ_QB_DSP,
586 /* DSP Compare-Pick Sub-class */
587 OPC_CMPU_EQ_QB = (0x00 << 6) | OPC_CMPU_EQ_QB_DSP,
588 OPC_CMPU_LT_QB = (0x01 << 6) | OPC_CMPU_EQ_QB_DSP,
589 OPC_CMPU_LE_QB = (0x02 << 6) | OPC_CMPU_EQ_QB_DSP,
590 OPC_CMPGU_EQ_QB = (0x04 << 6) | OPC_CMPU_EQ_QB_DSP,
591 OPC_CMPGU_LT_QB = (0x05 << 6) | OPC_CMPU_EQ_QB_DSP,
592 OPC_CMPGU_LE_QB = (0x06 << 6) | OPC_CMPU_EQ_QB_DSP,
593 OPC_CMPGDU_EQ_QB = (0x18 << 6) | OPC_CMPU_EQ_QB_DSP,
594 OPC_CMPGDU_LT_QB = (0x19 << 6) | OPC_CMPU_EQ_QB_DSP,
595 OPC_CMPGDU_LE_QB = (0x1A << 6) | OPC_CMPU_EQ_QB_DSP,
596 OPC_CMP_EQ_PH = (0x08 << 6) | OPC_CMPU_EQ_QB_DSP,
597 OPC_CMP_LT_PH = (0x09 << 6) | OPC_CMPU_EQ_QB_DSP,
598 OPC_CMP_LE_PH = (0x0A << 6) | OPC_CMPU_EQ_QB_DSP,
599 OPC_PICK_QB = (0x03 << 6) | OPC_CMPU_EQ_QB_DSP,
600 OPC_PICK_PH = (0x0B << 6) | OPC_CMPU_EQ_QB_DSP,
601 OPC_PACKRL_PH = (0x0E << 6) | OPC_CMPU_EQ_QB_DSP,
602 };
603
604 #define MASK_SHLL_QB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
605 enum {
606 /* MIPS DSP GPR-Based Shift Sub-class */
607 OPC_SHLL_QB = (0x00 << 6) | OPC_SHLL_QB_DSP,
608 OPC_SHLLV_QB = (0x02 << 6) | OPC_SHLL_QB_DSP,
609 OPC_SHLL_PH = (0x08 << 6) | OPC_SHLL_QB_DSP,
610 OPC_SHLLV_PH = (0x0A << 6) | OPC_SHLL_QB_DSP,
611 OPC_SHLL_S_PH = (0x0C << 6) | OPC_SHLL_QB_DSP,
612 OPC_SHLLV_S_PH = (0x0E << 6) | OPC_SHLL_QB_DSP,
613 OPC_SHLL_S_W = (0x14 << 6) | OPC_SHLL_QB_DSP,
614 OPC_SHLLV_S_W = (0x16 << 6) | OPC_SHLL_QB_DSP,
615 OPC_SHRL_QB = (0x01 << 6) | OPC_SHLL_QB_DSP,
616 OPC_SHRLV_QB = (0x03 << 6) | OPC_SHLL_QB_DSP,
617 OPC_SHRL_PH = (0x19 << 6) | OPC_SHLL_QB_DSP,
618 OPC_SHRLV_PH = (0x1B << 6) | OPC_SHLL_QB_DSP,
619 OPC_SHRA_QB = (0x04 << 6) | OPC_SHLL_QB_DSP,
620 OPC_SHRA_R_QB = (0x05 << 6) | OPC_SHLL_QB_DSP,
621 OPC_SHRAV_QB = (0x06 << 6) | OPC_SHLL_QB_DSP,
622 OPC_SHRAV_R_QB = (0x07 << 6) | OPC_SHLL_QB_DSP,
623 OPC_SHRA_PH = (0x09 << 6) | OPC_SHLL_QB_DSP,
624 OPC_SHRAV_PH = (0x0B << 6) | OPC_SHLL_QB_DSP,
625 OPC_SHRA_R_PH = (0x0D << 6) | OPC_SHLL_QB_DSP,
626 OPC_SHRAV_R_PH = (0x0F << 6) | OPC_SHLL_QB_DSP,
627 OPC_SHRA_R_W = (0x15 << 6) | OPC_SHLL_QB_DSP,
628 OPC_SHRAV_R_W = (0x17 << 6) | OPC_SHLL_QB_DSP,
629 };
630
631 #define MASK_DPA_W_PH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
632 enum {
633 /* MIPS DSP Multiply Sub-class insns */
634 OPC_DPAU_H_QBL = (0x03 << 6) | OPC_DPA_W_PH_DSP,
635 OPC_DPAU_H_QBR = (0x07 << 6) | OPC_DPA_W_PH_DSP,
636 OPC_DPSU_H_QBL = (0x0B << 6) | OPC_DPA_W_PH_DSP,
637 OPC_DPSU_H_QBR = (0x0F << 6) | OPC_DPA_W_PH_DSP,
638 OPC_DPA_W_PH = (0x00 << 6) | OPC_DPA_W_PH_DSP,
639 OPC_DPAX_W_PH = (0x08 << 6) | OPC_DPA_W_PH_DSP,
640 OPC_DPAQ_S_W_PH = (0x04 << 6) | OPC_DPA_W_PH_DSP,
641 OPC_DPAQX_S_W_PH = (0x18 << 6) | OPC_DPA_W_PH_DSP,
642 OPC_DPAQX_SA_W_PH = (0x1A << 6) | OPC_DPA_W_PH_DSP,
643 OPC_DPS_W_PH = (0x01 << 6) | OPC_DPA_W_PH_DSP,
644 OPC_DPSX_W_PH = (0x09 << 6) | OPC_DPA_W_PH_DSP,
645 OPC_DPSQ_S_W_PH = (0x05 << 6) | OPC_DPA_W_PH_DSP,
646 OPC_DPSQX_S_W_PH = (0x19 << 6) | OPC_DPA_W_PH_DSP,
647 OPC_DPSQX_SA_W_PH = (0x1B << 6) | OPC_DPA_W_PH_DSP,
648 OPC_MULSAQ_S_W_PH = (0x06 << 6) | OPC_DPA_W_PH_DSP,
649 OPC_DPAQ_SA_L_W = (0x0C << 6) | OPC_DPA_W_PH_DSP,
650 OPC_DPSQ_SA_L_W = (0x0D << 6) | OPC_DPA_W_PH_DSP,
651 OPC_MAQ_S_W_PHL = (0x14 << 6) | OPC_DPA_W_PH_DSP,
652 OPC_MAQ_S_W_PHR = (0x16 << 6) | OPC_DPA_W_PH_DSP,
653 OPC_MAQ_SA_W_PHL = (0x10 << 6) | OPC_DPA_W_PH_DSP,
654 OPC_MAQ_SA_W_PHR = (0x12 << 6) | OPC_DPA_W_PH_DSP,
655 OPC_MULSA_W_PH = (0x02 << 6) | OPC_DPA_W_PH_DSP,
656 };
657
658 #define MASK_INSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
659 enum {
660 /* DSP Bit/Manipulation Sub-class */
661 OPC_INSV = (0x00 << 6) | OPC_INSV_DSP,
662 };
663
664 #define MASK_APPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
665 enum {
666 /* MIPS DSP Append Sub-class */
667 OPC_APPEND = (0x00 << 6) | OPC_APPEND_DSP,
668 OPC_PREPEND = (0x01 << 6) | OPC_APPEND_DSP,
669 OPC_BALIGN = (0x10 << 6) | OPC_APPEND_DSP,
670 };
671
672 #define MASK_EXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
673 enum {
674 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
675 OPC_EXTR_W = (0x00 << 6) | OPC_EXTR_W_DSP,
676 OPC_EXTR_R_W = (0x04 << 6) | OPC_EXTR_W_DSP,
677 OPC_EXTR_RS_W = (0x06 << 6) | OPC_EXTR_W_DSP,
678 OPC_EXTR_S_H = (0x0E << 6) | OPC_EXTR_W_DSP,
679 OPC_EXTRV_S_H = (0x0F << 6) | OPC_EXTR_W_DSP,
680 OPC_EXTRV_W = (0x01 << 6) | OPC_EXTR_W_DSP,
681 OPC_EXTRV_R_W = (0x05 << 6) | OPC_EXTR_W_DSP,
682 OPC_EXTRV_RS_W = (0x07 << 6) | OPC_EXTR_W_DSP,
683 OPC_EXTP = (0x02 << 6) | OPC_EXTR_W_DSP,
684 OPC_EXTPV = (0x03 << 6) | OPC_EXTR_W_DSP,
685 OPC_EXTPDP = (0x0A << 6) | OPC_EXTR_W_DSP,
686 OPC_EXTPDPV = (0x0B << 6) | OPC_EXTR_W_DSP,
687 OPC_SHILO = (0x1A << 6) | OPC_EXTR_W_DSP,
688 OPC_SHILOV = (0x1B << 6) | OPC_EXTR_W_DSP,
689 OPC_MTHLIP = (0x1F << 6) | OPC_EXTR_W_DSP,
690 OPC_WRDSP = (0x13 << 6) | OPC_EXTR_W_DSP,
691 OPC_RDDSP = (0x12 << 6) | OPC_EXTR_W_DSP,
692 };
693
694 #define MASK_ABSQ_S_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
695 enum {
696 /* MIPS DSP Arithmetic Sub-class */
697 OPC_PRECEQ_L_PWL = (0x14 << 6) | OPC_ABSQ_S_QH_DSP,
698 OPC_PRECEQ_L_PWR = (0x15 << 6) | OPC_ABSQ_S_QH_DSP,
699 OPC_PRECEQ_PW_QHL = (0x0C << 6) | OPC_ABSQ_S_QH_DSP,
700 OPC_PRECEQ_PW_QHR = (0x0D << 6) | OPC_ABSQ_S_QH_DSP,
701 OPC_PRECEQ_PW_QHLA = (0x0E << 6) | OPC_ABSQ_S_QH_DSP,
702 OPC_PRECEQ_PW_QHRA = (0x0F << 6) | OPC_ABSQ_S_QH_DSP,
703 OPC_PRECEQU_QH_OBL = (0x04 << 6) | OPC_ABSQ_S_QH_DSP,
704 OPC_PRECEQU_QH_OBR = (0x05 << 6) | OPC_ABSQ_S_QH_DSP,
705 OPC_PRECEQU_QH_OBLA = (0x06 << 6) | OPC_ABSQ_S_QH_DSP,
706 OPC_PRECEQU_QH_OBRA = (0x07 << 6) | OPC_ABSQ_S_QH_DSP,
707 OPC_PRECEU_QH_OBL = (0x1C << 6) | OPC_ABSQ_S_QH_DSP,
708 OPC_PRECEU_QH_OBR = (0x1D << 6) | OPC_ABSQ_S_QH_DSP,
709 OPC_PRECEU_QH_OBLA = (0x1E << 6) | OPC_ABSQ_S_QH_DSP,
710 OPC_PRECEU_QH_OBRA = (0x1F << 6) | OPC_ABSQ_S_QH_DSP,
711 OPC_ABSQ_S_OB = (0x01 << 6) | OPC_ABSQ_S_QH_DSP,
712 OPC_ABSQ_S_PW = (0x11 << 6) | OPC_ABSQ_S_QH_DSP,
713 OPC_ABSQ_S_QH = (0x09 << 6) | OPC_ABSQ_S_QH_DSP,
714 /* DSP Bit/Manipulation Sub-class */
715 OPC_REPL_OB = (0x02 << 6) | OPC_ABSQ_S_QH_DSP,
716 OPC_REPL_PW = (0x12 << 6) | OPC_ABSQ_S_QH_DSP,
717 OPC_REPL_QH = (0x0A << 6) | OPC_ABSQ_S_QH_DSP,
718 OPC_REPLV_OB = (0x03 << 6) | OPC_ABSQ_S_QH_DSP,
719 OPC_REPLV_PW = (0x13 << 6) | OPC_ABSQ_S_QH_DSP,
720 OPC_REPLV_QH = (0x0B << 6) | OPC_ABSQ_S_QH_DSP,
721 };
722
723 #define MASK_ADDU_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
724 enum {
725 /* MIPS DSP Multiply Sub-class insns */
726 OPC_MULEQ_S_PW_QHL = (0x1C << 6) | OPC_ADDU_OB_DSP,
727 OPC_MULEQ_S_PW_QHR = (0x1D << 6) | OPC_ADDU_OB_DSP,
728 OPC_MULEU_S_QH_OBL = (0x06 << 6) | OPC_ADDU_OB_DSP,
729 OPC_MULEU_S_QH_OBR = (0x07 << 6) | OPC_ADDU_OB_DSP,
730 OPC_MULQ_RS_QH = (0x1F << 6) | OPC_ADDU_OB_DSP,
731 /* MIPS DSP Arithmetic Sub-class */
732 OPC_RADDU_L_OB = (0x14 << 6) | OPC_ADDU_OB_DSP,
733 OPC_SUBQ_PW = (0x13 << 6) | OPC_ADDU_OB_DSP,
734 OPC_SUBQ_S_PW = (0x17 << 6) | OPC_ADDU_OB_DSP,
735 OPC_SUBQ_QH = (0x0B << 6) | OPC_ADDU_OB_DSP,
736 OPC_SUBQ_S_QH = (0x0F << 6) | OPC_ADDU_OB_DSP,
737 OPC_SUBU_OB = (0x01 << 6) | OPC_ADDU_OB_DSP,
738 OPC_SUBU_S_OB = (0x05 << 6) | OPC_ADDU_OB_DSP,
739 OPC_SUBU_QH = (0x09 << 6) | OPC_ADDU_OB_DSP,
740 OPC_SUBU_S_QH = (0x0D << 6) | OPC_ADDU_OB_DSP,
741 OPC_SUBUH_OB = (0x19 << 6) | OPC_ADDU_OB_DSP,
742 OPC_SUBUH_R_OB = (0x1B << 6) | OPC_ADDU_OB_DSP,
743 OPC_ADDQ_PW = (0x12 << 6) | OPC_ADDU_OB_DSP,
744 OPC_ADDQ_S_PW = (0x16 << 6) | OPC_ADDU_OB_DSP,
745 OPC_ADDQ_QH = (0x0A << 6) | OPC_ADDU_OB_DSP,
746 OPC_ADDQ_S_QH = (0x0E << 6) | OPC_ADDU_OB_DSP,
747 OPC_ADDU_OB = (0x00 << 6) | OPC_ADDU_OB_DSP,
748 OPC_ADDU_S_OB = (0x04 << 6) | OPC_ADDU_OB_DSP,
749 OPC_ADDU_QH = (0x08 << 6) | OPC_ADDU_OB_DSP,
750 OPC_ADDU_S_QH = (0x0C << 6) | OPC_ADDU_OB_DSP,
751 OPC_ADDUH_OB = (0x18 << 6) | OPC_ADDU_OB_DSP,
752 OPC_ADDUH_R_OB = (0x1A << 6) | OPC_ADDU_OB_DSP,
753 };
754
755 #define MASK_CMPU_EQ_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
756 enum {
757 /* DSP Compare-Pick Sub-class */
758 OPC_CMP_EQ_PW = (0x10 << 6) | OPC_CMPU_EQ_OB_DSP,
759 OPC_CMP_LT_PW = (0x11 << 6) | OPC_CMPU_EQ_OB_DSP,
760 OPC_CMP_LE_PW = (0x12 << 6) | OPC_CMPU_EQ_OB_DSP,
761 OPC_CMP_EQ_QH = (0x08 << 6) | OPC_CMPU_EQ_OB_DSP,
762 OPC_CMP_LT_QH = (0x09 << 6) | OPC_CMPU_EQ_OB_DSP,
763 OPC_CMP_LE_QH = (0x0A << 6) | OPC_CMPU_EQ_OB_DSP,
764 OPC_CMPGDU_EQ_OB = (0x18 << 6) | OPC_CMPU_EQ_OB_DSP,
765 OPC_CMPGDU_LT_OB = (0x19 << 6) | OPC_CMPU_EQ_OB_DSP,
766 OPC_CMPGDU_LE_OB = (0x1A << 6) | OPC_CMPU_EQ_OB_DSP,
767 OPC_CMPGU_EQ_OB = (0x04 << 6) | OPC_CMPU_EQ_OB_DSP,
768 OPC_CMPGU_LT_OB = (0x05 << 6) | OPC_CMPU_EQ_OB_DSP,
769 OPC_CMPGU_LE_OB = (0x06 << 6) | OPC_CMPU_EQ_OB_DSP,
770 OPC_CMPU_EQ_OB = (0x00 << 6) | OPC_CMPU_EQ_OB_DSP,
771 OPC_CMPU_LT_OB = (0x01 << 6) | OPC_CMPU_EQ_OB_DSP,
772 OPC_CMPU_LE_OB = (0x02 << 6) | OPC_CMPU_EQ_OB_DSP,
773 OPC_PACKRL_PW = (0x0E << 6) | OPC_CMPU_EQ_OB_DSP,
774 OPC_PICK_OB = (0x03 << 6) | OPC_CMPU_EQ_OB_DSP,
775 OPC_PICK_PW = (0x13 << 6) | OPC_CMPU_EQ_OB_DSP,
776 OPC_PICK_QH = (0x0B << 6) | OPC_CMPU_EQ_OB_DSP,
777 /* MIPS DSP Arithmetic Sub-class */
778 OPC_PRECR_OB_QH = (0x0D << 6) | OPC_CMPU_EQ_OB_DSP,
779 OPC_PRECR_SRA_QH_PW = (0x1E << 6) | OPC_CMPU_EQ_OB_DSP,
780 OPC_PRECR_SRA_R_QH_PW = (0x1F << 6) | OPC_CMPU_EQ_OB_DSP,
781 OPC_PRECRQ_OB_QH = (0x0C << 6) | OPC_CMPU_EQ_OB_DSP,
782 OPC_PRECRQ_PW_L = (0x1C << 6) | OPC_CMPU_EQ_OB_DSP,
783 OPC_PRECRQ_QH_PW = (0x14 << 6) | OPC_CMPU_EQ_OB_DSP,
784 OPC_PRECRQ_RS_QH_PW = (0x15 << 6) | OPC_CMPU_EQ_OB_DSP,
785 OPC_PRECRQU_S_OB_QH = (0x0F << 6) | OPC_CMPU_EQ_OB_DSP,
786 };
787
788 #define MASK_DAPPEND(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
789 enum {
790 /* DSP Append Sub-class */
791 OPC_DAPPEND = (0x00 << 6) | OPC_DAPPEND_DSP,
792 OPC_PREPENDD = (0x03 << 6) | OPC_DAPPEND_DSP,
793 OPC_PREPENDW = (0x01 << 6) | OPC_DAPPEND_DSP,
794 OPC_DBALIGN = (0x10 << 6) | OPC_DAPPEND_DSP,
795 };
796
797 #define MASK_DEXTR_W(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
798 enum {
799 /* MIPS DSP Accumulator and DSPControl Access Sub-class */
800 OPC_DMTHLIP = (0x1F << 6) | OPC_DEXTR_W_DSP,
801 OPC_DSHILO = (0x1A << 6) | OPC_DEXTR_W_DSP,
802 OPC_DEXTP = (0x02 << 6) | OPC_DEXTR_W_DSP,
803 OPC_DEXTPDP = (0x0A << 6) | OPC_DEXTR_W_DSP,
804 OPC_DEXTPDPV = (0x0B << 6) | OPC_DEXTR_W_DSP,
805 OPC_DEXTPV = (0x03 << 6) | OPC_DEXTR_W_DSP,
806 OPC_DEXTR_L = (0x10 << 6) | OPC_DEXTR_W_DSP,
807 OPC_DEXTR_R_L = (0x14 << 6) | OPC_DEXTR_W_DSP,
808 OPC_DEXTR_RS_L = (0x16 << 6) | OPC_DEXTR_W_DSP,
809 OPC_DEXTR_W = (0x00 << 6) | OPC_DEXTR_W_DSP,
810 OPC_DEXTR_R_W = (0x04 << 6) | OPC_DEXTR_W_DSP,
811 OPC_DEXTR_RS_W = (0x06 << 6) | OPC_DEXTR_W_DSP,
812 OPC_DEXTR_S_H = (0x0E << 6) | OPC_DEXTR_W_DSP,
813 OPC_DEXTRV_L = (0x11 << 6) | OPC_DEXTR_W_DSP,
814 OPC_DEXTRV_R_L = (0x15 << 6) | OPC_DEXTR_W_DSP,
815 OPC_DEXTRV_RS_L = (0x17 << 6) | OPC_DEXTR_W_DSP,
816 OPC_DEXTRV_S_H = (0x0F << 6) | OPC_DEXTR_W_DSP,
817 OPC_DEXTRV_W = (0x01 << 6) | OPC_DEXTR_W_DSP,
818 OPC_DEXTRV_R_W = (0x05 << 6) | OPC_DEXTR_W_DSP,
819 OPC_DEXTRV_RS_W = (0x07 << 6) | OPC_DEXTR_W_DSP,
820 OPC_DSHILOV = (0x1B << 6) | OPC_DEXTR_W_DSP,
821 };
822
823 #define MASK_DINSV(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
824 enum {
825 /* DSP Bit/Manipulation Sub-class */
826 OPC_DINSV = (0x00 << 6) | OPC_DINSV_DSP,
827 };
828
829 #define MASK_DPAQ_W_QH(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
830 enum {
831 /* MIPS DSP Multiply Sub-class insns */
832 OPC_DMADD = (0x19 << 6) | OPC_DPAQ_W_QH_DSP,
833 OPC_DMADDU = (0x1D << 6) | OPC_DPAQ_W_QH_DSP,
834 OPC_DMSUB = (0x1B << 6) | OPC_DPAQ_W_QH_DSP,
835 OPC_DMSUBU = (0x1F << 6) | OPC_DPAQ_W_QH_DSP,
836 OPC_DPA_W_QH = (0x00 << 6) | OPC_DPAQ_W_QH_DSP,
837 OPC_DPAQ_S_W_QH = (0x04 << 6) | OPC_DPAQ_W_QH_DSP,
838 OPC_DPAQ_SA_L_PW = (0x0C << 6) | OPC_DPAQ_W_QH_DSP,
839 OPC_DPAU_H_OBL = (0x03 << 6) | OPC_DPAQ_W_QH_DSP,
840 OPC_DPAU_H_OBR = (0x07 << 6) | OPC_DPAQ_W_QH_DSP,
841 OPC_DPS_W_QH = (0x01 << 6) | OPC_DPAQ_W_QH_DSP,
842 OPC_DPSQ_S_W_QH = (0x05 << 6) | OPC_DPAQ_W_QH_DSP,
843 OPC_DPSQ_SA_L_PW = (0x0D << 6) | OPC_DPAQ_W_QH_DSP,
844 OPC_DPSU_H_OBL = (0x0B << 6) | OPC_DPAQ_W_QH_DSP,
845 OPC_DPSU_H_OBR = (0x0F << 6) | OPC_DPAQ_W_QH_DSP,
846 OPC_MAQ_S_L_PWL = (0x1C << 6) | OPC_DPAQ_W_QH_DSP,
847 OPC_MAQ_S_L_PWR = (0x1E << 6) | OPC_DPAQ_W_QH_DSP,
848 OPC_MAQ_S_W_QHLL = (0x14 << 6) | OPC_DPAQ_W_QH_DSP,
849 OPC_MAQ_SA_W_QHLL = (0x10 << 6) | OPC_DPAQ_W_QH_DSP,
850 OPC_MAQ_S_W_QHLR = (0x15 << 6) | OPC_DPAQ_W_QH_DSP,
851 OPC_MAQ_SA_W_QHLR = (0x11 << 6) | OPC_DPAQ_W_QH_DSP,
852 OPC_MAQ_S_W_QHRL = (0x16 << 6) | OPC_DPAQ_W_QH_DSP,
853 OPC_MAQ_SA_W_QHRL = (0x12 << 6) | OPC_DPAQ_W_QH_DSP,
854 OPC_MAQ_S_W_QHRR = (0x17 << 6) | OPC_DPAQ_W_QH_DSP,
855 OPC_MAQ_SA_W_QHRR = (0x13 << 6) | OPC_DPAQ_W_QH_DSP,
856 OPC_MULSAQ_S_L_PW = (0x0E << 6) | OPC_DPAQ_W_QH_DSP,
857 OPC_MULSAQ_S_W_QH = (0x06 << 6) | OPC_DPAQ_W_QH_DSP,
858 };
859
860 #define MASK_SHLL_OB(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6)))
861 enum {
862 /* MIPS DSP GPR-Based Shift Sub-class */
863 OPC_SHLL_PW = (0x10 << 6) | OPC_SHLL_OB_DSP,
864 OPC_SHLL_S_PW = (0x14 << 6) | OPC_SHLL_OB_DSP,
865 OPC_SHLLV_OB = (0x02 << 6) | OPC_SHLL_OB_DSP,
866 OPC_SHLLV_PW = (0x12 << 6) | OPC_SHLL_OB_DSP,
867 OPC_SHLLV_S_PW = (0x16 << 6) | OPC_SHLL_OB_DSP,
868 OPC_SHLLV_QH = (0x0A << 6) | OPC_SHLL_OB_DSP,
869 OPC_SHLLV_S_QH = (0x0E << 6) | OPC_SHLL_OB_DSP,
870 OPC_SHRA_PW = (0x11 << 6) | OPC_SHLL_OB_DSP,
871 OPC_SHRA_R_PW = (0x15 << 6) | OPC_SHLL_OB_DSP,
872 OPC_SHRAV_OB = (0x06 << 6) | OPC_SHLL_OB_DSP,
873 OPC_SHRAV_R_OB = (0x07 << 6) | OPC_SHLL_OB_DSP,
874 OPC_SHRAV_PW = (0x13 << 6) | OPC_SHLL_OB_DSP,
875 OPC_SHRAV_R_PW = (0x17 << 6) | OPC_SHLL_OB_DSP,
876 OPC_SHRAV_QH = (0x0B << 6) | OPC_SHLL_OB_DSP,
877 OPC_SHRAV_R_QH = (0x0F << 6) | OPC_SHLL_OB_DSP,
878 OPC_SHRLV_OB = (0x03 << 6) | OPC_SHLL_OB_DSP,
879 OPC_SHRLV_QH = (0x1B << 6) | OPC_SHLL_OB_DSP,
880 OPC_SHLL_OB = (0x00 << 6) | OPC_SHLL_OB_DSP,
881 OPC_SHLL_QH = (0x08 << 6) | OPC_SHLL_OB_DSP,
882 OPC_SHLL_S_QH = (0x0C << 6) | OPC_SHLL_OB_DSP,
883 OPC_SHRA_OB = (0x04 << 6) | OPC_SHLL_OB_DSP,
884 OPC_SHRA_R_OB = (0x05 << 6) | OPC_SHLL_OB_DSP,
885 OPC_SHRA_QH = (0x09 << 6) | OPC_SHLL_OB_DSP,
886 OPC_SHRA_R_QH = (0x0D << 6) | OPC_SHLL_OB_DSP,
887 OPC_SHRL_OB = (0x01 << 6) | OPC_SHLL_OB_DSP,
888 OPC_SHRL_QH = (0x19 << 6) | OPC_SHLL_OB_DSP,
889 };
890
891 /* Coprocessor 0 (rs field) */
892 #define MASK_CP0(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
893
894 enum {
895 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
896 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
897 OPC_MFHC0 = (0x02 << 21) | OPC_CP0,
898 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
899 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
900 OPC_MTHC0 = (0x06 << 21) | OPC_CP0,
901 OPC_MFTR = (0x08 << 21) | OPC_CP0,
902 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
903 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
904 OPC_MTTR = (0x0C << 21) | OPC_CP0,
905 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
906 OPC_C0 = (0x10 << 21) | OPC_CP0,
907 OPC_C0_1 = (0x11 << 21) | OPC_CP0,
908 OPC_C0_2 = (0x12 << 21) | OPC_CP0,
909 OPC_C0_3 = (0x13 << 21) | OPC_CP0,
910 OPC_C0_4 = (0x14 << 21) | OPC_CP0,
911 OPC_C0_5 = (0x15 << 21) | OPC_CP0,
912 OPC_C0_6 = (0x16 << 21) | OPC_CP0,
913 OPC_C0_7 = (0x17 << 21) | OPC_CP0,
914 OPC_C0_8 = (0x18 << 21) | OPC_CP0,
915 OPC_C0_9 = (0x19 << 21) | OPC_CP0,
916 OPC_C0_A = (0x1A << 21) | OPC_CP0,
917 OPC_C0_B = (0x1B << 21) | OPC_CP0,
918 OPC_C0_C = (0x1C << 21) | OPC_CP0,
919 OPC_C0_D = (0x1D << 21) | OPC_CP0,
920 OPC_C0_E = (0x1E << 21) | OPC_CP0,
921 OPC_C0_F = (0x1F << 21) | OPC_CP0,
922 };
923
924 /* MFMC0 opcodes */
925 #define MASK_MFMC0(op) (MASK_CP0(op) | (op & 0xFFFF))
926
927 enum {
928 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
929 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
930 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
931 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
932 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
933 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
934 OPC_DVP = 0x04 | (0 << 3) | (1 << 5) | (0 << 11) | OPC_MFMC0,
935 OPC_EVP = 0x04 | (0 << 3) | (0 << 5) | (0 << 11) | OPC_MFMC0,
936 };
937
938 /* Coprocessor 0 (with rs == C0) */
939 #define MASK_C0(op) (MASK_CP0(op) | (op & 0x3F))
940
941 enum {
942 OPC_TLBR = 0x01 | OPC_C0,
943 OPC_TLBWI = 0x02 | OPC_C0,
944 OPC_TLBINV = 0x03 | OPC_C0,
945 OPC_TLBINVF = 0x04 | OPC_C0,
946 OPC_TLBWR = 0x06 | OPC_C0,
947 OPC_TLBP = 0x08 | OPC_C0,
948 OPC_RFE = 0x10 | OPC_C0,
949 OPC_ERET = 0x18 | OPC_C0,
950 OPC_DERET = 0x1F | OPC_C0,
951 OPC_WAIT = 0x20 | OPC_C0,
952 };
953
954 #define MASK_CP2(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)))
955
956 enum {
957 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
958 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
959 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
960 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
961 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
962 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
963 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
964 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
965 OPC_BC2 = (0x08 << 21) | OPC_CP2,
966 OPC_BC2EQZ = (0x09 << 21) | OPC_CP2,
967 OPC_BC2NEZ = (0x0D << 21) | OPC_CP2,
968 };
969
970 #define MASK_LMMI(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 21)) | (op & 0x1F))
971
972 enum {
973 OPC_PADDSH = (24 << 21) | (0x00) | OPC_CP2,
974 OPC_PADDUSH = (25 << 21) | (0x00) | OPC_CP2,
975 OPC_PADDH = (26 << 21) | (0x00) | OPC_CP2,
976 OPC_PADDW = (27 << 21) | (0x00) | OPC_CP2,
977 OPC_PADDSB = (28 << 21) | (0x00) | OPC_CP2,
978 OPC_PADDUSB = (29 << 21) | (0x00) | OPC_CP2,
979 OPC_PADDB = (30 << 21) | (0x00) | OPC_CP2,
980 OPC_PADDD = (31 << 21) | (0x00) | OPC_CP2,
981
982 OPC_PSUBSH = (24 << 21) | (0x01) | OPC_CP2,
983 OPC_PSUBUSH = (25 << 21) | (0x01) | OPC_CP2,
984 OPC_PSUBH = (26 << 21) | (0x01) | OPC_CP2,
985 OPC_PSUBW = (27 << 21) | (0x01) | OPC_CP2,
986 OPC_PSUBSB = (28 << 21) | (0x01) | OPC_CP2,
987 OPC_PSUBUSB = (29 << 21) | (0x01) | OPC_CP2,
988 OPC_PSUBB = (30 << 21) | (0x01) | OPC_CP2,
989 OPC_PSUBD = (31 << 21) | (0x01) | OPC_CP2,
990
991 OPC_PSHUFH = (24 << 21) | (0x02) | OPC_CP2,
992 OPC_PACKSSWH = (25 << 21) | (0x02) | OPC_CP2,
993 OPC_PACKSSHB = (26 << 21) | (0x02) | OPC_CP2,
994 OPC_PACKUSHB = (27 << 21) | (0x02) | OPC_CP2,
995 OPC_XOR_CP2 = (28 << 21) | (0x02) | OPC_CP2,
996 OPC_NOR_CP2 = (29 << 21) | (0x02) | OPC_CP2,
997 OPC_AND_CP2 = (30 << 21) | (0x02) | OPC_CP2,
998 OPC_PANDN = (31 << 21) | (0x02) | OPC_CP2,
999
1000 OPC_PUNPCKLHW = (24 << 21) | (0x03) | OPC_CP2,
1001 OPC_PUNPCKHHW = (25 << 21) | (0x03) | OPC_CP2,
1002 OPC_PUNPCKLBH = (26 << 21) | (0x03) | OPC_CP2,
1003 OPC_PUNPCKHBH = (27 << 21) | (0x03) | OPC_CP2,
1004 OPC_PINSRH_0 = (28 << 21) | (0x03) | OPC_CP2,
1005 OPC_PINSRH_1 = (29 << 21) | (0x03) | OPC_CP2,
1006 OPC_PINSRH_2 = (30 << 21) | (0x03) | OPC_CP2,
1007 OPC_PINSRH_3 = (31 << 21) | (0x03) | OPC_CP2,
1008
1009 OPC_PAVGH = (24 << 21) | (0x08) | OPC_CP2,
1010 OPC_PAVGB = (25 << 21) | (0x08) | OPC_CP2,
1011 OPC_PMAXSH = (26 << 21) | (0x08) | OPC_CP2,
1012 OPC_PMINSH = (27 << 21) | (0x08) | OPC_CP2,
1013 OPC_PMAXUB = (28 << 21) | (0x08) | OPC_CP2,
1014 OPC_PMINUB = (29 << 21) | (0x08) | OPC_CP2,
1015
1016 OPC_PCMPEQW = (24 << 21) | (0x09) | OPC_CP2,
1017 OPC_PCMPGTW = (25 << 21) | (0x09) | OPC_CP2,
1018 OPC_PCMPEQH = (26 << 21) | (0x09) | OPC_CP2,
1019 OPC_PCMPGTH = (27 << 21) | (0x09) | OPC_CP2,
1020 OPC_PCMPEQB = (28 << 21) | (0x09) | OPC_CP2,
1021 OPC_PCMPGTB = (29 << 21) | (0x09) | OPC_CP2,
1022
1023 OPC_PSLLW = (24 << 21) | (0x0A) | OPC_CP2,
1024 OPC_PSLLH = (25 << 21) | (0x0A) | OPC_CP2,
1025 OPC_PMULLH = (26 << 21) | (0x0A) | OPC_CP2,
1026 OPC_PMULHH = (27 << 21) | (0x0A) | OPC_CP2,
1027 OPC_PMULUW = (28 << 21) | (0x0A) | OPC_CP2,
1028 OPC_PMULHUH = (29 << 21) | (0x0A) | OPC_CP2,
1029
1030 OPC_PSRLW = (24 << 21) | (0x0B) | OPC_CP2,
1031 OPC_PSRLH = (25 << 21) | (0x0B) | OPC_CP2,
1032 OPC_PSRAW = (26 << 21) | (0x0B) | OPC_CP2,
1033 OPC_PSRAH = (27 << 21) | (0x0B) | OPC_CP2,
1034 OPC_PUNPCKLWD = (28 << 21) | (0x0B) | OPC_CP2,
1035 OPC_PUNPCKHWD = (29 << 21) | (0x0B) | OPC_CP2,
1036
1037 OPC_ADDU_CP2 = (24 << 21) | (0x0C) | OPC_CP2,
1038 OPC_OR_CP2 = (25 << 21) | (0x0C) | OPC_CP2,
1039 OPC_ADD_CP2 = (26 << 21) | (0x0C) | OPC_CP2,
1040 OPC_DADD_CP2 = (27 << 21) | (0x0C) | OPC_CP2,
1041 OPC_SEQU_CP2 = (28 << 21) | (0x0C) | OPC_CP2,
1042 OPC_SEQ_CP2 = (29 << 21) | (0x0C) | OPC_CP2,
1043
1044 OPC_SUBU_CP2 = (24 << 21) | (0x0D) | OPC_CP2,
1045 OPC_PASUBUB = (25 << 21) | (0x0D) | OPC_CP2,
1046 OPC_SUB_CP2 = (26 << 21) | (0x0D) | OPC_CP2,
1047 OPC_DSUB_CP2 = (27 << 21) | (0x0D) | OPC_CP2,
1048 OPC_SLTU_CP2 = (28 << 21) | (0x0D) | OPC_CP2,
1049 OPC_SLT_CP2 = (29 << 21) | (0x0D) | OPC_CP2,
1050
1051 OPC_SLL_CP2 = (24 << 21) | (0x0E) | OPC_CP2,
1052 OPC_DSLL_CP2 = (25 << 21) | (0x0E) | OPC_CP2,
1053 OPC_PEXTRH = (26 << 21) | (0x0E) | OPC_CP2,
1054 OPC_PMADDHW = (27 << 21) | (0x0E) | OPC_CP2,
1055 OPC_SLEU_CP2 = (28 << 21) | (0x0E) | OPC_CP2,
1056 OPC_SLE_CP2 = (29 << 21) | (0x0E) | OPC_CP2,
1057
1058 OPC_SRL_CP2 = (24 << 21) | (0x0F) | OPC_CP2,
1059 OPC_DSRL_CP2 = (25 << 21) | (0x0F) | OPC_CP2,
1060 OPC_SRA_CP2 = (26 << 21) | (0x0F) | OPC_CP2,
1061 OPC_DSRA_CP2 = (27 << 21) | (0x0F) | OPC_CP2,
1062 OPC_BIADD = (28 << 21) | (0x0F) | OPC_CP2,
1063 OPC_PMOVMSKB = (29 << 21) | (0x0F) | OPC_CP2,
1064 };
1065
1066
1067 #define MASK_CP3(op) (MASK_OP_MAJOR(op) | (op & 0x3F))
1068
1069 enum {
1070 OPC_LWXC1 = 0x00 | OPC_CP3,
1071 OPC_LDXC1 = 0x01 | OPC_CP3,
1072 OPC_LUXC1 = 0x05 | OPC_CP3,
1073 OPC_SWXC1 = 0x08 | OPC_CP3,
1074 OPC_SDXC1 = 0x09 | OPC_CP3,
1075 OPC_SUXC1 = 0x0D | OPC_CP3,
1076 OPC_PREFX = 0x0F | OPC_CP3,
1077 OPC_ALNV_PS = 0x1E | OPC_CP3,
1078 OPC_MADD_S = 0x20 | OPC_CP3,
1079 OPC_MADD_D = 0x21 | OPC_CP3,
1080 OPC_MADD_PS = 0x26 | OPC_CP3,
1081 OPC_MSUB_S = 0x28 | OPC_CP3,
1082 OPC_MSUB_D = 0x29 | OPC_CP3,
1083 OPC_MSUB_PS = 0x2E | OPC_CP3,
1084 OPC_NMADD_S = 0x30 | OPC_CP3,
1085 OPC_NMADD_D = 0x31 | OPC_CP3,
1086 OPC_NMADD_PS = 0x36 | OPC_CP3,
1087 OPC_NMSUB_S = 0x38 | OPC_CP3,
1088 OPC_NMSUB_D = 0x39 | OPC_CP3,
1089 OPC_NMSUB_PS = 0x3E | OPC_CP3,
1090 };
1091
1092 /*
1093 * MMI (MultiMedia Instruction) encodings
1094 * ======================================
1095 *
1096 * MMI instructions encoding table keys:
1097 *
1098 * * This code is reserved for future use. An attempt to execute it
1099 * causes a Reserved Instruction exception.
1100 * % This code indicates an instruction class. The instruction word
1101 * must be further decoded by examining additional tables that show
1102 * the values for other instruction fields.
1103 * # This code is reserved for the unsupported instructions DMULT,
1104 * DMULTU, DDIV, DDIVU, LL, LLD, SC, SCD, LWC2 and SWC2. An attempt
1105 * to execute it causes a Reserved Instruction exception.
1106 *
1107 * MMI instructions encoded by opcode field (MMI, LQ, SQ):
1108 *
1109 * 31 26 0
1110 * +--------+----------------------------------------+
1111 * | opcode | |
1112 * +--------+----------------------------------------+
1113 *
1114 * opcode bits 28..26
1115 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1116 * 31..29 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1117 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1118 * 0 000 |SPECIAL| REGIMM| J | JAL | BEQ | BNE | BLEZ | BGTZ
1119 * 1 001 | ADDI | ADDIU | SLTI | SLTIU | ANDI | ORI | XORI | LUI
1120 * 2 010 | COP0 | COP1 | * | * | BEQL | BNEL | BLEZL | BGTZL
1121 * 3 011 | DADDI | DADDIU| LDL | LDR | MMI% | * | LQ | SQ
1122 * 4 100 | LB | LH | LWL | LW | LBU | LHU | LWR | LWU
1123 * 5 101 | SB | SH | SWL | SW | SDL | SDR | SWR | CACHE
1124 * 6 110 | # | LWC1 | # | PREF | # | LDC1 | # | LD
1125 * 7 111 | # | SWC1 | # | * | # | SDC1 | # | SD
1126 */
1127
1128 enum {
1129 MMI_OPC_CLASS_MMI = 0x1C << 26, /* Same as OPC_SPECIAL2 */
1130 MMI_OPC_SQ = 0x1F << 26, /* Same as OPC_SPECIAL3 */
1131 };
1132
1133 /*
1134 * MMI instructions with opcode field = MMI:
1135 *
1136 * 31 26 5 0
1137 * +--------+-------------------------------+--------+
1138 * | MMI | |function|
1139 * +--------+-------------------------------+--------+
1140 *
1141 * function bits 2..0
1142 * bits | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
1143 * 5..3 | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111
1144 * -------+-------+-------+-------+-------+-------+-------+-------+-------
1145 * 0 000 | MADD | MADDU | * | * | PLZCW | * | * | *
1146 * 1 001 | MMI0% | MMI2% | * | * | * | * | * | *
1147 * 2 010 | MFHI1 | MTHI1 | MFLO1 | MTLO1 | * | * | * | *
1148 * 3 011 | MULT1 | MULTU1| DIV1 | DIVU1 | * | * | * | *
1149 * 4 100 | MADD1 | MADDU1| * | * | * | * | * | *
1150 * 5 101 | MMI1% | MMI3% | * | * | * | * | * | *
1151 * 6 110 | PMFHL | PMTHL | * | * | PSLLH | * | PSRLH | PSRAH
1152 * 7 111 | * | * | * | * | PSLLW | * | PSRLW | PSRAW
1153 */
1154
1155 #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F))
1156 enum {
1157 MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */
1158 MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */
1159 MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */
1160 MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */
1161 MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */
1162 MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */
1163 MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI,
1164 MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI,
1165 };
1166
1167 /* global register indices */
1168 TCGv cpu_gpr[32], cpu_PC;
1169 /*
1170 * For CPUs using 128-bit GPR registers, we put the lower halves in cpu_gpr[])
1171 * and the upper halves in cpu_gpr_hi[].
1172 */
1173 TCGv_i64 cpu_gpr_hi[32];
1174 TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC];
1175 static TCGv cpu_dspctrl, btarget;
1176 TCGv bcond;
1177 static TCGv cpu_lladdr, cpu_llval;
1178 static TCGv_i32 hflags;
1179 TCGv_i32 fpu_fcr0, fpu_fcr31;
1180 TCGv_i64 fpu_f64[32];
1181
1182 static const char regnames_HI[][4] = {
1183 "HI0", "HI1", "HI2", "HI3",
1184 };
1185
1186 static const char regnames_LO[][4] = {
1187 "LO0", "LO1", "LO2", "LO3",
1188 };
1189
1190 /* General purpose registers moves. */
gen_load_gpr(TCGv t,int reg)1191 void gen_load_gpr(TCGv t, int reg)
1192 {
1193 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr));
1194 if (reg == 0) {
1195 tcg_gen_movi_tl(t, 0);
1196 } else {
1197 tcg_gen_mov_tl(t, cpu_gpr[reg]);
1198 }
1199 }
1200
gen_store_gpr(TCGv t,int reg)1201 void gen_store_gpr(TCGv t, int reg)
1202 {
1203 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr));
1204 if (reg != 0) {
1205 tcg_gen_mov_tl(cpu_gpr[reg], t);
1206 }
1207 }
1208
1209 #if defined(TARGET_MIPS64)
gen_load_gpr_hi(TCGv_i64 t,int reg)1210 void gen_load_gpr_hi(TCGv_i64 t, int reg)
1211 {
1212 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr_hi));
1213 if (reg == 0) {
1214 tcg_gen_movi_i64(t, 0);
1215 } else {
1216 tcg_gen_mov_i64(t, cpu_gpr_hi[reg]);
1217 }
1218 }
1219
gen_store_gpr_hi(TCGv_i64 t,int reg)1220 void gen_store_gpr_hi(TCGv_i64 t, int reg)
1221 {
1222 assert(reg >= 0 && reg <= ARRAY_SIZE(cpu_gpr_hi));
1223 if (reg != 0) {
1224 tcg_gen_mov_i64(cpu_gpr_hi[reg], t);
1225 }
1226 }
1227 #endif /* TARGET_MIPS64 */
1228
1229 /* Moves to/from shadow registers. */
gen_load_srsgpr(int from,int to)1230 static inline void gen_load_srsgpr(int from, int to)
1231 {
1232 TCGv t0 = tcg_temp_new();
1233
1234 if (from == 0) {
1235 tcg_gen_movi_tl(t0, 0);
1236 } else {
1237 TCGv_i32 t2 = tcg_temp_new_i32();
1238 TCGv_ptr addr = tcg_temp_new_ptr();
1239
1240 tcg_gen_ld_i32(t2, tcg_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1241 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1242 tcg_gen_andi_i32(t2, t2, 0xf);
1243 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1244 tcg_gen_ext_i32_ptr(addr, t2);
1245 tcg_gen_add_ptr(addr, tcg_env, addr);
1246
1247 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
1248 }
1249 gen_store_gpr(t0, to);
1250 }
1251
gen_store_srsgpr(int from,int to)1252 static inline void gen_store_srsgpr(int from, int to)
1253 {
1254 if (to != 0) {
1255 TCGv t0 = tcg_temp_new();
1256 TCGv_i32 t2 = tcg_temp_new_i32();
1257 TCGv_ptr addr = tcg_temp_new_ptr();
1258
1259 gen_load_gpr(t0, from);
1260 tcg_gen_ld_i32(t2, tcg_env, offsetof(CPUMIPSState, CP0_SRSCtl));
1261 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
1262 tcg_gen_andi_i32(t2, t2, 0xf);
1263 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
1264 tcg_gen_ext_i32_ptr(addr, t2);
1265 tcg_gen_add_ptr(addr, tcg_env, addr);
1266
1267 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
1268 }
1269 }
1270
1271 /* Tests */
gen_save_pc(target_ulong pc)1272 static inline void gen_save_pc(target_ulong pc)
1273 {
1274 tcg_gen_movi_tl(cpu_PC, pc);
1275 }
1276
save_cpu_state(DisasContext * ctx,int do_save_pc)1277 static inline void save_cpu_state(DisasContext *ctx, int do_save_pc)
1278 {
1279 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
1280 if (do_save_pc && ctx->base.pc_next != ctx->saved_pc) {
1281 gen_save_pc(ctx->base.pc_next);
1282 ctx->saved_pc = ctx->base.pc_next;
1283 }
1284 if (ctx->hflags != ctx->saved_hflags) {
1285 tcg_gen_movi_i32(hflags, ctx->hflags);
1286 ctx->saved_hflags = ctx->hflags;
1287 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1288 case MIPS_HFLAG_BR:
1289 break;
1290 case MIPS_HFLAG_BC:
1291 case MIPS_HFLAG_BL:
1292 case MIPS_HFLAG_B:
1293 tcg_gen_movi_tl(btarget, ctx->btarget);
1294 break;
1295 }
1296 }
1297 }
1298
restore_cpu_state(CPUMIPSState * env,DisasContext * ctx)1299 static inline void restore_cpu_state(CPUMIPSState *env, DisasContext *ctx)
1300 {
1301 ctx->saved_hflags = ctx->hflags;
1302 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
1303 case MIPS_HFLAG_BR:
1304 break;
1305 case MIPS_HFLAG_BC:
1306 case MIPS_HFLAG_BL:
1307 case MIPS_HFLAG_B:
1308 ctx->btarget = env->btarget;
1309 break;
1310 }
1311 }
1312
generate_exception_err(DisasContext * ctx,int excp,int err)1313 void generate_exception_err(DisasContext *ctx, int excp, int err)
1314 {
1315 save_cpu_state(ctx, 1);
1316 gen_helper_raise_exception_err(tcg_env, tcg_constant_i32(excp),
1317 tcg_constant_i32(err));
1318 ctx->base.is_jmp = DISAS_NORETURN;
1319 }
1320
generate_exception(DisasContext * ctx,int excp)1321 void generate_exception(DisasContext *ctx, int excp)
1322 {
1323 gen_helper_raise_exception(tcg_env, tcg_constant_i32(excp));
1324 }
1325
generate_exception_end(DisasContext * ctx,int excp)1326 void generate_exception_end(DisasContext *ctx, int excp)
1327 {
1328 generate_exception_err(ctx, excp, 0);
1329 }
1330
generate_exception_break(DisasContext * ctx,int code)1331 void generate_exception_break(DisasContext *ctx, int code)
1332 {
1333 #ifdef CONFIG_USER_ONLY
1334 /* Pass the break code along to cpu_loop. */
1335 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
1336 offsetof(CPUMIPSState, error_code));
1337 #endif
1338 generate_exception_end(ctx, EXCP_BREAK);
1339 }
1340
gen_reserved_instruction(DisasContext * ctx)1341 void gen_reserved_instruction(DisasContext *ctx)
1342 {
1343 generate_exception_end(ctx, EXCP_RI);
1344 }
1345
1346 /* Floating point register moves. */
gen_load_fpr32(DisasContext * ctx,TCGv_i32 t,int reg)1347 void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1348 {
1349 if (ctx->hflags & MIPS_HFLAG_FRE) {
1350 generate_exception(ctx, EXCP_RI);
1351 }
1352 tcg_gen_extrl_i64_i32(t, fpu_f64[reg]);
1353 }
1354
gen_store_fpr32(DisasContext * ctx,TCGv_i32 t,int reg)1355 void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
1356 {
1357 TCGv_i64 t64;
1358 if (ctx->hflags & MIPS_HFLAG_FRE) {
1359 generate_exception(ctx, EXCP_RI);
1360 }
1361 t64 = tcg_temp_new_i64();
1362 tcg_gen_extu_i32_i64(t64, t);
1363 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 0, 32);
1364 }
1365
gen_load_fpr32h(DisasContext * ctx,TCGv_i32 t,int reg)1366 static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1367 {
1368 if (ctx->hflags & MIPS_HFLAG_F64) {
1369 tcg_gen_extrh_i64_i32(t, fpu_f64[reg]);
1370 } else {
1371 gen_load_fpr32(ctx, t, reg | 1);
1372 }
1373 }
1374
gen_store_fpr32h(DisasContext * ctx,TCGv_i32 t,int reg)1375 static void gen_store_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
1376 {
1377 if (ctx->hflags & MIPS_HFLAG_F64) {
1378 TCGv_i64 t64 = tcg_temp_new_i64();
1379 tcg_gen_extu_i32_i64(t64, t);
1380 tcg_gen_deposit_i64(fpu_f64[reg], fpu_f64[reg], t64, 32, 32);
1381 } else {
1382 gen_store_fpr32(ctx, t, reg | 1);
1383 }
1384 }
1385
gen_load_fpr64(DisasContext * ctx,TCGv_i64 t,int reg)1386 void gen_load_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1387 {
1388 if (ctx->hflags & MIPS_HFLAG_F64) {
1389 tcg_gen_mov_i64(t, fpu_f64[reg]);
1390 } else {
1391 tcg_gen_concat32_i64(t, fpu_f64[reg & ~1], fpu_f64[reg | 1]);
1392 }
1393 }
1394
gen_store_fpr64(DisasContext * ctx,TCGv_i64 t,int reg)1395 void gen_store_fpr64(DisasContext *ctx, TCGv_i64 t, int reg)
1396 {
1397 if (ctx->hflags & MIPS_HFLAG_F64) {
1398 tcg_gen_mov_i64(fpu_f64[reg], t);
1399 } else {
1400 TCGv_i64 t0;
1401 tcg_gen_deposit_i64(fpu_f64[reg & ~1], fpu_f64[reg & ~1], t, 0, 32);
1402 t0 = tcg_temp_new_i64();
1403 tcg_gen_shri_i64(t0, t, 32);
1404 tcg_gen_deposit_i64(fpu_f64[reg | 1], fpu_f64[reg | 1], t0, 0, 32);
1405 }
1406 }
1407
get_fp_bit(int cc)1408 int get_fp_bit(int cc)
1409 {
1410 if (cc) {
1411 return 24 + cc;
1412 } else {
1413 return 23;
1414 }
1415 }
1416
1417 /* Addresses computation */
gen_op_addr_add(DisasContext * ctx,TCGv ret,TCGv arg0,TCGv arg1)1418 void gen_op_addr_add(DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
1419 {
1420 tcg_gen_add_tl(ret, arg0, arg1);
1421
1422 #if defined(TARGET_MIPS64)
1423 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1424 tcg_gen_ext32s_i64(ret, ret);
1425 }
1426 #endif
1427 }
1428
gen_op_addr_addi(DisasContext * ctx,TCGv ret,TCGv base,target_long ofs)1429 void gen_op_addr_addi(DisasContext *ctx, TCGv ret, TCGv base, target_long ofs)
1430 {
1431 tcg_gen_addi_tl(ret, base, ofs);
1432
1433 #if defined(TARGET_MIPS64)
1434 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1435 tcg_gen_ext32s_i64(ret, ret);
1436 }
1437 #endif
1438 }
1439
1440 /* Addresses computation (translation time) */
addr_add(DisasContext * ctx,target_long base,target_long offset)1441 static target_long addr_add(DisasContext *ctx, target_long base,
1442 target_long offset)
1443 {
1444 target_long sum = base + offset;
1445
1446 #if defined(TARGET_MIPS64)
1447 if (ctx->hflags & MIPS_HFLAG_AWRAP) {
1448 sum = (int32_t)sum;
1449 }
1450 #endif
1451 return sum;
1452 }
1453
1454 /* Sign-extract the low 32-bits to a target_long. */
gen_move_low32(TCGv ret,TCGv_i64 arg)1455 void gen_move_low32(TCGv ret, TCGv_i64 arg)
1456 {
1457 #if defined(TARGET_MIPS64)
1458 tcg_gen_ext32s_i64(ret, arg);
1459 #else
1460 tcg_gen_extrl_i64_i32(ret, arg);
1461 #endif
1462 }
1463
1464 /* Sign-extract the high 32-bits to a target_long. */
gen_move_high32(TCGv ret,TCGv_i64 arg)1465 void gen_move_high32(TCGv ret, TCGv_i64 arg)
1466 {
1467 #if defined(TARGET_MIPS64)
1468 tcg_gen_sari_i64(ret, arg, 32);
1469 #else
1470 tcg_gen_extrh_i64_i32(ret, arg);
1471 #endif
1472 }
1473
check_cp0_enabled(DisasContext * ctx)1474 bool check_cp0_enabled(DisasContext *ctx)
1475 {
1476 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1477 generate_exception_end(ctx, EXCP_CpU);
1478 return false;
1479 }
1480 return true;
1481 }
1482
check_cp1_enabled(DisasContext * ctx)1483 void check_cp1_enabled(DisasContext *ctx)
1484 {
1485 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU))) {
1486 generate_exception_err(ctx, EXCP_CpU, 1);
1487 }
1488 }
1489
1490 /*
1491 * Verify that the processor is running with COP1X instructions enabled.
1492 * This is associated with the nabla symbol in the MIPS32 and MIPS64
1493 * opcode tables.
1494 */
check_cop1x(DisasContext * ctx)1495 void check_cop1x(DisasContext *ctx)
1496 {
1497 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X))) {
1498 gen_reserved_instruction(ctx);
1499 }
1500 }
1501
1502 /*
1503 * Verify that the processor is running with 64-bit floating-point
1504 * operations enabled.
1505 */
check_cp1_64bitmode(DisasContext * ctx)1506 void check_cp1_64bitmode(DisasContext *ctx)
1507 {
1508 if (unlikely(~ctx->hflags & MIPS_HFLAG_F64)) {
1509 gen_reserved_instruction(ctx);
1510 }
1511 }
1512
1513 /*
1514 * Verify if floating point register is valid; an operation is not defined
1515 * if bit 0 of any register specification is set and the FR bit in the
1516 * Status register equals zero, since the register numbers specify an
1517 * even-odd pair of adjacent coprocessor general registers. When the FR bit
1518 * in the Status register equals one, both even and odd register numbers
1519 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
1520 *
1521 * Multiple 64 bit wide registers can be checked by calling
1522 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
1523 */
check_cp1_registers(DisasContext * ctx,int regs)1524 void check_cp1_registers(DisasContext *ctx, int regs)
1525 {
1526 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1))) {
1527 gen_reserved_instruction(ctx);
1528 }
1529 }
1530
1531 /*
1532 * Verify that the processor is running with DSP instructions enabled.
1533 * This is enabled by CP0 Status register MX(24) bit.
1534 */
check_dsp(DisasContext * ctx)1535 static inline void check_dsp(DisasContext *ctx)
1536 {
1537 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP))) {
1538 if (ctx->insn_flags & ASE_DSP) {
1539 generate_exception_end(ctx, EXCP_DSPDIS);
1540 } else {
1541 gen_reserved_instruction(ctx);
1542 }
1543 }
1544 }
1545
check_dsp_r2(DisasContext * ctx)1546 static inline void check_dsp_r2(DisasContext *ctx)
1547 {
1548 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R2))) {
1549 if (ctx->insn_flags & ASE_DSP) {
1550 generate_exception_end(ctx, EXCP_DSPDIS);
1551 } else {
1552 gen_reserved_instruction(ctx);
1553 }
1554 }
1555 }
1556
check_dsp_r3(DisasContext * ctx)1557 static inline void check_dsp_r3(DisasContext *ctx)
1558 {
1559 if (unlikely(!(ctx->hflags & MIPS_HFLAG_DSP_R3))) {
1560 if (ctx->insn_flags & ASE_DSP) {
1561 generate_exception_end(ctx, EXCP_DSPDIS);
1562 } else {
1563 gen_reserved_instruction(ctx);
1564 }
1565 }
1566 }
1567
1568 /*
1569 * This code generates a "reserved instruction" exception if the
1570 * CPU does not support the instruction set corresponding to flags.
1571 */
check_insn(DisasContext * ctx,uint64_t flags)1572 void check_insn(DisasContext *ctx, uint64_t flags)
1573 {
1574 if (unlikely(!(ctx->insn_flags & flags))) {
1575 gen_reserved_instruction(ctx);
1576 }
1577 }
1578
1579 /*
1580 * This code generates a "reserved instruction" exception if the
1581 * CPU has corresponding flag set which indicates that the instruction
1582 * has been removed.
1583 */
check_insn_opc_removed(DisasContext * ctx,uint64_t flags)1584 static inline void check_insn_opc_removed(DisasContext *ctx, uint64_t flags)
1585 {
1586 if (unlikely(ctx->insn_flags & flags)) {
1587 gen_reserved_instruction(ctx);
1588 }
1589 }
1590
1591 /*
1592 * The Linux kernel traps certain reserved instruction exceptions to
1593 * emulate the corresponding instructions. QEMU is the kernel in user
1594 * mode, so those traps are emulated by accepting the instructions.
1595 *
1596 * A reserved instruction exception is generated for flagged CPUs if
1597 * QEMU runs in system mode.
1598 */
check_insn_opc_user_only(DisasContext * ctx,uint64_t flags)1599 static inline void check_insn_opc_user_only(DisasContext *ctx, uint64_t flags)
1600 {
1601 #ifndef CONFIG_USER_ONLY
1602 check_insn_opc_removed(ctx, flags);
1603 #endif
1604 }
1605
1606 /*
1607 * This code generates a "reserved instruction" exception if the
1608 * CPU does not support 64-bit paired-single (PS) floating point data type.
1609 */
check_ps(DisasContext * ctx)1610 static inline void check_ps(DisasContext *ctx)
1611 {
1612 if (unlikely(!ctx->ps)) {
1613 generate_exception(ctx, EXCP_RI);
1614 }
1615 check_cp1_64bitmode(ctx);
1616 }
1617
decode_64bit_enabled(DisasContext * ctx)1618 bool decode_64bit_enabled(DisasContext *ctx)
1619 {
1620 return ctx->hflags & MIPS_HFLAG_64;
1621 }
1622
1623 /*
1624 * This code generates a "reserved instruction" exception if cpu is not
1625 * 64-bit or 64-bit instructions are not enabled.
1626 */
check_mips_64(DisasContext * ctx)1627 void check_mips_64(DisasContext *ctx)
1628 {
1629 if (unlikely((TARGET_LONG_BITS != 64) || !decode_64bit_enabled(ctx))) {
1630 gen_reserved_instruction(ctx);
1631 }
1632 }
1633
1634 #ifndef CONFIG_USER_ONLY
check_mvh(DisasContext * ctx)1635 static inline void check_mvh(DisasContext *ctx)
1636 {
1637 if (unlikely(!ctx->mvh)) {
1638 generate_exception(ctx, EXCP_RI);
1639 }
1640 }
1641 #endif
1642
1643 /*
1644 * This code generates a "reserved instruction" exception if the
1645 * Config5 XNP bit is set.
1646 */
check_xnp(DisasContext * ctx)1647 static inline void check_xnp(DisasContext *ctx)
1648 {
1649 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_XNP))) {
1650 gen_reserved_instruction(ctx);
1651 }
1652 }
1653
1654 #ifndef CONFIG_USER_ONLY
1655 /*
1656 * This code generates a "reserved instruction" exception if the
1657 * Config3 PW bit is NOT set.
1658 */
check_pw(DisasContext * ctx)1659 static inline void check_pw(DisasContext *ctx)
1660 {
1661 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_PW)))) {
1662 gen_reserved_instruction(ctx);
1663 }
1664 }
1665 #endif
1666
1667 /*
1668 * This code generates a "reserved instruction" exception if the
1669 * Config3 MT bit is NOT set.
1670 */
check_mt(DisasContext * ctx)1671 static inline void check_mt(DisasContext *ctx)
1672 {
1673 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1674 gen_reserved_instruction(ctx);
1675 }
1676 }
1677
1678 #ifndef CONFIG_USER_ONLY
1679 /*
1680 * This code generates a "coprocessor unusable" exception if CP0 is not
1681 * available, and, if that is not the case, generates a "reserved instruction"
1682 * exception if the Config5 MT bit is NOT set. This is needed for availability
1683 * control of some of MT ASE instructions.
1684 */
check_cp0_mt(DisasContext * ctx)1685 static inline void check_cp0_mt(DisasContext *ctx)
1686 {
1687 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0))) {
1688 generate_exception_end(ctx, EXCP_CpU);
1689 } else {
1690 if (unlikely(!(ctx->CP0_Config3 & (1 << CP0C3_MT)))) {
1691 gen_reserved_instruction(ctx);
1692 }
1693 }
1694 }
1695 #endif
1696
1697 /*
1698 * This code generates a "reserved instruction" exception if the
1699 * Config5 NMS bit is set.
1700 */
check_nms(DisasContext * ctx)1701 static inline void check_nms(DisasContext *ctx)
1702 {
1703 if (unlikely(ctx->CP0_Config5 & (1 << CP0C5_NMS))) {
1704 gen_reserved_instruction(ctx);
1705 }
1706 }
1707
1708 /*
1709 * This code generates a "reserved instruction" exception if the
1710 * Config5 NMS bit is set, and Config1 DL, Config1 IL, Config2 SL,
1711 * Config2 TL, and Config5 L2C are unset.
1712 */
check_nms_dl_il_sl_tl_l2c(DisasContext * ctx)1713 static inline void check_nms_dl_il_sl_tl_l2c(DisasContext *ctx)
1714 {
1715 if (unlikely((ctx->CP0_Config5 & (1 << CP0C5_NMS)) &&
1716 !(ctx->CP0_Config1 & (1 << CP0C1_DL)) &&
1717 !(ctx->CP0_Config1 & (1 << CP0C1_IL)) &&
1718 !(ctx->CP0_Config2 & (1 << CP0C2_SL)) &&
1719 !(ctx->CP0_Config2 & (1 << CP0C2_TL)) &&
1720 !(ctx->CP0_Config5 & (1 << CP0C5_L2C)))) {
1721 gen_reserved_instruction(ctx);
1722 }
1723 }
1724
1725 /*
1726 * This code generates a "reserved instruction" exception if the
1727 * Config5 EVA bit is NOT set.
1728 */
check_eva(DisasContext * ctx)1729 static inline void check_eva(DisasContext *ctx)
1730 {
1731 if (unlikely(!(ctx->CP0_Config5 & (1 << CP0C5_EVA)))) {
1732 gen_reserved_instruction(ctx);
1733 }
1734 }
1735
1736
1737 /*
1738 * Define small wrappers for gen_load_fpr* so that we have a uniform
1739 * calling interface for 32 and 64-bit FPRs. No sense in changing
1740 * all callers for gen_load_fpr32 when we need the CTX parameter for
1741 * this one use.
1742 */
1743 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(ctx, x, y)
1744 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
1745 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
1746 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
1747 int ft, int fs, int cc) \
1748 { \
1749 TCGv_i##bits fp0 = tcg_temp_new_i##bits(); \
1750 TCGv_i##bits fp1 = tcg_temp_new_i##bits(); \
1751 switch (ifmt) { \
1752 case FMT_PS: \
1753 check_ps(ctx); \
1754 break; \
1755 case FMT_D: \
1756 if (abs) { \
1757 check_cop1x(ctx); \
1758 } \
1759 check_cp1_registers(ctx, fs | ft); \
1760 break; \
1761 case FMT_S: \
1762 if (abs) { \
1763 check_cop1x(ctx); \
1764 } \
1765 break; \
1766 } \
1767 gen_ldcmp_fpr##bits(ctx, fp0, fs); \
1768 gen_ldcmp_fpr##bits(ctx, fp1, ft); \
1769 switch (n) { \
1770 case 0: \
1771 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); \
1772 break; \
1773 case 1: \
1774 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); \
1775 break; \
1776 case 2: \
1777 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); \
1778 break; \
1779 case 3: \
1780 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); \
1781 break; \
1782 case 4: \
1783 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); \
1784 break; \
1785 case 5: \
1786 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); \
1787 break; \
1788 case 6: \
1789 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); \
1790 break; \
1791 case 7: \
1792 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); \
1793 break; \
1794 case 8: \
1795 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); \
1796 break; \
1797 case 9: \
1798 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); \
1799 break; \
1800 case 10: \
1801 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); \
1802 break; \
1803 case 11: \
1804 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); \
1805 break; \
1806 case 12: \
1807 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); \
1808 break; \
1809 case 13: \
1810 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); \
1811 break; \
1812 case 14: \
1813 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); \
1814 break; \
1815 case 15: \
1816 gen_helper_0e2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); \
1817 break; \
1818 default: \
1819 abort(); \
1820 } \
1821 }
1822
1823 FOP_CONDS(, 0, d, FMT_D, 64)
1824 FOP_CONDS(abs, 1, d, FMT_D, 64)
1825 FOP_CONDS(, 0, s, FMT_S, 32)
1826 FOP_CONDS(abs, 1, s, FMT_S, 32)
1827 FOP_CONDS(, 0, ps, FMT_PS, 64)
1828 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
1829 #undef FOP_CONDS
1830
1831 #define FOP_CONDNS(fmt, ifmt, bits, STORE) \
1832 static inline void gen_r6_cmp_ ## fmt(DisasContext *ctx, int n, \
1833 int ft, int fs, int fd) \
1834 { \
1835 TCGv_i ## bits fp0 = tcg_temp_new_i ## bits(); \
1836 TCGv_i ## bits fp1 = tcg_temp_new_i ## bits(); \
1837 if (ifmt == FMT_D) { \
1838 check_cp1_registers(ctx, fs | ft | fd); \
1839 } \
1840 gen_ldcmp_fpr ## bits(ctx, fp0, fs); \
1841 gen_ldcmp_fpr ## bits(ctx, fp1, ft); \
1842 switch (n) { \
1843 case 0: \
1844 gen_helper_r6_cmp_ ## fmt ## _af(fp0, tcg_env, fp0, fp1); \
1845 break; \
1846 case 1: \
1847 gen_helper_r6_cmp_ ## fmt ## _un(fp0, tcg_env, fp0, fp1); \
1848 break; \
1849 case 2: \
1850 gen_helper_r6_cmp_ ## fmt ## _eq(fp0, tcg_env, fp0, fp1); \
1851 break; \
1852 case 3: \
1853 gen_helper_r6_cmp_ ## fmt ## _ueq(fp0, tcg_env, fp0, fp1); \
1854 break; \
1855 case 4: \
1856 gen_helper_r6_cmp_ ## fmt ## _lt(fp0, tcg_env, fp0, fp1); \
1857 break; \
1858 case 5: \
1859 gen_helper_r6_cmp_ ## fmt ## _ult(fp0, tcg_env, fp0, fp1); \
1860 break; \
1861 case 6: \
1862 gen_helper_r6_cmp_ ## fmt ## _le(fp0, tcg_env, fp0, fp1); \
1863 break; \
1864 case 7: \
1865 gen_helper_r6_cmp_ ## fmt ## _ule(fp0, tcg_env, fp0, fp1); \
1866 break; \
1867 case 8: \
1868 gen_helper_r6_cmp_ ## fmt ## _saf(fp0, tcg_env, fp0, fp1); \
1869 break; \
1870 case 9: \
1871 gen_helper_r6_cmp_ ## fmt ## _sun(fp0, tcg_env, fp0, fp1); \
1872 break; \
1873 case 10: \
1874 gen_helper_r6_cmp_ ## fmt ## _seq(fp0, tcg_env, fp0, fp1); \
1875 break; \
1876 case 11: \
1877 gen_helper_r6_cmp_ ## fmt ## _sueq(fp0, tcg_env, fp0, fp1); \
1878 break; \
1879 case 12: \
1880 gen_helper_r6_cmp_ ## fmt ## _slt(fp0, tcg_env, fp0, fp1); \
1881 break; \
1882 case 13: \
1883 gen_helper_r6_cmp_ ## fmt ## _sult(fp0, tcg_env, fp0, fp1); \
1884 break; \
1885 case 14: \
1886 gen_helper_r6_cmp_ ## fmt ## _sle(fp0, tcg_env, fp0, fp1); \
1887 break; \
1888 case 15: \
1889 gen_helper_r6_cmp_ ## fmt ## _sule(fp0, tcg_env, fp0, fp1); \
1890 break; \
1891 case 17: \
1892 gen_helper_r6_cmp_ ## fmt ## _or(fp0, tcg_env, fp0, fp1); \
1893 break; \
1894 case 18: \
1895 gen_helper_r6_cmp_ ## fmt ## _une(fp0, tcg_env, fp0, fp1); \
1896 break; \
1897 case 19: \
1898 gen_helper_r6_cmp_ ## fmt ## _ne(fp0, tcg_env, fp0, fp1); \
1899 break; \
1900 case 25: \
1901 gen_helper_r6_cmp_ ## fmt ## _sor(fp0, tcg_env, fp0, fp1); \
1902 break; \
1903 case 26: \
1904 gen_helper_r6_cmp_ ## fmt ## _sune(fp0, tcg_env, fp0, fp1); \
1905 break; \
1906 case 27: \
1907 gen_helper_r6_cmp_ ## fmt ## _sne(fp0, tcg_env, fp0, fp1); \
1908 break; \
1909 default: \
1910 abort(); \
1911 } \
1912 STORE; \
1913 }
1914
1915 FOP_CONDNS(d, FMT_D, 64, gen_store_fpr64(ctx, fp0, fd))
1916 FOP_CONDNS(s, FMT_S, 32, gen_store_fpr32(ctx, fp0, fd))
1917 #undef FOP_CONDNS
1918 #undef gen_ldcmp_fpr32
1919 #undef gen_ldcmp_fpr64
1920
1921 /* load/store instructions. */
1922 #ifdef CONFIG_USER_ONLY
1923 #define OP_LD_ATOMIC(insn, memop) \
1924 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1925 DisasContext *ctx) \
1926 { \
1927 TCGv t0 = tcg_temp_new(); \
1928 tcg_gen_mov_tl(t0, arg1); \
1929 tcg_gen_qemu_ld_tl(ret, arg1, ctx->mem_idx, memop); \
1930 tcg_gen_st_tl(t0, tcg_env, offsetof(CPUMIPSState, lladdr)); \
1931 tcg_gen_st_tl(ret, tcg_env, offsetof(CPUMIPSState, llval)); \
1932 }
1933 #else
1934 #define OP_LD_ATOMIC(insn, ignored_memop) \
1935 static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \
1936 DisasContext *ctx) \
1937 { \
1938 gen_helper_##insn(ret, tcg_env, arg1, tcg_constant_i32(mem_idx)); \
1939 }
1940 #endif
1941 OP_LD_ATOMIC(ll, mo_endian(ctx) | MO_SL);
1942 #if defined(TARGET_MIPS64)
1943 OP_LD_ATOMIC(lld, mo_endian(ctx) | MO_UQ);
1944 #endif
1945 #undef OP_LD_ATOMIC
1946
gen_base_offset_addr(DisasContext * ctx,TCGv addr,int base,int offset)1947 void gen_base_offset_addr(DisasContext *ctx, TCGv addr, int base, int offset)
1948 {
1949 if (base == 0) {
1950 tcg_gen_movi_tl(addr, offset);
1951 } else if (offset == 0) {
1952 gen_load_gpr(addr, base);
1953 } else {
1954 tcg_gen_movi_tl(addr, offset);
1955 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1956 }
1957 }
1958
pc_relative_pc(DisasContext * ctx)1959 static target_ulong pc_relative_pc(DisasContext *ctx)
1960 {
1961 target_ulong pc = ctx->base.pc_next;
1962
1963 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1964 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1965
1966 pc -= branch_bytes;
1967 }
1968
1969 pc &= ~(target_ulong)3;
1970 return pc;
1971 }
1972
1973 /* LWL or LDL, depending on MemOp. */
gen_lxl(DisasContext * ctx,TCGv reg,TCGv addr,int mem_idx,MemOp mop)1974 static void gen_lxl(DisasContext *ctx, TCGv reg, TCGv addr,
1975 int mem_idx, MemOp mop)
1976 {
1977 int sizem1 = memop_size(mop) - 1;
1978 TCGv t0 = tcg_temp_new();
1979 TCGv t1 = tcg_temp_new();
1980
1981 /*
1982 * Do a byte access to possibly trigger a page
1983 * fault with the unaligned address.
1984 */
1985 tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
1986 tcg_gen_andi_tl(t1, addr, sizem1);
1987 if (!disas_is_bigendian(ctx)) {
1988 tcg_gen_xori_tl(t1, t1, sizem1);
1989 }
1990 tcg_gen_shli_tl(t1, t1, 3);
1991 tcg_gen_andi_tl(t0, addr, ~sizem1);
1992 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mop);
1993 tcg_gen_shl_tl(t0, t0, t1);
1994 tcg_gen_shl_tl(t1, tcg_constant_tl(-1), t1);
1995 tcg_gen_andc_tl(t1, reg, t1);
1996 tcg_gen_or_tl(reg, t0, t1);
1997 }
1998
1999 /* LWR or LDR, depending on MemOp. */
gen_lxr(DisasContext * ctx,TCGv reg,TCGv addr,int mem_idx,MemOp mop)2000 static void gen_lxr(DisasContext *ctx, TCGv reg, TCGv addr,
2001 int mem_idx, MemOp mop)
2002 {
2003 int size = memop_size(mop);
2004 int sizem1 = size - 1;
2005 TCGv t0 = tcg_temp_new();
2006 TCGv t1 = tcg_temp_new();
2007
2008 /*
2009 * Do a byte access to possibly trigger a page
2010 * fault with the unaligned address.
2011 */
2012 tcg_gen_qemu_ld_tl(t1, addr, mem_idx, MO_UB);
2013 tcg_gen_andi_tl(t1, addr, sizem1);
2014 if (disas_is_bigendian(ctx)) {
2015 tcg_gen_xori_tl(t1, t1, sizem1);
2016 }
2017 tcg_gen_shli_tl(t1, t1, 3);
2018 tcg_gen_andi_tl(t0, addr, ~sizem1);
2019 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mop);
2020 tcg_gen_shr_tl(t0, t0, t1);
2021 tcg_gen_xori_tl(t1, t1, size * 8 - 1);
2022 tcg_gen_shl_tl(t1, tcg_constant_tl(~1), t1);
2023 tcg_gen_and_tl(t1, reg, t1);
2024 tcg_gen_or_tl(reg, t0, t1);
2025 }
2026
2027 /* Load */
gen_ld(DisasContext * ctx,uint32_t opc,int rt,int base,int offset)2028 static void gen_ld(DisasContext *ctx, uint32_t opc,
2029 int rt, int base, int offset)
2030 {
2031 TCGv t0, t1;
2032 int mem_idx = ctx->mem_idx;
2033
2034 if (rt == 0 && ctx->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F |
2035 INSN_LOONGSON3A)) {
2036 /*
2037 * Loongson CPU uses a load to zero register for prefetch.
2038 * We emulate it as a NOP. On other CPU we must perform the
2039 * actual memory access.
2040 */
2041 return;
2042 }
2043
2044 t0 = tcg_temp_new();
2045 gen_base_offset_addr(ctx, t0, base, offset);
2046
2047 switch (opc) {
2048 #if defined(TARGET_MIPS64)
2049 case OPC_LWU:
2050 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UL |
2051 ctx->default_tcg_memop_mask);
2052 gen_store_gpr(t0, rt);
2053 break;
2054 case OPC_LD:
2055 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UQ |
2056 ctx->default_tcg_memop_mask);
2057 gen_store_gpr(t0, rt);
2058 break;
2059 case OPC_LLD:
2060 case R6_OPC_LLD:
2061 op_ld_lld(t0, t0, mem_idx, ctx);
2062 gen_store_gpr(t0, rt);
2063 break;
2064 case OPC_LDL:
2065 t1 = tcg_temp_new();
2066 gen_load_gpr(t1, rt);
2067 gen_lxl(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UQ);
2068 gen_store_gpr(t1, rt);
2069 break;
2070 case OPC_LDR:
2071 t1 = tcg_temp_new();
2072 gen_load_gpr(t1, rt);
2073 gen_lxr(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UQ);
2074 gen_store_gpr(t1, rt);
2075 break;
2076 case OPC_LDPC:
2077 t1 = tcg_constant_tl(pc_relative_pc(ctx));
2078 gen_op_addr_add(ctx, t0, t0, t1);
2079 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UQ);
2080 gen_store_gpr(t0, rt);
2081 break;
2082 #endif
2083 case OPC_LWPC:
2084 t1 = tcg_constant_tl(pc_relative_pc(ctx));
2085 gen_op_addr_add(ctx, t0, t0, t1);
2086 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SL);
2087 gen_store_gpr(t0, rt);
2088 break;
2089 case OPC_LWE:
2090 mem_idx = MIPS_HFLAG_UM;
2091 /* fall through */
2092 case OPC_LW:
2093 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SL |
2094 ctx->default_tcg_memop_mask);
2095 gen_store_gpr(t0, rt);
2096 break;
2097 case OPC_LHE:
2098 mem_idx = MIPS_HFLAG_UM;
2099 /* fall through */
2100 case OPC_LH:
2101 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_SW |
2102 ctx->default_tcg_memop_mask);
2103 gen_store_gpr(t0, rt);
2104 break;
2105 case OPC_LHUE:
2106 mem_idx = MIPS_HFLAG_UM;
2107 /* fall through */
2108 case OPC_LHU:
2109 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, mo_endian(ctx) | MO_UW |
2110 ctx->default_tcg_memop_mask);
2111 gen_store_gpr(t0, rt);
2112 break;
2113 case OPC_LBE:
2114 mem_idx = MIPS_HFLAG_UM;
2115 /* fall through */
2116 case OPC_LB:
2117 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_SB);
2118 gen_store_gpr(t0, rt);
2119 break;
2120 case OPC_LBUE:
2121 mem_idx = MIPS_HFLAG_UM;
2122 /* fall through */
2123 case OPC_LBU:
2124 tcg_gen_qemu_ld_tl(t0, t0, mem_idx, MO_UB);
2125 gen_store_gpr(t0, rt);
2126 break;
2127 case OPC_LWLE:
2128 mem_idx = MIPS_HFLAG_UM;
2129 /* fall through */
2130 case OPC_LWL:
2131 t1 = tcg_temp_new();
2132 gen_load_gpr(t1, rt);
2133 gen_lxl(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UL);
2134 tcg_gen_ext32s_tl(t1, t1);
2135 gen_store_gpr(t1, rt);
2136 break;
2137 case OPC_LWRE:
2138 mem_idx = MIPS_HFLAG_UM;
2139 /* fall through */
2140 case OPC_LWR:
2141 t1 = tcg_temp_new();
2142 gen_load_gpr(t1, rt);
2143 gen_lxr(ctx, t1, t0, mem_idx, mo_endian(ctx) | MO_UL);
2144 tcg_gen_ext32s_tl(t1, t1);
2145 gen_store_gpr(t1, rt);
2146 break;
2147 case OPC_LLE:
2148 mem_idx = MIPS_HFLAG_UM;
2149 /* fall through */
2150 case OPC_LL:
2151 case R6_OPC_LL:
2152 op_ld_ll(t0, t0, mem_idx, ctx);
2153 gen_store_gpr(t0, rt);
2154 break;
2155 }
2156 }
2157
2158 /* Store */
gen_st(DisasContext * ctx,uint32_t opc,int rt,int base,int offset)2159 static void gen_st(DisasContext *ctx, uint32_t opc, int rt,
2160 int base, int offset)
2161 {
2162 TCGv t0 = tcg_temp_new();
2163 TCGv t1 = tcg_temp_new();
2164 int mem_idx = ctx->mem_idx;
2165
2166 gen_base_offset_addr(ctx, t0, base, offset);
2167 gen_load_gpr(t1, rt);
2168 switch (opc) {
2169 #if defined(TARGET_MIPS64)
2170 case OPC_SD:
2171 tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UQ |
2172 ctx->default_tcg_memop_mask);
2173 break;
2174 case OPC_SDL:
2175 gen_helper_0e2i(sdl, t1, t0, mem_idx);
2176 break;
2177 case OPC_SDR:
2178 gen_helper_0e2i(sdr, t1, t0, mem_idx);
2179 break;
2180 #endif
2181 case OPC_SWE:
2182 mem_idx = MIPS_HFLAG_UM;
2183 /* fall through */
2184 case OPC_SW:
2185 tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UL |
2186 ctx->default_tcg_memop_mask);
2187 break;
2188 case OPC_SHE:
2189 mem_idx = MIPS_HFLAG_UM;
2190 /* fall through */
2191 case OPC_SH:
2192 tcg_gen_qemu_st_tl(t1, t0, mem_idx, mo_endian(ctx) | MO_UW |
2193 ctx->default_tcg_memop_mask);
2194 break;
2195 case OPC_SBE:
2196 mem_idx = MIPS_HFLAG_UM;
2197 /* fall through */
2198 case OPC_SB:
2199 tcg_gen_qemu_st_tl(t1, t0, mem_idx, MO_8);
2200 break;
2201 case OPC_SWLE:
2202 mem_idx = MIPS_HFLAG_UM;
2203 /* fall through */
2204 case OPC_SWL:
2205 gen_helper_0e2i(swl, t1, t0, mem_idx);
2206 break;
2207 case OPC_SWRE:
2208 mem_idx = MIPS_HFLAG_UM;
2209 /* fall through */
2210 case OPC_SWR:
2211 gen_helper_0e2i(swr, t1, t0, mem_idx);
2212 break;
2213 }
2214 }
2215
2216
2217 /* Store conditional */
gen_st_cond(DisasContext * ctx,int rt,int base,int offset,MemOp tcg_mo,bool eva)2218 static void gen_st_cond(DisasContext *ctx, int rt, int base, int offset,
2219 MemOp tcg_mo, bool eva)
2220 {
2221 TCGv addr, t0, val;
2222 TCGLabel *l1 = gen_new_label();
2223 TCGLabel *done = gen_new_label();
2224
2225 t0 = tcg_temp_new();
2226 addr = tcg_temp_new();
2227 /* compare the address against that of the preceding LL */
2228 gen_base_offset_addr(ctx, addr, base, offset);
2229 tcg_gen_brcond_tl(TCG_COND_EQ, addr, cpu_lladdr, l1);
2230 gen_store_gpr(tcg_constant_tl(0), rt);
2231 tcg_gen_br(done);
2232
2233 gen_set_label(l1);
2234 /* generate cmpxchg */
2235 val = tcg_temp_new();
2236 gen_load_gpr(val, rt);
2237 tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval, val,
2238 eva ? MIPS_HFLAG_UM : ctx->mem_idx, tcg_mo);
2239 tcg_gen_setcond_tl(TCG_COND_EQ, t0, t0, cpu_llval);
2240 gen_store_gpr(t0, rt);
2241
2242 gen_set_label(done);
2243 }
2244
2245 /* Load and store */
gen_flt_ldst(DisasContext * ctx,uint32_t opc,int ft,TCGv t0)2246 static void gen_flt_ldst(DisasContext *ctx, uint32_t opc, int ft,
2247 TCGv t0)
2248 {
2249 /*
2250 * Don't do NOP if destination is zero: we must perform the actual
2251 * memory access.
2252 */
2253 switch (opc) {
2254 case OPC_LWC1:
2255 {
2256 TCGv_i32 fp0 = tcg_temp_new_i32();
2257 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
2258 ctx->default_tcg_memop_mask);
2259 gen_store_fpr32(ctx, fp0, ft);
2260 }
2261 break;
2262 case OPC_SWC1:
2263 {
2264 TCGv_i32 fp0 = tcg_temp_new_i32();
2265 gen_load_fpr32(ctx, fp0, ft);
2266 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
2267 ctx->default_tcg_memop_mask);
2268 }
2269 break;
2270 case OPC_LDC1:
2271 {
2272 TCGv_i64 fp0 = tcg_temp_new_i64();
2273 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
2274 ctx->default_tcg_memop_mask);
2275 gen_store_fpr64(ctx, fp0, ft);
2276 }
2277 break;
2278 case OPC_SDC1:
2279 {
2280 TCGv_i64 fp0 = tcg_temp_new_i64();
2281 gen_load_fpr64(ctx, fp0, ft);
2282 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
2283 ctx->default_tcg_memop_mask);
2284 }
2285 break;
2286 default:
2287 MIPS_INVAL("flt_ldst");
2288 gen_reserved_instruction(ctx);
2289 break;
2290 }
2291 }
2292
gen_cop1_ldst(DisasContext * ctx,uint32_t op,int rt,int rs,int16_t imm)2293 static void gen_cop1_ldst(DisasContext *ctx, uint32_t op, int rt,
2294 int rs, int16_t imm)
2295 {
2296 TCGv t0 = tcg_temp_new();
2297
2298 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
2299 check_cp1_enabled(ctx);
2300 switch (op) {
2301 case OPC_LDC1:
2302 case OPC_SDC1:
2303 check_insn(ctx, ISA_MIPS2);
2304 /* Fallthrough */
2305 default:
2306 gen_base_offset_addr(ctx, t0, rs, imm);
2307 gen_flt_ldst(ctx, op, rt, t0);
2308 }
2309 } else {
2310 generate_exception_err(ctx, EXCP_CpU, 1);
2311 }
2312 }
2313
2314 /* Arithmetic with immediate operand */
gen_arith_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int imm)2315 static void gen_arith_imm(DisasContext *ctx, uint32_t opc,
2316 int rt, int rs, int imm)
2317 {
2318 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2319
2320 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
2321 /*
2322 * If no destination, treat it as a NOP.
2323 * For addi, we must generate the overflow exception when needed.
2324 */
2325 return;
2326 }
2327 switch (opc) {
2328 case OPC_ADDI:
2329 {
2330 TCGv t0 = tcg_temp_new();
2331 TCGv t1 = tcg_temp_new();
2332 TCGv t2 = tcg_temp_new();
2333 TCGLabel *l1 = gen_new_label();
2334
2335 gen_load_gpr(t1, rs);
2336 tcg_gen_addi_tl(t0, t1, uimm);
2337 tcg_gen_ext32s_tl(t0, t0);
2338
2339 tcg_gen_xori_tl(t1, t1, ~uimm);
2340 tcg_gen_xori_tl(t2, t0, uimm);
2341 tcg_gen_and_tl(t1, t1, t2);
2342 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2343 /* operands of same sign, result different sign */
2344 generate_exception(ctx, EXCP_OVERFLOW);
2345 gen_set_label(l1);
2346 tcg_gen_ext32s_tl(t0, t0);
2347 gen_store_gpr(t0, rt);
2348 }
2349 break;
2350 case OPC_ADDIU:
2351 if (rs != 0) {
2352 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2353 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2354 } else {
2355 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2356 }
2357 break;
2358 #if defined(TARGET_MIPS64)
2359 case OPC_DADDI:
2360 {
2361 TCGv t0 = tcg_temp_new();
2362 TCGv t1 = tcg_temp_new();
2363 TCGv t2 = tcg_temp_new();
2364 TCGLabel *l1 = gen_new_label();
2365
2366 gen_load_gpr(t1, rs);
2367 tcg_gen_addi_tl(t0, t1, uimm);
2368
2369 tcg_gen_xori_tl(t1, t1, ~uimm);
2370 tcg_gen_xori_tl(t2, t0, uimm);
2371 tcg_gen_and_tl(t1, t1, t2);
2372 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2373 /* operands of same sign, result different sign */
2374 generate_exception(ctx, EXCP_OVERFLOW);
2375 gen_set_label(l1);
2376 gen_store_gpr(t0, rt);
2377 }
2378 break;
2379 case OPC_DADDIU:
2380 if (rs != 0) {
2381 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2382 } else {
2383 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2384 }
2385 break;
2386 #endif
2387 }
2388 }
2389
2390 /* Logic with immediate operand */
gen_logic_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int16_t imm)2391 static void gen_logic_imm(DisasContext *ctx, uint32_t opc,
2392 int rt, int rs, int16_t imm)
2393 {
2394 target_ulong uimm;
2395
2396 if (rt == 0) {
2397 /* If no destination, treat it as a NOP. */
2398 return;
2399 }
2400 uimm = (uint16_t)imm;
2401 switch (opc) {
2402 case OPC_ANDI:
2403 if (likely(rs != 0)) {
2404 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2405 } else {
2406 tcg_gen_movi_tl(cpu_gpr[rt], 0);
2407 }
2408 break;
2409 case OPC_ORI:
2410 if (rs != 0) {
2411 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2412 } else {
2413 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2414 }
2415 break;
2416 case OPC_XORI:
2417 if (likely(rs != 0)) {
2418 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
2419 } else {
2420 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
2421 }
2422 break;
2423 case OPC_LUI:
2424 if (rs != 0 && (ctx->insn_flags & ISA_MIPS_R6)) {
2425 /* OPC_AUI */
2426 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], imm << 16);
2427 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
2428 } else {
2429 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
2430 }
2431 break;
2432
2433 default:
2434 break;
2435 }
2436 }
2437
2438 /* Set on less than with immediate operand */
gen_slt_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int16_t imm)2439 static void gen_slt_imm(DisasContext *ctx, uint32_t opc,
2440 int rt, int rs, int16_t imm)
2441 {
2442 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
2443 TCGv t0;
2444
2445 if (rt == 0) {
2446 /* If no destination, treat it as a NOP. */
2447 return;
2448 }
2449 t0 = tcg_temp_new();
2450 gen_load_gpr(t0, rs);
2451 switch (opc) {
2452 case OPC_SLTI:
2453 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
2454 break;
2455 case OPC_SLTIU:
2456 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
2457 break;
2458 }
2459 }
2460
2461 /* Shifts with immediate operand */
gen_shift_imm(DisasContext * ctx,uint32_t opc,int rt,int rs,int16_t imm)2462 static void gen_shift_imm(DisasContext *ctx, uint32_t opc,
2463 int rt, int rs, int16_t imm)
2464 {
2465 target_ulong uimm = ((uint16_t)imm) & 0x1f;
2466 TCGv t0;
2467
2468 if (rt == 0) {
2469 /* If no destination, treat it as a NOP. */
2470 return;
2471 }
2472
2473 t0 = tcg_temp_new();
2474 gen_load_gpr(t0, rs);
2475 switch (opc) {
2476 case OPC_SLL:
2477 tcg_gen_shli_tl(t0, t0, uimm);
2478 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2479 break;
2480 case OPC_SRA:
2481 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2482 break;
2483 case OPC_SRL:
2484 if (uimm != 0) {
2485 tcg_gen_ext32u_tl(t0, t0);
2486 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2487 } else {
2488 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2489 }
2490 break;
2491 case OPC_ROTR:
2492 if (uimm != 0) {
2493 TCGv_i32 t1 = tcg_temp_new_i32();
2494
2495 tcg_gen_trunc_tl_i32(t1, t0);
2496 tcg_gen_rotri_i32(t1, t1, uimm);
2497 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
2498 } else {
2499 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
2500 }
2501 break;
2502 #if defined(TARGET_MIPS64)
2503 case OPC_DSLL:
2504 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
2505 break;
2506 case OPC_DSRA:
2507 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
2508 break;
2509 case OPC_DSRL:
2510 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
2511 break;
2512 case OPC_DROTR:
2513 if (uimm != 0) {
2514 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
2515 } else {
2516 tcg_gen_mov_tl(cpu_gpr[rt], t0);
2517 }
2518 break;
2519 case OPC_DSLL32:
2520 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
2521 break;
2522 case OPC_DSRA32:
2523 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
2524 break;
2525 case OPC_DSRL32:
2526 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
2527 break;
2528 case OPC_DROTR32:
2529 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
2530 break;
2531 #endif
2532 }
2533 }
2534
2535 /* Arithmetic */
gen_arith(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2536 static void gen_arith(DisasContext *ctx, uint32_t opc,
2537 int rd, int rs, int rt)
2538 {
2539 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
2540 && opc != OPC_DADD && opc != OPC_DSUB) {
2541 /*
2542 * If no destination, treat it as a NOP.
2543 * For add & sub, we must generate the overflow exception when needed.
2544 */
2545 return;
2546 }
2547
2548 switch (opc) {
2549 case OPC_ADD:
2550 {
2551 TCGv t0 = tcg_temp_new();
2552 TCGv t1 = tcg_temp_new();
2553 TCGv t2 = tcg_temp_new();
2554 TCGLabel *l1 = gen_new_label();
2555
2556 gen_load_gpr(t1, rs);
2557 gen_load_gpr(t2, rt);
2558 tcg_gen_add_tl(t0, t1, t2);
2559 tcg_gen_ext32s_tl(t0, t0);
2560 tcg_gen_xor_tl(t1, t1, t2);
2561 tcg_gen_xor_tl(t2, t0, t2);
2562 tcg_gen_andc_tl(t1, t2, t1);
2563 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2564 /* operands of same sign, result different sign */
2565 generate_exception(ctx, EXCP_OVERFLOW);
2566 gen_set_label(l1);
2567 gen_store_gpr(t0, rd);
2568 }
2569 break;
2570 case OPC_ADDU:
2571 if (rs != 0 && rt != 0) {
2572 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2573 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2574 } else if (rs == 0 && rt != 0) {
2575 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2576 } else if (rs != 0 && rt == 0) {
2577 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2578 } else {
2579 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2580 }
2581 break;
2582 case OPC_SUB:
2583 {
2584 TCGv t0 = tcg_temp_new();
2585 TCGv t1 = tcg_temp_new();
2586 TCGv t2 = tcg_temp_new();
2587 TCGLabel *l1 = gen_new_label();
2588
2589 gen_load_gpr(t1, rs);
2590 gen_load_gpr(t2, rt);
2591 tcg_gen_sub_tl(t0, t1, t2);
2592 tcg_gen_ext32s_tl(t0, t0);
2593 tcg_gen_xor_tl(t2, t1, t2);
2594 tcg_gen_xor_tl(t1, t0, t1);
2595 tcg_gen_and_tl(t1, t1, t2);
2596 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2597 /*
2598 * operands of different sign, first operand and the result
2599 * of different sign
2600 */
2601 generate_exception(ctx, EXCP_OVERFLOW);
2602 gen_set_label(l1);
2603 gen_store_gpr(t0, rd);
2604 }
2605 break;
2606 case OPC_SUBU:
2607 if (rs != 0 && rt != 0) {
2608 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2609 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2610 } else if (rs == 0 && rt != 0) {
2611 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2612 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2613 } else if (rs != 0 && rt == 0) {
2614 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2615 } else {
2616 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2617 }
2618 break;
2619 #if defined(TARGET_MIPS64)
2620 case OPC_DADD:
2621 {
2622 TCGv t0 = tcg_temp_new();
2623 TCGv t1 = tcg_temp_new();
2624 TCGv t2 = tcg_temp_new();
2625 TCGLabel *l1 = gen_new_label();
2626
2627 gen_load_gpr(t1, rs);
2628 gen_load_gpr(t2, rt);
2629 tcg_gen_add_tl(t0, t1, t2);
2630 tcg_gen_xor_tl(t1, t1, t2);
2631 tcg_gen_xor_tl(t2, t0, t2);
2632 tcg_gen_andc_tl(t1, t2, t1);
2633 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2634 /* operands of same sign, result different sign */
2635 generate_exception(ctx, EXCP_OVERFLOW);
2636 gen_set_label(l1);
2637 gen_store_gpr(t0, rd);
2638 }
2639 break;
2640 case OPC_DADDU:
2641 if (rs != 0 && rt != 0) {
2642 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2643 } else if (rs == 0 && rt != 0) {
2644 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2645 } else if (rs != 0 && rt == 0) {
2646 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2647 } else {
2648 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2649 }
2650 break;
2651 case OPC_DSUB:
2652 {
2653 TCGv t0 = tcg_temp_new();
2654 TCGv t1 = tcg_temp_new();
2655 TCGv t2 = tcg_temp_new();
2656 TCGLabel *l1 = gen_new_label();
2657
2658 gen_load_gpr(t1, rs);
2659 gen_load_gpr(t2, rt);
2660 tcg_gen_sub_tl(t0, t1, t2);
2661 tcg_gen_xor_tl(t2, t1, t2);
2662 tcg_gen_xor_tl(t1, t0, t1);
2663 tcg_gen_and_tl(t1, t1, t2);
2664 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
2665 /*
2666 * Operands of different sign, first operand and result different
2667 * sign.
2668 */
2669 generate_exception(ctx, EXCP_OVERFLOW);
2670 gen_set_label(l1);
2671 gen_store_gpr(t0, rd);
2672 }
2673 break;
2674 case OPC_DSUBU:
2675 if (rs != 0 && rt != 0) {
2676 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2677 } else if (rs == 0 && rt != 0) {
2678 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
2679 } else if (rs != 0 && rt == 0) {
2680 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2681 } else {
2682 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2683 }
2684 break;
2685 #endif
2686 case OPC_MUL:
2687 if (likely(rs != 0 && rt != 0)) {
2688 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2689 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2690 } else {
2691 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2692 }
2693 break;
2694 }
2695 }
2696
2697 /* Conditional move */
gen_cond_move(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2698 static void gen_cond_move(DisasContext *ctx, uint32_t opc,
2699 int rd, int rs, int rt)
2700 {
2701 TCGv t0, t1, t2;
2702
2703 if (rd == 0) {
2704 /* If no destination, treat it as a NOP. */
2705 return;
2706 }
2707
2708 t0 = tcg_temp_new();
2709 gen_load_gpr(t0, rt);
2710 t1 = tcg_constant_tl(0);
2711 t2 = tcg_temp_new();
2712 gen_load_gpr(t2, rs);
2713 switch (opc) {
2714 case OPC_MOVN:
2715 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2716 break;
2717 case OPC_MOVZ:
2718 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, cpu_gpr[rd]);
2719 break;
2720 case OPC_SELNEZ:
2721 tcg_gen_movcond_tl(TCG_COND_NE, cpu_gpr[rd], t0, t1, t2, t1);
2722 break;
2723 case OPC_SELEQZ:
2724 tcg_gen_movcond_tl(TCG_COND_EQ, cpu_gpr[rd], t0, t1, t2, t1);
2725 break;
2726 }
2727 }
2728
2729 /* Logic */
gen_logic(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2730 static void gen_logic(DisasContext *ctx, uint32_t opc,
2731 int rd, int rs, int rt)
2732 {
2733 if (rd == 0) {
2734 /* If no destination, treat it as a NOP. */
2735 return;
2736 }
2737
2738 switch (opc) {
2739 case OPC_AND:
2740 if (likely(rs != 0 && rt != 0)) {
2741 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2742 } else {
2743 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2744 }
2745 break;
2746 case OPC_NOR:
2747 if (rs != 0 && rt != 0) {
2748 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2749 } else if (rs == 0 && rt != 0) {
2750 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
2751 } else if (rs != 0 && rt == 0) {
2752 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
2753 } else {
2754 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
2755 }
2756 break;
2757 case OPC_OR:
2758 if (likely(rs != 0 && rt != 0)) {
2759 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2760 } else if (rs == 0 && rt != 0) {
2761 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2762 } else if (rs != 0 && rt == 0) {
2763 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2764 } else {
2765 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2766 }
2767 break;
2768 case OPC_XOR:
2769 if (likely(rs != 0 && rt != 0)) {
2770 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
2771 } else if (rs == 0 && rt != 0) {
2772 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
2773 } else if (rs != 0 && rt == 0) {
2774 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
2775 } else {
2776 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2777 }
2778 break;
2779 }
2780 }
2781
2782 /* Set on lower than */
gen_slt(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2783 static void gen_slt(DisasContext *ctx, uint32_t opc,
2784 int rd, int rs, int rt)
2785 {
2786 TCGv t0, t1;
2787
2788 if (rd == 0) {
2789 /* If no destination, treat it as a NOP. */
2790 return;
2791 }
2792
2793 t0 = tcg_temp_new();
2794 t1 = tcg_temp_new();
2795 gen_load_gpr(t0, rs);
2796 gen_load_gpr(t1, rt);
2797 switch (opc) {
2798 case OPC_SLT:
2799 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
2800 break;
2801 case OPC_SLTU:
2802 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
2803 break;
2804 }
2805 }
2806
2807 /* Shifts */
gen_shift(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)2808 static void gen_shift(DisasContext *ctx, uint32_t opc,
2809 int rd, int rs, int rt)
2810 {
2811 TCGv t0, t1;
2812
2813 if (rd == 0) {
2814 /*
2815 * If no destination, treat it as a NOP.
2816 * For add & sub, we must generate the overflow exception when needed.
2817 */
2818 return;
2819 }
2820
2821 t0 = tcg_temp_new();
2822 t1 = tcg_temp_new();
2823 gen_load_gpr(t0, rs);
2824 gen_load_gpr(t1, rt);
2825 switch (opc) {
2826 case OPC_SLLV:
2827 tcg_gen_andi_tl(t0, t0, 0x1f);
2828 tcg_gen_shl_tl(t0, t1, t0);
2829 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2830 break;
2831 case OPC_SRAV:
2832 tcg_gen_andi_tl(t0, t0, 0x1f);
2833 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2834 break;
2835 case OPC_SRLV:
2836 tcg_gen_ext32u_tl(t1, t1);
2837 tcg_gen_andi_tl(t0, t0, 0x1f);
2838 tcg_gen_shr_tl(t0, t1, t0);
2839 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
2840 break;
2841 case OPC_ROTRV:
2842 {
2843 TCGv_i32 t2 = tcg_temp_new_i32();
2844 TCGv_i32 t3 = tcg_temp_new_i32();
2845
2846 tcg_gen_trunc_tl_i32(t2, t0);
2847 tcg_gen_trunc_tl_i32(t3, t1);
2848 tcg_gen_andi_i32(t2, t2, 0x1f);
2849 tcg_gen_rotr_i32(t2, t3, t2);
2850 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
2851 }
2852 break;
2853 #if defined(TARGET_MIPS64)
2854 case OPC_DSLLV:
2855 tcg_gen_andi_tl(t0, t0, 0x3f);
2856 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
2857 break;
2858 case OPC_DSRAV:
2859 tcg_gen_andi_tl(t0, t0, 0x3f);
2860 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
2861 break;
2862 case OPC_DSRLV:
2863 tcg_gen_andi_tl(t0, t0, 0x3f);
2864 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
2865 break;
2866 case OPC_DROTRV:
2867 tcg_gen_andi_tl(t0, t0, 0x3f);
2868 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
2869 break;
2870 #endif
2871 }
2872 }
2873
2874 /* Arithmetic on HI/LO registers */
gen_HILO(DisasContext * ctx,uint32_t opc,int acc,int reg)2875 static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg)
2876 {
2877 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
2878 /* Treat as NOP. */
2879 return;
2880 }
2881
2882 if (acc != 0) {
2883 check_dsp(ctx);
2884 }
2885
2886 switch (opc) {
2887 case OPC_MFHI:
2888 #if defined(TARGET_MIPS64)
2889 if (acc != 0) {
2890 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_HI[acc]);
2891 } else
2892 #endif
2893 {
2894 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[acc]);
2895 }
2896 break;
2897 case OPC_MFLO:
2898 #if defined(TARGET_MIPS64)
2899 if (acc != 0) {
2900 tcg_gen_ext32s_tl(cpu_gpr[reg], cpu_LO[acc]);
2901 } else
2902 #endif
2903 {
2904 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[acc]);
2905 }
2906 break;
2907 case OPC_MTHI:
2908 if (reg != 0) {
2909 #if defined(TARGET_MIPS64)
2910 if (acc != 0) {
2911 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_gpr[reg]);
2912 } else
2913 #endif
2914 {
2915 tcg_gen_mov_tl(cpu_HI[acc], cpu_gpr[reg]);
2916 }
2917 } else {
2918 tcg_gen_movi_tl(cpu_HI[acc], 0);
2919 }
2920 break;
2921 case OPC_MTLO:
2922 if (reg != 0) {
2923 #if defined(TARGET_MIPS64)
2924 if (acc != 0) {
2925 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_gpr[reg]);
2926 } else
2927 #endif
2928 {
2929 tcg_gen_mov_tl(cpu_LO[acc], cpu_gpr[reg]);
2930 }
2931 } else {
2932 tcg_gen_movi_tl(cpu_LO[acc], 0);
2933 }
2934 break;
2935 }
2936 }
2937
gen_r6_ld(target_long addr,int reg,int memidx,MemOp memop)2938 static inline void gen_r6_ld(target_long addr, int reg, int memidx,
2939 MemOp memop)
2940 {
2941 TCGv t0 = tcg_temp_new();
2942 tcg_gen_qemu_ld_tl(t0, tcg_constant_tl(addr), memidx, memop);
2943 gen_store_gpr(t0, reg);
2944 }
2945
gen_pcrel(DisasContext * ctx,int opc,target_ulong pc,int rs)2946 static inline void gen_pcrel(DisasContext *ctx, int opc, target_ulong pc,
2947 int rs)
2948 {
2949 target_long offset;
2950 target_long addr;
2951
2952 switch (MASK_OPC_PCREL_TOP2BITS(opc)) {
2953 case OPC_ADDIUPC:
2954 if (rs != 0) {
2955 offset = sextract32(ctx->opcode << 2, 0, 21);
2956 addr = addr_add(ctx, pc, offset);
2957 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2958 }
2959 break;
2960 case R6_OPC_LWPC:
2961 offset = sextract32(ctx->opcode << 2, 0, 21);
2962 addr = addr_add(ctx, pc, offset);
2963 gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_SL);
2964 break;
2965 #if defined(TARGET_MIPS64)
2966 case OPC_LWUPC:
2967 check_mips_64(ctx);
2968 offset = sextract32(ctx->opcode << 2, 0, 21);
2969 addr = addr_add(ctx, pc, offset);
2970 gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_UL);
2971 break;
2972 #endif
2973 default:
2974 switch (MASK_OPC_PCREL_TOP5BITS(opc)) {
2975 case OPC_AUIPC:
2976 if (rs != 0) {
2977 offset = sextract32(ctx->opcode, 0, 16) << 16;
2978 addr = addr_add(ctx, pc, offset);
2979 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2980 }
2981 break;
2982 case OPC_ALUIPC:
2983 if (rs != 0) {
2984 offset = sextract32(ctx->opcode, 0, 16) << 16;
2985 addr = ~0xFFFF & addr_add(ctx, pc, offset);
2986 tcg_gen_movi_tl(cpu_gpr[rs], addr);
2987 }
2988 break;
2989 #if defined(TARGET_MIPS64)
2990 case R6_OPC_LDPC: /* bits 16 and 17 are part of immediate */
2991 case R6_OPC_LDPC + (1 << 16):
2992 case R6_OPC_LDPC + (2 << 16):
2993 case R6_OPC_LDPC + (3 << 16):
2994 check_mips_64(ctx);
2995 offset = sextract32(ctx->opcode << 3, 0, 21);
2996 addr = addr_add(ctx, (pc & ~0x7), offset);
2997 gen_r6_ld(addr, rs, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
2998 break;
2999 #endif
3000 default:
3001 MIPS_INVAL("OPC_PCREL");
3002 gen_reserved_instruction(ctx);
3003 break;
3004 }
3005 break;
3006 }
3007 }
3008
gen_r6_muldiv(DisasContext * ctx,int opc,int rd,int rs,int rt)3009 static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt)
3010 {
3011 TCGv t0, t1;
3012
3013 if (rd == 0) {
3014 /* Treat as NOP. */
3015 return;
3016 }
3017
3018 t0 = tcg_temp_new();
3019 t1 = tcg_temp_new();
3020
3021 gen_load_gpr(t0, rs);
3022 gen_load_gpr(t1, rt);
3023
3024 switch (opc) {
3025 case R6_OPC_DIV:
3026 {
3027 TCGv t2 = tcg_temp_new();
3028 TCGv t3 = tcg_temp_new();
3029 tcg_gen_ext32s_tl(t0, t0);
3030 tcg_gen_ext32s_tl(t1, t1);
3031 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3032 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3033 tcg_gen_and_tl(t2, t2, t3);
3034 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3035 tcg_gen_or_tl(t2, t2, t3);
3036 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3037 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3038 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3039 }
3040 break;
3041 case R6_OPC_MOD:
3042 {
3043 TCGv t2 = tcg_temp_new();
3044 TCGv t3 = tcg_temp_new();
3045 tcg_gen_ext32s_tl(t0, t0);
3046 tcg_gen_ext32s_tl(t1, t1);
3047 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3048 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3049 tcg_gen_and_tl(t2, t2, t3);
3050 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3051 tcg_gen_or_tl(t2, t2, t3);
3052 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3053 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3054 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3055 }
3056 break;
3057 case R6_OPC_DIVU:
3058 {
3059 tcg_gen_ext32u_tl(t0, t0);
3060 tcg_gen_ext32u_tl(t1, t1);
3061 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3062 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3063 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
3064 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3065 }
3066 break;
3067 case R6_OPC_MODU:
3068 {
3069 tcg_gen_ext32u_tl(t0, t0);
3070 tcg_gen_ext32u_tl(t1, t1);
3071 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3072 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3073 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
3074 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
3075 }
3076 break;
3077 case R6_OPC_MUL:
3078 {
3079 TCGv_i32 t2 = tcg_temp_new_i32();
3080 TCGv_i32 t3 = tcg_temp_new_i32();
3081 tcg_gen_trunc_tl_i32(t2, t0);
3082 tcg_gen_trunc_tl_i32(t3, t1);
3083 tcg_gen_mul_i32(t2, t2, t3);
3084 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3085 }
3086 break;
3087 case R6_OPC_MUH:
3088 {
3089 TCGv_i32 t2 = tcg_temp_new_i32();
3090 TCGv_i32 t3 = tcg_temp_new_i32();
3091 tcg_gen_trunc_tl_i32(t2, t0);
3092 tcg_gen_trunc_tl_i32(t3, t1);
3093 tcg_gen_muls2_i32(t2, t3, t2, t3);
3094 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3095 }
3096 break;
3097 case R6_OPC_MULU:
3098 {
3099 TCGv_i32 t2 = tcg_temp_new_i32();
3100 TCGv_i32 t3 = tcg_temp_new_i32();
3101 tcg_gen_trunc_tl_i32(t2, t0);
3102 tcg_gen_trunc_tl_i32(t3, t1);
3103 tcg_gen_mul_i32(t2, t2, t3);
3104 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3105 }
3106 break;
3107 case R6_OPC_MUHU:
3108 {
3109 TCGv_i32 t2 = tcg_temp_new_i32();
3110 TCGv_i32 t3 = tcg_temp_new_i32();
3111 tcg_gen_trunc_tl_i32(t2, t0);
3112 tcg_gen_trunc_tl_i32(t3, t1);
3113 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3114 tcg_gen_ext_i32_tl(cpu_gpr[rd], t3);
3115 }
3116 break;
3117 #if defined(TARGET_MIPS64)
3118 case R6_OPC_DDIV:
3119 {
3120 TCGv t2 = tcg_temp_new();
3121 TCGv t3 = tcg_temp_new();
3122 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3123 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3124 tcg_gen_and_tl(t2, t2, t3);
3125 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3126 tcg_gen_or_tl(t2, t2, t3);
3127 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3128 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
3129 }
3130 break;
3131 case R6_OPC_DMOD:
3132 {
3133 TCGv t2 = tcg_temp_new();
3134 TCGv t3 = tcg_temp_new();
3135 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3136 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3137 tcg_gen_and_tl(t2, t2, t3);
3138 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3139 tcg_gen_or_tl(t2, t2, t3);
3140 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3141 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
3142 }
3143 break;
3144 case R6_OPC_DDIVU:
3145 {
3146 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3147 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3148 tcg_gen_divu_i64(cpu_gpr[rd], t0, t1);
3149 }
3150 break;
3151 case R6_OPC_DMODU:
3152 {
3153 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3154 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3155 tcg_gen_remu_i64(cpu_gpr[rd], t0, t1);
3156 }
3157 break;
3158 case R6_OPC_DMUL:
3159 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3160 break;
3161 case R6_OPC_DMUH:
3162 {
3163 TCGv t2 = tcg_temp_new();
3164 tcg_gen_muls2_i64(t2, cpu_gpr[rd], t0, t1);
3165 }
3166 break;
3167 case R6_OPC_DMULU:
3168 tcg_gen_mul_i64(cpu_gpr[rd], t0, t1);
3169 break;
3170 case R6_OPC_DMUHU:
3171 {
3172 TCGv t2 = tcg_temp_new();
3173 tcg_gen_mulu2_i64(t2, cpu_gpr[rd], t0, t1);
3174 }
3175 break;
3176 #endif
3177 default:
3178 MIPS_INVAL("r6 mul/div");
3179 gen_reserved_instruction(ctx);
3180 break;
3181 }
3182 }
3183
3184 #if defined(TARGET_MIPS64)
gen_div1_tx79(DisasContext * ctx,uint32_t opc,int rs,int rt)3185 static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt)
3186 {
3187 TCGv t0, t1;
3188
3189 t0 = tcg_temp_new();
3190 t1 = tcg_temp_new();
3191
3192 gen_load_gpr(t0, rs);
3193 gen_load_gpr(t1, rt);
3194
3195 switch (opc) {
3196 case MMI_OPC_DIV1:
3197 {
3198 TCGv t2 = tcg_temp_new();
3199 TCGv t3 = tcg_temp_new();
3200 tcg_gen_ext32s_tl(t0, t0);
3201 tcg_gen_ext32s_tl(t1, t1);
3202 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3203 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3204 tcg_gen_and_tl(t2, t2, t3);
3205 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3206 tcg_gen_or_tl(t2, t2, t3);
3207 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3208 tcg_gen_div_tl(cpu_LO[1], t0, t1);
3209 tcg_gen_rem_tl(cpu_HI[1], t0, t1);
3210 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3211 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3212 }
3213 break;
3214 case MMI_OPC_DIVU1:
3215 {
3216 TCGv t2 = tcg_constant_tl(0);
3217 TCGv t3 = tcg_constant_tl(1);
3218 tcg_gen_ext32u_tl(t0, t0);
3219 tcg_gen_ext32u_tl(t1, t1);
3220 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3221 tcg_gen_divu_tl(cpu_LO[1], t0, t1);
3222 tcg_gen_remu_tl(cpu_HI[1], t0, t1);
3223 tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]);
3224 tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]);
3225 }
3226 break;
3227 default:
3228 MIPS_INVAL("div1 TX79");
3229 gen_reserved_instruction(ctx);
3230 break;
3231 }
3232 }
3233 #endif
3234
gen_muldiv(DisasContext * ctx,uint32_t opc,int acc,int rs,int rt)3235 static void gen_muldiv(DisasContext *ctx, uint32_t opc,
3236 int acc, int rs, int rt)
3237 {
3238 TCGv t0, t1;
3239
3240 t0 = tcg_temp_new();
3241 t1 = tcg_temp_new();
3242
3243 gen_load_gpr(t0, rs);
3244 gen_load_gpr(t1, rt);
3245
3246 if (acc != 0) {
3247 check_dsp(ctx);
3248 }
3249
3250 switch (opc) {
3251 case OPC_DIV:
3252 {
3253 TCGv t2 = tcg_temp_new();
3254 TCGv t3 = tcg_temp_new();
3255 tcg_gen_ext32s_tl(t0, t0);
3256 tcg_gen_ext32s_tl(t1, t1);
3257 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN);
3258 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1);
3259 tcg_gen_and_tl(t2, t2, t3);
3260 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3261 tcg_gen_or_tl(t2, t2, t3);
3262 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3263 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3264 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3265 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3266 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3267 }
3268 break;
3269 case OPC_DIVU:
3270 {
3271 TCGv t2 = tcg_constant_tl(0);
3272 TCGv t3 = tcg_constant_tl(1);
3273 tcg_gen_ext32u_tl(t0, t0);
3274 tcg_gen_ext32u_tl(t1, t1);
3275 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1);
3276 tcg_gen_divu_tl(cpu_LO[acc], t0, t1);
3277 tcg_gen_remu_tl(cpu_HI[acc], t0, t1);
3278 tcg_gen_ext32s_tl(cpu_LO[acc], cpu_LO[acc]);
3279 tcg_gen_ext32s_tl(cpu_HI[acc], cpu_HI[acc]);
3280 }
3281 break;
3282 case OPC_MULT:
3283 {
3284 TCGv_i32 t2 = tcg_temp_new_i32();
3285 TCGv_i32 t3 = tcg_temp_new_i32();
3286 tcg_gen_trunc_tl_i32(t2, t0);
3287 tcg_gen_trunc_tl_i32(t3, t1);
3288 tcg_gen_muls2_i32(t2, t3, t2, t3);
3289 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3290 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3291 }
3292 break;
3293 case OPC_MULTU:
3294 {
3295 TCGv_i32 t2 = tcg_temp_new_i32();
3296 TCGv_i32 t3 = tcg_temp_new_i32();
3297 tcg_gen_trunc_tl_i32(t2, t0);
3298 tcg_gen_trunc_tl_i32(t3, t1);
3299 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3300 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3301 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3302 }
3303 break;
3304 #if defined(TARGET_MIPS64)
3305 case OPC_DDIV:
3306 {
3307 TCGv t2 = tcg_temp_new();
3308 TCGv t3 = tcg_temp_new();
3309 tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, -1LL << 63);
3310 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1LL);
3311 tcg_gen_and_tl(t2, t2, t3);
3312 tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0);
3313 tcg_gen_or_tl(t2, t2, t3);
3314 tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, tcg_constant_tl(0), t2, t1);
3315 tcg_gen_div_tl(cpu_LO[acc], t0, t1);
3316 tcg_gen_rem_tl(cpu_HI[acc], t0, t1);
3317 }
3318 break;
3319 case OPC_DDIVU:
3320 {
3321 tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1,
3322 tcg_constant_tl(0), tcg_constant_tl(1), t1);
3323 tcg_gen_divu_i64(cpu_LO[acc], t0, t1);
3324 tcg_gen_remu_i64(cpu_HI[acc], t0, t1);
3325 }
3326 break;
3327 case OPC_DMULT:
3328 tcg_gen_muls2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3329 break;
3330 case OPC_DMULTU:
3331 tcg_gen_mulu2_i64(cpu_LO[acc], cpu_HI[acc], t0, t1);
3332 break;
3333 #endif
3334 case OPC_MADD:
3335 {
3336 TCGv_i64 t2 = tcg_temp_new_i64();
3337 TCGv_i64 t3 = tcg_temp_new_i64();
3338
3339 tcg_gen_ext_tl_i64(t2, t0);
3340 tcg_gen_ext_tl_i64(t3, t1);
3341 tcg_gen_mul_i64(t2, t2, t3);
3342 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3343 tcg_gen_add_i64(t2, t2, t3);
3344 gen_move_low32(cpu_LO[acc], t2);
3345 gen_move_high32(cpu_HI[acc], t2);
3346 }
3347 break;
3348 case OPC_MADDU:
3349 {
3350 TCGv_i64 t2 = tcg_temp_new_i64();
3351 TCGv_i64 t3 = tcg_temp_new_i64();
3352
3353 tcg_gen_ext32u_tl(t0, t0);
3354 tcg_gen_ext32u_tl(t1, t1);
3355 tcg_gen_extu_tl_i64(t2, t0);
3356 tcg_gen_extu_tl_i64(t3, t1);
3357 tcg_gen_mul_i64(t2, t2, t3);
3358 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3359 tcg_gen_add_i64(t2, t2, t3);
3360 gen_move_low32(cpu_LO[acc], t2);
3361 gen_move_high32(cpu_HI[acc], t2);
3362 }
3363 break;
3364 case OPC_MSUB:
3365 {
3366 TCGv_i64 t2 = tcg_temp_new_i64();
3367 TCGv_i64 t3 = tcg_temp_new_i64();
3368
3369 tcg_gen_ext_tl_i64(t2, t0);
3370 tcg_gen_ext_tl_i64(t3, t1);
3371 tcg_gen_mul_i64(t2, t2, t3);
3372 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3373 tcg_gen_sub_i64(t2, t3, t2);
3374 gen_move_low32(cpu_LO[acc], t2);
3375 gen_move_high32(cpu_HI[acc], t2);
3376 }
3377 break;
3378 case OPC_MSUBU:
3379 {
3380 TCGv_i64 t2 = tcg_temp_new_i64();
3381 TCGv_i64 t3 = tcg_temp_new_i64();
3382
3383 tcg_gen_ext32u_tl(t0, t0);
3384 tcg_gen_ext32u_tl(t1, t1);
3385 tcg_gen_extu_tl_i64(t2, t0);
3386 tcg_gen_extu_tl_i64(t3, t1);
3387 tcg_gen_mul_i64(t2, t2, t3);
3388 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3389 tcg_gen_sub_i64(t2, t3, t2);
3390 gen_move_low32(cpu_LO[acc], t2);
3391 gen_move_high32(cpu_HI[acc], t2);
3392 }
3393 break;
3394 default:
3395 MIPS_INVAL("mul/div");
3396 gen_reserved_instruction(ctx);
3397 break;
3398 }
3399 }
3400
3401 /*
3402 * These MULT[U] and MADD[U] instructions implemented in for example
3403 * the Toshiba/Sony R5900 and the Toshiba TX19, TX39 and TX79 core
3404 * architectures are special three-operand variants with the syntax
3405 *
3406 * MULT[U][1] rd, rs, rt
3407 *
3408 * such that
3409 *
3410 * (rd, LO, HI) <- rs * rt
3411 *
3412 * and
3413 *
3414 * MADD[U][1] rd, rs, rt
3415 *
3416 * such that
3417 *
3418 * (rd, LO, HI) <- (LO, HI) + rs * rt
3419 *
3420 * where the low-order 32-bits of the result is placed into both the
3421 * GPR rd and the special register LO. The high-order 32-bits of the
3422 * result is placed into the special register HI.
3423 *
3424 * If the GPR rd is omitted in assembly language, it is taken to be 0,
3425 * which is the zero register that always reads as 0.
3426 */
gen_mul_txx9(DisasContext * ctx,uint32_t opc,int rd,int rs,int rt)3427 static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
3428 int rd, int rs, int rt)
3429 {
3430 TCGv t0 = tcg_temp_new();
3431 TCGv t1 = tcg_temp_new();
3432 int acc = 0;
3433
3434 gen_load_gpr(t0, rs);
3435 gen_load_gpr(t1, rt);
3436
3437 switch (opc) {
3438 case MMI_OPC_MULT1:
3439 acc = 1;
3440 /* Fall through */
3441 case OPC_MULT:
3442 {
3443 TCGv_i32 t2 = tcg_temp_new_i32();
3444 TCGv_i32 t3 = tcg_temp_new_i32();
3445 tcg_gen_trunc_tl_i32(t2, t0);
3446 tcg_gen_trunc_tl_i32(t3, t1);
3447 tcg_gen_muls2_i32(t2, t3, t2, t3);
3448 if (rd) {
3449 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3450 }
3451 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3452 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3453 }
3454 break;
3455 case MMI_OPC_MULTU1:
3456 acc = 1;
3457 /* Fall through */
3458 case OPC_MULTU:
3459 {
3460 TCGv_i32 t2 = tcg_temp_new_i32();
3461 TCGv_i32 t3 = tcg_temp_new_i32();
3462 tcg_gen_trunc_tl_i32(t2, t0);
3463 tcg_gen_trunc_tl_i32(t3, t1);
3464 tcg_gen_mulu2_i32(t2, t3, t2, t3);
3465 if (rd) {
3466 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
3467 }
3468 tcg_gen_ext_i32_tl(cpu_LO[acc], t2);
3469 tcg_gen_ext_i32_tl(cpu_HI[acc], t3);
3470 }
3471 break;
3472 case MMI_OPC_MADD1:
3473 acc = 1;
3474 /* Fall through */
3475 case MMI_OPC_MADD:
3476 {
3477 TCGv_i64 t2 = tcg_temp_new_i64();
3478 TCGv_i64 t3 = tcg_temp_new_i64();
3479
3480 tcg_gen_ext_tl_i64(t2, t0);
3481 tcg_gen_ext_tl_i64(t3, t1);
3482 tcg_gen_mul_i64(t2, t2, t3);
3483 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3484 tcg_gen_add_i64(t2, t2, t3);
3485 gen_move_low32(cpu_LO[acc], t2);
3486 gen_move_high32(cpu_HI[acc], t2);
3487 if (rd) {
3488 gen_move_low32(cpu_gpr[rd], t2);
3489 }
3490 }
3491 break;
3492 case MMI_OPC_MADDU1:
3493 acc = 1;
3494 /* Fall through */
3495 case MMI_OPC_MADDU:
3496 {
3497 TCGv_i64 t2 = tcg_temp_new_i64();
3498 TCGv_i64 t3 = tcg_temp_new_i64();
3499
3500 tcg_gen_ext32u_tl(t0, t0);
3501 tcg_gen_ext32u_tl(t1, t1);
3502 tcg_gen_extu_tl_i64(t2, t0);
3503 tcg_gen_extu_tl_i64(t3, t1);
3504 tcg_gen_mul_i64(t2, t2, t3);
3505 tcg_gen_concat_tl_i64(t3, cpu_LO[acc], cpu_HI[acc]);
3506 tcg_gen_add_i64(t2, t2, t3);
3507 gen_move_low32(cpu_LO[acc], t2);
3508 gen_move_high32(cpu_HI[acc], t2);
3509 if (rd) {
3510 gen_move_low32(cpu_gpr[rd], t2);
3511 }
3512 }
3513 break;
3514 default:
3515 MIPS_INVAL("mul/madd TXx9");
3516 gen_reserved_instruction(ctx);
3517 break;
3518 }
3519 }
3520
gen_cl(DisasContext * ctx,uint32_t opc,int rd,int rs)3521 static void gen_cl(DisasContext *ctx, uint32_t opc,
3522 int rd, int rs)
3523 {
3524 TCGv t0;
3525
3526 if (rd == 0) {
3527 /* Treat as NOP. */
3528 return;
3529 }
3530 t0 = cpu_gpr[rd];
3531 gen_load_gpr(t0, rs);
3532
3533 switch (opc) {
3534 case OPC_CLO:
3535 case R6_OPC_CLO:
3536 #if defined(TARGET_MIPS64)
3537 case OPC_DCLO:
3538 case R6_OPC_DCLO:
3539 #endif
3540 tcg_gen_not_tl(t0, t0);
3541 break;
3542 }
3543
3544 switch (opc) {
3545 case OPC_CLO:
3546 case R6_OPC_CLO:
3547 case OPC_CLZ:
3548 case R6_OPC_CLZ:
3549 tcg_gen_ext32u_tl(t0, t0);
3550 tcg_gen_clzi_tl(t0, t0, TARGET_LONG_BITS);
3551 tcg_gen_subi_tl(t0, t0, TARGET_LONG_BITS - 32);
3552 break;
3553 #if defined(TARGET_MIPS64)
3554 case OPC_DCLO:
3555 case R6_OPC_DCLO:
3556 case OPC_DCLZ:
3557 case R6_OPC_DCLZ:
3558 tcg_gen_clzi_i64(t0, t0, 64);
3559 break;
3560 #endif
3561 }
3562 }
3563
3564 /* Loongson multimedia instructions */
gen_loongson_multimedia(DisasContext * ctx,int rd,int rs,int rt)3565 static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
3566 {
3567 uint32_t opc, shift_max;
3568 TCGv_i64 t0, t1;
3569 TCGCond cond;
3570
3571 opc = MASK_LMMI(ctx->opcode);
3572 check_cp1_enabled(ctx);
3573
3574 t0 = tcg_temp_new_i64();
3575 t1 = tcg_temp_new_i64();
3576 gen_load_fpr64(ctx, t0, rs);
3577 gen_load_fpr64(ctx, t1, rt);
3578
3579 switch (opc) {
3580 case OPC_PADDSH:
3581 gen_helper_paddsh(t0, t0, t1);
3582 break;
3583 case OPC_PADDUSH:
3584 gen_helper_paddush(t0, t0, t1);
3585 break;
3586 case OPC_PADDH:
3587 gen_helper_paddh(t0, t0, t1);
3588 break;
3589 case OPC_PADDW:
3590 gen_helper_paddw(t0, t0, t1);
3591 break;
3592 case OPC_PADDSB:
3593 gen_helper_paddsb(t0, t0, t1);
3594 break;
3595 case OPC_PADDUSB:
3596 gen_helper_paddusb(t0, t0, t1);
3597 break;
3598 case OPC_PADDB:
3599 gen_helper_paddb(t0, t0, t1);
3600 break;
3601
3602 case OPC_PSUBSH:
3603 gen_helper_psubsh(t0, t0, t1);
3604 break;
3605 case OPC_PSUBUSH:
3606 gen_helper_psubush(t0, t0, t1);
3607 break;
3608 case OPC_PSUBH:
3609 gen_helper_psubh(t0, t0, t1);
3610 break;
3611 case OPC_PSUBW:
3612 gen_helper_psubw(t0, t0, t1);
3613 break;
3614 case OPC_PSUBSB:
3615 gen_helper_psubsb(t0, t0, t1);
3616 break;
3617 case OPC_PSUBUSB:
3618 gen_helper_psubusb(t0, t0, t1);
3619 break;
3620 case OPC_PSUBB:
3621 gen_helper_psubb(t0, t0, t1);
3622 break;
3623
3624 case OPC_PSHUFH:
3625 gen_helper_pshufh(t0, t0, t1);
3626 break;
3627 case OPC_PACKSSWH:
3628 gen_helper_packsswh(t0, t0, t1);
3629 break;
3630 case OPC_PACKSSHB:
3631 gen_helper_packsshb(t0, t0, t1);
3632 break;
3633 case OPC_PACKUSHB:
3634 gen_helper_packushb(t0, t0, t1);
3635 break;
3636
3637 case OPC_PUNPCKLHW:
3638 gen_helper_punpcklhw(t0, t0, t1);
3639 break;
3640 case OPC_PUNPCKHHW:
3641 gen_helper_punpckhhw(t0, t0, t1);
3642 break;
3643 case OPC_PUNPCKLBH:
3644 gen_helper_punpcklbh(t0, t0, t1);
3645 break;
3646 case OPC_PUNPCKHBH:
3647 gen_helper_punpckhbh(t0, t0, t1);
3648 break;
3649 case OPC_PUNPCKLWD:
3650 gen_helper_punpcklwd(t0, t0, t1);
3651 break;
3652 case OPC_PUNPCKHWD:
3653 gen_helper_punpckhwd(t0, t0, t1);
3654 break;
3655
3656 case OPC_PAVGH:
3657 gen_helper_pavgh(t0, t0, t1);
3658 break;
3659 case OPC_PAVGB:
3660 gen_helper_pavgb(t0, t0, t1);
3661 break;
3662 case OPC_PMAXSH:
3663 gen_helper_pmaxsh(t0, t0, t1);
3664 break;
3665 case OPC_PMINSH:
3666 gen_helper_pminsh(t0, t0, t1);
3667 break;
3668 case OPC_PMAXUB:
3669 gen_helper_pmaxub(t0, t0, t1);
3670 break;
3671 case OPC_PMINUB:
3672 gen_helper_pminub(t0, t0, t1);
3673 break;
3674
3675 case OPC_PCMPEQW:
3676 gen_helper_pcmpeqw(t0, t0, t1);
3677 break;
3678 case OPC_PCMPGTW:
3679 gen_helper_pcmpgtw(t0, t0, t1);
3680 break;
3681 case OPC_PCMPEQH:
3682 gen_helper_pcmpeqh(t0, t0, t1);
3683 break;
3684 case OPC_PCMPGTH:
3685 gen_helper_pcmpgth(t0, t0, t1);
3686 break;
3687 case OPC_PCMPEQB:
3688 gen_helper_pcmpeqb(t0, t0, t1);
3689 break;
3690 case OPC_PCMPGTB:
3691 gen_helper_pcmpgtb(t0, t0, t1);
3692 break;
3693
3694 case OPC_PSLLW:
3695 gen_helper_psllw(t0, t0, t1);
3696 break;
3697 case OPC_PSLLH:
3698 gen_helper_psllh(t0, t0, t1);
3699 break;
3700 case OPC_PSRLW:
3701 gen_helper_psrlw(t0, t0, t1);
3702 break;
3703 case OPC_PSRLH:
3704 gen_helper_psrlh(t0, t0, t1);
3705 break;
3706 case OPC_PSRAW:
3707 gen_helper_psraw(t0, t0, t1);
3708 break;
3709 case OPC_PSRAH:
3710 gen_helper_psrah(t0, t0, t1);
3711 break;
3712
3713 case OPC_PMULLH:
3714 gen_helper_pmullh(t0, t0, t1);
3715 break;
3716 case OPC_PMULHH:
3717 gen_helper_pmulhh(t0, t0, t1);
3718 break;
3719 case OPC_PMULHUH:
3720 gen_helper_pmulhuh(t0, t0, t1);
3721 break;
3722 case OPC_PMADDHW:
3723 gen_helper_pmaddhw(t0, t0, t1);
3724 break;
3725
3726 case OPC_PASUBUB:
3727 gen_helper_pasubub(t0, t0, t1);
3728 break;
3729 case OPC_BIADD:
3730 gen_helper_biadd(t0, t0);
3731 break;
3732 case OPC_PMOVMSKB:
3733 gen_helper_pmovmskb(t0, t0);
3734 break;
3735
3736 case OPC_PADDD:
3737 tcg_gen_add_i64(t0, t0, t1);
3738 break;
3739 case OPC_PSUBD:
3740 tcg_gen_sub_i64(t0, t0, t1);
3741 break;
3742 case OPC_XOR_CP2:
3743 tcg_gen_xor_i64(t0, t0, t1);
3744 break;
3745 case OPC_NOR_CP2:
3746 tcg_gen_nor_i64(t0, t0, t1);
3747 break;
3748 case OPC_AND_CP2:
3749 tcg_gen_and_i64(t0, t0, t1);
3750 break;
3751 case OPC_OR_CP2:
3752 tcg_gen_or_i64(t0, t0, t1);
3753 break;
3754
3755 case OPC_PANDN:
3756 tcg_gen_andc_i64(t0, t1, t0);
3757 break;
3758
3759 case OPC_PINSRH_0:
3760 tcg_gen_deposit_i64(t0, t0, t1, 0, 16);
3761 break;
3762 case OPC_PINSRH_1:
3763 tcg_gen_deposit_i64(t0, t0, t1, 16, 16);
3764 break;
3765 case OPC_PINSRH_2:
3766 tcg_gen_deposit_i64(t0, t0, t1, 32, 16);
3767 break;
3768 case OPC_PINSRH_3:
3769 tcg_gen_deposit_i64(t0, t0, t1, 48, 16);
3770 break;
3771
3772 case OPC_PEXTRH:
3773 tcg_gen_andi_i64(t1, t1, 3);
3774 tcg_gen_shli_i64(t1, t1, 4);
3775 tcg_gen_shr_i64(t0, t0, t1);
3776 tcg_gen_ext16u_i64(t0, t0);
3777 break;
3778
3779 case OPC_ADDU_CP2:
3780 tcg_gen_add_i64(t0, t0, t1);
3781 tcg_gen_ext32s_i64(t0, t0);
3782 break;
3783 case OPC_SUBU_CP2:
3784 tcg_gen_sub_i64(t0, t0, t1);
3785 tcg_gen_ext32s_i64(t0, t0);
3786 break;
3787
3788 case OPC_SLL_CP2:
3789 shift_max = 32;
3790 goto do_shift;
3791 case OPC_SRL_CP2:
3792 shift_max = 32;
3793 goto do_shift;
3794 case OPC_SRA_CP2:
3795 shift_max = 32;
3796 goto do_shift;
3797 case OPC_DSLL_CP2:
3798 shift_max = 64;
3799 goto do_shift;
3800 case OPC_DSRL_CP2:
3801 shift_max = 64;
3802 goto do_shift;
3803 case OPC_DSRA_CP2:
3804 shift_max = 64;
3805 goto do_shift;
3806 do_shift:
3807 /* Make sure shift count isn't TCG undefined behaviour. */
3808 tcg_gen_andi_i64(t1, t1, shift_max - 1);
3809
3810 switch (opc) {
3811 case OPC_SLL_CP2:
3812 case OPC_DSLL_CP2:
3813 tcg_gen_shl_i64(t0, t0, t1);
3814 break;
3815 case OPC_SRA_CP2:
3816 case OPC_DSRA_CP2:
3817 /*
3818 * Since SRA is UndefinedResult without sign-extended inputs,
3819 * we can treat SRA and DSRA the same.
3820 */
3821 tcg_gen_sar_i64(t0, t0, t1);
3822 break;
3823 case OPC_SRL_CP2:
3824 /* We want to shift in zeros for SRL; zero-extend first. */
3825 tcg_gen_ext32u_i64(t0, t0);
3826 /* FALLTHRU */
3827 case OPC_DSRL_CP2:
3828 tcg_gen_shr_i64(t0, t0, t1);
3829 break;
3830 }
3831
3832 if (shift_max == 32) {
3833 tcg_gen_ext32s_i64(t0, t0);
3834 }
3835
3836 /* Shifts larger than MAX produce zero. */
3837 tcg_gen_setcondi_i64(TCG_COND_LTU, t1, t1, shift_max);
3838 tcg_gen_neg_i64(t1, t1);
3839 tcg_gen_and_i64(t0, t0, t1);
3840 break;
3841
3842 case OPC_ADD_CP2:
3843 case OPC_DADD_CP2:
3844 {
3845 TCGv_i64 t2 = tcg_temp_new_i64();
3846 TCGLabel *lab = gen_new_label();
3847
3848 tcg_gen_mov_i64(t2, t0);
3849 tcg_gen_add_i64(t0, t1, t2);
3850 if (opc == OPC_ADD_CP2) {
3851 tcg_gen_ext32s_i64(t0, t0);
3852 }
3853 tcg_gen_xor_i64(t1, t1, t2);
3854 tcg_gen_xor_i64(t2, t2, t0);
3855 tcg_gen_andc_i64(t1, t2, t1);
3856 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3857 generate_exception(ctx, EXCP_OVERFLOW);
3858 gen_set_label(lab);
3859 break;
3860 }
3861
3862 case OPC_SUB_CP2:
3863 case OPC_DSUB_CP2:
3864 {
3865 TCGv_i64 t2 = tcg_temp_new_i64();
3866 TCGLabel *lab = gen_new_label();
3867
3868 tcg_gen_mov_i64(t2, t0);
3869 tcg_gen_sub_i64(t0, t1, t2);
3870 if (opc == OPC_SUB_CP2) {
3871 tcg_gen_ext32s_i64(t0, t0);
3872 }
3873 tcg_gen_xor_i64(t1, t1, t2);
3874 tcg_gen_xor_i64(t2, t2, t0);
3875 tcg_gen_and_i64(t1, t1, t2);
3876 tcg_gen_brcondi_i64(TCG_COND_GE, t1, 0, lab);
3877 generate_exception(ctx, EXCP_OVERFLOW);
3878 gen_set_label(lab);
3879 break;
3880 }
3881
3882 case OPC_PMULUW:
3883 tcg_gen_ext32u_i64(t0, t0);
3884 tcg_gen_ext32u_i64(t1, t1);
3885 tcg_gen_mul_i64(t0, t0, t1);
3886 break;
3887
3888 case OPC_SEQU_CP2:
3889 case OPC_SEQ_CP2:
3890 cond = TCG_COND_EQ;
3891 goto do_cc_cond;
3892 break;
3893 case OPC_SLTU_CP2:
3894 cond = TCG_COND_LTU;
3895 goto do_cc_cond;
3896 break;
3897 case OPC_SLT_CP2:
3898 cond = TCG_COND_LT;
3899 goto do_cc_cond;
3900 break;
3901 case OPC_SLEU_CP2:
3902 cond = TCG_COND_LEU;
3903 goto do_cc_cond;
3904 break;
3905 case OPC_SLE_CP2:
3906 cond = TCG_COND_LE;
3907 do_cc_cond:
3908 {
3909 int cc = (ctx->opcode >> 8) & 0x7;
3910 TCGv_i64 t64 = tcg_temp_new_i64();
3911 TCGv_i32 t32 = tcg_temp_new_i32();
3912
3913 tcg_gen_setcond_i64(cond, t64, t0, t1);
3914 tcg_gen_extrl_i64_i32(t32, t64);
3915 tcg_gen_deposit_i32(fpu_fcr31, fpu_fcr31, t32,
3916 get_fp_bit(cc), 1);
3917 }
3918 return;
3919 default:
3920 MIPS_INVAL("loongson_cp2");
3921 gen_reserved_instruction(ctx);
3922 return;
3923 }
3924
3925 gen_store_fpr64(ctx, t0, rd);
3926 }
3927
gen_loongson_lswc2(DisasContext * ctx,int rt,int rs,int rd)3928 static void gen_loongson_lswc2(DisasContext *ctx, int rt,
3929 int rs, int rd)
3930 {
3931 TCGv t0, t1;
3932 TCGv_i32 fp0;
3933 #if defined(TARGET_MIPS64)
3934 int lsq_rt1 = ctx->opcode & 0x1f;
3935 int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4;
3936 #endif
3937 int shf_offset = sextract32(ctx->opcode, 6, 8);
3938
3939 t0 = tcg_temp_new();
3940
3941 switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) {
3942 #if defined(TARGET_MIPS64)
3943 case OPC_GSLQ:
3944 t1 = tcg_temp_new();
3945 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3946 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3947 ctx->default_tcg_memop_mask);
3948 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3949 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3950 ctx->default_tcg_memop_mask);
3951 gen_store_gpr(t1, rt);
3952 gen_store_gpr(t0, lsq_rt1);
3953 break;
3954 case OPC_GSLQC1:
3955 check_cp1_enabled(ctx);
3956 t1 = tcg_temp_new();
3957 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3958 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3959 ctx->default_tcg_memop_mask);
3960 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3961 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3962 ctx->default_tcg_memop_mask);
3963 gen_store_fpr64(ctx, t1, rt);
3964 gen_store_fpr64(ctx, t0, lsq_rt1);
3965 break;
3966 case OPC_GSSQ:
3967 t1 = tcg_temp_new();
3968 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3969 gen_load_gpr(t1, rt);
3970 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3971 ctx->default_tcg_memop_mask);
3972 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3973 gen_load_gpr(t1, lsq_rt1);
3974 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3975 ctx->default_tcg_memop_mask);
3976 break;
3977 case OPC_GSSQC1:
3978 check_cp1_enabled(ctx);
3979 t1 = tcg_temp_new();
3980 gen_base_offset_addr(ctx, t0, rs, lsq_offset);
3981 gen_load_fpr64(ctx, t1, rt);
3982 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3983 ctx->default_tcg_memop_mask);
3984 gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8);
3985 gen_load_fpr64(ctx, t1, lsq_rt1);
3986 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
3987 ctx->default_tcg_memop_mask);
3988 break;
3989 #endif
3990 case OPC_GSSHFL:
3991 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
3992 case OPC_GSLWLC1:
3993 check_cp1_enabled(ctx);
3994 gen_base_offset_addr(ctx, t0, rs, shf_offset);
3995 fp0 = tcg_temp_new_i32();
3996 gen_load_fpr32(ctx, fp0, rt);
3997 t1 = tcg_temp_new();
3998 tcg_gen_ext_i32_tl(t1, fp0);
3999 gen_lxl(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
4000 tcg_gen_trunc_tl_i32(fp0, t1);
4001 gen_store_fpr32(ctx, fp0, rt);
4002 break;
4003 case OPC_GSLWRC1:
4004 check_cp1_enabled(ctx);
4005 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4006 fp0 = tcg_temp_new_i32();
4007 gen_load_fpr32(ctx, fp0, rt);
4008 t1 = tcg_temp_new();
4009 tcg_gen_ext_i32_tl(t1, fp0);
4010 gen_lxr(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
4011 tcg_gen_trunc_tl_i32(fp0, t1);
4012 gen_store_fpr32(ctx, fp0, rt);
4013 break;
4014 #if defined(TARGET_MIPS64)
4015 case OPC_GSLDLC1:
4016 check_cp1_enabled(ctx);
4017 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4018 t1 = tcg_temp_new();
4019 gen_load_fpr64(ctx, t1, rt);
4020 gen_lxl(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
4021 gen_store_fpr64(ctx, t1, rt);
4022 break;
4023 case OPC_GSLDRC1:
4024 check_cp1_enabled(ctx);
4025 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4026 t1 = tcg_temp_new();
4027 gen_load_fpr64(ctx, t1, rt);
4028 gen_lxr(ctx, t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
4029 gen_store_fpr64(ctx, t1, rt);
4030 break;
4031 #endif
4032 default:
4033 MIPS_INVAL("loongson_gsshfl");
4034 gen_reserved_instruction(ctx);
4035 break;
4036 }
4037 break;
4038 case OPC_GSSHFS:
4039 switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) {
4040 case OPC_GSSWLC1:
4041 check_cp1_enabled(ctx);
4042 t1 = tcg_temp_new();
4043 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4044 fp0 = tcg_temp_new_i32();
4045 gen_load_fpr32(ctx, fp0, rt);
4046 tcg_gen_ext_i32_tl(t1, fp0);
4047 gen_helper_0e2i(swl, t1, t0, ctx->mem_idx);
4048 break;
4049 case OPC_GSSWRC1:
4050 check_cp1_enabled(ctx);
4051 t1 = tcg_temp_new();
4052 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4053 fp0 = tcg_temp_new_i32();
4054 gen_load_fpr32(ctx, fp0, rt);
4055 tcg_gen_ext_i32_tl(t1, fp0);
4056 gen_helper_0e2i(swr, t1, t0, ctx->mem_idx);
4057 break;
4058 #if defined(TARGET_MIPS64)
4059 case OPC_GSSDLC1:
4060 check_cp1_enabled(ctx);
4061 t1 = tcg_temp_new();
4062 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4063 gen_load_fpr64(ctx, t1, rt);
4064 gen_helper_0e2i(sdl, t1, t0, ctx->mem_idx);
4065 break;
4066 case OPC_GSSDRC1:
4067 check_cp1_enabled(ctx);
4068 t1 = tcg_temp_new();
4069 gen_base_offset_addr(ctx, t0, rs, shf_offset);
4070 gen_load_fpr64(ctx, t1, rt);
4071 gen_helper_0e2i(sdr, t1, t0, ctx->mem_idx);
4072 break;
4073 #endif
4074 default:
4075 MIPS_INVAL("loongson_gsshfs");
4076 gen_reserved_instruction(ctx);
4077 break;
4078 }
4079 break;
4080 default:
4081 MIPS_INVAL("loongson_gslsq");
4082 gen_reserved_instruction(ctx);
4083 break;
4084 }
4085 }
4086
4087 /* Loongson EXT LDC2/SDC2 */
gen_loongson_lsdc2(DisasContext * ctx,int rt,int rs,int rd)4088 static void gen_loongson_lsdc2(DisasContext *ctx, int rt,
4089 int rs, int rd)
4090 {
4091 int offset = sextract32(ctx->opcode, 3, 8);
4092 uint32_t opc = MASK_LOONGSON_LSDC2(ctx->opcode);
4093 TCGv t0, t1;
4094 TCGv_i32 fp0;
4095
4096 /* Pre-conditions */
4097 switch (opc) {
4098 case OPC_GSLBX:
4099 case OPC_GSLHX:
4100 case OPC_GSLWX:
4101 case OPC_GSLDX:
4102 /* prefetch, implement as NOP */
4103 if (rt == 0) {
4104 return;
4105 }
4106 break;
4107 case OPC_GSSBX:
4108 case OPC_GSSHX:
4109 case OPC_GSSWX:
4110 case OPC_GSSDX:
4111 break;
4112 case OPC_GSLWXC1:
4113 #if defined(TARGET_MIPS64)
4114 case OPC_GSLDXC1:
4115 #endif
4116 check_cp1_enabled(ctx);
4117 /* prefetch, implement as NOP */
4118 if (rt == 0) {
4119 return;
4120 }
4121 break;
4122 case OPC_GSSWXC1:
4123 #if defined(TARGET_MIPS64)
4124 case OPC_GSSDXC1:
4125 #endif
4126 check_cp1_enabled(ctx);
4127 break;
4128 default:
4129 MIPS_INVAL("loongson_lsdc2");
4130 gen_reserved_instruction(ctx);
4131 return;
4132 break;
4133 }
4134
4135 t0 = tcg_temp_new();
4136
4137 gen_base_offset_addr(ctx, t0, rs, offset);
4138 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4139
4140 switch (opc) {
4141 case OPC_GSLBX:
4142 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_SB);
4143 gen_store_gpr(t0, rt);
4144 break;
4145 case OPC_GSLHX:
4146 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SW |
4147 ctx->default_tcg_memop_mask);
4148 gen_store_gpr(t0, rt);
4149 break;
4150 case OPC_GSLWX:
4151 gen_base_offset_addr(ctx, t0, rs, offset);
4152 if (rd) {
4153 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4154 }
4155 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
4156 ctx->default_tcg_memop_mask);
4157 gen_store_gpr(t0, rt);
4158 break;
4159 #if defined(TARGET_MIPS64)
4160 case OPC_GSLDX:
4161 gen_base_offset_addr(ctx, t0, rs, offset);
4162 if (rd) {
4163 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4164 }
4165 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4166 ctx->default_tcg_memop_mask);
4167 gen_store_gpr(t0, rt);
4168 break;
4169 #endif
4170 case OPC_GSLWXC1:
4171 gen_base_offset_addr(ctx, t0, rs, offset);
4172 if (rd) {
4173 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4174 }
4175 fp0 = tcg_temp_new_i32();
4176 tcg_gen_qemu_ld_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL |
4177 ctx->default_tcg_memop_mask);
4178 gen_store_fpr32(ctx, fp0, rt);
4179 break;
4180 #if defined(TARGET_MIPS64)
4181 case OPC_GSLDXC1:
4182 gen_base_offset_addr(ctx, t0, rs, offset);
4183 if (rd) {
4184 gen_op_addr_add(ctx, t0, cpu_gpr[rd], t0);
4185 }
4186 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4187 ctx->default_tcg_memop_mask);
4188 gen_store_fpr64(ctx, t0, rt);
4189 break;
4190 #endif
4191 case OPC_GSSBX:
4192 t1 = tcg_temp_new();
4193 gen_load_gpr(t1, rt);
4194 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_SB);
4195 break;
4196 case OPC_GSSHX:
4197 t1 = tcg_temp_new();
4198 gen_load_gpr(t1, rt);
4199 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UW |
4200 ctx->default_tcg_memop_mask);
4201 break;
4202 case OPC_GSSWX:
4203 t1 = tcg_temp_new();
4204 gen_load_gpr(t1, rt);
4205 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
4206 ctx->default_tcg_memop_mask);
4207 break;
4208 #if defined(TARGET_MIPS64)
4209 case OPC_GSSDX:
4210 t1 = tcg_temp_new();
4211 gen_load_gpr(t1, rt);
4212 tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4213 ctx->default_tcg_memop_mask);
4214 break;
4215 #endif
4216 case OPC_GSSWXC1:
4217 fp0 = tcg_temp_new_i32();
4218 gen_load_fpr32(ctx, fp0, rt);
4219 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL |
4220 ctx->default_tcg_memop_mask);
4221 break;
4222 #if defined(TARGET_MIPS64)
4223 case OPC_GSSDXC1:
4224 t1 = tcg_temp_new();
4225 gen_load_fpr64(ctx, t1, rt);
4226 tcg_gen_qemu_st_i64(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ |
4227 ctx->default_tcg_memop_mask);
4228 break;
4229 #endif
4230 default:
4231 break;
4232 }
4233 }
4234
4235 /* Traps */
gen_trap(DisasContext * ctx,uint32_t opc,int rs,int rt,int16_t imm,int code)4236 static void gen_trap(DisasContext *ctx, uint32_t opc,
4237 int rs, int rt, int16_t imm, int code)
4238 {
4239 int cond;
4240 TCGv t0 = tcg_temp_new();
4241 TCGv t1 = tcg_temp_new();
4242
4243 cond = 0;
4244 /* Load needed operands */
4245 switch (opc) {
4246 case OPC_TEQ:
4247 case OPC_TGE:
4248 case OPC_TGEU:
4249 case OPC_TLT:
4250 case OPC_TLTU:
4251 case OPC_TNE:
4252 /* Compare two registers */
4253 if (rs != rt) {
4254 gen_load_gpr(t0, rs);
4255 gen_load_gpr(t1, rt);
4256 cond = 1;
4257 }
4258 break;
4259 case OPC_TEQI:
4260 case OPC_TGEI:
4261 case OPC_TGEIU:
4262 case OPC_TLTI:
4263 case OPC_TLTIU:
4264 case OPC_TNEI:
4265 /* Compare register to immediate */
4266 if (rs != 0 || imm != 0) {
4267 gen_load_gpr(t0, rs);
4268 tcg_gen_movi_tl(t1, (int32_t)imm);
4269 cond = 1;
4270 }
4271 break;
4272 }
4273 if (cond == 0) {
4274 switch (opc) {
4275 case OPC_TEQ: /* rs == rs */
4276 case OPC_TEQI: /* r0 == 0 */
4277 case OPC_TGE: /* rs >= rs */
4278 case OPC_TGEI: /* r0 >= 0 */
4279 case OPC_TGEU: /* rs >= rs unsigned */
4280 case OPC_TGEIU: /* r0 >= 0 unsigned */
4281 /* Always trap */
4282 #ifdef CONFIG_USER_ONLY
4283 /* Pass the break code along to cpu_loop. */
4284 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
4285 offsetof(CPUMIPSState, error_code));
4286 #endif
4287 generate_exception_end(ctx, EXCP_TRAP);
4288 break;
4289 case OPC_TLT: /* rs < rs */
4290 case OPC_TLTI: /* r0 < 0 */
4291 case OPC_TLTU: /* rs < rs unsigned */
4292 case OPC_TLTIU: /* r0 < 0 unsigned */
4293 case OPC_TNE: /* rs != rs */
4294 case OPC_TNEI: /* r0 != 0 */
4295 /* Never trap: treat as NOP. */
4296 break;
4297 }
4298 } else {
4299 TCGLabel *l1 = gen_new_label();
4300
4301 switch (opc) {
4302 case OPC_TEQ:
4303 case OPC_TEQI:
4304 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
4305 break;
4306 case OPC_TGE:
4307 case OPC_TGEI:
4308 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
4309 break;
4310 case OPC_TGEU:
4311 case OPC_TGEIU:
4312 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
4313 break;
4314 case OPC_TLT:
4315 case OPC_TLTI:
4316 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4317 break;
4318 case OPC_TLTU:
4319 case OPC_TLTIU:
4320 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
4321 break;
4322 case OPC_TNE:
4323 case OPC_TNEI:
4324 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
4325 break;
4326 }
4327 #ifdef CONFIG_USER_ONLY
4328 /* Pass the break code along to cpu_loop. */
4329 tcg_gen_st_i32(tcg_constant_i32(code), tcg_env,
4330 offsetof(CPUMIPSState, error_code));
4331 #endif
4332 /* Like save_cpu_state, only don't update saved values. */
4333 if (ctx->base.pc_next != ctx->saved_pc) {
4334 gen_save_pc(ctx->base.pc_next);
4335 }
4336 if (ctx->hflags != ctx->saved_hflags) {
4337 tcg_gen_movi_i32(hflags, ctx->hflags);
4338 }
4339 generate_exception(ctx, EXCP_TRAP);
4340 gen_set_label(l1);
4341 }
4342 }
4343
gen_goto_tb(DisasContext * ctx,int n,target_ulong dest)4344 static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
4345 {
4346 if (translator_use_goto_tb(&ctx->base, dest)) {
4347 tcg_gen_goto_tb(n);
4348 gen_save_pc(dest);
4349 tcg_gen_exit_tb(ctx->base.tb, n);
4350 } else {
4351 gen_save_pc(dest);
4352 tcg_gen_lookup_and_goto_ptr();
4353 }
4354 }
4355
4356 /* 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)4357 static void gen_compute_branch(DisasContext *ctx, uint32_t opc,
4358 int insn_bytes,
4359 int rs, int rt, int32_t offset,
4360 int delayslot_size)
4361 {
4362 target_ulong btgt = -1;
4363 int blink = 0;
4364 int bcond_compute = 0;
4365 TCGv t0 = tcg_temp_new();
4366 TCGv t1 = tcg_temp_new();
4367
4368 if (ctx->hflags & MIPS_HFLAG_BMASK) {
4369 #ifdef MIPS_DEBUG_DISAS
4370 LOG_DISAS("Branch in delay / forbidden slot at PC 0x%016"
4371 VADDR_PRIx "\n", ctx->base.pc_next);
4372 #endif
4373 gen_reserved_instruction(ctx);
4374 goto out;
4375 }
4376
4377 /* Load needed operands */
4378 switch (opc) {
4379 case OPC_BEQ:
4380 case OPC_BEQL:
4381 case OPC_BNE:
4382 case OPC_BNEL:
4383 /* Compare two registers */
4384 if (rs != rt) {
4385 gen_load_gpr(t0, rs);
4386 gen_load_gpr(t1, rt);
4387 bcond_compute = 1;
4388 }
4389 btgt = ctx->base.pc_next + insn_bytes + offset;
4390 break;
4391 case OPC_BGEZ:
4392 case OPC_BGEZAL:
4393 case OPC_BGEZALL:
4394 case OPC_BGEZL:
4395 case OPC_BGTZ:
4396 case OPC_BGTZL:
4397 case OPC_BLEZ:
4398 case OPC_BLEZL:
4399 case OPC_BLTZ:
4400 case OPC_BLTZAL:
4401 case OPC_BLTZALL:
4402 case OPC_BLTZL:
4403 /* Compare to zero */
4404 if (rs != 0) {
4405 gen_load_gpr(t0, rs);
4406 bcond_compute = 1;
4407 }
4408 btgt = ctx->base.pc_next + insn_bytes + offset;
4409 break;
4410 case OPC_BPOSGE32:
4411 #if defined(TARGET_MIPS64)
4412 case OPC_BPOSGE64:
4413 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x7F);
4414 #else
4415 tcg_gen_andi_tl(t0, cpu_dspctrl, 0x3F);
4416 #endif
4417 bcond_compute = 1;
4418 btgt = ctx->base.pc_next + insn_bytes + offset;
4419 break;
4420 case OPC_J:
4421 case OPC_JAL:
4422 {
4423 /* Jump to immediate */
4424 int jal_mask = ctx->hflags & MIPS_HFLAG_M16 ? 0xF8000000
4425 : 0xF0000000;
4426 btgt = ((ctx->base.pc_next + insn_bytes) & jal_mask)
4427 | (uint32_t)offset;
4428 break;
4429 }
4430 case OPC_JALX:
4431 /* Jump to immediate */
4432 btgt = ((ctx->base.pc_next + insn_bytes) & (int32_t)0xF0000000) |
4433 (uint32_t)offset;
4434 break;
4435 case OPC_JR:
4436 case OPC_JALR:
4437 /* Jump to register */
4438 if (offset != 0 && offset != 16) {
4439 /*
4440 * Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
4441 * others are reserved.
4442 */
4443 MIPS_INVAL("jump hint");
4444 gen_reserved_instruction(ctx);
4445 goto out;
4446 }
4447 gen_load_gpr(btarget, rs);
4448 break;
4449 default:
4450 MIPS_INVAL("branch/jump");
4451 gen_reserved_instruction(ctx);
4452 goto out;
4453 }
4454 if (bcond_compute == 0) {
4455 /* No condition to be computed */
4456 switch (opc) {
4457 case OPC_BEQ: /* rx == rx */
4458 case OPC_BEQL: /* rx == rx likely */
4459 case OPC_BGEZ: /* 0 >= 0 */
4460 case OPC_BGEZL: /* 0 >= 0 likely */
4461 case OPC_BLEZ: /* 0 <= 0 */
4462 case OPC_BLEZL: /* 0 <= 0 likely */
4463 /* Always take */
4464 ctx->hflags |= MIPS_HFLAG_B;
4465 break;
4466 case OPC_BGEZAL: /* 0 >= 0 */
4467 case OPC_BGEZALL: /* 0 >= 0 likely */
4468 /* Always take and link */
4469 blink = 31;
4470 ctx->hflags |= MIPS_HFLAG_B;
4471 break;
4472 case OPC_BNE: /* rx != rx */
4473 case OPC_BGTZ: /* 0 > 0 */
4474 case OPC_BLTZ: /* 0 < 0 */
4475 /* Treat as NOP. */
4476 goto out;
4477 case OPC_BLTZAL: /* 0 < 0 */
4478 /*
4479 * Handle as an unconditional branch to get correct delay
4480 * slot checking.
4481 */
4482 blink = 31;
4483 btgt = ctx->base.pc_next + insn_bytes + delayslot_size;
4484 ctx->hflags |= MIPS_HFLAG_B;
4485 break;
4486 case OPC_BLTZALL: /* 0 < 0 likely */
4487 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 8);
4488 /* Skip the instruction in the delay slot */
4489 ctx->base.pc_next += 4;
4490 goto out;
4491 case OPC_BNEL: /* rx != rx likely */
4492 case OPC_BGTZL: /* 0 > 0 likely */
4493 case OPC_BLTZL: /* 0 < 0 likely */
4494 /* Skip the instruction in the delay slot */
4495 ctx->base.pc_next += 4;
4496 goto out;
4497 case OPC_J:
4498 ctx->hflags |= MIPS_HFLAG_B;
4499 break;
4500 case OPC_JALX:
4501 ctx->hflags |= MIPS_HFLAG_BX;
4502 /* Fallthrough */
4503 case OPC_JAL:
4504 blink = 31;
4505 ctx->hflags |= MIPS_HFLAG_B;
4506 break;
4507 case OPC_JR:
4508 ctx->hflags |= MIPS_HFLAG_BR;
4509 break;
4510 case OPC_JALR:
4511 blink = rt;
4512 ctx->hflags |= MIPS_HFLAG_BR;
4513 break;
4514 default:
4515 MIPS_INVAL("branch/jump");
4516 gen_reserved_instruction(ctx);
4517 goto out;
4518 }
4519 } else {
4520 switch (opc) {
4521 case OPC_BEQ:
4522 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4523 goto not_likely;
4524 case OPC_BEQL:
4525 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
4526 goto likely;
4527 case OPC_BNE:
4528 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4529 goto not_likely;
4530 case OPC_BNEL:
4531 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
4532 goto likely;
4533 case OPC_BGEZ:
4534 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4535 goto not_likely;
4536 case OPC_BGEZL:
4537 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4538 goto likely;
4539 case OPC_BGEZAL:
4540 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4541 blink = 31;
4542 goto not_likely;
4543 case OPC_BGEZALL:
4544 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
4545 blink = 31;
4546 goto likely;
4547 case OPC_BGTZ:
4548 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4549 goto not_likely;
4550 case OPC_BGTZL:
4551 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
4552 goto likely;
4553 case OPC_BLEZ:
4554 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4555 goto not_likely;
4556 case OPC_BLEZL:
4557 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
4558 goto likely;
4559 case OPC_BLTZ:
4560 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4561 goto not_likely;
4562 case OPC_BLTZL:
4563 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4564 goto likely;
4565 case OPC_BPOSGE32:
4566 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 32);
4567 goto not_likely;
4568 #if defined(TARGET_MIPS64)
4569 case OPC_BPOSGE64:
4570 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 64);
4571 goto not_likely;
4572 #endif
4573 case OPC_BLTZAL:
4574 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4575 blink = 31;
4576 not_likely:
4577 ctx->hflags |= MIPS_HFLAG_BC;
4578 break;
4579 case OPC_BLTZALL:
4580 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
4581 blink = 31;
4582 likely:
4583 ctx->hflags |= MIPS_HFLAG_BL;
4584 break;
4585 default:
4586 MIPS_INVAL("conditional branch/jump");
4587 gen_reserved_instruction(ctx);
4588 goto out;
4589 }
4590 }
4591
4592 ctx->btarget = btgt;
4593
4594 switch (delayslot_size) {
4595 case 2:
4596 ctx->hflags |= MIPS_HFLAG_BDS16;
4597 break;
4598 case 4:
4599 ctx->hflags |= MIPS_HFLAG_BDS32;
4600 break;
4601 }
4602
4603 if (blink > 0) {
4604 int post_delay = insn_bytes + delayslot_size;
4605 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
4606
4607 tcg_gen_movi_tl(cpu_gpr[blink],
4608 ctx->base.pc_next + post_delay + lowbit);
4609 }
4610
4611 out:
4612 if (insn_bytes == 2) {
4613 ctx->hflags |= MIPS_HFLAG_B16;
4614 }
4615 }
4616
4617
4618 /* special3 bitfield operations */
gen_bitops(DisasContext * ctx,uint32_t opc,int rt,int rs,int lsb,int msb)4619 static void gen_bitops(DisasContext *ctx, uint32_t opc, int rt,
4620 int rs, int lsb, int msb)
4621 {
4622 TCGv t0 = tcg_temp_new();
4623 TCGv t1 = tcg_temp_new();
4624
4625 gen_load_gpr(t1, rs);
4626 switch (opc) {
4627 case OPC_EXT:
4628 if (lsb + msb > 31) {
4629 goto fail;
4630 }
4631 if (msb != 31) {
4632 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4633 } else {
4634 /*
4635 * The two checks together imply that lsb == 0,
4636 * so this is a simple sign-extension.
4637 */
4638 tcg_gen_ext32s_tl(t0, t1);
4639 }
4640 break;
4641 #if defined(TARGET_MIPS64)
4642 case OPC_DEXTU:
4643 lsb += 32;
4644 goto do_dext;
4645 case OPC_DEXTM:
4646 msb += 32;
4647 goto do_dext;
4648 case OPC_DEXT:
4649 do_dext:
4650 if (lsb + msb > 63) {
4651 goto fail;
4652 }
4653 tcg_gen_extract_tl(t0, t1, lsb, msb + 1);
4654 break;
4655 #endif
4656 case OPC_INS:
4657 if (lsb > msb) {
4658 goto fail;
4659 }
4660 gen_load_gpr(t0, rt);
4661 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4662 tcg_gen_ext32s_tl(t0, t0);
4663 break;
4664 #if defined(TARGET_MIPS64)
4665 case OPC_DINSU:
4666 lsb += 32;
4667 /* FALLTHRU */
4668 case OPC_DINSM:
4669 msb += 32;
4670 /* FALLTHRU */
4671 case OPC_DINS:
4672 if (lsb > msb) {
4673 goto fail;
4674 }
4675 gen_load_gpr(t0, rt);
4676 tcg_gen_deposit_tl(t0, t0, t1, lsb, msb - lsb + 1);
4677 break;
4678 #endif
4679 default:
4680 fail:
4681 MIPS_INVAL("bitops");
4682 gen_reserved_instruction(ctx);
4683 return;
4684 }
4685 gen_store_gpr(t0, rt);
4686 }
4687
gen_bshfl(DisasContext * ctx,uint32_t op2,int rt,int rd)4688 static void gen_bshfl(DisasContext *ctx, uint32_t op2, int rt, int rd)
4689 {
4690 TCGv t0;
4691
4692 if (rd == 0) {
4693 /* If no destination, treat it as a NOP. */
4694 return;
4695 }
4696
4697 t0 = tcg_temp_new();
4698 gen_load_gpr(t0, rt);
4699 switch (op2) {
4700 case OPC_WSBH:
4701 {
4702 TCGv t1 = tcg_temp_new();
4703 TCGv t2 = tcg_constant_tl(0x00FF00FF);
4704
4705 tcg_gen_shri_tl(t1, t0, 8);
4706 tcg_gen_and_tl(t1, t1, t2);
4707 tcg_gen_and_tl(t0, t0, t2);
4708 tcg_gen_shli_tl(t0, t0, 8);
4709 tcg_gen_or_tl(t0, t0, t1);
4710 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4711 }
4712 break;
4713 case OPC_SEB:
4714 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
4715 break;
4716 case OPC_SEH:
4717 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
4718 break;
4719 #if defined(TARGET_MIPS64)
4720 case OPC_DSBH:
4721 {
4722 TCGv t1 = tcg_temp_new();
4723 TCGv t2 = tcg_constant_tl(0x00FF00FF00FF00FFULL);
4724
4725 tcg_gen_shri_tl(t1, t0, 8);
4726 tcg_gen_and_tl(t1, t1, t2);
4727 tcg_gen_and_tl(t0, t0, t2);
4728 tcg_gen_shli_tl(t0, t0, 8);
4729 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4730 }
4731 break;
4732 case OPC_DSHD:
4733 {
4734 TCGv t1 = tcg_temp_new();
4735 TCGv t2 = tcg_constant_tl(0x0000FFFF0000FFFFULL);
4736
4737 tcg_gen_shri_tl(t1, t0, 16);
4738 tcg_gen_and_tl(t1, t1, t2);
4739 tcg_gen_and_tl(t0, t0, t2);
4740 tcg_gen_shli_tl(t0, t0, 16);
4741 tcg_gen_or_tl(t0, t0, t1);
4742 tcg_gen_shri_tl(t1, t0, 32);
4743 tcg_gen_shli_tl(t0, t0, 32);
4744 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
4745 }
4746 break;
4747 #endif
4748 default:
4749 MIPS_INVAL("bsfhl");
4750 gen_reserved_instruction(ctx);
4751 return;
4752 }
4753 }
4754
gen_align_bits(DisasContext * ctx,int wordsz,int rd,int rs,int rt,int bits)4755 static void gen_align_bits(DisasContext *ctx, int wordsz, int rd, int rs,
4756 int rt, int bits)
4757 {
4758 TCGv t0;
4759 if (rd == 0) {
4760 /* Treat as NOP. */
4761 return;
4762 }
4763 t0 = tcg_temp_new();
4764 if (bits == 0 || bits == wordsz) {
4765 if (bits == 0) {
4766 gen_load_gpr(t0, rt);
4767 } else {
4768 gen_load_gpr(t0, rs);
4769 }
4770 switch (wordsz) {
4771 case 32:
4772 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
4773 break;
4774 #if defined(TARGET_MIPS64)
4775 case 64:
4776 tcg_gen_mov_tl(cpu_gpr[rd], t0);
4777 break;
4778 #endif
4779 }
4780 } else {
4781 TCGv t1 = tcg_temp_new();
4782 gen_load_gpr(t0, rt);
4783 gen_load_gpr(t1, rs);
4784 switch (wordsz) {
4785 case 32:
4786 {
4787 TCGv_i64 t2 = tcg_temp_new_i64();
4788 tcg_gen_concat_tl_i64(t2, t1, t0);
4789 tcg_gen_shri_i64(t2, t2, 32 - bits);
4790 gen_move_low32(cpu_gpr[rd], t2);
4791 }
4792 break;
4793 #if defined(TARGET_MIPS64)
4794 case 64:
4795 tcg_gen_shli_tl(t0, t0, bits);
4796 tcg_gen_shri_tl(t1, t1, 64 - bits);
4797 tcg_gen_or_tl(cpu_gpr[rd], t1, t0);
4798 break;
4799 #endif
4800 }
4801 }
4802 }
4803
gen_align(DisasContext * ctx,int wordsz,int rd,int rs,int rt,int bp)4804 void gen_align(DisasContext *ctx, int wordsz, int rd, int rs, int rt, int bp)
4805 {
4806 gen_align_bits(ctx, wordsz, rd, rs, rt, bp * 8);
4807 }
4808
gen_bitswap(DisasContext * ctx,int opc,int rd,int rt)4809 static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
4810 {
4811 TCGv t0;
4812 if (rd == 0) {
4813 /* Treat as NOP. */
4814 return;
4815 }
4816 t0 = tcg_temp_new();
4817 gen_load_gpr(t0, rt);
4818 switch (opc) {
4819 case OPC_BITSWAP:
4820 gen_helper_bitswap(cpu_gpr[rd], t0);
4821 break;
4822 #if defined(TARGET_MIPS64)
4823 case OPC_DBITSWAP:
4824 gen_helper_dbitswap(cpu_gpr[rd], t0);
4825 break;
4826 #endif
4827 }
4828 }
4829
4830 #ifndef CONFIG_USER_ONLY
4831 /* CP0 (MMU and control) */
gen_mthc0_entrylo(TCGv arg,target_ulong off)4832 static inline void gen_mthc0_entrylo(TCGv arg, target_ulong off)
4833 {
4834 TCGv_i64 t0 = tcg_temp_new_i64();
4835 TCGv_i64 t1 = tcg_temp_new_i64();
4836
4837 tcg_gen_ext_tl_i64(t0, arg);
4838 tcg_gen_ld_i64(t1, tcg_env, off);
4839 #if defined(TARGET_MIPS64)
4840 tcg_gen_deposit_i64(t1, t1, t0, 30, 32);
4841 #else
4842 tcg_gen_concat32_i64(t1, t1, t0);
4843 #endif
4844 tcg_gen_st_i64(t1, tcg_env, off);
4845 }
4846
gen_mthc0_store64(TCGv arg,target_ulong off)4847 static inline void gen_mthc0_store64(TCGv arg, target_ulong off)
4848 {
4849 TCGv_i64 t0 = tcg_temp_new_i64();
4850 TCGv_i64 t1 = tcg_temp_new_i64();
4851
4852 tcg_gen_ext_tl_i64(t0, arg);
4853 tcg_gen_ld_i64(t1, tcg_env, off);
4854 tcg_gen_concat32_i64(t1, t1, t0);
4855 tcg_gen_st_i64(t1, tcg_env, off);
4856 }
4857
gen_mfhc0_entrylo(TCGv arg,target_ulong off)4858 static inline void gen_mfhc0_entrylo(TCGv arg, target_ulong off)
4859 {
4860 TCGv_i64 t0 = tcg_temp_new_i64();
4861
4862 tcg_gen_ld_i64(t0, tcg_env, off);
4863 #if defined(TARGET_MIPS64)
4864 tcg_gen_shri_i64(t0, t0, 30);
4865 #else
4866 tcg_gen_shri_i64(t0, t0, 32);
4867 #endif
4868 gen_move_low32(arg, t0);
4869 }
4870
gen_mfhc0_load64(TCGv arg,target_ulong off,int shift)4871 static inline void gen_mfhc0_load64(TCGv arg, target_ulong off, int shift)
4872 {
4873 TCGv_i64 t0 = tcg_temp_new_i64();
4874
4875 tcg_gen_ld_i64(t0, tcg_env, off);
4876 tcg_gen_shri_i64(t0, t0, 32 + shift);
4877 gen_move_low32(arg, t0);
4878 }
4879
gen_mfc0_load32(TCGv arg,target_ulong off)4880 static inline void gen_mfc0_load32(TCGv arg, target_ulong off)
4881 {
4882 TCGv_i32 t0 = tcg_temp_new_i32();
4883
4884 tcg_gen_ld_i32(t0, tcg_env, off);
4885 tcg_gen_ext_i32_tl(arg, t0);
4886 }
4887
gen_mfc0_load64(TCGv arg,target_ulong off)4888 static inline void gen_mfc0_load64(TCGv arg, target_ulong off)
4889 {
4890 tcg_gen_ld_tl(arg, tcg_env, off);
4891 tcg_gen_ext32s_tl(arg, arg);
4892 }
4893
gen_mtc0_store32(TCGv arg,target_ulong off)4894 static inline void gen_mtc0_store32(TCGv arg, target_ulong off)
4895 {
4896 TCGv_i32 t0 = tcg_temp_new_i32();
4897
4898 tcg_gen_trunc_tl_i32(t0, arg);
4899 tcg_gen_st_i32(t0, tcg_env, off);
4900 }
4901
4902 #define CP0_CHECK(c) \
4903 do { \
4904 if (!(c)) { \
4905 goto cp0_unimplemented; \
4906 } \
4907 } while (0)
4908
gen_mfhc0(DisasContext * ctx,TCGv arg,int reg,int sel)4909 static void gen_mfhc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4910 {
4911 const char *register_name = "invalid";
4912
4913 switch (reg) {
4914 case CP0_REGISTER_02:
4915 switch (sel) {
4916 case 0:
4917 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4918 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
4919 register_name = "EntryLo0";
4920 break;
4921 default:
4922 goto cp0_unimplemented;
4923 }
4924 break;
4925 case CP0_REGISTER_03:
4926 switch (sel) {
4927 case CP0_REG03__ENTRYLO1:
4928 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
4929 gen_mfhc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
4930 register_name = "EntryLo1";
4931 break;
4932 default:
4933 goto cp0_unimplemented;
4934 }
4935 break;
4936 case CP0_REGISTER_17:
4937 switch (sel) {
4938 case CP0_REG17__LLADDR:
4939 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_LLAddr),
4940 ctx->CP0_LLAddr_shift);
4941 register_name = "LLAddr";
4942 break;
4943 case CP0_REG17__MAAR:
4944 CP0_CHECK(ctx->mrp);
4945 gen_helper_mfhc0_maar(arg, tcg_env);
4946 register_name = "MAAR";
4947 break;
4948 default:
4949 goto cp0_unimplemented;
4950 }
4951 break;
4952 case CP0_REGISTER_19:
4953 switch (sel) {
4954 case CP0_REG19__WATCHHI0:
4955 case CP0_REG19__WATCHHI1:
4956 case CP0_REG19__WATCHHI2:
4957 case CP0_REG19__WATCHHI3:
4958 case CP0_REG19__WATCHHI4:
4959 case CP0_REG19__WATCHHI5:
4960 case CP0_REG19__WATCHHI6:
4961 case CP0_REG19__WATCHHI7:
4962 /* upper 32 bits are only available when Config5MI != 0 */
4963 CP0_CHECK(ctx->mi);
4964 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_WatchHi[sel]), 0);
4965 register_name = "WatchHi";
4966 break;
4967 default:
4968 goto cp0_unimplemented;
4969 }
4970 break;
4971 case CP0_REGISTER_28:
4972 switch (sel) {
4973 case 0:
4974 case 2:
4975 case 4:
4976 case 6:
4977 gen_mfhc0_load64(arg, offsetof(CPUMIPSState, CP0_TagLo), 0);
4978 register_name = "TagLo";
4979 break;
4980 default:
4981 goto cp0_unimplemented;
4982 }
4983 break;
4984 default:
4985 goto cp0_unimplemented;
4986 }
4987 trace_mips_translate_c0("mfhc0", register_name, reg, sel);
4988 return;
4989
4990 cp0_unimplemented:
4991 qemu_log_mask(LOG_UNIMP, "mfhc0 %s (reg %d sel %d)\n",
4992 register_name, reg, sel);
4993 tcg_gen_movi_tl(arg, 0);
4994 }
4995
gen_mthc0(DisasContext * ctx,TCGv arg,int reg,int sel)4996 static void gen_mthc0(DisasContext *ctx, TCGv arg, int reg, int sel)
4997 {
4998 const char *register_name = "invalid";
4999 uint64_t mask = ctx->PAMask >> 36;
5000
5001 switch (reg) {
5002 case CP0_REGISTER_02:
5003 switch (sel) {
5004 case 0:
5005 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5006 tcg_gen_andi_tl(arg, arg, mask);
5007 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo0));
5008 register_name = "EntryLo0";
5009 break;
5010 default:
5011 goto cp0_unimplemented;
5012 }
5013 break;
5014 case CP0_REGISTER_03:
5015 switch (sel) {
5016 case CP0_REG03__ENTRYLO1:
5017 CP0_CHECK(ctx->hflags & MIPS_HFLAG_ELPA);
5018 tcg_gen_andi_tl(arg, arg, mask);
5019 gen_mthc0_entrylo(arg, offsetof(CPUMIPSState, CP0_EntryLo1));
5020 register_name = "EntryLo1";
5021 break;
5022 default:
5023 goto cp0_unimplemented;
5024 }
5025 break;
5026 case CP0_REGISTER_17:
5027 switch (sel) {
5028 case CP0_REG17__LLADDR:
5029 /*
5030 * LLAddr is read-only (the only exception is bit 0 if LLB is
5031 * supported); the CP0_LLAddr_rw_bitmask does not seem to be
5032 * relevant for modern MIPS cores supporting MTHC0, therefore
5033 * treating MTHC0 to LLAddr as NOP.
5034 */
5035 register_name = "LLAddr";
5036 break;
5037 case CP0_REG17__MAAR:
5038 CP0_CHECK(ctx->mrp);
5039 gen_helper_mthc0_maar(tcg_env, arg);
5040 register_name = "MAAR";
5041 break;
5042 default:
5043 goto cp0_unimplemented;
5044 }
5045 break;
5046 case CP0_REGISTER_19:
5047 switch (sel) {
5048 case CP0_REG19__WATCHHI0:
5049 case CP0_REG19__WATCHHI1:
5050 case CP0_REG19__WATCHHI2:
5051 case CP0_REG19__WATCHHI3:
5052 case CP0_REG19__WATCHHI4:
5053 case CP0_REG19__WATCHHI5:
5054 case CP0_REG19__WATCHHI6:
5055 case CP0_REG19__WATCHHI7:
5056 /* upper 32 bits are only available when Config5MI != 0 */
5057 CP0_CHECK(ctx->mi);
5058 gen_helper_0e1i(mthc0_watchhi, arg, sel);
5059 register_name = "WatchHi";
5060 break;
5061 default:
5062 goto cp0_unimplemented;
5063 }
5064 break;
5065 case CP0_REGISTER_28:
5066 switch (sel) {
5067 case 0:
5068 case 2:
5069 case 4:
5070 case 6:
5071 tcg_gen_andi_tl(arg, arg, mask);
5072 gen_mthc0_store64(arg, offsetof(CPUMIPSState, CP0_TagLo));
5073 register_name = "TagLo";
5074 break;
5075 default:
5076 goto cp0_unimplemented;
5077 }
5078 break;
5079 default:
5080 goto cp0_unimplemented;
5081 }
5082 trace_mips_translate_c0("mthc0", register_name, reg, sel);
5083 return;
5084
5085 cp0_unimplemented:
5086 qemu_log_mask(LOG_UNIMP, "mthc0 %s (reg %d sel %d)\n",
5087 register_name, reg, sel);
5088 }
5089
gen_mfc0_unimplemented(DisasContext * ctx,TCGv arg)5090 static inline void gen_mfc0_unimplemented(DisasContext *ctx, TCGv arg)
5091 {
5092 if (ctx->insn_flags & ISA_MIPS_R6) {
5093 tcg_gen_movi_tl(arg, 0);
5094 } else {
5095 tcg_gen_movi_tl(arg, ~0);
5096 }
5097 }
5098
gen_mfc0(DisasContext * ctx,TCGv arg,int reg,int sel)5099 static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5100 {
5101 const char *register_name = "invalid";
5102
5103 if (sel != 0) {
5104 check_insn(ctx, ISA_MIPS_R1);
5105 }
5106
5107 switch (reg) {
5108 case CP0_REGISTER_00:
5109 switch (sel) {
5110 case CP0_REG00__INDEX:
5111 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
5112 register_name = "Index";
5113 break;
5114 case CP0_REG00__MVPCONTROL:
5115 CP0_CHECK(disas_mt_available(ctx));
5116 gen_helper_mfc0_mvpcontrol(arg, tcg_env);
5117 register_name = "MVPControl";
5118 break;
5119 case CP0_REG00__MVPCONF0:
5120 CP0_CHECK(disas_mt_available(ctx));
5121 gen_helper_mfc0_mvpconf0(arg, tcg_env);
5122 register_name = "MVPConf0";
5123 break;
5124 case CP0_REG00__MVPCONF1:
5125 CP0_CHECK(disas_mt_available(ctx));
5126 gen_helper_mfc0_mvpconf1(arg, tcg_env);
5127 register_name = "MVPConf1";
5128 break;
5129 case CP0_REG00__VPCONTROL:
5130 CP0_CHECK(ctx->vp);
5131 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
5132 register_name = "VPControl";
5133 break;
5134 default:
5135 goto cp0_unimplemented;
5136 }
5137 break;
5138 case CP0_REGISTER_01:
5139 switch (sel) {
5140 case CP0_REG01__RANDOM:
5141 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
5142 gen_helper_mfc0_random(arg, tcg_env);
5143 register_name = "Random";
5144 break;
5145 case CP0_REG01__VPECONTROL:
5146 CP0_CHECK(disas_mt_available(ctx));
5147 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
5148 register_name = "VPEControl";
5149 break;
5150 case CP0_REG01__VPECONF0:
5151 CP0_CHECK(disas_mt_available(ctx));
5152 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
5153 register_name = "VPEConf0";
5154 break;
5155 case CP0_REG01__VPECONF1:
5156 CP0_CHECK(disas_mt_available(ctx));
5157 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
5158 register_name = "VPEConf1";
5159 break;
5160 case CP0_REG01__YQMASK:
5161 CP0_CHECK(disas_mt_available(ctx));
5162 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
5163 register_name = "YQMask";
5164 break;
5165 case CP0_REG01__VPESCHEDULE:
5166 CP0_CHECK(disas_mt_available(ctx));
5167 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
5168 register_name = "VPESchedule";
5169 break;
5170 case CP0_REG01__VPESCHEFBACK:
5171 CP0_CHECK(disas_mt_available(ctx));
5172 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
5173 register_name = "VPEScheFBack";
5174 break;
5175 case CP0_REG01__VPEOPT:
5176 CP0_CHECK(disas_mt_available(ctx));
5177 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
5178 register_name = "VPEOpt";
5179 break;
5180 default:
5181 goto cp0_unimplemented;
5182 }
5183 break;
5184 case CP0_REGISTER_02:
5185 switch (sel) {
5186 case CP0_REG02__ENTRYLO0:
5187 {
5188 TCGv_i64 tmp = tcg_temp_new_i64();
5189 tcg_gen_ld_i64(tmp, tcg_env,
5190 offsetof(CPUMIPSState, CP0_EntryLo0));
5191 #if defined(TARGET_MIPS64)
5192 if (ctx->rxi) {
5193 /* Move RI/XI fields to bits 31:30 */
5194 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5195 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5196 }
5197 #endif
5198 gen_move_low32(arg, tmp);
5199 }
5200 register_name = "EntryLo0";
5201 break;
5202 case CP0_REG02__TCSTATUS:
5203 CP0_CHECK(disas_mt_available(ctx));
5204 gen_helper_mfc0_tcstatus(arg, tcg_env);
5205 register_name = "TCStatus";
5206 break;
5207 case CP0_REG02__TCBIND:
5208 CP0_CHECK(disas_mt_available(ctx));
5209 gen_helper_mfc0_tcbind(arg, tcg_env);
5210 register_name = "TCBind";
5211 break;
5212 case CP0_REG02__TCRESTART:
5213 CP0_CHECK(disas_mt_available(ctx));
5214 gen_helper_mfc0_tcrestart(arg, tcg_env);
5215 register_name = "TCRestart";
5216 break;
5217 case CP0_REG02__TCHALT:
5218 CP0_CHECK(disas_mt_available(ctx));
5219 gen_helper_mfc0_tchalt(arg, tcg_env);
5220 register_name = "TCHalt";
5221 break;
5222 case CP0_REG02__TCCONTEXT:
5223 CP0_CHECK(disas_mt_available(ctx));
5224 gen_helper_mfc0_tccontext(arg, tcg_env);
5225 register_name = "TCContext";
5226 break;
5227 case CP0_REG02__TCSCHEDULE:
5228 CP0_CHECK(disas_mt_available(ctx));
5229 gen_helper_mfc0_tcschedule(arg, tcg_env);
5230 register_name = "TCSchedule";
5231 break;
5232 case CP0_REG02__TCSCHEFBACK:
5233 CP0_CHECK(disas_mt_available(ctx));
5234 gen_helper_mfc0_tcschefback(arg, tcg_env);
5235 register_name = "TCScheFBack";
5236 break;
5237 default:
5238 goto cp0_unimplemented;
5239 }
5240 break;
5241 case CP0_REGISTER_03:
5242 switch (sel) {
5243 case CP0_REG03__ENTRYLO1:
5244 {
5245 TCGv_i64 tmp = tcg_temp_new_i64();
5246 tcg_gen_ld_i64(tmp, tcg_env,
5247 offsetof(CPUMIPSState, CP0_EntryLo1));
5248 #if defined(TARGET_MIPS64)
5249 if (ctx->rxi) {
5250 /* Move RI/XI fields to bits 31:30 */
5251 tcg_gen_shri_tl(arg, tmp, CP0EnLo_XI);
5252 tcg_gen_deposit_tl(tmp, tmp, arg, 30, 2);
5253 }
5254 #endif
5255 gen_move_low32(arg, tmp);
5256 }
5257 register_name = "EntryLo1";
5258 break;
5259 case CP0_REG03__GLOBALNUM:
5260 CP0_CHECK(ctx->vp);
5261 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
5262 register_name = "GlobalNumber";
5263 break;
5264 default:
5265 goto cp0_unimplemented;
5266 }
5267 break;
5268 case CP0_REGISTER_04:
5269 switch (sel) {
5270 case CP0_REG04__CONTEXT:
5271 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_Context));
5272 tcg_gen_ext32s_tl(arg, arg);
5273 register_name = "Context";
5274 break;
5275 case CP0_REG04__CONTEXTCONFIG:
5276 /* SmartMIPS ASE */
5277 /* gen_helper_mfc0_contextconfig(arg); */
5278 register_name = "ContextConfig";
5279 goto cp0_unimplemented;
5280 case CP0_REG04__USERLOCAL:
5281 CP0_CHECK(ctx->ulri);
5282 tcg_gen_ld_tl(arg, tcg_env,
5283 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
5284 tcg_gen_ext32s_tl(arg, arg);
5285 register_name = "UserLocal";
5286 break;
5287 case CP0_REG04__MMID:
5288 CP0_CHECK(ctx->mi);
5289 gen_helper_mtc0_memorymapid(tcg_env, arg);
5290 register_name = "MMID";
5291 break;
5292 default:
5293 goto cp0_unimplemented;
5294 }
5295 break;
5296 case CP0_REGISTER_05:
5297 switch (sel) {
5298 case CP0_REG05__PAGEMASK:
5299 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
5300 register_name = "PageMask";
5301 break;
5302 case CP0_REG05__PAGEGRAIN:
5303 check_insn(ctx, ISA_MIPS_R2);
5304 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
5305 register_name = "PageGrain";
5306 break;
5307 case CP0_REG05__SEGCTL0:
5308 CP0_CHECK(ctx->sc);
5309 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl0));
5310 tcg_gen_ext32s_tl(arg, arg);
5311 register_name = "SegCtl0";
5312 break;
5313 case CP0_REG05__SEGCTL1:
5314 CP0_CHECK(ctx->sc);
5315 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl1));
5316 tcg_gen_ext32s_tl(arg, arg);
5317 register_name = "SegCtl1";
5318 break;
5319 case CP0_REG05__SEGCTL2:
5320 CP0_CHECK(ctx->sc);
5321 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl2));
5322 tcg_gen_ext32s_tl(arg, arg);
5323 register_name = "SegCtl2";
5324 break;
5325 case CP0_REG05__PWBASE:
5326 check_pw(ctx);
5327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWBase));
5328 register_name = "PWBase";
5329 break;
5330 case CP0_REG05__PWFIELD:
5331 check_pw(ctx);
5332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWField));
5333 register_name = "PWField";
5334 break;
5335 case CP0_REG05__PWSIZE:
5336 check_pw(ctx);
5337 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWSize));
5338 register_name = "PWSize";
5339 break;
5340 default:
5341 goto cp0_unimplemented;
5342 }
5343 break;
5344 case CP0_REGISTER_06:
5345 switch (sel) {
5346 case CP0_REG06__WIRED:
5347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
5348 register_name = "Wired";
5349 break;
5350 case CP0_REG06__SRSCONF0:
5351 check_insn(ctx, ISA_MIPS_R2);
5352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
5353 register_name = "SRSConf0";
5354 break;
5355 case CP0_REG06__SRSCONF1:
5356 check_insn(ctx, ISA_MIPS_R2);
5357 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
5358 register_name = "SRSConf1";
5359 break;
5360 case CP0_REG06__SRSCONF2:
5361 check_insn(ctx, ISA_MIPS_R2);
5362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
5363 register_name = "SRSConf2";
5364 break;
5365 case CP0_REG06__SRSCONF3:
5366 check_insn(ctx, ISA_MIPS_R2);
5367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
5368 register_name = "SRSConf3";
5369 break;
5370 case CP0_REG06__SRSCONF4:
5371 check_insn(ctx, ISA_MIPS_R2);
5372 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
5373 register_name = "SRSConf4";
5374 break;
5375 case CP0_REG06__PWCTL:
5376 check_pw(ctx);
5377 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
5378 register_name = "PWCtl";
5379 break;
5380 default:
5381 goto cp0_unimplemented;
5382 }
5383 break;
5384 case CP0_REGISTER_07:
5385 switch (sel) {
5386 case CP0_REG07__HWRENA:
5387 check_insn(ctx, ISA_MIPS_R2);
5388 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
5389 register_name = "HWREna";
5390 break;
5391 default:
5392 goto cp0_unimplemented;
5393 }
5394 break;
5395 case CP0_REGISTER_08:
5396 switch (sel) {
5397 case CP0_REG08__BADVADDR:
5398 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_BadVAddr));
5399 tcg_gen_ext32s_tl(arg, arg);
5400 register_name = "BadVAddr";
5401 break;
5402 case CP0_REG08__BADINSTR:
5403 CP0_CHECK(ctx->bi);
5404 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
5405 register_name = "BadInstr";
5406 break;
5407 case CP0_REG08__BADINSTRP:
5408 CP0_CHECK(ctx->bp);
5409 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
5410 register_name = "BadInstrP";
5411 break;
5412 case CP0_REG08__BADINSTRX:
5413 CP0_CHECK(ctx->bi);
5414 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
5415 tcg_gen_andi_tl(arg, arg, ~0xffff);
5416 register_name = "BadInstrX";
5417 break;
5418 default:
5419 goto cp0_unimplemented;
5420 }
5421 break;
5422 case CP0_REGISTER_09:
5423 switch (sel) {
5424 case CP0_REG09__COUNT:
5425 /* Mark as an IO operation because we read the time. */
5426 translator_io_start(&ctx->base);
5427
5428 gen_helper_mfc0_count(arg, tcg_env);
5429 /*
5430 * Break the TB to be able to take timer interrupts immediately
5431 * after reading count. DISAS_STOP isn't sufficient, we need to
5432 * ensure we break completely out of translated code.
5433 */
5434 gen_save_pc(ctx->base.pc_next + 4);
5435 ctx->base.is_jmp = DISAS_EXIT;
5436 register_name = "Count";
5437 break;
5438 default:
5439 goto cp0_unimplemented;
5440 }
5441 break;
5442 case CP0_REGISTER_10:
5443 switch (sel) {
5444 case CP0_REG10__ENTRYHI:
5445 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryHi));
5446 tcg_gen_ext32s_tl(arg, arg);
5447 register_name = "EntryHi";
5448 break;
5449 default:
5450 goto cp0_unimplemented;
5451 }
5452 break;
5453 case CP0_REGISTER_11:
5454 switch (sel) {
5455 case CP0_REG11__COMPARE:
5456 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
5457 register_name = "Compare";
5458 break;
5459 /* 6,7 are implementation dependent */
5460 default:
5461 goto cp0_unimplemented;
5462 }
5463 break;
5464 case CP0_REGISTER_12:
5465 switch (sel) {
5466 case CP0_REG12__STATUS:
5467 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
5468 register_name = "Status";
5469 break;
5470 case CP0_REG12__INTCTL:
5471 check_insn(ctx, ISA_MIPS_R2);
5472 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
5473 register_name = "IntCtl";
5474 break;
5475 case CP0_REG12__SRSCTL:
5476 check_insn(ctx, ISA_MIPS_R2);
5477 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
5478 register_name = "SRSCtl";
5479 break;
5480 case CP0_REG12__SRSMAP:
5481 check_insn(ctx, ISA_MIPS_R2);
5482 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5483 register_name = "SRSMap";
5484 break;
5485 default:
5486 goto cp0_unimplemented;
5487 }
5488 break;
5489 case CP0_REGISTER_13:
5490 switch (sel) {
5491 case CP0_REG13__CAUSE:
5492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
5493 register_name = "Cause";
5494 break;
5495 default:
5496 goto cp0_unimplemented;
5497 }
5498 break;
5499 case CP0_REGISTER_14:
5500 switch (sel) {
5501 case CP0_REG14__EPC:
5502 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
5503 tcg_gen_ext32s_tl(arg, arg);
5504 register_name = "EPC";
5505 break;
5506 default:
5507 goto cp0_unimplemented;
5508 }
5509 break;
5510 case CP0_REGISTER_15:
5511 switch (sel) {
5512 case CP0_REG15__PRID:
5513 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
5514 register_name = "PRid";
5515 break;
5516 case CP0_REG15__EBASE:
5517 check_insn(ctx, ISA_MIPS_R2);
5518 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EBase));
5519 tcg_gen_ext32s_tl(arg, arg);
5520 register_name = "EBase";
5521 break;
5522 case CP0_REG15__CMGCRBASE:
5523 check_insn(ctx, ISA_MIPS_R2);
5524 CP0_CHECK(ctx->cmgcr);
5525 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
5526 tcg_gen_ext32s_tl(arg, arg);
5527 register_name = "CMGCRBase";
5528 break;
5529 default:
5530 goto cp0_unimplemented;
5531 }
5532 break;
5533 case CP0_REGISTER_16:
5534 switch (sel) {
5535 case CP0_REG16__CONFIG:
5536 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
5537 register_name = "Config";
5538 break;
5539 case CP0_REG16__CONFIG1:
5540 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
5541 register_name = "Config1";
5542 break;
5543 case CP0_REG16__CONFIG2:
5544 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
5545 register_name = "Config2";
5546 break;
5547 case CP0_REG16__CONFIG3:
5548 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
5549 register_name = "Config3";
5550 break;
5551 case CP0_REG16__CONFIG4:
5552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
5553 register_name = "Config4";
5554 break;
5555 case CP0_REG16__CONFIG5:
5556 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
5557 register_name = "Config5";
5558 break;
5559 /* 6,7 are implementation dependent */
5560 case CP0_REG16__CONFIG6:
5561 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
5562 register_name = "Config6";
5563 break;
5564 case CP0_REG16__CONFIG7:
5565 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
5566 register_name = "Config7";
5567 break;
5568 default:
5569 goto cp0_unimplemented;
5570 }
5571 break;
5572 case CP0_REGISTER_17:
5573 switch (sel) {
5574 case CP0_REG17__LLADDR:
5575 gen_helper_mfc0_lladdr(arg, tcg_env);
5576 register_name = "LLAddr";
5577 break;
5578 case CP0_REG17__MAAR:
5579 CP0_CHECK(ctx->mrp);
5580 gen_helper_mfc0_maar(arg, tcg_env);
5581 register_name = "MAAR";
5582 break;
5583 case CP0_REG17__MAARI:
5584 CP0_CHECK(ctx->mrp);
5585 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
5586 register_name = "MAARI";
5587 break;
5588 default:
5589 goto cp0_unimplemented;
5590 }
5591 break;
5592 case CP0_REGISTER_18:
5593 switch (sel) {
5594 case CP0_REG18__WATCHLO0:
5595 case CP0_REG18__WATCHLO1:
5596 case CP0_REG18__WATCHLO2:
5597 case CP0_REG18__WATCHLO3:
5598 case CP0_REG18__WATCHLO4:
5599 case CP0_REG18__WATCHLO5:
5600 case CP0_REG18__WATCHLO6:
5601 case CP0_REG18__WATCHLO7:
5602 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5603 gen_helper_1e0i(mfc0_watchlo, arg, sel);
5604 register_name = "WatchLo";
5605 break;
5606 default:
5607 goto cp0_unimplemented;
5608 }
5609 break;
5610 case CP0_REGISTER_19:
5611 switch (sel) {
5612 case CP0_REG19__WATCHHI0:
5613 case CP0_REG19__WATCHHI1:
5614 case CP0_REG19__WATCHHI2:
5615 case CP0_REG19__WATCHHI3:
5616 case CP0_REG19__WATCHHI4:
5617 case CP0_REG19__WATCHHI5:
5618 case CP0_REG19__WATCHHI6:
5619 case CP0_REG19__WATCHHI7:
5620 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
5621 gen_helper_1e0i(mfc0_watchhi, arg, sel);
5622 register_name = "WatchHi";
5623 break;
5624 default:
5625 goto cp0_unimplemented;
5626 }
5627 break;
5628 case CP0_REGISTER_20:
5629 switch (sel) {
5630 case CP0_REG20__XCONTEXT:
5631 #if defined(TARGET_MIPS64)
5632 check_insn(ctx, ISA_MIPS3);
5633 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_XContext));
5634 tcg_gen_ext32s_tl(arg, arg);
5635 register_name = "XContext";
5636 break;
5637 #endif
5638 default:
5639 goto cp0_unimplemented;
5640 }
5641 break;
5642 case CP0_REGISTER_21:
5643 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5644 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
5645 switch (sel) {
5646 case 0:
5647 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
5648 register_name = "Framemask";
5649 break;
5650 default:
5651 goto cp0_unimplemented;
5652 }
5653 break;
5654 case CP0_REGISTER_22:
5655 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5656 register_name = "'Diagnostic"; /* implementation dependent */
5657 break;
5658 case CP0_REGISTER_23:
5659 switch (sel) {
5660 case CP0_REG23__DEBUG:
5661 gen_helper_mfc0_debug(arg, tcg_env); /* EJTAG support */
5662 register_name = "Debug";
5663 break;
5664 case CP0_REG23__TRACECONTROL:
5665 /* PDtrace support */
5666 /* gen_helper_mfc0_tracecontrol(arg); */
5667 register_name = "TraceControl";
5668 goto cp0_unimplemented;
5669 case CP0_REG23__TRACECONTROL2:
5670 /* PDtrace support */
5671 /* gen_helper_mfc0_tracecontrol2(arg); */
5672 register_name = "TraceControl2";
5673 goto cp0_unimplemented;
5674 case CP0_REG23__USERTRACEDATA1:
5675 /* PDtrace support */
5676 /* gen_helper_mfc0_usertracedata1(arg);*/
5677 register_name = "UserTraceData1";
5678 goto cp0_unimplemented;
5679 case CP0_REG23__TRACEIBPC:
5680 /* PDtrace support */
5681 /* gen_helper_mfc0_traceibpc(arg); */
5682 register_name = "TraceIBPC";
5683 goto cp0_unimplemented;
5684 case CP0_REG23__TRACEDBPC:
5685 /* PDtrace support */
5686 /* gen_helper_mfc0_tracedbpc(arg); */
5687 register_name = "TraceDBPC";
5688 goto cp0_unimplemented;
5689 default:
5690 goto cp0_unimplemented;
5691 }
5692 break;
5693 case CP0_REGISTER_24:
5694 switch (sel) {
5695 case CP0_REG24__DEPC:
5696 /* EJTAG support */
5697 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
5698 tcg_gen_ext32s_tl(arg, arg);
5699 register_name = "DEPC";
5700 break;
5701 default:
5702 goto cp0_unimplemented;
5703 }
5704 break;
5705 case CP0_REGISTER_25:
5706 switch (sel) {
5707 case CP0_REG25__PERFCTL0:
5708 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
5709 register_name = "Performance0";
5710 break;
5711 case CP0_REG25__PERFCNT0:
5712 /* gen_helper_mfc0_performance1(arg); */
5713 register_name = "Performance1";
5714 goto cp0_unimplemented;
5715 case CP0_REG25__PERFCTL1:
5716 /* gen_helper_mfc0_performance2(arg); */
5717 register_name = "Performance2";
5718 goto cp0_unimplemented;
5719 case CP0_REG25__PERFCNT1:
5720 /* gen_helper_mfc0_performance3(arg); */
5721 register_name = "Performance3";
5722 goto cp0_unimplemented;
5723 case CP0_REG25__PERFCTL2:
5724 /* gen_helper_mfc0_performance4(arg); */
5725 register_name = "Performance4";
5726 goto cp0_unimplemented;
5727 case CP0_REG25__PERFCNT2:
5728 /* gen_helper_mfc0_performance5(arg); */
5729 register_name = "Performance5";
5730 goto cp0_unimplemented;
5731 case CP0_REG25__PERFCTL3:
5732 /* gen_helper_mfc0_performance6(arg); */
5733 register_name = "Performance6";
5734 goto cp0_unimplemented;
5735 case CP0_REG25__PERFCNT3:
5736 /* gen_helper_mfc0_performance7(arg); */
5737 register_name = "Performance7";
5738 goto cp0_unimplemented;
5739 default:
5740 goto cp0_unimplemented;
5741 }
5742 break;
5743 case CP0_REGISTER_26:
5744 switch (sel) {
5745 case CP0_REG26__ERRCTL:
5746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
5747 register_name = "ErrCtl";
5748 break;
5749 default:
5750 goto cp0_unimplemented;
5751 }
5752 break;
5753 case CP0_REGISTER_27:
5754 switch (sel) {
5755 case CP0_REG27__CACHERR:
5756 tcg_gen_movi_tl(arg, 0); /* unimplemented */
5757 register_name = "CacheErr";
5758 break;
5759 default:
5760 goto cp0_unimplemented;
5761 }
5762 break;
5763 case CP0_REGISTER_28:
5764 switch (sel) {
5765 case CP0_REG28__TAGLO:
5766 case CP0_REG28__TAGLO1:
5767 case CP0_REG28__TAGLO2:
5768 case CP0_REG28__TAGLO3:
5769 {
5770 TCGv_i64 tmp = tcg_temp_new_i64();
5771 tcg_gen_ld_i64(tmp, tcg_env, offsetof(CPUMIPSState, CP0_TagLo));
5772 gen_move_low32(arg, tmp);
5773 }
5774 register_name = "TagLo";
5775 break;
5776 case CP0_REG28__DATALO:
5777 case CP0_REG28__DATALO1:
5778 case CP0_REG28__DATALO2:
5779 case CP0_REG28__DATALO3:
5780 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
5781 register_name = "DataLo";
5782 break;
5783 default:
5784 goto cp0_unimplemented;
5785 }
5786 break;
5787 case CP0_REGISTER_29:
5788 switch (sel) {
5789 case CP0_REG29__TAGHI:
5790 case CP0_REG29__TAGHI1:
5791 case CP0_REG29__TAGHI2:
5792 case CP0_REG29__TAGHI3:
5793 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
5794 register_name = "TagHi";
5795 break;
5796 case CP0_REG29__DATAHI:
5797 case CP0_REG29__DATAHI1:
5798 case CP0_REG29__DATAHI2:
5799 case CP0_REG29__DATAHI3:
5800 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
5801 register_name = "DataHi";
5802 break;
5803 default:
5804 goto cp0_unimplemented;
5805 }
5806 break;
5807 case CP0_REGISTER_30:
5808 switch (sel) {
5809 case CP0_REG30__ERROREPC:
5810 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5811 tcg_gen_ext32s_tl(arg, arg);
5812 register_name = "ErrorEPC";
5813 break;
5814 default:
5815 goto cp0_unimplemented;
5816 }
5817 break;
5818 case CP0_REGISTER_31:
5819 switch (sel) {
5820 case CP0_REG31__DESAVE:
5821 /* EJTAG support */
5822 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5823 register_name = "DESAVE";
5824 break;
5825 case CP0_REG31__KSCRATCH1:
5826 case CP0_REG31__KSCRATCH2:
5827 case CP0_REG31__KSCRATCH3:
5828 case CP0_REG31__KSCRATCH4:
5829 case CP0_REG31__KSCRATCH5:
5830 case CP0_REG31__KSCRATCH6:
5831 CP0_CHECK(ctx->kscrexist & (1 << sel));
5832 tcg_gen_ld_tl(arg, tcg_env,
5833 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
5834 tcg_gen_ext32s_tl(arg, arg);
5835 register_name = "KScratch";
5836 break;
5837 default:
5838 goto cp0_unimplemented;
5839 }
5840 break;
5841 default:
5842 goto cp0_unimplemented;
5843 }
5844 trace_mips_translate_c0("mfc0", register_name, reg, sel);
5845 return;
5846
5847 cp0_unimplemented:
5848 qemu_log_mask(LOG_UNIMP, "mfc0 %s (reg %d sel %d)\n",
5849 register_name, reg, sel);
5850 gen_mfc0_unimplemented(ctx, arg);
5851 }
5852
gen_mtc0(DisasContext * ctx,TCGv arg,int reg,int sel)5853 static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
5854 {
5855 const char *register_name = "invalid";
5856 bool icount;
5857
5858 if (sel != 0) {
5859 check_insn(ctx, ISA_MIPS_R1);
5860 }
5861
5862 icount = translator_io_start(&ctx->base);
5863
5864 switch (reg) {
5865 case CP0_REGISTER_00:
5866 switch (sel) {
5867 case CP0_REG00__INDEX:
5868 gen_helper_mtc0_index(tcg_env, arg);
5869 register_name = "Index";
5870 break;
5871 case CP0_REG00__MVPCONTROL:
5872 CP0_CHECK(disas_mt_available(ctx));
5873 gen_helper_mtc0_mvpcontrol(tcg_env, arg);
5874 register_name = "MVPControl";
5875 break;
5876 case CP0_REG00__MVPCONF0:
5877 CP0_CHECK(disas_mt_available(ctx));
5878 /* ignored */
5879 register_name = "MVPConf0";
5880 break;
5881 case CP0_REG00__MVPCONF1:
5882 CP0_CHECK(disas_mt_available(ctx));
5883 /* ignored */
5884 register_name = "MVPConf1";
5885 break;
5886 case CP0_REG00__VPCONTROL:
5887 CP0_CHECK(ctx->vp);
5888 /* ignored */
5889 register_name = "VPControl";
5890 break;
5891 default:
5892 goto cp0_unimplemented;
5893 }
5894 break;
5895 case CP0_REGISTER_01:
5896 switch (sel) {
5897 case CP0_REG01__RANDOM:
5898 /* ignored */
5899 register_name = "Random";
5900 break;
5901 case CP0_REG01__VPECONTROL:
5902 CP0_CHECK(disas_mt_available(ctx));
5903 gen_helper_mtc0_vpecontrol(tcg_env, arg);
5904 register_name = "VPEControl";
5905 break;
5906 case CP0_REG01__VPECONF0:
5907 CP0_CHECK(disas_mt_available(ctx));
5908 gen_helper_mtc0_vpeconf0(tcg_env, arg);
5909 register_name = "VPEConf0";
5910 break;
5911 case CP0_REG01__VPECONF1:
5912 CP0_CHECK(disas_mt_available(ctx));
5913 gen_helper_mtc0_vpeconf1(tcg_env, arg);
5914 register_name = "VPEConf1";
5915 break;
5916 case CP0_REG01__YQMASK:
5917 CP0_CHECK(disas_mt_available(ctx));
5918 gen_helper_mtc0_yqmask(tcg_env, arg);
5919 register_name = "YQMask";
5920 break;
5921 case CP0_REG01__VPESCHEDULE:
5922 CP0_CHECK(disas_mt_available(ctx));
5923 tcg_gen_st_tl(arg, tcg_env,
5924 offsetof(CPUMIPSState, CP0_VPESchedule));
5925 register_name = "VPESchedule";
5926 break;
5927 case CP0_REG01__VPESCHEFBACK:
5928 CP0_CHECK(disas_mt_available(ctx));
5929 tcg_gen_st_tl(arg, tcg_env,
5930 offsetof(CPUMIPSState, CP0_VPEScheFBack));
5931 register_name = "VPEScheFBack";
5932 break;
5933 case CP0_REG01__VPEOPT:
5934 CP0_CHECK(disas_mt_available(ctx));
5935 gen_helper_mtc0_vpeopt(tcg_env, arg);
5936 register_name = "VPEOpt";
5937 break;
5938 default:
5939 goto cp0_unimplemented;
5940 }
5941 break;
5942 case CP0_REGISTER_02:
5943 switch (sel) {
5944 case CP0_REG02__ENTRYLO0:
5945 gen_helper_mtc0_entrylo0(tcg_env, arg);
5946 register_name = "EntryLo0";
5947 break;
5948 case CP0_REG02__TCSTATUS:
5949 CP0_CHECK(disas_mt_available(ctx));
5950 gen_helper_mtc0_tcstatus(tcg_env, arg);
5951 register_name = "TCStatus";
5952 break;
5953 case CP0_REG02__TCBIND:
5954 CP0_CHECK(disas_mt_available(ctx));
5955 gen_helper_mtc0_tcbind(tcg_env, arg);
5956 register_name = "TCBind";
5957 break;
5958 case CP0_REG02__TCRESTART:
5959 CP0_CHECK(disas_mt_available(ctx));
5960 gen_helper_mtc0_tcrestart(tcg_env, arg);
5961 register_name = "TCRestart";
5962 break;
5963 case CP0_REG02__TCHALT:
5964 CP0_CHECK(disas_mt_available(ctx));
5965 gen_helper_mtc0_tchalt(tcg_env, arg);
5966 register_name = "TCHalt";
5967 break;
5968 case CP0_REG02__TCCONTEXT:
5969 CP0_CHECK(disas_mt_available(ctx));
5970 gen_helper_mtc0_tccontext(tcg_env, arg);
5971 register_name = "TCContext";
5972 break;
5973 case CP0_REG02__TCSCHEDULE:
5974 CP0_CHECK(disas_mt_available(ctx));
5975 gen_helper_mtc0_tcschedule(tcg_env, arg);
5976 register_name = "TCSchedule";
5977 break;
5978 case CP0_REG02__TCSCHEFBACK:
5979 CP0_CHECK(disas_mt_available(ctx));
5980 gen_helper_mtc0_tcschefback(tcg_env, arg);
5981 register_name = "TCScheFBack";
5982 break;
5983 default:
5984 goto cp0_unimplemented;
5985 }
5986 break;
5987 case CP0_REGISTER_03:
5988 switch (sel) {
5989 case CP0_REG03__ENTRYLO1:
5990 gen_helper_mtc0_entrylo1(tcg_env, arg);
5991 register_name = "EntryLo1";
5992 break;
5993 case CP0_REG03__GLOBALNUM:
5994 CP0_CHECK(ctx->vp);
5995 /* ignored */
5996 register_name = "GlobalNumber";
5997 break;
5998 default:
5999 goto cp0_unimplemented;
6000 }
6001 break;
6002 case CP0_REGISTER_04:
6003 switch (sel) {
6004 case CP0_REG04__CONTEXT:
6005 gen_helper_mtc0_context(tcg_env, arg);
6006 register_name = "Context";
6007 break;
6008 case CP0_REG04__CONTEXTCONFIG:
6009 /* SmartMIPS ASE */
6010 /* gen_helper_mtc0_contextconfig(arg); */
6011 register_name = "ContextConfig";
6012 goto cp0_unimplemented;
6013 case CP0_REG04__USERLOCAL:
6014 CP0_CHECK(ctx->ulri);
6015 tcg_gen_st_tl(arg, tcg_env,
6016 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6017 register_name = "UserLocal";
6018 break;
6019 case CP0_REG04__MMID:
6020 CP0_CHECK(ctx->mi);
6021 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
6022 register_name = "MMID";
6023 break;
6024 default:
6025 goto cp0_unimplemented;
6026 }
6027 break;
6028 case CP0_REGISTER_05:
6029 switch (sel) {
6030 case CP0_REG05__PAGEMASK:
6031 gen_helper_mtc0_pagemask(tcg_env, arg);
6032 register_name = "PageMask";
6033 break;
6034 case CP0_REG05__PAGEGRAIN:
6035 check_insn(ctx, ISA_MIPS_R2);
6036 gen_helper_mtc0_pagegrain(tcg_env, arg);
6037 register_name = "PageGrain";
6038 ctx->base.is_jmp = DISAS_STOP;
6039 break;
6040 case CP0_REG05__SEGCTL0:
6041 CP0_CHECK(ctx->sc);
6042 gen_helper_mtc0_segctl0(tcg_env, arg);
6043 register_name = "SegCtl0";
6044 break;
6045 case CP0_REG05__SEGCTL1:
6046 CP0_CHECK(ctx->sc);
6047 gen_helper_mtc0_segctl1(tcg_env, arg);
6048 register_name = "SegCtl1";
6049 break;
6050 case CP0_REG05__SEGCTL2:
6051 CP0_CHECK(ctx->sc);
6052 gen_helper_mtc0_segctl2(tcg_env, arg);
6053 register_name = "SegCtl2";
6054 break;
6055 case CP0_REG05__PWBASE:
6056 check_pw(ctx);
6057 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_PWBase));
6058 register_name = "PWBase";
6059 break;
6060 case CP0_REG05__PWFIELD:
6061 check_pw(ctx);
6062 gen_helper_mtc0_pwfield(tcg_env, arg);
6063 register_name = "PWField";
6064 break;
6065 case CP0_REG05__PWSIZE:
6066 check_pw(ctx);
6067 gen_helper_mtc0_pwsize(tcg_env, arg);
6068 register_name = "PWSize";
6069 break;
6070 default:
6071 goto cp0_unimplemented;
6072 }
6073 break;
6074 case CP0_REGISTER_06:
6075 switch (sel) {
6076 case CP0_REG06__WIRED:
6077 gen_helper_mtc0_wired(tcg_env, arg);
6078 register_name = "Wired";
6079 break;
6080 case CP0_REG06__SRSCONF0:
6081 check_insn(ctx, ISA_MIPS_R2);
6082 gen_helper_mtc0_srsconf0(tcg_env, arg);
6083 register_name = "SRSConf0";
6084 break;
6085 case CP0_REG06__SRSCONF1:
6086 check_insn(ctx, ISA_MIPS_R2);
6087 gen_helper_mtc0_srsconf1(tcg_env, arg);
6088 register_name = "SRSConf1";
6089 break;
6090 case CP0_REG06__SRSCONF2:
6091 check_insn(ctx, ISA_MIPS_R2);
6092 gen_helper_mtc0_srsconf2(tcg_env, arg);
6093 register_name = "SRSConf2";
6094 break;
6095 case CP0_REG06__SRSCONF3:
6096 check_insn(ctx, ISA_MIPS_R2);
6097 gen_helper_mtc0_srsconf3(tcg_env, arg);
6098 register_name = "SRSConf3";
6099 break;
6100 case CP0_REG06__SRSCONF4:
6101 check_insn(ctx, ISA_MIPS_R2);
6102 gen_helper_mtc0_srsconf4(tcg_env, arg);
6103 register_name = "SRSConf4";
6104 break;
6105 case CP0_REG06__PWCTL:
6106 check_pw(ctx);
6107 gen_helper_mtc0_pwctl(tcg_env, arg);
6108 register_name = "PWCtl";
6109 break;
6110 default:
6111 goto cp0_unimplemented;
6112 }
6113 break;
6114 case CP0_REGISTER_07:
6115 switch (sel) {
6116 case CP0_REG07__HWRENA:
6117 check_insn(ctx, ISA_MIPS_R2);
6118 gen_helper_mtc0_hwrena(tcg_env, arg);
6119 ctx->base.is_jmp = DISAS_STOP;
6120 register_name = "HWREna";
6121 break;
6122 default:
6123 goto cp0_unimplemented;
6124 }
6125 break;
6126 case CP0_REGISTER_08:
6127 switch (sel) {
6128 case CP0_REG08__BADVADDR:
6129 /* ignored */
6130 register_name = "BadVAddr";
6131 break;
6132 case CP0_REG08__BADINSTR:
6133 /* ignored */
6134 register_name = "BadInstr";
6135 break;
6136 case CP0_REG08__BADINSTRP:
6137 /* ignored */
6138 register_name = "BadInstrP";
6139 break;
6140 case CP0_REG08__BADINSTRX:
6141 /* ignored */
6142 register_name = "BadInstrX";
6143 break;
6144 default:
6145 goto cp0_unimplemented;
6146 }
6147 break;
6148 case CP0_REGISTER_09:
6149 switch (sel) {
6150 case CP0_REG09__COUNT:
6151 gen_helper_mtc0_count(tcg_env, arg);
6152 register_name = "Count";
6153 break;
6154 default:
6155 goto cp0_unimplemented;
6156 }
6157 break;
6158 case CP0_REGISTER_10:
6159 switch (sel) {
6160 case CP0_REG10__ENTRYHI:
6161 gen_helper_mtc0_entryhi(tcg_env, arg);
6162 register_name = "EntryHi";
6163 break;
6164 default:
6165 goto cp0_unimplemented;
6166 }
6167 break;
6168 case CP0_REGISTER_11:
6169 switch (sel) {
6170 case CP0_REG11__COMPARE:
6171 gen_helper_mtc0_compare(tcg_env, arg);
6172 register_name = "Compare";
6173 break;
6174 /* 6,7 are implementation dependent */
6175 default:
6176 goto cp0_unimplemented;
6177 }
6178 break;
6179 case CP0_REGISTER_12:
6180 switch (sel) {
6181 case CP0_REG12__STATUS:
6182 save_cpu_state(ctx, 1);
6183 gen_helper_mtc0_status(tcg_env, arg);
6184 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6185 gen_save_pc(ctx->base.pc_next + 4);
6186 ctx->base.is_jmp = DISAS_EXIT;
6187 register_name = "Status";
6188 break;
6189 case CP0_REG12__INTCTL:
6190 check_insn(ctx, ISA_MIPS_R2);
6191 gen_helper_mtc0_intctl(tcg_env, arg);
6192 /* Stop translation as we may have switched the execution mode */
6193 ctx->base.is_jmp = DISAS_STOP;
6194 register_name = "IntCtl";
6195 break;
6196 case CP0_REG12__SRSCTL:
6197 check_insn(ctx, ISA_MIPS_R2);
6198 gen_helper_mtc0_srsctl(tcg_env, arg);
6199 /* Stop translation as we may have switched the execution mode */
6200 ctx->base.is_jmp = DISAS_STOP;
6201 register_name = "SRSCtl";
6202 break;
6203 case CP0_REG12__SRSMAP:
6204 check_insn(ctx, ISA_MIPS_R2);
6205 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6206 /* Stop translation as we may have switched the execution mode */
6207 ctx->base.is_jmp = DISAS_STOP;
6208 register_name = "SRSMap";
6209 break;
6210 default:
6211 goto cp0_unimplemented;
6212 }
6213 break;
6214 case CP0_REGISTER_13:
6215 switch (sel) {
6216 case CP0_REG13__CAUSE:
6217 save_cpu_state(ctx, 1);
6218 gen_helper_mtc0_cause(tcg_env, arg);
6219 /*
6220 * Stop translation as we may have triggered an interrupt.
6221 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6222 * translated code to check for pending interrupts.
6223 */
6224 gen_save_pc(ctx->base.pc_next + 4);
6225 ctx->base.is_jmp = DISAS_EXIT;
6226 register_name = "Cause";
6227 break;
6228 default:
6229 goto cp0_unimplemented;
6230 }
6231 break;
6232 case CP0_REGISTER_14:
6233 switch (sel) {
6234 case CP0_REG14__EPC:
6235 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
6236 register_name = "EPC";
6237 break;
6238 default:
6239 goto cp0_unimplemented;
6240 }
6241 break;
6242 case CP0_REGISTER_15:
6243 switch (sel) {
6244 case CP0_REG15__PRID:
6245 /* ignored */
6246 register_name = "PRid";
6247 break;
6248 case CP0_REG15__EBASE:
6249 check_insn(ctx, ISA_MIPS_R2);
6250 gen_helper_mtc0_ebase(tcg_env, arg);
6251 register_name = "EBase";
6252 break;
6253 default:
6254 goto cp0_unimplemented;
6255 }
6256 break;
6257 case CP0_REGISTER_16:
6258 switch (sel) {
6259 case CP0_REG16__CONFIG:
6260 gen_helper_mtc0_config0(tcg_env, arg);
6261 register_name = "Config";
6262 /* Stop translation as we may have switched the execution mode */
6263 ctx->base.is_jmp = DISAS_STOP;
6264 break;
6265 case CP0_REG16__CONFIG1:
6266 /* ignored, read only */
6267 register_name = "Config1";
6268 break;
6269 case CP0_REG16__CONFIG2:
6270 gen_helper_mtc0_config2(tcg_env, arg);
6271 register_name = "Config2";
6272 /* Stop translation as we may have switched the execution mode */
6273 ctx->base.is_jmp = DISAS_STOP;
6274 break;
6275 case CP0_REG16__CONFIG3:
6276 gen_helper_mtc0_config3(tcg_env, arg);
6277 register_name = "Config3";
6278 /* Stop translation as we may have switched the execution mode */
6279 ctx->base.is_jmp = DISAS_STOP;
6280 break;
6281 case CP0_REG16__CONFIG4:
6282 gen_helper_mtc0_config4(tcg_env, arg);
6283 register_name = "Config4";
6284 ctx->base.is_jmp = DISAS_STOP;
6285 break;
6286 case CP0_REG16__CONFIG5:
6287 gen_helper_mtc0_config5(tcg_env, arg);
6288 register_name = "Config5";
6289 /* Stop translation as we may have switched the execution mode */
6290 ctx->base.is_jmp = DISAS_STOP;
6291 break;
6292 /* 6,7 are implementation dependent */
6293 case CP0_REG16__CONFIG6:
6294 /* ignored */
6295 register_name = "Config6";
6296 break;
6297 case CP0_REG16__CONFIG7:
6298 /* ignored */
6299 register_name = "Config7";
6300 break;
6301 default:
6302 register_name = "Invalid config selector";
6303 goto cp0_unimplemented;
6304 }
6305 break;
6306 case CP0_REGISTER_17:
6307 switch (sel) {
6308 case CP0_REG17__LLADDR:
6309 gen_helper_mtc0_lladdr(tcg_env, arg);
6310 register_name = "LLAddr";
6311 break;
6312 case CP0_REG17__MAAR:
6313 CP0_CHECK(ctx->mrp);
6314 gen_helper_mtc0_maar(tcg_env, arg);
6315 register_name = "MAAR";
6316 break;
6317 case CP0_REG17__MAARI:
6318 CP0_CHECK(ctx->mrp);
6319 gen_helper_mtc0_maari(tcg_env, arg);
6320 register_name = "MAARI";
6321 break;
6322 default:
6323 goto cp0_unimplemented;
6324 }
6325 break;
6326 case CP0_REGISTER_18:
6327 switch (sel) {
6328 case CP0_REG18__WATCHLO0:
6329 case CP0_REG18__WATCHLO1:
6330 case CP0_REG18__WATCHLO2:
6331 case CP0_REG18__WATCHLO3:
6332 case CP0_REG18__WATCHLO4:
6333 case CP0_REG18__WATCHLO5:
6334 case CP0_REG18__WATCHLO6:
6335 case CP0_REG18__WATCHLO7:
6336 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6337 gen_helper_0e1i(mtc0_watchlo, arg, sel);
6338 register_name = "WatchLo";
6339 break;
6340 default:
6341 goto cp0_unimplemented;
6342 }
6343 break;
6344 case CP0_REGISTER_19:
6345 switch (sel) {
6346 case CP0_REG19__WATCHHI0:
6347 case CP0_REG19__WATCHHI1:
6348 case CP0_REG19__WATCHHI2:
6349 case CP0_REG19__WATCHHI3:
6350 case CP0_REG19__WATCHHI4:
6351 case CP0_REG19__WATCHHI5:
6352 case CP0_REG19__WATCHHI6:
6353 case CP0_REG19__WATCHHI7:
6354 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
6355 gen_helper_0e1i(mtc0_watchhi, arg, sel);
6356 register_name = "WatchHi";
6357 break;
6358 default:
6359 goto cp0_unimplemented;
6360 }
6361 break;
6362 case CP0_REGISTER_20:
6363 switch (sel) {
6364 case CP0_REG20__XCONTEXT:
6365 #if defined(TARGET_MIPS64)
6366 check_insn(ctx, ISA_MIPS3);
6367 gen_helper_mtc0_xcontext(tcg_env, arg);
6368 register_name = "XContext";
6369 break;
6370 #endif
6371 default:
6372 goto cp0_unimplemented;
6373 }
6374 break;
6375 case CP0_REGISTER_21:
6376 /* Officially reserved, but sel 0 is used for R1x000 framemask */
6377 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6378 switch (sel) {
6379 case 0:
6380 gen_helper_mtc0_framemask(tcg_env, arg);
6381 register_name = "Framemask";
6382 break;
6383 default:
6384 goto cp0_unimplemented;
6385 }
6386 break;
6387 case CP0_REGISTER_22:
6388 /* ignored */
6389 register_name = "Diagnostic"; /* implementation dependent */
6390 break;
6391 case CP0_REGISTER_23:
6392 switch (sel) {
6393 case CP0_REG23__DEBUG:
6394 gen_helper_mtc0_debug(tcg_env, arg); /* EJTAG support */
6395 /* DISAS_STOP isn't good enough here, hflags may have changed. */
6396 gen_save_pc(ctx->base.pc_next + 4);
6397 ctx->base.is_jmp = DISAS_EXIT;
6398 register_name = "Debug";
6399 break;
6400 case CP0_REG23__TRACECONTROL:
6401 /* PDtrace support */
6402 /* gen_helper_mtc0_tracecontrol(tcg_env, arg); */
6403 register_name = "TraceControl";
6404 /* Stop translation as we may have switched the execution mode */
6405 ctx->base.is_jmp = DISAS_STOP;
6406 goto cp0_unimplemented;
6407 case CP0_REG23__TRACECONTROL2:
6408 /* PDtrace support */
6409 /* gen_helper_mtc0_tracecontrol2(tcg_env, arg); */
6410 register_name = "TraceControl2";
6411 /* Stop translation as we may have switched the execution mode */
6412 ctx->base.is_jmp = DISAS_STOP;
6413 goto cp0_unimplemented;
6414 case CP0_REG23__USERTRACEDATA1:
6415 /* Stop translation as we may have switched the execution mode */
6416 ctx->base.is_jmp = DISAS_STOP;
6417 /* PDtrace support */
6418 /* gen_helper_mtc0_usertracedata1(tcg_env, arg);*/
6419 register_name = "UserTraceData";
6420 /* Stop translation as we may have switched the execution mode */
6421 ctx->base.is_jmp = DISAS_STOP;
6422 goto cp0_unimplemented;
6423 case CP0_REG23__TRACEIBPC:
6424 /* PDtrace support */
6425 /* gen_helper_mtc0_traceibpc(tcg_env, arg); */
6426 /* Stop translation as we may have switched the execution mode */
6427 ctx->base.is_jmp = DISAS_STOP;
6428 register_name = "TraceIBPC";
6429 goto cp0_unimplemented;
6430 case CP0_REG23__TRACEDBPC:
6431 /* PDtrace support */
6432 /* gen_helper_mtc0_tracedbpc(tcg_env, arg); */
6433 /* Stop translation as we may have switched the execution mode */
6434 ctx->base.is_jmp = DISAS_STOP;
6435 register_name = "TraceDBPC";
6436 goto cp0_unimplemented;
6437 default:
6438 goto cp0_unimplemented;
6439 }
6440 break;
6441 case CP0_REGISTER_24:
6442 switch (sel) {
6443 case CP0_REG24__DEPC:
6444 /* EJTAG support */
6445 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
6446 register_name = "DEPC";
6447 break;
6448 default:
6449 goto cp0_unimplemented;
6450 }
6451 break;
6452 case CP0_REGISTER_25:
6453 switch (sel) {
6454 case CP0_REG25__PERFCTL0:
6455 gen_helper_mtc0_performance0(tcg_env, arg);
6456 register_name = "Performance0";
6457 break;
6458 case CP0_REG25__PERFCNT0:
6459 /* gen_helper_mtc0_performance1(arg); */
6460 register_name = "Performance1";
6461 goto cp0_unimplemented;
6462 case CP0_REG25__PERFCTL1:
6463 /* gen_helper_mtc0_performance2(arg); */
6464 register_name = "Performance2";
6465 goto cp0_unimplemented;
6466 case CP0_REG25__PERFCNT1:
6467 /* gen_helper_mtc0_performance3(arg); */
6468 register_name = "Performance3";
6469 goto cp0_unimplemented;
6470 case CP0_REG25__PERFCTL2:
6471 /* gen_helper_mtc0_performance4(arg); */
6472 register_name = "Performance4";
6473 goto cp0_unimplemented;
6474 case CP0_REG25__PERFCNT2:
6475 /* gen_helper_mtc0_performance5(arg); */
6476 register_name = "Performance5";
6477 goto cp0_unimplemented;
6478 case CP0_REG25__PERFCTL3:
6479 /* gen_helper_mtc0_performance6(arg); */
6480 register_name = "Performance6";
6481 goto cp0_unimplemented;
6482 case CP0_REG25__PERFCNT3:
6483 /* gen_helper_mtc0_performance7(arg); */
6484 register_name = "Performance7";
6485 goto cp0_unimplemented;
6486 default:
6487 goto cp0_unimplemented;
6488 }
6489 break;
6490 case CP0_REGISTER_26:
6491 switch (sel) {
6492 case CP0_REG26__ERRCTL:
6493 gen_helper_mtc0_errctl(tcg_env, arg);
6494 ctx->base.is_jmp = DISAS_STOP;
6495 register_name = "ErrCtl";
6496 break;
6497 default:
6498 goto cp0_unimplemented;
6499 }
6500 break;
6501 case CP0_REGISTER_27:
6502 switch (sel) {
6503 case CP0_REG27__CACHERR:
6504 /* ignored */
6505 register_name = "CacheErr";
6506 break;
6507 default:
6508 goto cp0_unimplemented;
6509 }
6510 break;
6511 case CP0_REGISTER_28:
6512 switch (sel) {
6513 case CP0_REG28__TAGLO:
6514 case CP0_REG28__TAGLO1:
6515 case CP0_REG28__TAGLO2:
6516 case CP0_REG28__TAGLO3:
6517 gen_helper_mtc0_taglo(tcg_env, arg);
6518 register_name = "TagLo";
6519 break;
6520 case CP0_REG28__DATALO:
6521 case CP0_REG28__DATALO1:
6522 case CP0_REG28__DATALO2:
6523 case CP0_REG28__DATALO3:
6524 gen_helper_mtc0_datalo(tcg_env, arg);
6525 register_name = "DataLo";
6526 break;
6527 default:
6528 goto cp0_unimplemented;
6529 }
6530 break;
6531 case CP0_REGISTER_29:
6532 switch (sel) {
6533 case CP0_REG29__TAGHI:
6534 case CP0_REG29__TAGHI1:
6535 case CP0_REG29__TAGHI2:
6536 case CP0_REG29__TAGHI3:
6537 gen_helper_mtc0_taghi(tcg_env, arg);
6538 register_name = "TagHi";
6539 break;
6540 case CP0_REG29__DATAHI:
6541 case CP0_REG29__DATAHI1:
6542 case CP0_REG29__DATAHI2:
6543 case CP0_REG29__DATAHI3:
6544 gen_helper_mtc0_datahi(tcg_env, arg);
6545 register_name = "DataHi";
6546 break;
6547 default:
6548 register_name = "invalid sel";
6549 goto cp0_unimplemented;
6550 }
6551 break;
6552 case CP0_REGISTER_30:
6553 switch (sel) {
6554 case CP0_REG30__ERROREPC:
6555 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
6556 register_name = "ErrorEPC";
6557 break;
6558 default:
6559 goto cp0_unimplemented;
6560 }
6561 break;
6562 case CP0_REGISTER_31:
6563 switch (sel) {
6564 case CP0_REG31__DESAVE:
6565 /* EJTAG support */
6566 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
6567 register_name = "DESAVE";
6568 break;
6569 case CP0_REG31__KSCRATCH1:
6570 case CP0_REG31__KSCRATCH2:
6571 case CP0_REG31__KSCRATCH3:
6572 case CP0_REG31__KSCRATCH4:
6573 case CP0_REG31__KSCRATCH5:
6574 case CP0_REG31__KSCRATCH6:
6575 CP0_CHECK(ctx->kscrexist & (1 << sel));
6576 tcg_gen_st_tl(arg, tcg_env,
6577 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
6578 register_name = "KScratch";
6579 break;
6580 default:
6581 goto cp0_unimplemented;
6582 }
6583 break;
6584 default:
6585 goto cp0_unimplemented;
6586 }
6587 trace_mips_translate_c0("mtc0", register_name, reg, sel);
6588
6589 /* For simplicity assume that all writes can cause interrupts. */
6590 if (icount) {
6591 /*
6592 * DISAS_STOP isn't sufficient, we need to ensure we break out of
6593 * translated code to check for pending interrupts.
6594 */
6595 gen_save_pc(ctx->base.pc_next + 4);
6596 ctx->base.is_jmp = DISAS_EXIT;
6597 }
6598 return;
6599
6600 cp0_unimplemented:
6601 qemu_log_mask(LOG_UNIMP, "mtc0 %s (reg %d sel %d)\n",
6602 register_name, reg, sel);
6603 }
6604
6605 #if defined(TARGET_MIPS64)
gen_dmfc0(DisasContext * ctx,TCGv arg,int reg,int sel)6606 static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
6607 {
6608 const char *register_name = "invalid";
6609
6610 if (sel != 0) {
6611 check_insn(ctx, ISA_MIPS_R1);
6612 }
6613
6614 switch (reg) {
6615 case CP0_REGISTER_00:
6616 switch (sel) {
6617 case CP0_REG00__INDEX:
6618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
6619 register_name = "Index";
6620 break;
6621 case CP0_REG00__MVPCONTROL:
6622 CP0_CHECK(disas_mt_available(ctx));
6623 gen_helper_mfc0_mvpcontrol(arg, tcg_env);
6624 register_name = "MVPControl";
6625 break;
6626 case CP0_REG00__MVPCONF0:
6627 CP0_CHECK(disas_mt_available(ctx));
6628 gen_helper_mfc0_mvpconf0(arg, tcg_env);
6629 register_name = "MVPConf0";
6630 break;
6631 case CP0_REG00__MVPCONF1:
6632 CP0_CHECK(disas_mt_available(ctx));
6633 gen_helper_mfc0_mvpconf1(arg, tcg_env);
6634 register_name = "MVPConf1";
6635 break;
6636 case CP0_REG00__VPCONTROL:
6637 CP0_CHECK(ctx->vp);
6638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPControl));
6639 register_name = "VPControl";
6640 break;
6641 default:
6642 goto cp0_unimplemented;
6643 }
6644 break;
6645 case CP0_REGISTER_01:
6646 switch (sel) {
6647 case CP0_REG01__RANDOM:
6648 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
6649 gen_helper_mfc0_random(arg, tcg_env);
6650 register_name = "Random";
6651 break;
6652 case CP0_REG01__VPECONTROL:
6653 CP0_CHECK(disas_mt_available(ctx));
6654 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
6655 register_name = "VPEControl";
6656 break;
6657 case CP0_REG01__VPECONF0:
6658 CP0_CHECK(disas_mt_available(ctx));
6659 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
6660 register_name = "VPEConf0";
6661 break;
6662 case CP0_REG01__VPECONF1:
6663 CP0_CHECK(disas_mt_available(ctx));
6664 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
6665 register_name = "VPEConf1";
6666 break;
6667 case CP0_REG01__YQMASK:
6668 CP0_CHECK(disas_mt_available(ctx));
6669 tcg_gen_ld_tl(arg, tcg_env,
6670 offsetof(CPUMIPSState, CP0_YQMask));
6671 register_name = "YQMask";
6672 break;
6673 case CP0_REG01__VPESCHEDULE:
6674 CP0_CHECK(disas_mt_available(ctx));
6675 tcg_gen_ld_tl(arg, tcg_env,
6676 offsetof(CPUMIPSState, CP0_VPESchedule));
6677 register_name = "VPESchedule";
6678 break;
6679 case CP0_REG01__VPESCHEFBACK:
6680 CP0_CHECK(disas_mt_available(ctx));
6681 tcg_gen_ld_tl(arg, tcg_env,
6682 offsetof(CPUMIPSState, CP0_VPEScheFBack));
6683 register_name = "VPEScheFBack";
6684 break;
6685 case CP0_REG01__VPEOPT:
6686 CP0_CHECK(disas_mt_available(ctx));
6687 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
6688 register_name = "VPEOpt";
6689 break;
6690 default:
6691 goto cp0_unimplemented;
6692 }
6693 break;
6694 case CP0_REGISTER_02:
6695 switch (sel) {
6696 case CP0_REG02__ENTRYLO0:
6697 tcg_gen_ld_tl(arg, tcg_env,
6698 offsetof(CPUMIPSState, CP0_EntryLo0));
6699 register_name = "EntryLo0";
6700 break;
6701 case CP0_REG02__TCSTATUS:
6702 CP0_CHECK(disas_mt_available(ctx));
6703 gen_helper_mfc0_tcstatus(arg, tcg_env);
6704 register_name = "TCStatus";
6705 break;
6706 case CP0_REG02__TCBIND:
6707 CP0_CHECK(disas_mt_available(ctx));
6708 gen_helper_mfc0_tcbind(arg, tcg_env);
6709 register_name = "TCBind";
6710 break;
6711 case CP0_REG02__TCRESTART:
6712 CP0_CHECK(disas_mt_available(ctx));
6713 gen_helper_dmfc0_tcrestart(arg, tcg_env);
6714 register_name = "TCRestart";
6715 break;
6716 case CP0_REG02__TCHALT:
6717 CP0_CHECK(disas_mt_available(ctx));
6718 gen_helper_dmfc0_tchalt(arg, tcg_env);
6719 register_name = "TCHalt";
6720 break;
6721 case CP0_REG02__TCCONTEXT:
6722 CP0_CHECK(disas_mt_available(ctx));
6723 gen_helper_dmfc0_tccontext(arg, tcg_env);
6724 register_name = "TCContext";
6725 break;
6726 case CP0_REG02__TCSCHEDULE:
6727 CP0_CHECK(disas_mt_available(ctx));
6728 gen_helper_dmfc0_tcschedule(arg, tcg_env);
6729 register_name = "TCSchedule";
6730 break;
6731 case CP0_REG02__TCSCHEFBACK:
6732 CP0_CHECK(disas_mt_available(ctx));
6733 gen_helper_dmfc0_tcschefback(arg, tcg_env);
6734 register_name = "TCScheFBack";
6735 break;
6736 default:
6737 goto cp0_unimplemented;
6738 }
6739 break;
6740 case CP0_REGISTER_03:
6741 switch (sel) {
6742 case CP0_REG03__ENTRYLO1:
6743 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryLo1));
6744 register_name = "EntryLo1";
6745 break;
6746 case CP0_REG03__GLOBALNUM:
6747 CP0_CHECK(ctx->vp);
6748 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_GlobalNumber));
6749 register_name = "GlobalNumber";
6750 break;
6751 default:
6752 goto cp0_unimplemented;
6753 }
6754 break;
6755 case CP0_REGISTER_04:
6756 switch (sel) {
6757 case CP0_REG04__CONTEXT:
6758 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_Context));
6759 register_name = "Context";
6760 break;
6761 case CP0_REG04__CONTEXTCONFIG:
6762 /* SmartMIPS ASE */
6763 /* gen_helper_dmfc0_contextconfig(arg); */
6764 register_name = "ContextConfig";
6765 goto cp0_unimplemented;
6766 case CP0_REG04__USERLOCAL:
6767 CP0_CHECK(ctx->ulri);
6768 tcg_gen_ld_tl(arg, tcg_env,
6769 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
6770 register_name = "UserLocal";
6771 break;
6772 case CP0_REG04__MMID:
6773 CP0_CHECK(ctx->mi);
6774 gen_helper_mtc0_memorymapid(tcg_env, arg);
6775 register_name = "MMID";
6776 break;
6777 default:
6778 goto cp0_unimplemented;
6779 }
6780 break;
6781 case CP0_REGISTER_05:
6782 switch (sel) {
6783 case CP0_REG05__PAGEMASK:
6784 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
6785 register_name = "PageMask";
6786 break;
6787 case CP0_REG05__PAGEGRAIN:
6788 check_insn(ctx, ISA_MIPS_R2);
6789 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
6790 register_name = "PageGrain";
6791 break;
6792 case CP0_REG05__SEGCTL0:
6793 CP0_CHECK(ctx->sc);
6794 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl0));
6795 register_name = "SegCtl0";
6796 break;
6797 case CP0_REG05__SEGCTL1:
6798 CP0_CHECK(ctx->sc);
6799 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl1));
6800 register_name = "SegCtl1";
6801 break;
6802 case CP0_REG05__SEGCTL2:
6803 CP0_CHECK(ctx->sc);
6804 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_SegCtl2));
6805 register_name = "SegCtl2";
6806 break;
6807 case CP0_REG05__PWBASE:
6808 check_pw(ctx);
6809 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWBase));
6810 register_name = "PWBase";
6811 break;
6812 case CP0_REG05__PWFIELD:
6813 check_pw(ctx);
6814 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWField));
6815 register_name = "PWField";
6816 break;
6817 case CP0_REG05__PWSIZE:
6818 check_pw(ctx);
6819 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWSize));
6820 register_name = "PWSize";
6821 break;
6822 default:
6823 goto cp0_unimplemented;
6824 }
6825 break;
6826 case CP0_REGISTER_06:
6827 switch (sel) {
6828 case CP0_REG06__WIRED:
6829 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
6830 register_name = "Wired";
6831 break;
6832 case CP0_REG06__SRSCONF0:
6833 check_insn(ctx, ISA_MIPS_R2);
6834 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
6835 register_name = "SRSConf0";
6836 break;
6837 case CP0_REG06__SRSCONF1:
6838 check_insn(ctx, ISA_MIPS_R2);
6839 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
6840 register_name = "SRSConf1";
6841 break;
6842 case CP0_REG06__SRSCONF2:
6843 check_insn(ctx, ISA_MIPS_R2);
6844 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
6845 register_name = "SRSConf2";
6846 break;
6847 case CP0_REG06__SRSCONF3:
6848 check_insn(ctx, ISA_MIPS_R2);
6849 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
6850 register_name = "SRSConf3";
6851 break;
6852 case CP0_REG06__SRSCONF4:
6853 check_insn(ctx, ISA_MIPS_R2);
6854 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
6855 register_name = "SRSConf4";
6856 break;
6857 case CP0_REG06__PWCTL:
6858 check_pw(ctx);
6859 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PWCtl));
6860 register_name = "PWCtl";
6861 break;
6862 default:
6863 goto cp0_unimplemented;
6864 }
6865 break;
6866 case CP0_REGISTER_07:
6867 switch (sel) {
6868 case CP0_REG07__HWRENA:
6869 check_insn(ctx, ISA_MIPS_R2);
6870 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
6871 register_name = "HWREna";
6872 break;
6873 default:
6874 goto cp0_unimplemented;
6875 }
6876 break;
6877 case CP0_REGISTER_08:
6878 switch (sel) {
6879 case CP0_REG08__BADVADDR:
6880 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_BadVAddr));
6881 register_name = "BadVAddr";
6882 break;
6883 case CP0_REG08__BADINSTR:
6884 CP0_CHECK(ctx->bi);
6885 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstr));
6886 register_name = "BadInstr";
6887 break;
6888 case CP0_REG08__BADINSTRP:
6889 CP0_CHECK(ctx->bp);
6890 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrP));
6891 register_name = "BadInstrP";
6892 break;
6893 case CP0_REG08__BADINSTRX:
6894 CP0_CHECK(ctx->bi);
6895 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_BadInstrX));
6896 tcg_gen_andi_tl(arg, arg, ~0xffff);
6897 register_name = "BadInstrX";
6898 break;
6899 default:
6900 goto cp0_unimplemented;
6901 }
6902 break;
6903 case CP0_REGISTER_09:
6904 switch (sel) {
6905 case CP0_REG09__COUNT:
6906 /* Mark as an IO operation because we read the time. */
6907 translator_io_start(&ctx->base);
6908 gen_helper_mfc0_count(arg, tcg_env);
6909 /*
6910 * Break the TB to be able to take timer interrupts immediately
6911 * after reading count. DISAS_STOP isn't sufficient, we need to
6912 * ensure we break completely out of translated code.
6913 */
6914 gen_save_pc(ctx->base.pc_next + 4);
6915 ctx->base.is_jmp = DISAS_EXIT;
6916 register_name = "Count";
6917 break;
6918 default:
6919 goto cp0_unimplemented;
6920 }
6921 break;
6922 case CP0_REGISTER_10:
6923 switch (sel) {
6924 case CP0_REG10__ENTRYHI:
6925 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EntryHi));
6926 register_name = "EntryHi";
6927 break;
6928 default:
6929 goto cp0_unimplemented;
6930 }
6931 break;
6932 case CP0_REGISTER_11:
6933 switch (sel) {
6934 case CP0_REG11__COMPARE:
6935 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
6936 register_name = "Compare";
6937 break;
6938 /* 6,7 are implementation dependent */
6939 default:
6940 goto cp0_unimplemented;
6941 }
6942 break;
6943 case CP0_REGISTER_12:
6944 switch (sel) {
6945 case CP0_REG12__STATUS:
6946 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
6947 register_name = "Status";
6948 break;
6949 case CP0_REG12__INTCTL:
6950 check_insn(ctx, ISA_MIPS_R2);
6951 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
6952 register_name = "IntCtl";
6953 break;
6954 case CP0_REG12__SRSCTL:
6955 check_insn(ctx, ISA_MIPS_R2);
6956 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
6957 register_name = "SRSCtl";
6958 break;
6959 case CP0_REG12__SRSMAP:
6960 check_insn(ctx, ISA_MIPS_R2);
6961 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
6962 register_name = "SRSMap";
6963 break;
6964 default:
6965 goto cp0_unimplemented;
6966 }
6967 break;
6968 case CP0_REGISTER_13:
6969 switch (sel) {
6970 case CP0_REG13__CAUSE:
6971 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
6972 register_name = "Cause";
6973 break;
6974 default:
6975 goto cp0_unimplemented;
6976 }
6977 break;
6978 case CP0_REGISTER_14:
6979 switch (sel) {
6980 case CP0_REG14__EPC:
6981 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
6982 register_name = "EPC";
6983 break;
6984 default:
6985 goto cp0_unimplemented;
6986 }
6987 break;
6988 case CP0_REGISTER_15:
6989 switch (sel) {
6990 case CP0_REG15__PRID:
6991 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
6992 register_name = "PRid";
6993 break;
6994 case CP0_REG15__EBASE:
6995 check_insn(ctx, ISA_MIPS_R2);
6996 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EBase));
6997 register_name = "EBase";
6998 break;
6999 case CP0_REG15__CMGCRBASE:
7000 check_insn(ctx, ISA_MIPS_R2);
7001 CP0_CHECK(ctx->cmgcr);
7002 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
7003 register_name = "CMGCRBase";
7004 break;
7005 default:
7006 goto cp0_unimplemented;
7007 }
7008 break;
7009 case CP0_REGISTER_16:
7010 switch (sel) {
7011 case CP0_REG16__CONFIG:
7012 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
7013 register_name = "Config";
7014 break;
7015 case CP0_REG16__CONFIG1:
7016 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
7017 register_name = "Config1";
7018 break;
7019 case CP0_REG16__CONFIG2:
7020 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
7021 register_name = "Config2";
7022 break;
7023 case CP0_REG16__CONFIG3:
7024 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
7025 register_name = "Config3";
7026 break;
7027 case CP0_REG16__CONFIG4:
7028 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config4));
7029 register_name = "Config4";
7030 break;
7031 case CP0_REG16__CONFIG5:
7032 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config5));
7033 register_name = "Config5";
7034 break;
7035 /* 6,7 are implementation dependent */
7036 case CP0_REG16__CONFIG6:
7037 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
7038 register_name = "Config6";
7039 break;
7040 case CP0_REG16__CONFIG7:
7041 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
7042 register_name = "Config7";
7043 break;
7044 default:
7045 goto cp0_unimplemented;
7046 }
7047 break;
7048 case CP0_REGISTER_17:
7049 switch (sel) {
7050 case CP0_REG17__LLADDR:
7051 gen_helper_dmfc0_lladdr(arg, tcg_env);
7052 register_name = "LLAddr";
7053 break;
7054 case CP0_REG17__MAAR:
7055 CP0_CHECK(ctx->mrp);
7056 gen_helper_dmfc0_maar(arg, tcg_env);
7057 register_name = "MAAR";
7058 break;
7059 case CP0_REG17__MAARI:
7060 CP0_CHECK(ctx->mrp);
7061 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MAARI));
7062 register_name = "MAARI";
7063 break;
7064 default:
7065 goto cp0_unimplemented;
7066 }
7067 break;
7068 case CP0_REGISTER_18:
7069 switch (sel) {
7070 case CP0_REG18__WATCHLO0:
7071 case CP0_REG18__WATCHLO1:
7072 case CP0_REG18__WATCHLO2:
7073 case CP0_REG18__WATCHLO3:
7074 case CP0_REG18__WATCHLO4:
7075 case CP0_REG18__WATCHLO5:
7076 case CP0_REG18__WATCHLO6:
7077 case CP0_REG18__WATCHLO7:
7078 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7079 gen_helper_1e0i(dmfc0_watchlo, arg, sel);
7080 register_name = "WatchLo";
7081 break;
7082 default:
7083 goto cp0_unimplemented;
7084 }
7085 break;
7086 case CP0_REGISTER_19:
7087 switch (sel) {
7088 case CP0_REG19__WATCHHI0:
7089 case CP0_REG19__WATCHHI1:
7090 case CP0_REG19__WATCHHI2:
7091 case CP0_REG19__WATCHHI3:
7092 case CP0_REG19__WATCHHI4:
7093 case CP0_REG19__WATCHHI5:
7094 case CP0_REG19__WATCHHI6:
7095 case CP0_REG19__WATCHHI7:
7096 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7097 gen_helper_1e0i(dmfc0_watchhi, arg, sel);
7098 register_name = "WatchHi";
7099 break;
7100 default:
7101 goto cp0_unimplemented;
7102 }
7103 break;
7104 case CP0_REGISTER_20:
7105 switch (sel) {
7106 case CP0_REG20__XCONTEXT:
7107 check_insn(ctx, ISA_MIPS3);
7108 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_XContext));
7109 register_name = "XContext";
7110 break;
7111 default:
7112 goto cp0_unimplemented;
7113 }
7114 break;
7115 case CP0_REGISTER_21:
7116 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7117 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7118 switch (sel) {
7119 case 0:
7120 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
7121 register_name = "Framemask";
7122 break;
7123 default:
7124 goto cp0_unimplemented;
7125 }
7126 break;
7127 case CP0_REGISTER_22:
7128 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7129 register_name = "'Diagnostic"; /* implementation dependent */
7130 break;
7131 case CP0_REGISTER_23:
7132 switch (sel) {
7133 case CP0_REG23__DEBUG:
7134 gen_helper_mfc0_debug(arg, tcg_env); /* EJTAG support */
7135 register_name = "Debug";
7136 break;
7137 case CP0_REG23__TRACECONTROL:
7138 /* PDtrace support */
7139 /* gen_helper_dmfc0_tracecontrol(arg, tcg_env); */
7140 register_name = "TraceControl";
7141 goto cp0_unimplemented;
7142 case CP0_REG23__TRACECONTROL2:
7143 /* PDtrace support */
7144 /* gen_helper_dmfc0_tracecontrol2(arg, tcg_env); */
7145 register_name = "TraceControl2";
7146 goto cp0_unimplemented;
7147 case CP0_REG23__USERTRACEDATA1:
7148 /* PDtrace support */
7149 /* gen_helper_dmfc0_usertracedata1(arg, tcg_env);*/
7150 register_name = "UserTraceData1";
7151 goto cp0_unimplemented;
7152 case CP0_REG23__TRACEIBPC:
7153 /* PDtrace support */
7154 /* gen_helper_dmfc0_traceibpc(arg, tcg_env); */
7155 register_name = "TraceIBPC";
7156 goto cp0_unimplemented;
7157 case CP0_REG23__TRACEDBPC:
7158 /* PDtrace support */
7159 /* gen_helper_dmfc0_tracedbpc(arg, tcg_env); */
7160 register_name = "TraceDBPC";
7161 goto cp0_unimplemented;
7162 default:
7163 goto cp0_unimplemented;
7164 }
7165 break;
7166 case CP0_REGISTER_24:
7167 switch (sel) {
7168 case CP0_REG24__DEPC:
7169 /* EJTAG support */
7170 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
7171 register_name = "DEPC";
7172 break;
7173 default:
7174 goto cp0_unimplemented;
7175 }
7176 break;
7177 case CP0_REGISTER_25:
7178 switch (sel) {
7179 case CP0_REG25__PERFCTL0:
7180 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
7181 register_name = "Performance0";
7182 break;
7183 case CP0_REG25__PERFCNT0:
7184 /* gen_helper_dmfc0_performance1(arg); */
7185 register_name = "Performance1";
7186 goto cp0_unimplemented;
7187 case CP0_REG25__PERFCTL1:
7188 /* gen_helper_dmfc0_performance2(arg); */
7189 register_name = "Performance2";
7190 goto cp0_unimplemented;
7191 case CP0_REG25__PERFCNT1:
7192 /* gen_helper_dmfc0_performance3(arg); */
7193 register_name = "Performance3";
7194 goto cp0_unimplemented;
7195 case CP0_REG25__PERFCTL2:
7196 /* gen_helper_dmfc0_performance4(arg); */
7197 register_name = "Performance4";
7198 goto cp0_unimplemented;
7199 case CP0_REG25__PERFCNT2:
7200 /* gen_helper_dmfc0_performance5(arg); */
7201 register_name = "Performance5";
7202 goto cp0_unimplemented;
7203 case CP0_REG25__PERFCTL3:
7204 /* gen_helper_dmfc0_performance6(arg); */
7205 register_name = "Performance6";
7206 goto cp0_unimplemented;
7207 case CP0_REG25__PERFCNT3:
7208 /* gen_helper_dmfc0_performance7(arg); */
7209 register_name = "Performance7";
7210 goto cp0_unimplemented;
7211 default:
7212 goto cp0_unimplemented;
7213 }
7214 break;
7215 case CP0_REGISTER_26:
7216 switch (sel) {
7217 case CP0_REG26__ERRCTL:
7218 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_ErrCtl));
7219 register_name = "ErrCtl";
7220 break;
7221 default:
7222 goto cp0_unimplemented;
7223 }
7224 break;
7225 case CP0_REGISTER_27:
7226 switch (sel) {
7227 /* ignored */
7228 case CP0_REG27__CACHERR:
7229 tcg_gen_movi_tl(arg, 0); /* unimplemented */
7230 register_name = "CacheErr";
7231 break;
7232 default:
7233 goto cp0_unimplemented;
7234 }
7235 break;
7236 case CP0_REGISTER_28:
7237 switch (sel) {
7238 case CP0_REG28__TAGLO:
7239 case CP0_REG28__TAGLO1:
7240 case CP0_REG28__TAGLO2:
7241 case CP0_REG28__TAGLO3:
7242 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
7243 register_name = "TagLo";
7244 break;
7245 case CP0_REG28__DATALO:
7246 case CP0_REG28__DATALO1:
7247 case CP0_REG28__DATALO2:
7248 case CP0_REG28__DATALO3:
7249 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
7250 register_name = "DataLo";
7251 break;
7252 default:
7253 goto cp0_unimplemented;
7254 }
7255 break;
7256 case CP0_REGISTER_29:
7257 switch (sel) {
7258 case CP0_REG29__TAGHI:
7259 case CP0_REG29__TAGHI1:
7260 case CP0_REG29__TAGHI2:
7261 case CP0_REG29__TAGHI3:
7262 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
7263 register_name = "TagHi";
7264 break;
7265 case CP0_REG29__DATAHI:
7266 case CP0_REG29__DATAHI1:
7267 case CP0_REG29__DATAHI2:
7268 case CP0_REG29__DATAHI3:
7269 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
7270 register_name = "DataHi";
7271 break;
7272 default:
7273 goto cp0_unimplemented;
7274 }
7275 break;
7276 case CP0_REGISTER_30:
7277 switch (sel) {
7278 case CP0_REG30__ERROREPC:
7279 tcg_gen_ld_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
7280 register_name = "ErrorEPC";
7281 break;
7282 default:
7283 goto cp0_unimplemented;
7284 }
7285 break;
7286 case CP0_REGISTER_31:
7287 switch (sel) {
7288 case CP0_REG31__DESAVE:
7289 /* EJTAG support */
7290 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
7291 register_name = "DESAVE";
7292 break;
7293 case CP0_REG31__KSCRATCH1:
7294 case CP0_REG31__KSCRATCH2:
7295 case CP0_REG31__KSCRATCH3:
7296 case CP0_REG31__KSCRATCH4:
7297 case CP0_REG31__KSCRATCH5:
7298 case CP0_REG31__KSCRATCH6:
7299 CP0_CHECK(ctx->kscrexist & (1 << sel));
7300 tcg_gen_ld_tl(arg, tcg_env,
7301 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
7302 register_name = "KScratch";
7303 break;
7304 default:
7305 goto cp0_unimplemented;
7306 }
7307 break;
7308 default:
7309 goto cp0_unimplemented;
7310 }
7311 trace_mips_translate_c0("dmfc0", register_name, reg, sel);
7312 return;
7313
7314 cp0_unimplemented:
7315 qemu_log_mask(LOG_UNIMP, "dmfc0 %s (reg %d sel %d)\n",
7316 register_name, reg, sel);
7317 gen_mfc0_unimplemented(ctx, arg);
7318 }
7319
gen_dmtc0(DisasContext * ctx,TCGv arg,int reg,int sel)7320 static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
7321 {
7322 const char *register_name = "invalid";
7323 bool icount;
7324
7325 if (sel != 0) {
7326 check_insn(ctx, ISA_MIPS_R1);
7327 }
7328
7329 icount = translator_io_start(&ctx->base);
7330
7331 switch (reg) {
7332 case CP0_REGISTER_00:
7333 switch (sel) {
7334 case CP0_REG00__INDEX:
7335 gen_helper_mtc0_index(tcg_env, arg);
7336 register_name = "Index";
7337 break;
7338 case CP0_REG00__MVPCONTROL:
7339 CP0_CHECK(disas_mt_available(ctx));
7340 gen_helper_mtc0_mvpcontrol(tcg_env, arg);
7341 register_name = "MVPControl";
7342 break;
7343 case CP0_REG00__MVPCONF0:
7344 CP0_CHECK(disas_mt_available(ctx));
7345 /* ignored */
7346 register_name = "MVPConf0";
7347 break;
7348 case CP0_REG00__MVPCONF1:
7349 CP0_CHECK(disas_mt_available(ctx));
7350 /* ignored */
7351 register_name = "MVPConf1";
7352 break;
7353 case CP0_REG00__VPCONTROL:
7354 CP0_CHECK(ctx->vp);
7355 /* ignored */
7356 register_name = "VPControl";
7357 break;
7358 default:
7359 goto cp0_unimplemented;
7360 }
7361 break;
7362 case CP0_REGISTER_01:
7363 switch (sel) {
7364 case CP0_REG01__RANDOM:
7365 /* ignored */
7366 register_name = "Random";
7367 break;
7368 case CP0_REG01__VPECONTROL:
7369 CP0_CHECK(disas_mt_available(ctx));
7370 gen_helper_mtc0_vpecontrol(tcg_env, arg);
7371 register_name = "VPEControl";
7372 break;
7373 case CP0_REG01__VPECONF0:
7374 CP0_CHECK(disas_mt_available(ctx));
7375 gen_helper_mtc0_vpeconf0(tcg_env, arg);
7376 register_name = "VPEConf0";
7377 break;
7378 case CP0_REG01__VPECONF1:
7379 CP0_CHECK(disas_mt_available(ctx));
7380 gen_helper_mtc0_vpeconf1(tcg_env, arg);
7381 register_name = "VPEConf1";
7382 break;
7383 case CP0_REG01__YQMASK:
7384 CP0_CHECK(disas_mt_available(ctx));
7385 gen_helper_mtc0_yqmask(tcg_env, arg);
7386 register_name = "YQMask";
7387 break;
7388 case CP0_REG01__VPESCHEDULE:
7389 CP0_CHECK(disas_mt_available(ctx));
7390 tcg_gen_st_tl(arg, tcg_env,
7391 offsetof(CPUMIPSState, CP0_VPESchedule));
7392 register_name = "VPESchedule";
7393 break;
7394 case CP0_REG01__VPESCHEFBACK:
7395 CP0_CHECK(disas_mt_available(ctx));
7396 tcg_gen_st_tl(arg, tcg_env,
7397 offsetof(CPUMIPSState, CP0_VPEScheFBack));
7398 register_name = "VPEScheFBack";
7399 break;
7400 case CP0_REG01__VPEOPT:
7401 CP0_CHECK(disas_mt_available(ctx));
7402 gen_helper_mtc0_vpeopt(tcg_env, arg);
7403 register_name = "VPEOpt";
7404 break;
7405 default:
7406 goto cp0_unimplemented;
7407 }
7408 break;
7409 case CP0_REGISTER_02:
7410 switch (sel) {
7411 case CP0_REG02__ENTRYLO0:
7412 gen_helper_dmtc0_entrylo0(tcg_env, arg);
7413 register_name = "EntryLo0";
7414 break;
7415 case CP0_REG02__TCSTATUS:
7416 CP0_CHECK(disas_mt_available(ctx));
7417 gen_helper_mtc0_tcstatus(tcg_env, arg);
7418 register_name = "TCStatus";
7419 break;
7420 case CP0_REG02__TCBIND:
7421 CP0_CHECK(disas_mt_available(ctx));
7422 gen_helper_mtc0_tcbind(tcg_env, arg);
7423 register_name = "TCBind";
7424 break;
7425 case CP0_REG02__TCRESTART:
7426 CP0_CHECK(disas_mt_available(ctx));
7427 gen_helper_mtc0_tcrestart(tcg_env, arg);
7428 register_name = "TCRestart";
7429 break;
7430 case CP0_REG02__TCHALT:
7431 CP0_CHECK(disas_mt_available(ctx));
7432 gen_helper_mtc0_tchalt(tcg_env, arg);
7433 register_name = "TCHalt";
7434 break;
7435 case CP0_REG02__TCCONTEXT:
7436 CP0_CHECK(disas_mt_available(ctx));
7437 gen_helper_mtc0_tccontext(tcg_env, arg);
7438 register_name = "TCContext";
7439 break;
7440 case CP0_REG02__TCSCHEDULE:
7441 CP0_CHECK(disas_mt_available(ctx));
7442 gen_helper_mtc0_tcschedule(tcg_env, arg);
7443 register_name = "TCSchedule";
7444 break;
7445 case CP0_REG02__TCSCHEFBACK:
7446 CP0_CHECK(disas_mt_available(ctx));
7447 gen_helper_mtc0_tcschefback(tcg_env, arg);
7448 register_name = "TCScheFBack";
7449 break;
7450 default:
7451 goto cp0_unimplemented;
7452 }
7453 break;
7454 case CP0_REGISTER_03:
7455 switch (sel) {
7456 case CP0_REG03__ENTRYLO1:
7457 gen_helper_dmtc0_entrylo1(tcg_env, arg);
7458 register_name = "EntryLo1";
7459 break;
7460 case CP0_REG03__GLOBALNUM:
7461 CP0_CHECK(ctx->vp);
7462 /* ignored */
7463 register_name = "GlobalNumber";
7464 break;
7465 default:
7466 goto cp0_unimplemented;
7467 }
7468 break;
7469 case CP0_REGISTER_04:
7470 switch (sel) {
7471 case CP0_REG04__CONTEXT:
7472 gen_helper_mtc0_context(tcg_env, arg);
7473 register_name = "Context";
7474 break;
7475 case CP0_REG04__CONTEXTCONFIG:
7476 /* SmartMIPS ASE */
7477 /* gen_helper_dmtc0_contextconfig(arg); */
7478 register_name = "ContextConfig";
7479 goto cp0_unimplemented;
7480 case CP0_REG04__USERLOCAL:
7481 CP0_CHECK(ctx->ulri);
7482 tcg_gen_st_tl(arg, tcg_env,
7483 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
7484 register_name = "UserLocal";
7485 break;
7486 case CP0_REG04__MMID:
7487 CP0_CHECK(ctx->mi);
7488 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_MemoryMapID));
7489 register_name = "MMID";
7490 break;
7491 default:
7492 goto cp0_unimplemented;
7493 }
7494 break;
7495 case CP0_REGISTER_05:
7496 switch (sel) {
7497 case CP0_REG05__PAGEMASK:
7498 gen_helper_mtc0_pagemask(tcg_env, arg);
7499 register_name = "PageMask";
7500 break;
7501 case CP0_REG05__PAGEGRAIN:
7502 check_insn(ctx, ISA_MIPS_R2);
7503 gen_helper_mtc0_pagegrain(tcg_env, arg);
7504 register_name = "PageGrain";
7505 break;
7506 case CP0_REG05__SEGCTL0:
7507 CP0_CHECK(ctx->sc);
7508 gen_helper_mtc0_segctl0(tcg_env, arg);
7509 register_name = "SegCtl0";
7510 break;
7511 case CP0_REG05__SEGCTL1:
7512 CP0_CHECK(ctx->sc);
7513 gen_helper_mtc0_segctl1(tcg_env, arg);
7514 register_name = "SegCtl1";
7515 break;
7516 case CP0_REG05__SEGCTL2:
7517 CP0_CHECK(ctx->sc);
7518 gen_helper_mtc0_segctl2(tcg_env, arg);
7519 register_name = "SegCtl2";
7520 break;
7521 case CP0_REG05__PWBASE:
7522 check_pw(ctx);
7523 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_PWBase));
7524 register_name = "PWBase";
7525 break;
7526 case CP0_REG05__PWFIELD:
7527 check_pw(ctx);
7528 gen_helper_mtc0_pwfield(tcg_env, arg);
7529 register_name = "PWField";
7530 break;
7531 case CP0_REG05__PWSIZE:
7532 check_pw(ctx);
7533 gen_helper_mtc0_pwsize(tcg_env, arg);
7534 register_name = "PWSize";
7535 break;
7536 default:
7537 goto cp0_unimplemented;
7538 }
7539 break;
7540 case CP0_REGISTER_06:
7541 switch (sel) {
7542 case CP0_REG06__WIRED:
7543 gen_helper_mtc0_wired(tcg_env, arg);
7544 register_name = "Wired";
7545 break;
7546 case CP0_REG06__SRSCONF0:
7547 check_insn(ctx, ISA_MIPS_R2);
7548 gen_helper_mtc0_srsconf0(tcg_env, arg);
7549 register_name = "SRSConf0";
7550 break;
7551 case CP0_REG06__SRSCONF1:
7552 check_insn(ctx, ISA_MIPS_R2);
7553 gen_helper_mtc0_srsconf1(tcg_env, arg);
7554 register_name = "SRSConf1";
7555 break;
7556 case CP0_REG06__SRSCONF2:
7557 check_insn(ctx, ISA_MIPS_R2);
7558 gen_helper_mtc0_srsconf2(tcg_env, arg);
7559 register_name = "SRSConf2";
7560 break;
7561 case CP0_REG06__SRSCONF3:
7562 check_insn(ctx, ISA_MIPS_R2);
7563 gen_helper_mtc0_srsconf3(tcg_env, arg);
7564 register_name = "SRSConf3";
7565 break;
7566 case CP0_REG06__SRSCONF4:
7567 check_insn(ctx, ISA_MIPS_R2);
7568 gen_helper_mtc0_srsconf4(tcg_env, arg);
7569 register_name = "SRSConf4";
7570 break;
7571 case CP0_REG06__PWCTL:
7572 check_pw(ctx);
7573 gen_helper_mtc0_pwctl(tcg_env, arg);
7574 register_name = "PWCtl";
7575 break;
7576 default:
7577 goto cp0_unimplemented;
7578 }
7579 break;
7580 case CP0_REGISTER_07:
7581 switch (sel) {
7582 case CP0_REG07__HWRENA:
7583 check_insn(ctx, ISA_MIPS_R2);
7584 gen_helper_mtc0_hwrena(tcg_env, arg);
7585 ctx->base.is_jmp = DISAS_STOP;
7586 register_name = "HWREna";
7587 break;
7588 default:
7589 goto cp0_unimplemented;
7590 }
7591 break;
7592 case CP0_REGISTER_08:
7593 switch (sel) {
7594 case CP0_REG08__BADVADDR:
7595 /* ignored */
7596 register_name = "BadVAddr";
7597 break;
7598 case CP0_REG08__BADINSTR:
7599 /* ignored */
7600 register_name = "BadInstr";
7601 break;
7602 case CP0_REG08__BADINSTRP:
7603 /* ignored */
7604 register_name = "BadInstrP";
7605 break;
7606 case CP0_REG08__BADINSTRX:
7607 /* ignored */
7608 register_name = "BadInstrX";
7609 break;
7610 default:
7611 goto cp0_unimplemented;
7612 }
7613 break;
7614 case CP0_REGISTER_09:
7615 switch (sel) {
7616 case CP0_REG09__COUNT:
7617 gen_helper_mtc0_count(tcg_env, arg);
7618 register_name = "Count";
7619 break;
7620 default:
7621 goto cp0_unimplemented;
7622 }
7623 /* Stop translation as we may have switched the execution mode */
7624 ctx->base.is_jmp = DISAS_STOP;
7625 break;
7626 case CP0_REGISTER_10:
7627 switch (sel) {
7628 case CP0_REG10__ENTRYHI:
7629 gen_helper_mtc0_entryhi(tcg_env, arg);
7630 register_name = "EntryHi";
7631 break;
7632 default:
7633 goto cp0_unimplemented;
7634 }
7635 break;
7636 case CP0_REGISTER_11:
7637 switch (sel) {
7638 case CP0_REG11__COMPARE:
7639 gen_helper_mtc0_compare(tcg_env, arg);
7640 register_name = "Compare";
7641 break;
7642 /* 6,7 are implementation dependent */
7643 default:
7644 goto cp0_unimplemented;
7645 }
7646 /* Stop translation as we may have switched the execution mode */
7647 ctx->base.is_jmp = DISAS_STOP;
7648 break;
7649 case CP0_REGISTER_12:
7650 switch (sel) {
7651 case CP0_REG12__STATUS:
7652 save_cpu_state(ctx, 1);
7653 gen_helper_mtc0_status(tcg_env, arg);
7654 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7655 gen_save_pc(ctx->base.pc_next + 4);
7656 ctx->base.is_jmp = DISAS_EXIT;
7657 register_name = "Status";
7658 break;
7659 case CP0_REG12__INTCTL:
7660 check_insn(ctx, ISA_MIPS_R2);
7661 gen_helper_mtc0_intctl(tcg_env, arg);
7662 /* Stop translation as we may have switched the execution mode */
7663 ctx->base.is_jmp = DISAS_STOP;
7664 register_name = "IntCtl";
7665 break;
7666 case CP0_REG12__SRSCTL:
7667 check_insn(ctx, ISA_MIPS_R2);
7668 gen_helper_mtc0_srsctl(tcg_env, arg);
7669 /* Stop translation as we may have switched the execution mode */
7670 ctx->base.is_jmp = DISAS_STOP;
7671 register_name = "SRSCtl";
7672 break;
7673 case CP0_REG12__SRSMAP:
7674 check_insn(ctx, ISA_MIPS_R2);
7675 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
7676 /* Stop translation as we may have switched the execution mode */
7677 ctx->base.is_jmp = DISAS_STOP;
7678 register_name = "SRSMap";
7679 break;
7680 default:
7681 goto cp0_unimplemented;
7682 }
7683 break;
7684 case CP0_REGISTER_13:
7685 switch (sel) {
7686 case CP0_REG13__CAUSE:
7687 save_cpu_state(ctx, 1);
7688 gen_helper_mtc0_cause(tcg_env, arg);
7689 /*
7690 * Stop translation as we may have triggered an interrupt.
7691 * DISAS_STOP isn't sufficient, we need to ensure we break out of
7692 * translated code to check for pending interrupts.
7693 */
7694 gen_save_pc(ctx->base.pc_next + 4);
7695 ctx->base.is_jmp = DISAS_EXIT;
7696 register_name = "Cause";
7697 break;
7698 default:
7699 goto cp0_unimplemented;
7700 }
7701 break;
7702 case CP0_REGISTER_14:
7703 switch (sel) {
7704 case CP0_REG14__EPC:
7705 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_EPC));
7706 register_name = "EPC";
7707 break;
7708 default:
7709 goto cp0_unimplemented;
7710 }
7711 break;
7712 case CP0_REGISTER_15:
7713 switch (sel) {
7714 case CP0_REG15__PRID:
7715 /* ignored */
7716 register_name = "PRid";
7717 break;
7718 case CP0_REG15__EBASE:
7719 check_insn(ctx, ISA_MIPS_R2);
7720 gen_helper_mtc0_ebase(tcg_env, arg);
7721 register_name = "EBase";
7722 break;
7723 default:
7724 goto cp0_unimplemented;
7725 }
7726 break;
7727 case CP0_REGISTER_16:
7728 switch (sel) {
7729 case CP0_REG16__CONFIG:
7730 gen_helper_mtc0_config0(tcg_env, arg);
7731 register_name = "Config";
7732 /* Stop translation as we may have switched the execution mode */
7733 ctx->base.is_jmp = DISAS_STOP;
7734 break;
7735 case CP0_REG16__CONFIG1:
7736 /* ignored, read only */
7737 register_name = "Config1";
7738 break;
7739 case CP0_REG16__CONFIG2:
7740 gen_helper_mtc0_config2(tcg_env, arg);
7741 register_name = "Config2";
7742 /* Stop translation as we may have switched the execution mode */
7743 ctx->base.is_jmp = DISAS_STOP;
7744 break;
7745 case CP0_REG16__CONFIG3:
7746 gen_helper_mtc0_config3(tcg_env, arg);
7747 register_name = "Config3";
7748 /* Stop translation as we may have switched the execution mode */
7749 ctx->base.is_jmp = DISAS_STOP;
7750 break;
7751 case CP0_REG16__CONFIG4:
7752 /* currently ignored */
7753 register_name = "Config4";
7754 break;
7755 case CP0_REG16__CONFIG5:
7756 gen_helper_mtc0_config5(tcg_env, arg);
7757 register_name = "Config5";
7758 /* Stop translation as we may have switched the execution mode */
7759 ctx->base.is_jmp = DISAS_STOP;
7760 break;
7761 /* 6,7 are implementation dependent */
7762 default:
7763 register_name = "Invalid config selector";
7764 goto cp0_unimplemented;
7765 }
7766 break;
7767 case CP0_REGISTER_17:
7768 switch (sel) {
7769 case CP0_REG17__LLADDR:
7770 gen_helper_mtc0_lladdr(tcg_env, arg);
7771 register_name = "LLAddr";
7772 break;
7773 case CP0_REG17__MAAR:
7774 CP0_CHECK(ctx->mrp);
7775 gen_helper_mtc0_maar(tcg_env, arg);
7776 register_name = "MAAR";
7777 break;
7778 case CP0_REG17__MAARI:
7779 CP0_CHECK(ctx->mrp);
7780 gen_helper_mtc0_maari(tcg_env, arg);
7781 register_name = "MAARI";
7782 break;
7783 default:
7784 goto cp0_unimplemented;
7785 }
7786 break;
7787 case CP0_REGISTER_18:
7788 switch (sel) {
7789 case CP0_REG18__WATCHLO0:
7790 case CP0_REG18__WATCHLO1:
7791 case CP0_REG18__WATCHLO2:
7792 case CP0_REG18__WATCHLO3:
7793 case CP0_REG18__WATCHLO4:
7794 case CP0_REG18__WATCHLO5:
7795 case CP0_REG18__WATCHLO6:
7796 case CP0_REG18__WATCHLO7:
7797 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7798 gen_helper_0e1i(mtc0_watchlo, arg, sel);
7799 register_name = "WatchLo";
7800 break;
7801 default:
7802 goto cp0_unimplemented;
7803 }
7804 break;
7805 case CP0_REGISTER_19:
7806 switch (sel) {
7807 case CP0_REG19__WATCHHI0:
7808 case CP0_REG19__WATCHHI1:
7809 case CP0_REG19__WATCHHI2:
7810 case CP0_REG19__WATCHHI3:
7811 case CP0_REG19__WATCHHI4:
7812 case CP0_REG19__WATCHHI5:
7813 case CP0_REG19__WATCHHI6:
7814 case CP0_REG19__WATCHHI7:
7815 CP0_CHECK(ctx->CP0_Config1 & (1 << CP0C1_WR));
7816 gen_helper_0e1i(mtc0_watchhi, arg, sel);
7817 register_name = "WatchHi";
7818 break;
7819 default:
7820 goto cp0_unimplemented;
7821 }
7822 break;
7823 case CP0_REGISTER_20:
7824 switch (sel) {
7825 case CP0_REG20__XCONTEXT:
7826 check_insn(ctx, ISA_MIPS3);
7827 gen_helper_mtc0_xcontext(tcg_env, arg);
7828 register_name = "XContext";
7829 break;
7830 default:
7831 goto cp0_unimplemented;
7832 }
7833 break;
7834 case CP0_REGISTER_21:
7835 /* Officially reserved, but sel 0 is used for R1x000 framemask */
7836 CP0_CHECK(!(ctx->insn_flags & ISA_MIPS_R6));
7837 switch (sel) {
7838 case 0:
7839 gen_helper_mtc0_framemask(tcg_env, arg);
7840 register_name = "Framemask";
7841 break;
7842 default:
7843 goto cp0_unimplemented;
7844 }
7845 break;
7846 case CP0_REGISTER_22:
7847 /* ignored */
7848 register_name = "Diagnostic"; /* implementation dependent */
7849 break;
7850 case CP0_REGISTER_23:
7851 switch (sel) {
7852 case CP0_REG23__DEBUG:
7853 gen_helper_mtc0_debug(tcg_env, arg); /* EJTAG support */
7854 /* DISAS_STOP isn't good enough here, hflags may have changed. */
7855 gen_save_pc(ctx->base.pc_next + 4);
7856 ctx->base.is_jmp = DISAS_EXIT;
7857 register_name = "Debug";
7858 break;
7859 case CP0_REG23__TRACECONTROL:
7860 /* PDtrace support */
7861 /* gen_helper_mtc0_tracecontrol(tcg_env, arg); */
7862 /* Stop translation as we may have switched the execution mode */
7863 ctx->base.is_jmp = DISAS_STOP;
7864 register_name = "TraceControl";
7865 goto cp0_unimplemented;
7866 case CP0_REG23__TRACECONTROL2:
7867 /* PDtrace support */
7868 /* gen_helper_mtc0_tracecontrol2(tcg_env, arg); */
7869 /* Stop translation as we may have switched the execution mode */
7870 ctx->base.is_jmp = DISAS_STOP;
7871 register_name = "TraceControl2";
7872 goto cp0_unimplemented;
7873 case CP0_REG23__USERTRACEDATA1:
7874 /* PDtrace support */
7875 /* gen_helper_mtc0_usertracedata1(tcg_env, arg);*/
7876 /* Stop translation as we may have switched the execution mode */
7877 ctx->base.is_jmp = DISAS_STOP;
7878 register_name = "UserTraceData1";
7879 goto cp0_unimplemented;
7880 case CP0_REG23__TRACEIBPC:
7881 /* PDtrace support */
7882 /* gen_helper_mtc0_traceibpc(tcg_env, arg); */
7883 /* Stop translation as we may have switched the execution mode */
7884 ctx->base.is_jmp = DISAS_STOP;
7885 register_name = "TraceIBPC";
7886 goto cp0_unimplemented;
7887 case CP0_REG23__TRACEDBPC:
7888 /* PDtrace support */
7889 /* gen_helper_mtc0_tracedbpc(tcg_env, arg); */
7890 /* Stop translation as we may have switched the execution mode */
7891 ctx->base.is_jmp = DISAS_STOP;
7892 register_name = "TraceDBPC";
7893 goto cp0_unimplemented;
7894 default:
7895 goto cp0_unimplemented;
7896 }
7897 break;
7898 case CP0_REGISTER_24:
7899 switch (sel) {
7900 case CP0_REG24__DEPC:
7901 /* EJTAG support */
7902 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_DEPC));
7903 register_name = "DEPC";
7904 break;
7905 default:
7906 goto cp0_unimplemented;
7907 }
7908 break;
7909 case CP0_REGISTER_25:
7910 switch (sel) {
7911 case CP0_REG25__PERFCTL0:
7912 gen_helper_mtc0_performance0(tcg_env, arg);
7913 register_name = "Performance0";
7914 break;
7915 case CP0_REG25__PERFCNT0:
7916 /* gen_helper_mtc0_performance1(tcg_env, arg); */
7917 register_name = "Performance1";
7918 goto cp0_unimplemented;
7919 case CP0_REG25__PERFCTL1:
7920 /* gen_helper_mtc0_performance2(tcg_env, arg); */
7921 register_name = "Performance2";
7922 goto cp0_unimplemented;
7923 case CP0_REG25__PERFCNT1:
7924 /* gen_helper_mtc0_performance3(tcg_env, arg); */
7925 register_name = "Performance3";
7926 goto cp0_unimplemented;
7927 case CP0_REG25__PERFCTL2:
7928 /* gen_helper_mtc0_performance4(tcg_env, arg); */
7929 register_name = "Performance4";
7930 goto cp0_unimplemented;
7931 case CP0_REG25__PERFCNT2:
7932 /* gen_helper_mtc0_performance5(tcg_env, arg); */
7933 register_name = "Performance5";
7934 goto cp0_unimplemented;
7935 case CP0_REG25__PERFCTL3:
7936 /* gen_helper_mtc0_performance6(tcg_env, arg); */
7937 register_name = "Performance6";
7938 goto cp0_unimplemented;
7939 case CP0_REG25__PERFCNT3:
7940 /* gen_helper_mtc0_performance7(tcg_env, arg); */
7941 register_name = "Performance7";
7942 goto cp0_unimplemented;
7943 default:
7944 goto cp0_unimplemented;
7945 }
7946 break;
7947 case CP0_REGISTER_26:
7948 switch (sel) {
7949 case CP0_REG26__ERRCTL:
7950 gen_helper_mtc0_errctl(tcg_env, arg);
7951 ctx->base.is_jmp = DISAS_STOP;
7952 register_name = "ErrCtl";
7953 break;
7954 default:
7955 goto cp0_unimplemented;
7956 }
7957 break;
7958 case CP0_REGISTER_27:
7959 switch (sel) {
7960 case CP0_REG27__CACHERR:
7961 /* ignored */
7962 register_name = "CacheErr";
7963 break;
7964 default:
7965 goto cp0_unimplemented;
7966 }
7967 break;
7968 case CP0_REGISTER_28:
7969 switch (sel) {
7970 case CP0_REG28__TAGLO:
7971 case CP0_REG28__TAGLO1:
7972 case CP0_REG28__TAGLO2:
7973 case CP0_REG28__TAGLO3:
7974 gen_helper_mtc0_taglo(tcg_env, arg);
7975 register_name = "TagLo";
7976 break;
7977 case CP0_REG28__DATALO:
7978 case CP0_REG28__DATALO1:
7979 case CP0_REG28__DATALO2:
7980 case CP0_REG28__DATALO3:
7981 gen_helper_mtc0_datalo(tcg_env, arg);
7982 register_name = "DataLo";
7983 break;
7984 default:
7985 goto cp0_unimplemented;
7986 }
7987 break;
7988 case CP0_REGISTER_29:
7989 switch (sel) {
7990 case CP0_REG29__TAGHI:
7991 case CP0_REG29__TAGHI1:
7992 case CP0_REG29__TAGHI2:
7993 case CP0_REG29__TAGHI3:
7994 gen_helper_mtc0_taghi(tcg_env, arg);
7995 register_name = "TagHi";
7996 break;
7997 case CP0_REG29__DATAHI:
7998 case CP0_REG29__DATAHI1:
7999 case CP0_REG29__DATAHI2:
8000 case CP0_REG29__DATAHI3:
8001 gen_helper_mtc0_datahi(tcg_env, arg);
8002 register_name = "DataHi";
8003 break;
8004 default:
8005 register_name = "invalid sel";
8006 goto cp0_unimplemented;
8007 }
8008 break;
8009 case CP0_REGISTER_30:
8010 switch (sel) {
8011 case CP0_REG30__ERROREPC:
8012 tcg_gen_st_tl(arg, tcg_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
8013 register_name = "ErrorEPC";
8014 break;
8015 default:
8016 goto cp0_unimplemented;
8017 }
8018 break;
8019 case CP0_REGISTER_31:
8020 switch (sel) {
8021 case CP0_REG31__DESAVE:
8022 /* EJTAG support */
8023 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
8024 register_name = "DESAVE";
8025 break;
8026 case CP0_REG31__KSCRATCH1:
8027 case CP0_REG31__KSCRATCH2:
8028 case CP0_REG31__KSCRATCH3:
8029 case CP0_REG31__KSCRATCH4:
8030 case CP0_REG31__KSCRATCH5:
8031 case CP0_REG31__KSCRATCH6:
8032 CP0_CHECK(ctx->kscrexist & (1 << sel));
8033 tcg_gen_st_tl(arg, tcg_env,
8034 offsetof(CPUMIPSState, CP0_KScratch[sel - 2]));
8035 register_name = "KScratch";
8036 break;
8037 default:
8038 goto cp0_unimplemented;
8039 }
8040 break;
8041 default:
8042 goto cp0_unimplemented;
8043 }
8044 trace_mips_translate_c0("dmtc0", register_name, reg, sel);
8045
8046 /* For simplicity assume that all writes can cause interrupts. */
8047 if (icount) {
8048 /*
8049 * DISAS_STOP isn't sufficient, we need to ensure we break out of
8050 * translated code to check for pending interrupts.
8051 */
8052 gen_save_pc(ctx->base.pc_next + 4);
8053 ctx->base.is_jmp = DISAS_EXIT;
8054 }
8055 return;
8056
8057 cp0_unimplemented:
8058 qemu_log_mask(LOG_UNIMP, "dmtc0 %s (reg %d sel %d)\n",
8059 register_name, reg, sel);
8060 }
8061 #endif /* TARGET_MIPS64 */
8062
gen_mftr(CPUMIPSState * env,DisasContext * ctx,int rt,int rd,int u,int sel,int h)8063 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
8064 int u, int sel, int h)
8065 {
8066 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8067 TCGv t0 = tcg_temp_new();
8068
8069 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8070 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8071 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8072 tcg_gen_movi_tl(t0, -1);
8073 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8074 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8075 tcg_gen_movi_tl(t0, -1);
8076 } else if (u == 0) {
8077 switch (rt) {
8078 case 1:
8079 switch (sel) {
8080 case 1:
8081 gen_helper_mftc0_vpecontrol(t0, tcg_env);
8082 break;
8083 case 2:
8084 gen_helper_mftc0_vpeconf0(t0, tcg_env);
8085 break;
8086 default:
8087 goto die;
8088 break;
8089 }
8090 break;
8091 case 2:
8092 switch (sel) {
8093 case 1:
8094 gen_helper_mftc0_tcstatus(t0, tcg_env);
8095 break;
8096 case 2:
8097 gen_helper_mftc0_tcbind(t0, tcg_env);
8098 break;
8099 case 3:
8100 gen_helper_mftc0_tcrestart(t0, tcg_env);
8101 break;
8102 case 4:
8103 gen_helper_mftc0_tchalt(t0, tcg_env);
8104 break;
8105 case 5:
8106 gen_helper_mftc0_tccontext(t0, tcg_env);
8107 break;
8108 case 6:
8109 gen_helper_mftc0_tcschedule(t0, tcg_env);
8110 break;
8111 case 7:
8112 gen_helper_mftc0_tcschefback(t0, tcg_env);
8113 break;
8114 default:
8115 gen_mfc0(ctx, t0, rt, sel);
8116 break;
8117 }
8118 break;
8119 case 10:
8120 switch (sel) {
8121 case 0:
8122 gen_helper_mftc0_entryhi(t0, tcg_env);
8123 break;
8124 default:
8125 gen_mfc0(ctx, t0, rt, sel);
8126 break;
8127 }
8128 break;
8129 case 12:
8130 switch (sel) {
8131 case 0:
8132 gen_helper_mftc0_status(t0, tcg_env);
8133 break;
8134 default:
8135 gen_mfc0(ctx, t0, rt, sel);
8136 break;
8137 }
8138 break;
8139 case 13:
8140 switch (sel) {
8141 case 0:
8142 gen_helper_mftc0_cause(t0, tcg_env);
8143 break;
8144 default:
8145 goto die;
8146 break;
8147 }
8148 break;
8149 case 14:
8150 switch (sel) {
8151 case 0:
8152 gen_helper_mftc0_epc(t0, tcg_env);
8153 break;
8154 default:
8155 goto die;
8156 break;
8157 }
8158 break;
8159 case 15:
8160 switch (sel) {
8161 case 1:
8162 gen_helper_mftc0_ebase(t0, tcg_env);
8163 break;
8164 default:
8165 goto die;
8166 break;
8167 }
8168 break;
8169 case 16:
8170 switch (sel) {
8171 case 0:
8172 case 1:
8173 case 2:
8174 case 3:
8175 case 4:
8176 case 5:
8177 case 6:
8178 case 7:
8179 gen_helper_mftc0_configx(t0, tcg_env, tcg_constant_tl(sel));
8180 break;
8181 default:
8182 goto die;
8183 break;
8184 }
8185 break;
8186 case 23:
8187 switch (sel) {
8188 case 0:
8189 gen_helper_mftc0_debug(t0, tcg_env);
8190 break;
8191 default:
8192 gen_mfc0(ctx, t0, rt, sel);
8193 break;
8194 }
8195 break;
8196 default:
8197 gen_mfc0(ctx, t0, rt, sel);
8198 }
8199 } else {
8200 switch (sel) {
8201 /* GPR registers. */
8202 case 0:
8203 gen_helper_1e0i(mftgpr, t0, rt);
8204 break;
8205 /* Auxiliary CPU registers */
8206 case 1:
8207 switch (rt) {
8208 case 0:
8209 gen_helper_1e0i(mftlo, t0, 0);
8210 break;
8211 case 1:
8212 gen_helper_1e0i(mfthi, t0, 0);
8213 break;
8214 case 2:
8215 gen_helper_1e0i(mftacx, t0, 0);
8216 break;
8217 case 4:
8218 gen_helper_1e0i(mftlo, t0, 1);
8219 break;
8220 case 5:
8221 gen_helper_1e0i(mfthi, t0, 1);
8222 break;
8223 case 6:
8224 gen_helper_1e0i(mftacx, t0, 1);
8225 break;
8226 case 8:
8227 gen_helper_1e0i(mftlo, t0, 2);
8228 break;
8229 case 9:
8230 gen_helper_1e0i(mfthi, t0, 2);
8231 break;
8232 case 10:
8233 gen_helper_1e0i(mftacx, t0, 2);
8234 break;
8235 case 12:
8236 gen_helper_1e0i(mftlo, t0, 3);
8237 break;
8238 case 13:
8239 gen_helper_1e0i(mfthi, t0, 3);
8240 break;
8241 case 14:
8242 gen_helper_1e0i(mftacx, t0, 3);
8243 break;
8244 case 16:
8245 gen_helper_mftdsp(t0, tcg_env);
8246 break;
8247 default:
8248 goto die;
8249 }
8250 break;
8251 /* Floating point (COP1). */
8252 case 2:
8253 /* XXX: For now we support only a single FPU context. */
8254 if (h == 0) {
8255 TCGv_i32 fp0 = tcg_temp_new_i32();
8256
8257 gen_load_fpr32(ctx, fp0, rt);
8258 tcg_gen_ext_i32_tl(t0, fp0);
8259 } else {
8260 TCGv_i32 fp0 = tcg_temp_new_i32();
8261
8262 gen_load_fpr32h(ctx, fp0, rt);
8263 tcg_gen_ext_i32_tl(t0, fp0);
8264 }
8265 break;
8266 case 3:
8267 /* XXX: For now we support only a single FPU context. */
8268 gen_helper_1e0i(cfc1, t0, rt);
8269 break;
8270 /* COP2: Not implemented. */
8271 case 4:
8272 case 5:
8273 /* fall through */
8274 default:
8275 goto die;
8276 }
8277 }
8278 trace_mips_translate_tr("mftr", rt, u, sel, h);
8279 gen_store_gpr(t0, rd);
8280 return;
8281
8282 die:
8283 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
8284 gen_reserved_instruction(ctx);
8285 }
8286
gen_mttr(CPUMIPSState * env,DisasContext * ctx,int rd,int rt,int u,int sel,int h)8287 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
8288 int u, int sel, int h)
8289 {
8290 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
8291 TCGv t0 = tcg_temp_new();
8292
8293 gen_load_gpr(t0, rt);
8294 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
8295 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
8296 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE)))) {
8297 /* NOP */
8298 ;
8299 } else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
8300 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC))) {
8301 /* NOP */
8302 ;
8303 } else if (u == 0) {
8304 switch (rd) {
8305 case 1:
8306 switch (sel) {
8307 case 1:
8308 gen_helper_mttc0_vpecontrol(tcg_env, t0);
8309 break;
8310 case 2:
8311 gen_helper_mttc0_vpeconf0(tcg_env, t0);
8312 break;
8313 default:
8314 goto die;
8315 break;
8316 }
8317 break;
8318 case 2:
8319 switch (sel) {
8320 case 1:
8321 gen_helper_mttc0_tcstatus(tcg_env, t0);
8322 break;
8323 case 2:
8324 gen_helper_mttc0_tcbind(tcg_env, t0);
8325 break;
8326 case 3:
8327 gen_helper_mttc0_tcrestart(tcg_env, t0);
8328 break;
8329 case 4:
8330 gen_helper_mttc0_tchalt(tcg_env, t0);
8331 break;
8332 case 5:
8333 gen_helper_mttc0_tccontext(tcg_env, t0);
8334 break;
8335 case 6:
8336 gen_helper_mttc0_tcschedule(tcg_env, t0);
8337 break;
8338 case 7:
8339 gen_helper_mttc0_tcschefback(tcg_env, t0);
8340 break;
8341 default:
8342 gen_mtc0(ctx, t0, rd, sel);
8343 break;
8344 }
8345 break;
8346 case 10:
8347 switch (sel) {
8348 case 0:
8349 gen_helper_mttc0_entryhi(tcg_env, t0);
8350 break;
8351 default:
8352 gen_mtc0(ctx, t0, rd, sel);
8353 break;
8354 }
8355 break;
8356 case 12:
8357 switch (sel) {
8358 case 0:
8359 gen_helper_mttc0_status(tcg_env, t0);
8360 break;
8361 default:
8362 gen_mtc0(ctx, t0, rd, sel);
8363 break;
8364 }
8365 break;
8366 case 13:
8367 switch (sel) {
8368 case 0:
8369 gen_helper_mttc0_cause(tcg_env, t0);
8370 break;
8371 default:
8372 goto die;
8373 break;
8374 }
8375 break;
8376 case 15:
8377 switch (sel) {
8378 case 1:
8379 gen_helper_mttc0_ebase(tcg_env, t0);
8380 break;
8381 default:
8382 goto die;
8383 break;
8384 }
8385 break;
8386 case 23:
8387 switch (sel) {
8388 case 0:
8389 gen_helper_mttc0_debug(tcg_env, t0);
8390 break;
8391 default:
8392 gen_mtc0(ctx, t0, rd, sel);
8393 break;
8394 }
8395 break;
8396 default:
8397 gen_mtc0(ctx, t0, rd, sel);
8398 }
8399 } else {
8400 switch (sel) {
8401 /* GPR registers. */
8402 case 0:
8403 gen_helper_0e1i(mttgpr, t0, rd);
8404 break;
8405 /* Auxiliary CPU registers */
8406 case 1:
8407 switch (rd) {
8408 case 0:
8409 gen_helper_0e1i(mttlo, t0, 0);
8410 break;
8411 case 1:
8412 gen_helper_0e1i(mtthi, t0, 0);
8413 break;
8414 case 2:
8415 gen_helper_0e1i(mttacx, t0, 0);
8416 break;
8417 case 4:
8418 gen_helper_0e1i(mttlo, t0, 1);
8419 break;
8420 case 5:
8421 gen_helper_0e1i(mtthi, t0, 1);
8422 break;
8423 case 6:
8424 gen_helper_0e1i(mttacx, t0, 1);
8425 break;
8426 case 8:
8427 gen_helper_0e1i(mttlo, t0, 2);
8428 break;
8429 case 9:
8430 gen_helper_0e1i(mtthi, t0, 2);
8431 break;
8432 case 10:
8433 gen_helper_0e1i(mttacx, t0, 2);
8434 break;
8435 case 12:
8436 gen_helper_0e1i(mttlo, t0, 3);
8437 break;
8438 case 13:
8439 gen_helper_0e1i(mtthi, t0, 3);
8440 break;
8441 case 14:
8442 gen_helper_0e1i(mttacx, t0, 3);
8443 break;
8444 case 16:
8445 gen_helper_mttdsp(tcg_env, t0);
8446 break;
8447 default:
8448 goto die;
8449 }
8450 break;
8451 /* Floating point (COP1). */
8452 case 2:
8453 /* XXX: For now we support only a single FPU context. */
8454 if (h == 0) {
8455 TCGv_i32 fp0 = tcg_temp_new_i32();
8456
8457 tcg_gen_trunc_tl_i32(fp0, t0);
8458 gen_store_fpr32(ctx, fp0, rd);
8459 } else {
8460 TCGv_i32 fp0 = tcg_temp_new_i32();
8461
8462 tcg_gen_trunc_tl_i32(fp0, t0);
8463 gen_store_fpr32h(ctx, fp0, rd);
8464 }
8465 break;
8466 case 3:
8467 /* XXX: For now we support only a single FPU context. */
8468 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(rd), rt);
8469 /* Stop translation as we may have changed hflags */
8470 ctx->base.is_jmp = DISAS_STOP;
8471 break;
8472 /* COP2: Not implemented. */
8473 case 4:
8474 case 5:
8475 /* fall through */
8476 default:
8477 goto die;
8478 }
8479 }
8480 trace_mips_translate_tr("mttr", rd, u, sel, h);
8481 return;
8482
8483 die:
8484 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
8485 gen_reserved_instruction(ctx);
8486 }
8487
gen_cp0(CPUMIPSState * env,DisasContext * ctx,uint32_t opc,int rt,int rd)8488 static void gen_cp0(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
8489 int rt, int rd)
8490 {
8491 const char *opn = "ldst";
8492
8493 check_cp0_enabled(ctx);
8494 switch (opc) {
8495 case OPC_MFC0:
8496 if (rt == 0) {
8497 /* Treat as NOP. */
8498 return;
8499 }
8500 gen_mfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8501 opn = "mfc0";
8502 break;
8503 case OPC_MTC0:
8504 {
8505 TCGv t0 = tcg_temp_new();
8506
8507 gen_load_gpr(t0, rt);
8508 gen_mtc0(ctx, t0, rd, ctx->opcode & 0x7);
8509 }
8510 opn = "mtc0";
8511 break;
8512 #if defined(TARGET_MIPS64)
8513 case OPC_DMFC0:
8514 check_insn(ctx, ISA_MIPS3);
8515 if (rt == 0) {
8516 /* Treat as NOP. */
8517 return;
8518 }
8519 gen_dmfc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8520 opn = "dmfc0";
8521 break;
8522 case OPC_DMTC0:
8523 check_insn(ctx, ISA_MIPS3);
8524 {
8525 TCGv t0 = tcg_temp_new();
8526
8527 gen_load_gpr(t0, rt);
8528 gen_dmtc0(ctx, t0, rd, ctx->opcode & 0x7);
8529 }
8530 opn = "dmtc0";
8531 break;
8532 #endif
8533 case OPC_MFHC0:
8534 check_mvh(ctx);
8535 if (rt == 0) {
8536 /* Treat as NOP. */
8537 return;
8538 }
8539 gen_mfhc0(ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
8540 opn = "mfhc0";
8541 break;
8542 case OPC_MTHC0:
8543 check_mvh(ctx);
8544 {
8545 TCGv t0 = tcg_temp_new();
8546 gen_load_gpr(t0, rt);
8547 gen_mthc0(ctx, t0, rd, ctx->opcode & 0x7);
8548 }
8549 opn = "mthc0";
8550 break;
8551 case OPC_MFTR:
8552 check_cp0_enabled(ctx);
8553 if (rd == 0) {
8554 /* Treat as NOP. */
8555 return;
8556 }
8557 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
8558 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8559 opn = "mftr";
8560 break;
8561 case OPC_MTTR:
8562 check_cp0_enabled(ctx);
8563 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
8564 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
8565 opn = "mttr";
8566 break;
8567 case OPC_TLBWI:
8568 opn = "tlbwi";
8569 if (!env->tlb->helper_tlbwi) {
8570 goto die;
8571 }
8572 gen_helper_tlbwi(tcg_env);
8573 break;
8574 case OPC_TLBINV:
8575 opn = "tlbinv";
8576 if (ctx->ie >= 2) {
8577 if (!env->tlb->helper_tlbinv) {
8578 goto die;
8579 }
8580 gen_helper_tlbinv(tcg_env);
8581 } /* treat as nop if TLBINV not supported */
8582 break;
8583 case OPC_TLBINVF:
8584 opn = "tlbinvf";
8585 if (ctx->ie >= 2) {
8586 if (!env->tlb->helper_tlbinvf) {
8587 goto die;
8588 }
8589 gen_helper_tlbinvf(tcg_env);
8590 } /* treat as nop if TLBINV not supported */
8591 break;
8592 case OPC_TLBWR:
8593 opn = "tlbwr";
8594 if (!env->tlb->helper_tlbwr) {
8595 goto die;
8596 }
8597 gen_helper_tlbwr(tcg_env);
8598 break;
8599 case OPC_TLBP:
8600 opn = "tlbp";
8601 if (!env->tlb->helper_tlbp) {
8602 goto die;
8603 }
8604 gen_helper_tlbp(tcg_env);
8605 break;
8606 case OPC_TLBR:
8607 opn = "tlbr";
8608 if (!env->tlb->helper_tlbr) {
8609 goto die;
8610 }
8611 gen_helper_tlbr(tcg_env);
8612 break;
8613 case OPC_ERET: /* OPC_ERETNC */
8614 if ((ctx->insn_flags & ISA_MIPS_R6) &&
8615 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8616 goto die;
8617 } else {
8618 int bit_shift = (ctx->hflags & MIPS_HFLAG_M16) ? 16 : 6;
8619 if (ctx->opcode & (1 << bit_shift)) {
8620 /* OPC_ERETNC */
8621 opn = "eretnc";
8622 check_insn(ctx, ISA_MIPS_R5);
8623 gen_helper_eretnc(tcg_env);
8624 } else {
8625 /* OPC_ERET */
8626 opn = "eret";
8627 check_insn(ctx, ISA_MIPS2);
8628 gen_helper_eret(tcg_env);
8629 }
8630 ctx->base.is_jmp = DISAS_EXIT;
8631 }
8632 break;
8633 case OPC_DERET:
8634 opn = "deret";
8635 check_insn(ctx, ISA_MIPS_R1);
8636 if ((ctx->insn_flags & ISA_MIPS_R6) &&
8637 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8638 goto die;
8639 }
8640 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
8641 MIPS_INVAL(opn);
8642 gen_reserved_instruction(ctx);
8643 } else {
8644 gen_helper_deret(tcg_env);
8645 ctx->base.is_jmp = DISAS_EXIT;
8646 }
8647 break;
8648 case OPC_WAIT:
8649 opn = "wait";
8650 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
8651 if ((ctx->insn_flags & ISA_MIPS_R6) &&
8652 (ctx->hflags & MIPS_HFLAG_BMASK)) {
8653 goto die;
8654 }
8655 /* If we get an exception, we want to restart at next instruction */
8656 ctx->base.pc_next += 4;
8657 save_cpu_state(ctx, 1);
8658 ctx->base.pc_next -= 4;
8659 gen_helper_wait(tcg_env);
8660 ctx->base.is_jmp = DISAS_NORETURN;
8661 break;
8662 default:
8663 die:
8664 MIPS_INVAL(opn);
8665 gen_reserved_instruction(ctx);
8666 return;
8667 }
8668 (void)opn; /* avoid a compiler warning */
8669 }
8670 #endif /* !CONFIG_USER_ONLY */
8671
8672 /* CP1 Branches (before delay slot) */
gen_compute_branch1(DisasContext * ctx,uint32_t op,int32_t cc,int32_t offset)8673 static void gen_compute_branch1(DisasContext *ctx, uint32_t op,
8674 int32_t cc, int32_t offset)
8675 {
8676 target_ulong btarget;
8677 TCGv_i32 t0 = tcg_temp_new_i32();
8678
8679 if ((ctx->insn_flags & ISA_MIPS_R6) && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8680 gen_reserved_instruction(ctx);
8681 return;
8682 }
8683
8684 if (cc != 0) {
8685 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
8686 }
8687
8688 btarget = ctx->base.pc_next + 4 + offset;
8689
8690 switch (op) {
8691 case OPC_BC1F:
8692 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8693 tcg_gen_not_i32(t0, t0);
8694 tcg_gen_andi_i32(t0, t0, 1);
8695 tcg_gen_extu_i32_tl(bcond, t0);
8696 goto not_likely;
8697 case OPC_BC1FL:
8698 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8699 tcg_gen_not_i32(t0, t0);
8700 tcg_gen_andi_i32(t0, t0, 1);
8701 tcg_gen_extu_i32_tl(bcond, t0);
8702 goto likely;
8703 case OPC_BC1T:
8704 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8705 tcg_gen_andi_i32(t0, t0, 1);
8706 tcg_gen_extu_i32_tl(bcond, t0);
8707 goto not_likely;
8708 case OPC_BC1TL:
8709 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8710 tcg_gen_andi_i32(t0, t0, 1);
8711 tcg_gen_extu_i32_tl(bcond, t0);
8712 likely:
8713 ctx->hflags |= MIPS_HFLAG_BL;
8714 break;
8715 case OPC_BC1FANY2:
8716 {
8717 TCGv_i32 t1 = tcg_temp_new_i32();
8718 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8719 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8720 tcg_gen_nand_i32(t0, t0, t1);
8721 tcg_gen_andi_i32(t0, t0, 1);
8722 tcg_gen_extu_i32_tl(bcond, t0);
8723 }
8724 goto not_likely;
8725 case OPC_BC1TANY2:
8726 {
8727 TCGv_i32 t1 = tcg_temp_new_i32();
8728 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8729 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8730 tcg_gen_or_i32(t0, t0, t1);
8731 tcg_gen_andi_i32(t0, t0, 1);
8732 tcg_gen_extu_i32_tl(bcond, t0);
8733 }
8734 goto not_likely;
8735 case OPC_BC1FANY4:
8736 {
8737 TCGv_i32 t1 = tcg_temp_new_i32();
8738 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8739 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8740 tcg_gen_and_i32(t0, t0, t1);
8741 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
8742 tcg_gen_and_i32(t0, t0, t1);
8743 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
8744 tcg_gen_nand_i32(t0, t0, t1);
8745 tcg_gen_andi_i32(t0, t0, 1);
8746 tcg_gen_extu_i32_tl(bcond, t0);
8747 }
8748 goto not_likely;
8749 case OPC_BC1TANY4:
8750 {
8751 TCGv_i32 t1 = tcg_temp_new_i32();
8752 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
8753 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 1));
8754 tcg_gen_or_i32(t0, t0, t1);
8755 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 2));
8756 tcg_gen_or_i32(t0, t0, t1);
8757 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc + 3));
8758 tcg_gen_or_i32(t0, t0, t1);
8759 tcg_gen_andi_i32(t0, t0, 1);
8760 tcg_gen_extu_i32_tl(bcond, t0);
8761 }
8762 not_likely:
8763 ctx->hflags |= MIPS_HFLAG_BC;
8764 break;
8765 default:
8766 MIPS_INVAL("cp1 cond branch");
8767 gen_reserved_instruction(ctx);
8768 return;
8769 }
8770 ctx->btarget = btarget;
8771 ctx->hflags |= MIPS_HFLAG_BDS32;
8772 }
8773
8774 /* R6 CP1 Branches */
gen_compute_branch1_r6(DisasContext * ctx,uint32_t op,int32_t ft,int32_t offset,int delayslot_size)8775 static void gen_compute_branch1_r6(DisasContext *ctx, uint32_t op,
8776 int32_t ft, int32_t offset,
8777 int delayslot_size)
8778 {
8779 target_ulong btarget;
8780 TCGv_i64 t0 = tcg_temp_new_i64();
8781
8782 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8783 #ifdef MIPS_DEBUG_DISAS
8784 LOG_DISAS("Branch in delay / forbidden slot at PC 0x%016"
8785 VADDR_PRIx "\n", ctx->base.pc_next);
8786 #endif
8787 gen_reserved_instruction(ctx);
8788 return;
8789 }
8790
8791 gen_load_fpr64(ctx, t0, ft);
8792 tcg_gen_andi_i64(t0, t0, 1);
8793
8794 btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
8795
8796 switch (op) {
8797 case OPC_BC1EQZ:
8798 tcg_gen_xori_i64(t0, t0, 1);
8799 ctx->hflags |= MIPS_HFLAG_BC;
8800 break;
8801 case OPC_BC1NEZ:
8802 /* t0 already set */
8803 ctx->hflags |= MIPS_HFLAG_BC;
8804 break;
8805 default:
8806 MIPS_INVAL("cp1 cond branch");
8807 gen_reserved_instruction(ctx);
8808 return;
8809 }
8810
8811 tcg_gen_trunc_i64_tl(bcond, t0);
8812
8813 ctx->btarget = btarget;
8814
8815 switch (delayslot_size) {
8816 case 2:
8817 ctx->hflags |= MIPS_HFLAG_BDS16;
8818 break;
8819 case 4:
8820 ctx->hflags |= MIPS_HFLAG_BDS32;
8821 break;
8822 }
8823 }
8824
8825 /* Coprocessor 1 (FPU) */
8826
8827 #define FOP(func, fmt) (((fmt) << 21) | (func))
8828
8829 enum fopcode {
8830 OPC_ADD_S = FOP(0, FMT_S),
8831 OPC_SUB_S = FOP(1, FMT_S),
8832 OPC_MUL_S = FOP(2, FMT_S),
8833 OPC_DIV_S = FOP(3, FMT_S),
8834 OPC_SQRT_S = FOP(4, FMT_S),
8835 OPC_ABS_S = FOP(5, FMT_S),
8836 OPC_MOV_S = FOP(6, FMT_S),
8837 OPC_NEG_S = FOP(7, FMT_S),
8838 OPC_ROUND_L_S = FOP(8, FMT_S),
8839 OPC_TRUNC_L_S = FOP(9, FMT_S),
8840 OPC_CEIL_L_S = FOP(10, FMT_S),
8841 OPC_FLOOR_L_S = FOP(11, FMT_S),
8842 OPC_ROUND_W_S = FOP(12, FMT_S),
8843 OPC_TRUNC_W_S = FOP(13, FMT_S),
8844 OPC_CEIL_W_S = FOP(14, FMT_S),
8845 OPC_FLOOR_W_S = FOP(15, FMT_S),
8846 OPC_SEL_S = FOP(16, FMT_S),
8847 OPC_MOVCF_S = FOP(17, FMT_S),
8848 OPC_MOVZ_S = FOP(18, FMT_S),
8849 OPC_MOVN_S = FOP(19, FMT_S),
8850 OPC_SELEQZ_S = FOP(20, FMT_S),
8851 OPC_RECIP_S = FOP(21, FMT_S),
8852 OPC_RSQRT_S = FOP(22, FMT_S),
8853 OPC_SELNEZ_S = FOP(23, FMT_S),
8854 OPC_MADDF_S = FOP(24, FMT_S),
8855 OPC_MSUBF_S = FOP(25, FMT_S),
8856 OPC_RINT_S = FOP(26, FMT_S),
8857 OPC_CLASS_S = FOP(27, FMT_S),
8858 OPC_MIN_S = FOP(28, FMT_S),
8859 OPC_RECIP2_S = FOP(28, FMT_S),
8860 OPC_MINA_S = FOP(29, FMT_S),
8861 OPC_RECIP1_S = FOP(29, FMT_S),
8862 OPC_MAX_S = FOP(30, FMT_S),
8863 OPC_RSQRT1_S = FOP(30, FMT_S),
8864 OPC_MAXA_S = FOP(31, FMT_S),
8865 OPC_RSQRT2_S = FOP(31, FMT_S),
8866 OPC_CVT_D_S = FOP(33, FMT_S),
8867 OPC_CVT_W_S = FOP(36, FMT_S),
8868 OPC_CVT_L_S = FOP(37, FMT_S),
8869 OPC_CVT_PS_S = FOP(38, FMT_S),
8870 OPC_CMP_F_S = FOP(48, FMT_S),
8871 OPC_CMP_UN_S = FOP(49, FMT_S),
8872 OPC_CMP_EQ_S = FOP(50, FMT_S),
8873 OPC_CMP_UEQ_S = FOP(51, FMT_S),
8874 OPC_CMP_OLT_S = FOP(52, FMT_S),
8875 OPC_CMP_ULT_S = FOP(53, FMT_S),
8876 OPC_CMP_OLE_S = FOP(54, FMT_S),
8877 OPC_CMP_ULE_S = FOP(55, FMT_S),
8878 OPC_CMP_SF_S = FOP(56, FMT_S),
8879 OPC_CMP_NGLE_S = FOP(57, FMT_S),
8880 OPC_CMP_SEQ_S = FOP(58, FMT_S),
8881 OPC_CMP_NGL_S = FOP(59, FMT_S),
8882 OPC_CMP_LT_S = FOP(60, FMT_S),
8883 OPC_CMP_NGE_S = FOP(61, FMT_S),
8884 OPC_CMP_LE_S = FOP(62, FMT_S),
8885 OPC_CMP_NGT_S = FOP(63, FMT_S),
8886
8887 OPC_ADD_D = FOP(0, FMT_D),
8888 OPC_SUB_D = FOP(1, FMT_D),
8889 OPC_MUL_D = FOP(2, FMT_D),
8890 OPC_DIV_D = FOP(3, FMT_D),
8891 OPC_SQRT_D = FOP(4, FMT_D),
8892 OPC_ABS_D = FOP(5, FMT_D),
8893 OPC_MOV_D = FOP(6, FMT_D),
8894 OPC_NEG_D = FOP(7, FMT_D),
8895 OPC_ROUND_L_D = FOP(8, FMT_D),
8896 OPC_TRUNC_L_D = FOP(9, FMT_D),
8897 OPC_CEIL_L_D = FOP(10, FMT_D),
8898 OPC_FLOOR_L_D = FOP(11, FMT_D),
8899 OPC_ROUND_W_D = FOP(12, FMT_D),
8900 OPC_TRUNC_W_D = FOP(13, FMT_D),
8901 OPC_CEIL_W_D = FOP(14, FMT_D),
8902 OPC_FLOOR_W_D = FOP(15, FMT_D),
8903 OPC_SEL_D = FOP(16, FMT_D),
8904 OPC_MOVCF_D = FOP(17, FMT_D),
8905 OPC_MOVZ_D = FOP(18, FMT_D),
8906 OPC_MOVN_D = FOP(19, FMT_D),
8907 OPC_SELEQZ_D = FOP(20, FMT_D),
8908 OPC_RECIP_D = FOP(21, FMT_D),
8909 OPC_RSQRT_D = FOP(22, FMT_D),
8910 OPC_SELNEZ_D = FOP(23, FMT_D),
8911 OPC_MADDF_D = FOP(24, FMT_D),
8912 OPC_MSUBF_D = FOP(25, FMT_D),
8913 OPC_RINT_D = FOP(26, FMT_D),
8914 OPC_CLASS_D = FOP(27, FMT_D),
8915 OPC_MIN_D = FOP(28, FMT_D),
8916 OPC_RECIP2_D = FOP(28, FMT_D),
8917 OPC_MINA_D = FOP(29, FMT_D),
8918 OPC_RECIP1_D = FOP(29, FMT_D),
8919 OPC_MAX_D = FOP(30, FMT_D),
8920 OPC_RSQRT1_D = FOP(30, FMT_D),
8921 OPC_MAXA_D = FOP(31, FMT_D),
8922 OPC_RSQRT2_D = FOP(31, FMT_D),
8923 OPC_CVT_S_D = FOP(32, FMT_D),
8924 OPC_CVT_W_D = FOP(36, FMT_D),
8925 OPC_CVT_L_D = FOP(37, FMT_D),
8926 OPC_CMP_F_D = FOP(48, FMT_D),
8927 OPC_CMP_UN_D = FOP(49, FMT_D),
8928 OPC_CMP_EQ_D = FOP(50, FMT_D),
8929 OPC_CMP_UEQ_D = FOP(51, FMT_D),
8930 OPC_CMP_OLT_D = FOP(52, FMT_D),
8931 OPC_CMP_ULT_D = FOP(53, FMT_D),
8932 OPC_CMP_OLE_D = FOP(54, FMT_D),
8933 OPC_CMP_ULE_D = FOP(55, FMT_D),
8934 OPC_CMP_SF_D = FOP(56, FMT_D),
8935 OPC_CMP_NGLE_D = FOP(57, FMT_D),
8936 OPC_CMP_SEQ_D = FOP(58, FMT_D),
8937 OPC_CMP_NGL_D = FOP(59, FMT_D),
8938 OPC_CMP_LT_D = FOP(60, FMT_D),
8939 OPC_CMP_NGE_D = FOP(61, FMT_D),
8940 OPC_CMP_LE_D = FOP(62, FMT_D),
8941 OPC_CMP_NGT_D = FOP(63, FMT_D),
8942
8943 OPC_CVT_S_W = FOP(32, FMT_W),
8944 OPC_CVT_D_W = FOP(33, FMT_W),
8945 OPC_CVT_S_L = FOP(32, FMT_L),
8946 OPC_CVT_D_L = FOP(33, FMT_L),
8947 OPC_CVT_PS_PW = FOP(38, FMT_W),
8948
8949 OPC_ADD_PS = FOP(0, FMT_PS),
8950 OPC_SUB_PS = FOP(1, FMT_PS),
8951 OPC_MUL_PS = FOP(2, FMT_PS),
8952 OPC_DIV_PS = FOP(3, FMT_PS),
8953 OPC_ABS_PS = FOP(5, FMT_PS),
8954 OPC_MOV_PS = FOP(6, FMT_PS),
8955 OPC_NEG_PS = FOP(7, FMT_PS),
8956 OPC_MOVCF_PS = FOP(17, FMT_PS),
8957 OPC_MOVZ_PS = FOP(18, FMT_PS),
8958 OPC_MOVN_PS = FOP(19, FMT_PS),
8959 OPC_ADDR_PS = FOP(24, FMT_PS),
8960 OPC_MULR_PS = FOP(26, FMT_PS),
8961 OPC_RECIP2_PS = FOP(28, FMT_PS),
8962 OPC_RECIP1_PS = FOP(29, FMT_PS),
8963 OPC_RSQRT1_PS = FOP(30, FMT_PS),
8964 OPC_RSQRT2_PS = FOP(31, FMT_PS),
8965
8966 OPC_CVT_S_PU = FOP(32, FMT_PS),
8967 OPC_CVT_PW_PS = FOP(36, FMT_PS),
8968 OPC_CVT_S_PL = FOP(40, FMT_PS),
8969 OPC_PLL_PS = FOP(44, FMT_PS),
8970 OPC_PLU_PS = FOP(45, FMT_PS),
8971 OPC_PUL_PS = FOP(46, FMT_PS),
8972 OPC_PUU_PS = FOP(47, FMT_PS),
8973 OPC_CMP_F_PS = FOP(48, FMT_PS),
8974 OPC_CMP_UN_PS = FOP(49, FMT_PS),
8975 OPC_CMP_EQ_PS = FOP(50, FMT_PS),
8976 OPC_CMP_UEQ_PS = FOP(51, FMT_PS),
8977 OPC_CMP_OLT_PS = FOP(52, FMT_PS),
8978 OPC_CMP_ULT_PS = FOP(53, FMT_PS),
8979 OPC_CMP_OLE_PS = FOP(54, FMT_PS),
8980 OPC_CMP_ULE_PS = FOP(55, FMT_PS),
8981 OPC_CMP_SF_PS = FOP(56, FMT_PS),
8982 OPC_CMP_NGLE_PS = FOP(57, FMT_PS),
8983 OPC_CMP_SEQ_PS = FOP(58, FMT_PS),
8984 OPC_CMP_NGL_PS = FOP(59, FMT_PS),
8985 OPC_CMP_LT_PS = FOP(60, FMT_PS),
8986 OPC_CMP_NGE_PS = FOP(61, FMT_PS),
8987 OPC_CMP_LE_PS = FOP(62, FMT_PS),
8988 OPC_CMP_NGT_PS = FOP(63, FMT_PS),
8989 };
8990
8991 enum r6_f_cmp_op {
8992 R6_OPC_CMP_AF_S = FOP(0, FMT_W),
8993 R6_OPC_CMP_UN_S = FOP(1, FMT_W),
8994 R6_OPC_CMP_EQ_S = FOP(2, FMT_W),
8995 R6_OPC_CMP_UEQ_S = FOP(3, FMT_W),
8996 R6_OPC_CMP_LT_S = FOP(4, FMT_W),
8997 R6_OPC_CMP_ULT_S = FOP(5, FMT_W),
8998 R6_OPC_CMP_LE_S = FOP(6, FMT_W),
8999 R6_OPC_CMP_ULE_S = FOP(7, FMT_W),
9000 R6_OPC_CMP_SAF_S = FOP(8, FMT_W),
9001 R6_OPC_CMP_SUN_S = FOP(9, FMT_W),
9002 R6_OPC_CMP_SEQ_S = FOP(10, FMT_W),
9003 R6_OPC_CMP_SEUQ_S = FOP(11, FMT_W),
9004 R6_OPC_CMP_SLT_S = FOP(12, FMT_W),
9005 R6_OPC_CMP_SULT_S = FOP(13, FMT_W),
9006 R6_OPC_CMP_SLE_S = FOP(14, FMT_W),
9007 R6_OPC_CMP_SULE_S = FOP(15, FMT_W),
9008 R6_OPC_CMP_OR_S = FOP(17, FMT_W),
9009 R6_OPC_CMP_UNE_S = FOP(18, FMT_W),
9010 R6_OPC_CMP_NE_S = FOP(19, FMT_W),
9011 R6_OPC_CMP_SOR_S = FOP(25, FMT_W),
9012 R6_OPC_CMP_SUNE_S = FOP(26, FMT_W),
9013 R6_OPC_CMP_SNE_S = FOP(27, FMT_W),
9014
9015 R6_OPC_CMP_AF_D = FOP(0, FMT_L),
9016 R6_OPC_CMP_UN_D = FOP(1, FMT_L),
9017 R6_OPC_CMP_EQ_D = FOP(2, FMT_L),
9018 R6_OPC_CMP_UEQ_D = FOP(3, FMT_L),
9019 R6_OPC_CMP_LT_D = FOP(4, FMT_L),
9020 R6_OPC_CMP_ULT_D = FOP(5, FMT_L),
9021 R6_OPC_CMP_LE_D = FOP(6, FMT_L),
9022 R6_OPC_CMP_ULE_D = FOP(7, FMT_L),
9023 R6_OPC_CMP_SAF_D = FOP(8, FMT_L),
9024 R6_OPC_CMP_SUN_D = FOP(9, FMT_L),
9025 R6_OPC_CMP_SEQ_D = FOP(10, FMT_L),
9026 R6_OPC_CMP_SEUQ_D = FOP(11, FMT_L),
9027 R6_OPC_CMP_SLT_D = FOP(12, FMT_L),
9028 R6_OPC_CMP_SULT_D = FOP(13, FMT_L),
9029 R6_OPC_CMP_SLE_D = FOP(14, FMT_L),
9030 R6_OPC_CMP_SULE_D = FOP(15, FMT_L),
9031 R6_OPC_CMP_OR_D = FOP(17, FMT_L),
9032 R6_OPC_CMP_UNE_D = FOP(18, FMT_L),
9033 R6_OPC_CMP_NE_D = FOP(19, FMT_L),
9034 R6_OPC_CMP_SOR_D = FOP(25, FMT_L),
9035 R6_OPC_CMP_SUNE_D = FOP(26, FMT_L),
9036 R6_OPC_CMP_SNE_D = FOP(27, FMT_L),
9037 };
9038
gen_cp1(DisasContext * ctx,uint32_t opc,int rt,int fs)9039 static void gen_cp1(DisasContext *ctx, uint32_t opc, int rt, int fs)
9040 {
9041 TCGv t0 = tcg_temp_new();
9042
9043 switch (opc) {
9044 case OPC_MFC1:
9045 {
9046 TCGv_i32 fp0 = tcg_temp_new_i32();
9047
9048 gen_load_fpr32(ctx, fp0, fs);
9049 tcg_gen_ext_i32_tl(t0, fp0);
9050 }
9051 gen_store_gpr(t0, rt);
9052 break;
9053 case OPC_MTC1:
9054 gen_load_gpr(t0, rt);
9055 {
9056 TCGv_i32 fp0 = tcg_temp_new_i32();
9057
9058 tcg_gen_trunc_tl_i32(fp0, t0);
9059 gen_store_fpr32(ctx, fp0, fs);
9060 }
9061 break;
9062 case OPC_CFC1:
9063 gen_helper_1e0i(cfc1, t0, fs);
9064 gen_store_gpr(t0, rt);
9065 break;
9066 case OPC_CTC1:
9067 gen_load_gpr(t0, rt);
9068 save_cpu_state(ctx, 0);
9069 gen_helper_0e2i(ctc1, t0, tcg_constant_i32(fs), rt);
9070 /* Stop translation as we may have changed hflags */
9071 ctx->base.is_jmp = DISAS_STOP;
9072 break;
9073 #if defined(TARGET_MIPS64)
9074 case OPC_DMFC1:
9075 gen_load_fpr64(ctx, t0, fs);
9076 gen_store_gpr(t0, rt);
9077 break;
9078 case OPC_DMTC1:
9079 gen_load_gpr(t0, rt);
9080 gen_store_fpr64(ctx, t0, fs);
9081 break;
9082 #endif
9083 case OPC_MFHC1:
9084 {
9085 TCGv_i32 fp0 = tcg_temp_new_i32();
9086
9087 gen_load_fpr32h(ctx, fp0, fs);
9088 tcg_gen_ext_i32_tl(t0, fp0);
9089 }
9090 gen_store_gpr(t0, rt);
9091 break;
9092 case OPC_MTHC1:
9093 gen_load_gpr(t0, rt);
9094 {
9095 TCGv_i32 fp0 = tcg_temp_new_i32();
9096
9097 tcg_gen_trunc_tl_i32(fp0, t0);
9098 gen_store_fpr32h(ctx, fp0, fs);
9099 }
9100 break;
9101 default:
9102 MIPS_INVAL("cp1 move");
9103 gen_reserved_instruction(ctx);
9104 return;
9105 }
9106 }
9107
gen_movci(DisasContext * ctx,int rd,int rs,int cc,int tf)9108 static void gen_movci(DisasContext *ctx, int rd, int rs, int cc, int tf)
9109 {
9110 TCGLabel *l1;
9111 TCGCond cond;
9112 TCGv_i32 t0;
9113
9114 if (rd == 0) {
9115 /* Treat as NOP. */
9116 return;
9117 }
9118
9119 if (tf) {
9120 cond = TCG_COND_EQ;
9121 } else {
9122 cond = TCG_COND_NE;
9123 }
9124
9125 l1 = gen_new_label();
9126 t0 = tcg_temp_new_i32();
9127 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9128 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9129 gen_load_gpr(cpu_gpr[rd], rs);
9130 gen_set_label(l1);
9131 }
9132
gen_movcf_s(DisasContext * ctx,int fs,int fd,int cc,int tf)9133 static inline void gen_movcf_s(DisasContext *ctx, int fs, int fd, int cc,
9134 int tf)
9135 {
9136 int cond;
9137 TCGv_i32 t0 = tcg_temp_new_i32();
9138 TCGLabel *l1 = gen_new_label();
9139
9140 if (tf) {
9141 cond = TCG_COND_EQ;
9142 } else {
9143 cond = TCG_COND_NE;
9144 }
9145
9146 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9147 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9148 gen_load_fpr32(ctx, t0, fs);
9149 gen_store_fpr32(ctx, t0, fd);
9150 gen_set_label(l1);
9151 }
9152
gen_movcf_d(DisasContext * ctx,int fs,int fd,int cc,int tf)9153 static inline void gen_movcf_d(DisasContext *ctx, int fs, int fd, int cc,
9154 int tf)
9155 {
9156 int cond;
9157 TCGv_i32 t0 = tcg_temp_new_i32();
9158 TCGv_i64 fp0;
9159 TCGLabel *l1 = gen_new_label();
9160
9161 if (tf) {
9162 cond = TCG_COND_EQ;
9163 } else {
9164 cond = TCG_COND_NE;
9165 }
9166
9167 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9168 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9169 fp0 = tcg_temp_new_i64();
9170 gen_load_fpr64(ctx, fp0, fs);
9171 gen_store_fpr64(ctx, fp0, fd);
9172 gen_set_label(l1);
9173 }
9174
gen_movcf_ps(DisasContext * ctx,int fs,int fd,int cc,int tf)9175 static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
9176 int cc, int tf)
9177 {
9178 int cond;
9179 TCGv_i32 t0 = tcg_temp_new_i32();
9180 TCGLabel *l1 = gen_new_label();
9181 TCGLabel *l2 = gen_new_label();
9182
9183 if (tf) {
9184 cond = TCG_COND_EQ;
9185 } else {
9186 cond = TCG_COND_NE;
9187 }
9188
9189 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
9190 tcg_gen_brcondi_i32(cond, t0, 0, l1);
9191 gen_load_fpr32(ctx, t0, fs);
9192 gen_store_fpr32(ctx, t0, fd);
9193 gen_set_label(l1);
9194
9195 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc + 1));
9196 tcg_gen_brcondi_i32(cond, t0, 0, l2);
9197 gen_load_fpr32h(ctx, t0, fs);
9198 gen_store_fpr32h(ctx, t0, fd);
9199 gen_set_label(l2);
9200 }
9201
gen_sel_s(DisasContext * ctx,enum fopcode op1,int fd,int ft,int fs)9202 static void gen_sel_s(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9203 int fs)
9204 {
9205 TCGv_i32 t1 = tcg_constant_i32(0);
9206 TCGv_i32 fp0 = tcg_temp_new_i32();
9207 TCGv_i32 fp1 = tcg_temp_new_i32();
9208 TCGv_i32 fp2 = tcg_temp_new_i32();
9209 gen_load_fpr32(ctx, fp0, fd);
9210 gen_load_fpr32(ctx, fp1, ft);
9211 gen_load_fpr32(ctx, fp2, fs);
9212
9213 switch (op1) {
9214 case OPC_SEL_S:
9215 tcg_gen_andi_i32(fp0, fp0, 1);
9216 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9217 break;
9218 case OPC_SELEQZ_S:
9219 tcg_gen_andi_i32(fp1, fp1, 1);
9220 tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9221 break;
9222 case OPC_SELNEZ_S:
9223 tcg_gen_andi_i32(fp1, fp1, 1);
9224 tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9225 break;
9226 default:
9227 MIPS_INVAL("gen_sel_s");
9228 gen_reserved_instruction(ctx);
9229 break;
9230 }
9231
9232 gen_store_fpr32(ctx, fp0, fd);
9233 }
9234
gen_sel_d(DisasContext * ctx,enum fopcode op1,int fd,int ft,int fs)9235 static void gen_sel_d(DisasContext *ctx, enum fopcode op1, int fd, int ft,
9236 int fs)
9237 {
9238 TCGv_i64 t1 = tcg_constant_i64(0);
9239 TCGv_i64 fp0 = tcg_temp_new_i64();
9240 TCGv_i64 fp1 = tcg_temp_new_i64();
9241 TCGv_i64 fp2 = tcg_temp_new_i64();
9242 gen_load_fpr64(ctx, fp0, fd);
9243 gen_load_fpr64(ctx, fp1, ft);
9244 gen_load_fpr64(ctx, fp2, fs);
9245
9246 switch (op1) {
9247 case OPC_SEL_D:
9248 tcg_gen_andi_i64(fp0, fp0, 1);
9249 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
9250 break;
9251 case OPC_SELEQZ_D:
9252 tcg_gen_andi_i64(fp1, fp1, 1);
9253 tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
9254 break;
9255 case OPC_SELNEZ_D:
9256 tcg_gen_andi_i64(fp1, fp1, 1);
9257 tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
9258 break;
9259 default:
9260 MIPS_INVAL("gen_sel_d");
9261 gen_reserved_instruction(ctx);
9262 break;
9263 }
9264
9265 gen_store_fpr64(ctx, fp0, fd);
9266 }
9267
gen_farith(DisasContext * ctx,enum fopcode op1,int ft,int fs,int fd,int cc)9268 static void gen_farith(DisasContext *ctx, enum fopcode op1,
9269 int ft, int fs, int fd, int cc)
9270 {
9271 uint32_t func = ctx->opcode & 0x3f;
9272 switch (op1) {
9273 case OPC_ADD_S:
9274 {
9275 TCGv_i32 fp0 = tcg_temp_new_i32();
9276 TCGv_i32 fp1 = tcg_temp_new_i32();
9277
9278 gen_load_fpr32(ctx, fp0, fs);
9279 gen_load_fpr32(ctx, fp1, ft);
9280 gen_helper_float_add_s(fp0, tcg_env, fp0, fp1);
9281 gen_store_fpr32(ctx, fp0, fd);
9282 }
9283 break;
9284 case OPC_SUB_S:
9285 {
9286 TCGv_i32 fp0 = tcg_temp_new_i32();
9287 TCGv_i32 fp1 = tcg_temp_new_i32();
9288
9289 gen_load_fpr32(ctx, fp0, fs);
9290 gen_load_fpr32(ctx, fp1, ft);
9291 gen_helper_float_sub_s(fp0, tcg_env, fp0, fp1);
9292 gen_store_fpr32(ctx, fp0, fd);
9293 }
9294 break;
9295 case OPC_MUL_S:
9296 {
9297 TCGv_i32 fp0 = tcg_temp_new_i32();
9298 TCGv_i32 fp1 = tcg_temp_new_i32();
9299
9300 gen_load_fpr32(ctx, fp0, fs);
9301 gen_load_fpr32(ctx, fp1, ft);
9302 gen_helper_float_mul_s(fp0, tcg_env, fp0, fp1);
9303 gen_store_fpr32(ctx, fp0, fd);
9304 }
9305 break;
9306 case OPC_DIV_S:
9307 {
9308 TCGv_i32 fp0 = tcg_temp_new_i32();
9309 TCGv_i32 fp1 = tcg_temp_new_i32();
9310
9311 gen_load_fpr32(ctx, fp0, fs);
9312 gen_load_fpr32(ctx, fp1, ft);
9313 gen_helper_float_div_s(fp0, tcg_env, fp0, fp1);
9314 gen_store_fpr32(ctx, fp0, fd);
9315 }
9316 break;
9317 case OPC_SQRT_S:
9318 {
9319 TCGv_i32 fp0 = tcg_temp_new_i32();
9320
9321 gen_load_fpr32(ctx, fp0, fs);
9322 gen_helper_float_sqrt_s(fp0, tcg_env, fp0);
9323 gen_store_fpr32(ctx, fp0, fd);
9324 }
9325 break;
9326 case OPC_ABS_S:
9327 {
9328 TCGv_i32 fp0 = tcg_temp_new_i32();
9329
9330 gen_load_fpr32(ctx, fp0, fs);
9331 if (ctx->abs2008) {
9332 tcg_gen_andi_i32(fp0, fp0, 0x7fffffffUL);
9333 } else {
9334 gen_helper_float_abs_s(fp0, fp0);
9335 }
9336 gen_store_fpr32(ctx, fp0, fd);
9337 }
9338 break;
9339 case OPC_MOV_S:
9340 {
9341 TCGv_i32 fp0 = tcg_temp_new_i32();
9342
9343 gen_load_fpr32(ctx, fp0, fs);
9344 gen_store_fpr32(ctx, fp0, fd);
9345 }
9346 break;
9347 case OPC_NEG_S:
9348 {
9349 TCGv_i32 fp0 = tcg_temp_new_i32();
9350
9351 gen_load_fpr32(ctx, fp0, fs);
9352 if (ctx->abs2008) {
9353 tcg_gen_xori_i32(fp0, fp0, 1UL << 31);
9354 } else {
9355 gen_helper_float_chs_s(fp0, fp0);
9356 }
9357 gen_store_fpr32(ctx, fp0, fd);
9358 }
9359 break;
9360 case OPC_ROUND_L_S:
9361 check_cp1_64bitmode(ctx);
9362 {
9363 TCGv_i32 fp32 = tcg_temp_new_i32();
9364 TCGv_i64 fp64 = tcg_temp_new_i64();
9365
9366 gen_load_fpr32(ctx, fp32, fs);
9367 if (ctx->nan2008) {
9368 gen_helper_float_round_2008_l_s(fp64, tcg_env, fp32);
9369 } else {
9370 gen_helper_float_round_l_s(fp64, tcg_env, fp32);
9371 }
9372 gen_store_fpr64(ctx, fp64, fd);
9373 }
9374 break;
9375 case OPC_TRUNC_L_S:
9376 check_cp1_64bitmode(ctx);
9377 {
9378 TCGv_i32 fp32 = tcg_temp_new_i32();
9379 TCGv_i64 fp64 = tcg_temp_new_i64();
9380
9381 gen_load_fpr32(ctx, fp32, fs);
9382 if (ctx->nan2008) {
9383 gen_helper_float_trunc_2008_l_s(fp64, tcg_env, fp32);
9384 } else {
9385 gen_helper_float_trunc_l_s(fp64, tcg_env, fp32);
9386 }
9387 gen_store_fpr64(ctx, fp64, fd);
9388 }
9389 break;
9390 case OPC_CEIL_L_S:
9391 check_cp1_64bitmode(ctx);
9392 {
9393 TCGv_i32 fp32 = tcg_temp_new_i32();
9394 TCGv_i64 fp64 = tcg_temp_new_i64();
9395
9396 gen_load_fpr32(ctx, fp32, fs);
9397 if (ctx->nan2008) {
9398 gen_helper_float_ceil_2008_l_s(fp64, tcg_env, fp32);
9399 } else {
9400 gen_helper_float_ceil_l_s(fp64, tcg_env, fp32);
9401 }
9402 gen_store_fpr64(ctx, fp64, fd);
9403 }
9404 break;
9405 case OPC_FLOOR_L_S:
9406 check_cp1_64bitmode(ctx);
9407 {
9408 TCGv_i32 fp32 = tcg_temp_new_i32();
9409 TCGv_i64 fp64 = tcg_temp_new_i64();
9410
9411 gen_load_fpr32(ctx, fp32, fs);
9412 if (ctx->nan2008) {
9413 gen_helper_float_floor_2008_l_s(fp64, tcg_env, fp32);
9414 } else {
9415 gen_helper_float_floor_l_s(fp64, tcg_env, fp32);
9416 }
9417 gen_store_fpr64(ctx, fp64, fd);
9418 }
9419 break;
9420 case OPC_ROUND_W_S:
9421 {
9422 TCGv_i32 fp0 = tcg_temp_new_i32();
9423
9424 gen_load_fpr32(ctx, fp0, fs);
9425 if (ctx->nan2008) {
9426 gen_helper_float_round_2008_w_s(fp0, tcg_env, fp0);
9427 } else {
9428 gen_helper_float_round_w_s(fp0, tcg_env, fp0);
9429 }
9430 gen_store_fpr32(ctx, fp0, fd);
9431 }
9432 break;
9433 case OPC_TRUNC_W_S:
9434 {
9435 TCGv_i32 fp0 = tcg_temp_new_i32();
9436
9437 gen_load_fpr32(ctx, fp0, fs);
9438 if (ctx->nan2008) {
9439 gen_helper_float_trunc_2008_w_s(fp0, tcg_env, fp0);
9440 } else {
9441 gen_helper_float_trunc_w_s(fp0, tcg_env, fp0);
9442 }
9443 gen_store_fpr32(ctx, fp0, fd);
9444 }
9445 break;
9446 case OPC_CEIL_W_S:
9447 {
9448 TCGv_i32 fp0 = tcg_temp_new_i32();
9449
9450 gen_load_fpr32(ctx, fp0, fs);
9451 if (ctx->nan2008) {
9452 gen_helper_float_ceil_2008_w_s(fp0, tcg_env, fp0);
9453 } else {
9454 gen_helper_float_ceil_w_s(fp0, tcg_env, fp0);
9455 }
9456 gen_store_fpr32(ctx, fp0, fd);
9457 }
9458 break;
9459 case OPC_FLOOR_W_S:
9460 {
9461 TCGv_i32 fp0 = tcg_temp_new_i32();
9462
9463 gen_load_fpr32(ctx, fp0, fs);
9464 if (ctx->nan2008) {
9465 gen_helper_float_floor_2008_w_s(fp0, tcg_env, fp0);
9466 } else {
9467 gen_helper_float_floor_w_s(fp0, tcg_env, fp0);
9468 }
9469 gen_store_fpr32(ctx, fp0, fd);
9470 }
9471 break;
9472 case OPC_SEL_S:
9473 check_insn(ctx, ISA_MIPS_R6);
9474 gen_sel_s(ctx, op1, fd, ft, fs);
9475 break;
9476 case OPC_SELEQZ_S:
9477 check_insn(ctx, ISA_MIPS_R6);
9478 gen_sel_s(ctx, op1, fd, ft, fs);
9479 break;
9480 case OPC_SELNEZ_S:
9481 check_insn(ctx, ISA_MIPS_R6);
9482 gen_sel_s(ctx, op1, fd, ft, fs);
9483 break;
9484 case OPC_MOVCF_S:
9485 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9486 gen_movcf_s(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9487 break;
9488 case OPC_MOVZ_S:
9489 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9490 {
9491 TCGLabel *l1 = gen_new_label();
9492 TCGv_i32 fp0;
9493
9494 if (ft != 0) {
9495 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9496 }
9497 fp0 = tcg_temp_new_i32();
9498 gen_load_fpr32(ctx, fp0, fs);
9499 gen_store_fpr32(ctx, fp0, fd);
9500 gen_set_label(l1);
9501 }
9502 break;
9503 case OPC_MOVN_S:
9504 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9505 {
9506 TCGLabel *l1 = gen_new_label();
9507 TCGv_i32 fp0;
9508
9509 if (ft != 0) {
9510 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9511 fp0 = tcg_temp_new_i32();
9512 gen_load_fpr32(ctx, fp0, fs);
9513 gen_store_fpr32(ctx, fp0, fd);
9514 gen_set_label(l1);
9515 }
9516 }
9517 break;
9518 case OPC_RECIP_S:
9519 {
9520 TCGv_i32 fp0 = tcg_temp_new_i32();
9521
9522 gen_load_fpr32(ctx, fp0, fs);
9523 gen_helper_float_recip_s(fp0, tcg_env, fp0);
9524 gen_store_fpr32(ctx, fp0, fd);
9525 }
9526 break;
9527 case OPC_RSQRT_S:
9528 {
9529 TCGv_i32 fp0 = tcg_temp_new_i32();
9530
9531 gen_load_fpr32(ctx, fp0, fs);
9532 gen_helper_float_rsqrt_s(fp0, tcg_env, fp0);
9533 gen_store_fpr32(ctx, fp0, fd);
9534 }
9535 break;
9536 case OPC_MADDF_S:
9537 check_insn(ctx, ISA_MIPS_R6);
9538 {
9539 TCGv_i32 fp0 = tcg_temp_new_i32();
9540 TCGv_i32 fp1 = tcg_temp_new_i32();
9541 TCGv_i32 fp2 = tcg_temp_new_i32();
9542 gen_load_fpr32(ctx, fp0, fs);
9543 gen_load_fpr32(ctx, fp1, ft);
9544 gen_load_fpr32(ctx, fp2, fd);
9545 gen_helper_float_maddf_s(fp2, tcg_env, fp0, fp1, fp2);
9546 gen_store_fpr32(ctx, fp2, fd);
9547 }
9548 break;
9549 case OPC_MSUBF_S:
9550 check_insn(ctx, ISA_MIPS_R6);
9551 {
9552 TCGv_i32 fp0 = tcg_temp_new_i32();
9553 TCGv_i32 fp1 = tcg_temp_new_i32();
9554 TCGv_i32 fp2 = tcg_temp_new_i32();
9555 gen_load_fpr32(ctx, fp0, fs);
9556 gen_load_fpr32(ctx, fp1, ft);
9557 gen_load_fpr32(ctx, fp2, fd);
9558 gen_helper_float_msubf_s(fp2, tcg_env, fp0, fp1, fp2);
9559 gen_store_fpr32(ctx, fp2, fd);
9560 }
9561 break;
9562 case OPC_RINT_S:
9563 check_insn(ctx, ISA_MIPS_R6);
9564 {
9565 TCGv_i32 fp0 = tcg_temp_new_i32();
9566 gen_load_fpr32(ctx, fp0, fs);
9567 gen_helper_float_rint_s(fp0, tcg_env, fp0);
9568 gen_store_fpr32(ctx, fp0, fd);
9569 }
9570 break;
9571 case OPC_CLASS_S:
9572 check_insn(ctx, ISA_MIPS_R6);
9573 {
9574 TCGv_i32 fp0 = tcg_temp_new_i32();
9575 gen_load_fpr32(ctx, fp0, fs);
9576 gen_helper_float_class_s(fp0, tcg_env, fp0);
9577 gen_store_fpr32(ctx, fp0, fd);
9578 }
9579 break;
9580 case OPC_MIN_S: /* OPC_RECIP2_S */
9581 if (ctx->insn_flags & ISA_MIPS_R6) {
9582 /* OPC_MIN_S */
9583 TCGv_i32 fp0 = tcg_temp_new_i32();
9584 TCGv_i32 fp1 = tcg_temp_new_i32();
9585 TCGv_i32 fp2 = tcg_temp_new_i32();
9586 gen_load_fpr32(ctx, fp0, fs);
9587 gen_load_fpr32(ctx, fp1, ft);
9588 gen_helper_float_min_s(fp2, tcg_env, fp0, fp1);
9589 gen_store_fpr32(ctx, fp2, fd);
9590 } else {
9591 /* OPC_RECIP2_S */
9592 check_cp1_64bitmode(ctx);
9593 {
9594 TCGv_i32 fp0 = tcg_temp_new_i32();
9595 TCGv_i32 fp1 = tcg_temp_new_i32();
9596
9597 gen_load_fpr32(ctx, fp0, fs);
9598 gen_load_fpr32(ctx, fp1, ft);
9599 gen_helper_float_recip2_s(fp0, tcg_env, fp0, fp1);
9600 gen_store_fpr32(ctx, fp0, fd);
9601 }
9602 }
9603 break;
9604 case OPC_MINA_S: /* OPC_RECIP1_S */
9605 if (ctx->insn_flags & ISA_MIPS_R6) {
9606 /* OPC_MINA_S */
9607 TCGv_i32 fp0 = tcg_temp_new_i32();
9608 TCGv_i32 fp1 = tcg_temp_new_i32();
9609 TCGv_i32 fp2 = tcg_temp_new_i32();
9610 gen_load_fpr32(ctx, fp0, fs);
9611 gen_load_fpr32(ctx, fp1, ft);
9612 gen_helper_float_mina_s(fp2, tcg_env, fp0, fp1);
9613 gen_store_fpr32(ctx, fp2, fd);
9614 } else {
9615 /* OPC_RECIP1_S */
9616 check_cp1_64bitmode(ctx);
9617 {
9618 TCGv_i32 fp0 = tcg_temp_new_i32();
9619
9620 gen_load_fpr32(ctx, fp0, fs);
9621 gen_helper_float_recip1_s(fp0, tcg_env, fp0);
9622 gen_store_fpr32(ctx, fp0, fd);
9623 }
9624 }
9625 break;
9626 case OPC_MAX_S: /* OPC_RSQRT1_S */
9627 if (ctx->insn_flags & ISA_MIPS_R6) {
9628 /* OPC_MAX_S */
9629 TCGv_i32 fp0 = tcg_temp_new_i32();
9630 TCGv_i32 fp1 = tcg_temp_new_i32();
9631 gen_load_fpr32(ctx, fp0, fs);
9632 gen_load_fpr32(ctx, fp1, ft);
9633 gen_helper_float_max_s(fp1, tcg_env, fp0, fp1);
9634 gen_store_fpr32(ctx, fp1, fd);
9635 } else {
9636 /* OPC_RSQRT1_S */
9637 check_cp1_64bitmode(ctx);
9638 {
9639 TCGv_i32 fp0 = tcg_temp_new_i32();
9640
9641 gen_load_fpr32(ctx, fp0, fs);
9642 gen_helper_float_rsqrt1_s(fp0, tcg_env, fp0);
9643 gen_store_fpr32(ctx, fp0, fd);
9644 }
9645 }
9646 break;
9647 case OPC_MAXA_S: /* OPC_RSQRT2_S */
9648 if (ctx->insn_flags & ISA_MIPS_R6) {
9649 /* OPC_MAXA_S */
9650 TCGv_i32 fp0 = tcg_temp_new_i32();
9651 TCGv_i32 fp1 = tcg_temp_new_i32();
9652 gen_load_fpr32(ctx, fp0, fs);
9653 gen_load_fpr32(ctx, fp1, ft);
9654 gen_helper_float_maxa_s(fp1, tcg_env, fp0, fp1);
9655 gen_store_fpr32(ctx, fp1, fd);
9656 } else {
9657 /* OPC_RSQRT2_S */
9658 check_cp1_64bitmode(ctx);
9659 {
9660 TCGv_i32 fp0 = tcg_temp_new_i32();
9661 TCGv_i32 fp1 = tcg_temp_new_i32();
9662
9663 gen_load_fpr32(ctx, fp0, fs);
9664 gen_load_fpr32(ctx, fp1, ft);
9665 gen_helper_float_rsqrt2_s(fp0, tcg_env, fp0, fp1);
9666 gen_store_fpr32(ctx, fp0, fd);
9667 }
9668 }
9669 break;
9670 case OPC_CVT_D_S:
9671 check_cp1_registers(ctx, fd);
9672 {
9673 TCGv_i32 fp32 = tcg_temp_new_i32();
9674 TCGv_i64 fp64 = tcg_temp_new_i64();
9675
9676 gen_load_fpr32(ctx, fp32, fs);
9677 gen_helper_float_cvtd_s(fp64, tcg_env, fp32);
9678 gen_store_fpr64(ctx, fp64, fd);
9679 }
9680 break;
9681 case OPC_CVT_W_S:
9682 {
9683 TCGv_i32 fp0 = tcg_temp_new_i32();
9684
9685 gen_load_fpr32(ctx, fp0, fs);
9686 if (ctx->nan2008) {
9687 gen_helper_float_cvt_2008_w_s(fp0, tcg_env, fp0);
9688 } else {
9689 gen_helper_float_cvt_w_s(fp0, tcg_env, fp0);
9690 }
9691 gen_store_fpr32(ctx, fp0, fd);
9692 }
9693 break;
9694 case OPC_CVT_L_S:
9695 check_cp1_64bitmode(ctx);
9696 {
9697 TCGv_i32 fp32 = tcg_temp_new_i32();
9698 TCGv_i64 fp64 = tcg_temp_new_i64();
9699
9700 gen_load_fpr32(ctx, fp32, fs);
9701 if (ctx->nan2008) {
9702 gen_helper_float_cvt_2008_l_s(fp64, tcg_env, fp32);
9703 } else {
9704 gen_helper_float_cvt_l_s(fp64, tcg_env, fp32);
9705 }
9706 gen_store_fpr64(ctx, fp64, fd);
9707 }
9708 break;
9709 case OPC_CVT_PS_S:
9710 check_ps(ctx);
9711 {
9712 TCGv_i64 fp64 = tcg_temp_new_i64();
9713 TCGv_i32 fp32_0 = tcg_temp_new_i32();
9714 TCGv_i32 fp32_1 = tcg_temp_new_i32();
9715
9716 gen_load_fpr32(ctx, fp32_0, fs);
9717 gen_load_fpr32(ctx, fp32_1, ft);
9718 tcg_gen_concat_i32_i64(fp64, fp32_1, fp32_0);
9719 gen_store_fpr64(ctx, fp64, fd);
9720 }
9721 break;
9722 case OPC_CMP_F_S:
9723 case OPC_CMP_UN_S:
9724 case OPC_CMP_EQ_S:
9725 case OPC_CMP_UEQ_S:
9726 case OPC_CMP_OLT_S:
9727 case OPC_CMP_ULT_S:
9728 case OPC_CMP_OLE_S:
9729 case OPC_CMP_ULE_S:
9730 case OPC_CMP_SF_S:
9731 case OPC_CMP_NGLE_S:
9732 case OPC_CMP_SEQ_S:
9733 case OPC_CMP_NGL_S:
9734 case OPC_CMP_LT_S:
9735 case OPC_CMP_NGE_S:
9736 case OPC_CMP_LE_S:
9737 case OPC_CMP_NGT_S:
9738 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9739 if (ctx->opcode & (1 << 6)) {
9740 gen_cmpabs_s(ctx, func - 48, ft, fs, cc);
9741 } else {
9742 gen_cmp_s(ctx, func - 48, ft, fs, cc);
9743 }
9744 break;
9745 case OPC_ADD_D:
9746 check_cp1_registers(ctx, fs | ft | fd);
9747 {
9748 TCGv_i64 fp0 = tcg_temp_new_i64();
9749 TCGv_i64 fp1 = tcg_temp_new_i64();
9750
9751 gen_load_fpr64(ctx, fp0, fs);
9752 gen_load_fpr64(ctx, fp1, ft);
9753 gen_helper_float_add_d(fp0, tcg_env, fp0, fp1);
9754 gen_store_fpr64(ctx, fp0, fd);
9755 }
9756 break;
9757 case OPC_SUB_D:
9758 check_cp1_registers(ctx, fs | ft | fd);
9759 {
9760 TCGv_i64 fp0 = tcg_temp_new_i64();
9761 TCGv_i64 fp1 = tcg_temp_new_i64();
9762
9763 gen_load_fpr64(ctx, fp0, fs);
9764 gen_load_fpr64(ctx, fp1, ft);
9765 gen_helper_float_sub_d(fp0, tcg_env, fp0, fp1);
9766 gen_store_fpr64(ctx, fp0, fd);
9767 }
9768 break;
9769 case OPC_MUL_D:
9770 check_cp1_registers(ctx, fs | ft | fd);
9771 {
9772 TCGv_i64 fp0 = tcg_temp_new_i64();
9773 TCGv_i64 fp1 = tcg_temp_new_i64();
9774
9775 gen_load_fpr64(ctx, fp0, fs);
9776 gen_load_fpr64(ctx, fp1, ft);
9777 gen_helper_float_mul_d(fp0, tcg_env, fp0, fp1);
9778 gen_store_fpr64(ctx, fp0, fd);
9779 }
9780 break;
9781 case OPC_DIV_D:
9782 check_cp1_registers(ctx, fs | ft | fd);
9783 {
9784 TCGv_i64 fp0 = tcg_temp_new_i64();
9785 TCGv_i64 fp1 = tcg_temp_new_i64();
9786
9787 gen_load_fpr64(ctx, fp0, fs);
9788 gen_load_fpr64(ctx, fp1, ft);
9789 gen_helper_float_div_d(fp0, tcg_env, fp0, fp1);
9790 gen_store_fpr64(ctx, fp0, fd);
9791 }
9792 break;
9793 case OPC_SQRT_D:
9794 check_cp1_registers(ctx, fs | fd);
9795 {
9796 TCGv_i64 fp0 = tcg_temp_new_i64();
9797
9798 gen_load_fpr64(ctx, fp0, fs);
9799 gen_helper_float_sqrt_d(fp0, tcg_env, fp0);
9800 gen_store_fpr64(ctx, fp0, fd);
9801 }
9802 break;
9803 case OPC_ABS_D:
9804 check_cp1_registers(ctx, fs | fd);
9805 {
9806 TCGv_i64 fp0 = tcg_temp_new_i64();
9807
9808 gen_load_fpr64(ctx, fp0, fs);
9809 if (ctx->abs2008) {
9810 tcg_gen_andi_i64(fp0, fp0, 0x7fffffffffffffffULL);
9811 } else {
9812 gen_helper_float_abs_d(fp0, fp0);
9813 }
9814 gen_store_fpr64(ctx, fp0, fd);
9815 }
9816 break;
9817 case OPC_MOV_D:
9818 check_cp1_registers(ctx, fs | fd);
9819 {
9820 TCGv_i64 fp0 = tcg_temp_new_i64();
9821
9822 gen_load_fpr64(ctx, fp0, fs);
9823 gen_store_fpr64(ctx, fp0, fd);
9824 }
9825 break;
9826 case OPC_NEG_D:
9827 check_cp1_registers(ctx, fs | fd);
9828 {
9829 TCGv_i64 fp0 = tcg_temp_new_i64();
9830
9831 gen_load_fpr64(ctx, fp0, fs);
9832 if (ctx->abs2008) {
9833 tcg_gen_xori_i64(fp0, fp0, 1ULL << 63);
9834 } else {
9835 gen_helper_float_chs_d(fp0, fp0);
9836 }
9837 gen_store_fpr64(ctx, fp0, fd);
9838 }
9839 break;
9840 case OPC_ROUND_L_D:
9841 check_cp1_64bitmode(ctx);
9842 {
9843 TCGv_i64 fp0 = tcg_temp_new_i64();
9844
9845 gen_load_fpr64(ctx, fp0, fs);
9846 if (ctx->nan2008) {
9847 gen_helper_float_round_2008_l_d(fp0, tcg_env, fp0);
9848 } else {
9849 gen_helper_float_round_l_d(fp0, tcg_env, fp0);
9850 }
9851 gen_store_fpr64(ctx, fp0, fd);
9852 }
9853 break;
9854 case OPC_TRUNC_L_D:
9855 check_cp1_64bitmode(ctx);
9856 {
9857 TCGv_i64 fp0 = tcg_temp_new_i64();
9858
9859 gen_load_fpr64(ctx, fp0, fs);
9860 if (ctx->nan2008) {
9861 gen_helper_float_trunc_2008_l_d(fp0, tcg_env, fp0);
9862 } else {
9863 gen_helper_float_trunc_l_d(fp0, tcg_env, fp0);
9864 }
9865 gen_store_fpr64(ctx, fp0, fd);
9866 }
9867 break;
9868 case OPC_CEIL_L_D:
9869 check_cp1_64bitmode(ctx);
9870 {
9871 TCGv_i64 fp0 = tcg_temp_new_i64();
9872
9873 gen_load_fpr64(ctx, fp0, fs);
9874 if (ctx->nan2008) {
9875 gen_helper_float_ceil_2008_l_d(fp0, tcg_env, fp0);
9876 } else {
9877 gen_helper_float_ceil_l_d(fp0, tcg_env, fp0);
9878 }
9879 gen_store_fpr64(ctx, fp0, fd);
9880 }
9881 break;
9882 case OPC_FLOOR_L_D:
9883 check_cp1_64bitmode(ctx);
9884 {
9885 TCGv_i64 fp0 = tcg_temp_new_i64();
9886
9887 gen_load_fpr64(ctx, fp0, fs);
9888 if (ctx->nan2008) {
9889 gen_helper_float_floor_2008_l_d(fp0, tcg_env, fp0);
9890 } else {
9891 gen_helper_float_floor_l_d(fp0, tcg_env, fp0);
9892 }
9893 gen_store_fpr64(ctx, fp0, fd);
9894 }
9895 break;
9896 case OPC_ROUND_W_D:
9897 check_cp1_registers(ctx, fs);
9898 {
9899 TCGv_i32 fp32 = tcg_temp_new_i32();
9900 TCGv_i64 fp64 = tcg_temp_new_i64();
9901
9902 gen_load_fpr64(ctx, fp64, fs);
9903 if (ctx->nan2008) {
9904 gen_helper_float_round_2008_w_d(fp32, tcg_env, fp64);
9905 } else {
9906 gen_helper_float_round_w_d(fp32, tcg_env, fp64);
9907 }
9908 gen_store_fpr32(ctx, fp32, fd);
9909 }
9910 break;
9911 case OPC_TRUNC_W_D:
9912 check_cp1_registers(ctx, fs);
9913 {
9914 TCGv_i32 fp32 = tcg_temp_new_i32();
9915 TCGv_i64 fp64 = tcg_temp_new_i64();
9916
9917 gen_load_fpr64(ctx, fp64, fs);
9918 if (ctx->nan2008) {
9919 gen_helper_float_trunc_2008_w_d(fp32, tcg_env, fp64);
9920 } else {
9921 gen_helper_float_trunc_w_d(fp32, tcg_env, fp64);
9922 }
9923 gen_store_fpr32(ctx, fp32, fd);
9924 }
9925 break;
9926 case OPC_CEIL_W_D:
9927 check_cp1_registers(ctx, fs);
9928 {
9929 TCGv_i32 fp32 = tcg_temp_new_i32();
9930 TCGv_i64 fp64 = tcg_temp_new_i64();
9931
9932 gen_load_fpr64(ctx, fp64, fs);
9933 if (ctx->nan2008) {
9934 gen_helper_float_ceil_2008_w_d(fp32, tcg_env, fp64);
9935 } else {
9936 gen_helper_float_ceil_w_d(fp32, tcg_env, fp64);
9937 }
9938 gen_store_fpr32(ctx, fp32, fd);
9939 }
9940 break;
9941 case OPC_FLOOR_W_D:
9942 check_cp1_registers(ctx, fs);
9943 {
9944 TCGv_i32 fp32 = tcg_temp_new_i32();
9945 TCGv_i64 fp64 = tcg_temp_new_i64();
9946
9947 gen_load_fpr64(ctx, fp64, fs);
9948 if (ctx->nan2008) {
9949 gen_helper_float_floor_2008_w_d(fp32, tcg_env, fp64);
9950 } else {
9951 gen_helper_float_floor_w_d(fp32, tcg_env, fp64);
9952 }
9953 gen_store_fpr32(ctx, fp32, fd);
9954 }
9955 break;
9956 case OPC_SEL_D:
9957 check_insn(ctx, ISA_MIPS_R6);
9958 gen_sel_d(ctx, op1, fd, ft, fs);
9959 break;
9960 case OPC_SELEQZ_D:
9961 check_insn(ctx, ISA_MIPS_R6);
9962 gen_sel_d(ctx, op1, fd, ft, fs);
9963 break;
9964 case OPC_SELNEZ_D:
9965 check_insn(ctx, ISA_MIPS_R6);
9966 gen_sel_d(ctx, op1, fd, ft, fs);
9967 break;
9968 case OPC_MOVCF_D:
9969 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9970 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
9971 break;
9972 case OPC_MOVZ_D:
9973 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9974 {
9975 TCGLabel *l1 = gen_new_label();
9976 TCGv_i64 fp0;
9977
9978 if (ft != 0) {
9979 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
9980 }
9981 fp0 = tcg_temp_new_i64();
9982 gen_load_fpr64(ctx, fp0, fs);
9983 gen_store_fpr64(ctx, fp0, fd);
9984 gen_set_label(l1);
9985 }
9986 break;
9987 case OPC_MOVN_D:
9988 check_insn_opc_removed(ctx, ISA_MIPS_R6);
9989 {
9990 TCGLabel *l1 = gen_new_label();
9991 TCGv_i64 fp0;
9992
9993 if (ft != 0) {
9994 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
9995 fp0 = tcg_temp_new_i64();
9996 gen_load_fpr64(ctx, fp0, fs);
9997 gen_store_fpr64(ctx, fp0, fd);
9998 gen_set_label(l1);
9999 }
10000 }
10001 break;
10002 case OPC_RECIP_D:
10003 check_cp1_registers(ctx, fs | fd);
10004 {
10005 TCGv_i64 fp0 = tcg_temp_new_i64();
10006
10007 gen_load_fpr64(ctx, fp0, fs);
10008 gen_helper_float_recip_d(fp0, tcg_env, fp0);
10009 gen_store_fpr64(ctx, fp0, fd);
10010 }
10011 break;
10012 case OPC_RSQRT_D:
10013 check_cp1_registers(ctx, fs | fd);
10014 {
10015 TCGv_i64 fp0 = tcg_temp_new_i64();
10016
10017 gen_load_fpr64(ctx, fp0, fs);
10018 gen_helper_float_rsqrt_d(fp0, tcg_env, fp0);
10019 gen_store_fpr64(ctx, fp0, fd);
10020 }
10021 break;
10022 case OPC_MADDF_D:
10023 check_insn(ctx, ISA_MIPS_R6);
10024 {
10025 TCGv_i64 fp0 = tcg_temp_new_i64();
10026 TCGv_i64 fp1 = tcg_temp_new_i64();
10027 TCGv_i64 fp2 = tcg_temp_new_i64();
10028 gen_load_fpr64(ctx, fp0, fs);
10029 gen_load_fpr64(ctx, fp1, ft);
10030 gen_load_fpr64(ctx, fp2, fd);
10031 gen_helper_float_maddf_d(fp2, tcg_env, fp0, fp1, fp2);
10032 gen_store_fpr64(ctx, fp2, fd);
10033 }
10034 break;
10035 case OPC_MSUBF_D:
10036 check_insn(ctx, ISA_MIPS_R6);
10037 {
10038 TCGv_i64 fp0 = tcg_temp_new_i64();
10039 TCGv_i64 fp1 = tcg_temp_new_i64();
10040 TCGv_i64 fp2 = tcg_temp_new_i64();
10041 gen_load_fpr64(ctx, fp0, fs);
10042 gen_load_fpr64(ctx, fp1, ft);
10043 gen_load_fpr64(ctx, fp2, fd);
10044 gen_helper_float_msubf_d(fp2, tcg_env, fp0, fp1, fp2);
10045 gen_store_fpr64(ctx, fp2, fd);
10046 }
10047 break;
10048 case OPC_RINT_D:
10049 check_insn(ctx, ISA_MIPS_R6);
10050 {
10051 TCGv_i64 fp0 = tcg_temp_new_i64();
10052 gen_load_fpr64(ctx, fp0, fs);
10053 gen_helper_float_rint_d(fp0, tcg_env, fp0);
10054 gen_store_fpr64(ctx, fp0, fd);
10055 }
10056 break;
10057 case OPC_CLASS_D:
10058 check_insn(ctx, ISA_MIPS_R6);
10059 {
10060 TCGv_i64 fp0 = tcg_temp_new_i64();
10061 gen_load_fpr64(ctx, fp0, fs);
10062 gen_helper_float_class_d(fp0, tcg_env, fp0);
10063 gen_store_fpr64(ctx, fp0, fd);
10064 }
10065 break;
10066 case OPC_MIN_D: /* OPC_RECIP2_D */
10067 if (ctx->insn_flags & ISA_MIPS_R6) {
10068 /* OPC_MIN_D */
10069 TCGv_i64 fp0 = tcg_temp_new_i64();
10070 TCGv_i64 fp1 = tcg_temp_new_i64();
10071 gen_load_fpr64(ctx, fp0, fs);
10072 gen_load_fpr64(ctx, fp1, ft);
10073 gen_helper_float_min_d(fp1, tcg_env, fp0, fp1);
10074 gen_store_fpr64(ctx, fp1, fd);
10075 } else {
10076 /* OPC_RECIP2_D */
10077 check_cp1_64bitmode(ctx);
10078 {
10079 TCGv_i64 fp0 = tcg_temp_new_i64();
10080 TCGv_i64 fp1 = tcg_temp_new_i64();
10081
10082 gen_load_fpr64(ctx, fp0, fs);
10083 gen_load_fpr64(ctx, fp1, ft);
10084 gen_helper_float_recip2_d(fp0, tcg_env, fp0, fp1);
10085 gen_store_fpr64(ctx, fp0, fd);
10086 }
10087 }
10088 break;
10089 case OPC_MINA_D: /* OPC_RECIP1_D */
10090 if (ctx->insn_flags & ISA_MIPS_R6) {
10091 /* OPC_MINA_D */
10092 TCGv_i64 fp0 = tcg_temp_new_i64();
10093 TCGv_i64 fp1 = tcg_temp_new_i64();
10094 gen_load_fpr64(ctx, fp0, fs);
10095 gen_load_fpr64(ctx, fp1, ft);
10096 gen_helper_float_mina_d(fp1, tcg_env, fp0, fp1);
10097 gen_store_fpr64(ctx, fp1, fd);
10098 } else {
10099 /* OPC_RECIP1_D */
10100 check_cp1_64bitmode(ctx);
10101 {
10102 TCGv_i64 fp0 = tcg_temp_new_i64();
10103
10104 gen_load_fpr64(ctx, fp0, fs);
10105 gen_helper_float_recip1_d(fp0, tcg_env, fp0);
10106 gen_store_fpr64(ctx, fp0, fd);
10107 }
10108 }
10109 break;
10110 case OPC_MAX_D: /* OPC_RSQRT1_D */
10111 if (ctx->insn_flags & ISA_MIPS_R6) {
10112 /* OPC_MAX_D */
10113 TCGv_i64 fp0 = tcg_temp_new_i64();
10114 TCGv_i64 fp1 = tcg_temp_new_i64();
10115 gen_load_fpr64(ctx, fp0, fs);
10116 gen_load_fpr64(ctx, fp1, ft);
10117 gen_helper_float_max_d(fp1, tcg_env, fp0, fp1);
10118 gen_store_fpr64(ctx, fp1, fd);
10119 } else {
10120 /* OPC_RSQRT1_D */
10121 check_cp1_64bitmode(ctx);
10122 {
10123 TCGv_i64 fp0 = tcg_temp_new_i64();
10124
10125 gen_load_fpr64(ctx, fp0, fs);
10126 gen_helper_float_rsqrt1_d(fp0, tcg_env, fp0);
10127 gen_store_fpr64(ctx, fp0, fd);
10128 }
10129 }
10130 break;
10131 case OPC_MAXA_D: /* OPC_RSQRT2_D */
10132 if (ctx->insn_flags & ISA_MIPS_R6) {
10133 /* OPC_MAXA_D */
10134 TCGv_i64 fp0 = tcg_temp_new_i64();
10135 TCGv_i64 fp1 = tcg_temp_new_i64();
10136 gen_load_fpr64(ctx, fp0, fs);
10137 gen_load_fpr64(ctx, fp1, ft);
10138 gen_helper_float_maxa_d(fp1, tcg_env, fp0, fp1);
10139 gen_store_fpr64(ctx, fp1, fd);
10140 } else {
10141 /* OPC_RSQRT2_D */
10142 check_cp1_64bitmode(ctx);
10143 {
10144 TCGv_i64 fp0 = tcg_temp_new_i64();
10145 TCGv_i64 fp1 = tcg_temp_new_i64();
10146
10147 gen_load_fpr64(ctx, fp0, fs);
10148 gen_load_fpr64(ctx, fp1, ft);
10149 gen_helper_float_rsqrt2_d(fp0, tcg_env, fp0, fp1);
10150 gen_store_fpr64(ctx, fp0, fd);
10151 }
10152 }
10153 break;
10154 case OPC_CMP_F_D:
10155 case OPC_CMP_UN_D:
10156 case OPC_CMP_EQ_D:
10157 case OPC_CMP_UEQ_D:
10158 case OPC_CMP_OLT_D:
10159 case OPC_CMP_ULT_D:
10160 case OPC_CMP_OLE_D:
10161 case OPC_CMP_ULE_D:
10162 case OPC_CMP_SF_D:
10163 case OPC_CMP_NGLE_D:
10164 case OPC_CMP_SEQ_D:
10165 case OPC_CMP_NGL_D:
10166 case OPC_CMP_LT_D:
10167 case OPC_CMP_NGE_D:
10168 case OPC_CMP_LE_D:
10169 case OPC_CMP_NGT_D:
10170 check_insn_opc_removed(ctx, ISA_MIPS_R6);
10171 if (ctx->opcode & (1 << 6)) {
10172 gen_cmpabs_d(ctx, func - 48, ft, fs, cc);
10173 } else {
10174 gen_cmp_d(ctx, func - 48, ft, fs, cc);
10175 }
10176 break;
10177 case OPC_CVT_S_D:
10178 check_cp1_registers(ctx, fs);
10179 {
10180 TCGv_i32 fp32 = tcg_temp_new_i32();
10181 TCGv_i64 fp64 = tcg_temp_new_i64();
10182
10183 gen_load_fpr64(ctx, fp64, fs);
10184 gen_helper_float_cvts_d(fp32, tcg_env, fp64);
10185 gen_store_fpr32(ctx, fp32, fd);
10186 }
10187 break;
10188 case OPC_CVT_W_D:
10189 check_cp1_registers(ctx, fs);
10190 {
10191 TCGv_i32 fp32 = tcg_temp_new_i32();
10192 TCGv_i64 fp64 = tcg_temp_new_i64();
10193
10194 gen_load_fpr64(ctx, fp64, fs);
10195 if (ctx->nan2008) {
10196 gen_helper_float_cvt_2008_w_d(fp32, tcg_env, fp64);
10197 } else {
10198 gen_helper_float_cvt_w_d(fp32, tcg_env, fp64);
10199 }
10200 gen_store_fpr32(ctx, fp32, fd);
10201 }
10202 break;
10203 case OPC_CVT_L_D:
10204 check_cp1_64bitmode(ctx);
10205 {
10206 TCGv_i64 fp0 = tcg_temp_new_i64();
10207
10208 gen_load_fpr64(ctx, fp0, fs);
10209 if (ctx->nan2008) {
10210 gen_helper_float_cvt_2008_l_d(fp0, tcg_env, fp0);
10211 } else {
10212 gen_helper_float_cvt_l_d(fp0, tcg_env, fp0);
10213 }
10214 gen_store_fpr64(ctx, fp0, fd);
10215 }
10216 break;
10217 case OPC_CVT_S_W:
10218 {
10219 TCGv_i32 fp0 = tcg_temp_new_i32();
10220
10221 gen_load_fpr32(ctx, fp0, fs);
10222 gen_helper_float_cvts_w(fp0, tcg_env, fp0);
10223 gen_store_fpr32(ctx, fp0, fd);
10224 }
10225 break;
10226 case OPC_CVT_D_W:
10227 check_cp1_registers(ctx, fd);
10228 {
10229 TCGv_i32 fp32 = tcg_temp_new_i32();
10230 TCGv_i64 fp64 = tcg_temp_new_i64();
10231
10232 gen_load_fpr32(ctx, fp32, fs);
10233 gen_helper_float_cvtd_w(fp64, tcg_env, fp32);
10234 gen_store_fpr64(ctx, fp64, fd);
10235 }
10236 break;
10237 case OPC_CVT_S_L:
10238 check_cp1_64bitmode(ctx);
10239 {
10240 TCGv_i32 fp32 = tcg_temp_new_i32();
10241 TCGv_i64 fp64 = tcg_temp_new_i64();
10242
10243 gen_load_fpr64(ctx, fp64, fs);
10244 gen_helper_float_cvts_l(fp32, tcg_env, fp64);
10245 gen_store_fpr32(ctx, fp32, fd);
10246 }
10247 break;
10248 case OPC_CVT_D_L:
10249 check_cp1_64bitmode(ctx);
10250 {
10251 TCGv_i64 fp0 = tcg_temp_new_i64();
10252
10253 gen_load_fpr64(ctx, fp0, fs);
10254 gen_helper_float_cvtd_l(fp0, tcg_env, fp0);
10255 gen_store_fpr64(ctx, fp0, fd);
10256 }
10257 break;
10258 case OPC_CVT_PS_PW:
10259 check_ps(ctx);
10260 {
10261 TCGv_i64 fp0 = tcg_temp_new_i64();
10262
10263 gen_load_fpr64(ctx, fp0, fs);
10264 gen_helper_float_cvtps_pw(fp0, tcg_env, fp0);
10265 gen_store_fpr64(ctx, fp0, fd);
10266 }
10267 break;
10268 case OPC_ADD_PS:
10269 check_ps(ctx);
10270 {
10271 TCGv_i64 fp0 = tcg_temp_new_i64();
10272 TCGv_i64 fp1 = tcg_temp_new_i64();
10273
10274 gen_load_fpr64(ctx, fp0, fs);
10275 gen_load_fpr64(ctx, fp1, ft);
10276 gen_helper_float_add_ps(fp0, tcg_env, fp0, fp1);
10277 gen_store_fpr64(ctx, fp0, fd);
10278 }
10279 break;
10280 case OPC_SUB_PS:
10281 check_ps(ctx);
10282 {
10283 TCGv_i64 fp0 = tcg_temp_new_i64();
10284 TCGv_i64 fp1 = tcg_temp_new_i64();
10285
10286 gen_load_fpr64(ctx, fp0, fs);
10287 gen_load_fpr64(ctx, fp1, ft);
10288 gen_helper_float_sub_ps(fp0, tcg_env, fp0, fp1);
10289 gen_store_fpr64(ctx, fp0, fd);
10290 }
10291 break;
10292 case OPC_MUL_PS:
10293 check_ps(ctx);
10294 {
10295 TCGv_i64 fp0 = tcg_temp_new_i64();
10296 TCGv_i64 fp1 = tcg_temp_new_i64();
10297
10298 gen_load_fpr64(ctx, fp0, fs);
10299 gen_load_fpr64(ctx, fp1, ft);
10300 gen_helper_float_mul_ps(fp0, tcg_env, fp0, fp1);
10301 gen_store_fpr64(ctx, fp0, fd);
10302 }
10303 break;
10304 case OPC_ABS_PS:
10305 check_ps(ctx);
10306 {
10307 TCGv_i64 fp0 = tcg_temp_new_i64();
10308
10309 gen_load_fpr64(ctx, fp0, fs);
10310 gen_helper_float_abs_ps(fp0, fp0);
10311 gen_store_fpr64(ctx, fp0, fd);
10312 }
10313 break;
10314 case OPC_MOV_PS:
10315 check_ps(ctx);
10316 {
10317 TCGv_i64 fp0 = tcg_temp_new_i64();
10318
10319 gen_load_fpr64(ctx, fp0, fs);
10320 gen_store_fpr64(ctx, fp0, fd);
10321 }
10322 break;
10323 case OPC_NEG_PS:
10324 check_ps(ctx);
10325 {
10326 TCGv_i64 fp0 = tcg_temp_new_i64();
10327
10328 gen_load_fpr64(ctx, fp0, fs);
10329 gen_helper_float_chs_ps(fp0, fp0);
10330 gen_store_fpr64(ctx, fp0, fd);
10331 }
10332 break;
10333 case OPC_MOVCF_PS:
10334 check_ps(ctx);
10335 gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
10336 break;
10337 case OPC_MOVZ_PS:
10338 check_ps(ctx);
10339 {
10340 TCGLabel *l1 = gen_new_label();
10341 TCGv_i64 fp0;
10342
10343 if (ft != 0) {
10344 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
10345 }
10346 fp0 = tcg_temp_new_i64();
10347 gen_load_fpr64(ctx, fp0, fs);
10348 gen_store_fpr64(ctx, fp0, fd);
10349 gen_set_label(l1);
10350 }
10351 break;
10352 case OPC_MOVN_PS:
10353 check_ps(ctx);
10354 {
10355 TCGLabel *l1 = gen_new_label();
10356 TCGv_i64 fp0;
10357
10358 if (ft != 0) {
10359 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
10360 fp0 = tcg_temp_new_i64();
10361 gen_load_fpr64(ctx, fp0, fs);
10362 gen_store_fpr64(ctx, fp0, fd);
10363 gen_set_label(l1);
10364 }
10365 }
10366 break;
10367 case OPC_ADDR_PS:
10368 check_ps(ctx);
10369 {
10370 TCGv_i64 fp0 = tcg_temp_new_i64();
10371 TCGv_i64 fp1 = tcg_temp_new_i64();
10372
10373 gen_load_fpr64(ctx, fp0, ft);
10374 gen_load_fpr64(ctx, fp1, fs);
10375 gen_helper_float_addr_ps(fp0, tcg_env, fp0, fp1);
10376 gen_store_fpr64(ctx, fp0, fd);
10377 }
10378 break;
10379 case OPC_MULR_PS:
10380 check_ps(ctx);
10381 {
10382 TCGv_i64 fp0 = tcg_temp_new_i64();
10383 TCGv_i64 fp1 = tcg_temp_new_i64();
10384
10385 gen_load_fpr64(ctx, fp0, ft);
10386 gen_load_fpr64(ctx, fp1, fs);
10387 gen_helper_float_mulr_ps(fp0, tcg_env, fp0, fp1);
10388 gen_store_fpr64(ctx, fp0, fd);
10389 }
10390 break;
10391 case OPC_RECIP2_PS:
10392 check_ps(ctx);
10393 {
10394 TCGv_i64 fp0 = tcg_temp_new_i64();
10395 TCGv_i64 fp1 = tcg_temp_new_i64();
10396
10397 gen_load_fpr64(ctx, fp0, fs);
10398 gen_load_fpr64(ctx, fp1, ft);
10399 gen_helper_float_recip2_ps(fp0, tcg_env, fp0, fp1);
10400 gen_store_fpr64(ctx, fp0, fd);
10401 }
10402 break;
10403 case OPC_RECIP1_PS:
10404 check_ps(ctx);
10405 {
10406 TCGv_i64 fp0 = tcg_temp_new_i64();
10407
10408 gen_load_fpr64(ctx, fp0, fs);
10409 gen_helper_float_recip1_ps(fp0, tcg_env, fp0);
10410 gen_store_fpr64(ctx, fp0, fd);
10411 }
10412 break;
10413 case OPC_RSQRT1_PS:
10414 check_ps(ctx);
10415 {
10416 TCGv_i64 fp0 = tcg_temp_new_i64();
10417
10418 gen_load_fpr64(ctx, fp0, fs);
10419 gen_helper_float_rsqrt1_ps(fp0, tcg_env, fp0);
10420 gen_store_fpr64(ctx, fp0, fd);
10421 }
10422 break;
10423 case OPC_RSQRT2_PS:
10424 check_ps(ctx);
10425 {
10426 TCGv_i64 fp0 = tcg_temp_new_i64();
10427 TCGv_i64 fp1 = tcg_temp_new_i64();
10428
10429 gen_load_fpr64(ctx, fp0, fs);
10430 gen_load_fpr64(ctx, fp1, ft);
10431 gen_helper_float_rsqrt2_ps(fp0, tcg_env, fp0, fp1);
10432 gen_store_fpr64(ctx, fp0, fd);
10433 }
10434 break;
10435 case OPC_CVT_S_PU:
10436 check_cp1_64bitmode(ctx);
10437 {
10438 TCGv_i32 fp0 = tcg_temp_new_i32();
10439
10440 gen_load_fpr32h(ctx, fp0, fs);
10441 gen_helper_float_cvts_pu(fp0, tcg_env, fp0);
10442 gen_store_fpr32(ctx, fp0, fd);
10443 }
10444 break;
10445 case OPC_CVT_PW_PS:
10446 check_ps(ctx);
10447 {
10448 TCGv_i64 fp0 = tcg_temp_new_i64();
10449
10450 gen_load_fpr64(ctx, fp0, fs);
10451 gen_helper_float_cvtpw_ps(fp0, tcg_env, fp0);
10452 gen_store_fpr64(ctx, fp0, fd);
10453 }
10454 break;
10455 case OPC_CVT_S_PL:
10456 check_cp1_64bitmode(ctx);
10457 {
10458 TCGv_i32 fp0 = tcg_temp_new_i32();
10459
10460 gen_load_fpr32(ctx, fp0, fs);
10461 gen_helper_float_cvts_pl(fp0, tcg_env, fp0);
10462 gen_store_fpr32(ctx, fp0, fd);
10463 }
10464 break;
10465 case OPC_PLL_PS:
10466 check_ps(ctx);
10467 {
10468 TCGv_i32 fp0 = tcg_temp_new_i32();
10469 TCGv_i32 fp1 = tcg_temp_new_i32();
10470
10471 gen_load_fpr32(ctx, fp0, fs);
10472 gen_load_fpr32(ctx, fp1, ft);
10473 gen_store_fpr32h(ctx, fp0, fd);
10474 gen_store_fpr32(ctx, fp1, fd);
10475 }
10476 break;
10477 case OPC_PLU_PS:
10478 check_ps(ctx);
10479 {
10480 TCGv_i32 fp0 = tcg_temp_new_i32();
10481 TCGv_i32 fp1 = tcg_temp_new_i32();
10482
10483 gen_load_fpr32(ctx, fp0, fs);
10484 gen_load_fpr32h(ctx, fp1, ft);
10485 gen_store_fpr32(ctx, fp1, fd);
10486 gen_store_fpr32h(ctx, fp0, fd);
10487 }
10488 break;
10489 case OPC_PUL_PS:
10490 check_ps(ctx);
10491 {
10492 TCGv_i32 fp0 = tcg_temp_new_i32();
10493 TCGv_i32 fp1 = tcg_temp_new_i32();
10494
10495 gen_load_fpr32h(ctx, fp0, fs);
10496 gen_load_fpr32(ctx, fp1, ft);
10497 gen_store_fpr32(ctx, fp1, fd);
10498 gen_store_fpr32h(ctx, fp0, fd);
10499 }
10500 break;
10501 case OPC_PUU_PS:
10502 check_ps(ctx);
10503 {
10504 TCGv_i32 fp0 = tcg_temp_new_i32();
10505 TCGv_i32 fp1 = tcg_temp_new_i32();
10506
10507 gen_load_fpr32h(ctx, fp0, fs);
10508 gen_load_fpr32h(ctx, fp1, ft);
10509 gen_store_fpr32(ctx, fp1, fd);
10510 gen_store_fpr32h(ctx, fp0, fd);
10511 }
10512 break;
10513 case OPC_CMP_F_PS:
10514 case OPC_CMP_UN_PS:
10515 case OPC_CMP_EQ_PS:
10516 case OPC_CMP_UEQ_PS:
10517 case OPC_CMP_OLT_PS:
10518 case OPC_CMP_ULT_PS:
10519 case OPC_CMP_OLE_PS:
10520 case OPC_CMP_ULE_PS:
10521 case OPC_CMP_SF_PS:
10522 case OPC_CMP_NGLE_PS:
10523 case OPC_CMP_SEQ_PS:
10524 case OPC_CMP_NGL_PS:
10525 case OPC_CMP_LT_PS:
10526 case OPC_CMP_NGE_PS:
10527 case OPC_CMP_LE_PS:
10528 case OPC_CMP_NGT_PS:
10529 if (ctx->opcode & (1 << 6)) {
10530 gen_cmpabs_ps(ctx, func - 48, ft, fs, cc);
10531 } else {
10532 gen_cmp_ps(ctx, func - 48, ft, fs, cc);
10533 }
10534 break;
10535 default:
10536 MIPS_INVAL("farith");
10537 gen_reserved_instruction(ctx);
10538 return;
10539 }
10540 }
10541
10542 /* Coprocessor 3 (FPU) */
gen_flt3_ldst(DisasContext * ctx,uint32_t opc,int fd,int fs,int base,int index)10543 static void gen_flt3_ldst(DisasContext *ctx, uint32_t opc,
10544 int fd, int fs, int base, int index)
10545 {
10546 TCGv t0 = tcg_temp_new();
10547
10548 if (base == 0) {
10549 gen_load_gpr(t0, index);
10550 } else if (index == 0) {
10551 gen_load_gpr(t0, base);
10552 } else {
10553 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[index]);
10554 }
10555 /*
10556 * Don't do NOP if destination is zero: we must perform the actual
10557 * memory access.
10558 */
10559 switch (opc) {
10560 case OPC_LWXC1:
10561 check_cop1x(ctx);
10562 {
10563 TCGv_i32 fp0 = tcg_temp_new_i32();
10564
10565 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
10566 tcg_gen_trunc_tl_i32(fp0, t0);
10567 gen_store_fpr32(ctx, fp0, fd);
10568 }
10569 break;
10570 case OPC_LDXC1:
10571 check_cop1x(ctx);
10572 check_cp1_registers(ctx, fd);
10573 {
10574 TCGv_i64 fp0 = tcg_temp_new_i64();
10575 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10576 gen_store_fpr64(ctx, fp0, fd);
10577 }
10578 break;
10579 case OPC_LUXC1:
10580 check_cp1_64bitmode(ctx);
10581 tcg_gen_andi_tl(t0, t0, ~0x7);
10582 {
10583 TCGv_i64 fp0 = tcg_temp_new_i64();
10584
10585 tcg_gen_qemu_ld_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10586 gen_store_fpr64(ctx, fp0, fd);
10587 }
10588 break;
10589 case OPC_SWXC1:
10590 check_cop1x(ctx);
10591 {
10592 TCGv_i32 fp0 = tcg_temp_new_i32();
10593 gen_load_fpr32(ctx, fp0, fs);
10594 tcg_gen_qemu_st_i32(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UL);
10595 }
10596 break;
10597 case OPC_SDXC1:
10598 check_cop1x(ctx);
10599 check_cp1_registers(ctx, fs);
10600 {
10601 TCGv_i64 fp0 = tcg_temp_new_i64();
10602 gen_load_fpr64(ctx, fp0, fs);
10603 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10604 }
10605 break;
10606 case OPC_SUXC1:
10607 check_cp1_64bitmode(ctx);
10608 tcg_gen_andi_tl(t0, t0, ~0x7);
10609 {
10610 TCGv_i64 fp0 = tcg_temp_new_i64();
10611 gen_load_fpr64(ctx, fp0, fs);
10612 tcg_gen_qemu_st_i64(fp0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
10613 }
10614 break;
10615 }
10616 }
10617
gen_flt3_arith(DisasContext * ctx,uint32_t opc,int fd,int fr,int fs,int ft)10618 static void gen_flt3_arith(DisasContext *ctx, uint32_t opc,
10619 int fd, int fr, int fs, int ft)
10620 {
10621 switch (opc) {
10622 case OPC_ALNV_PS:
10623 check_ps(ctx);
10624 {
10625 TCGv t0 = tcg_temp_new();
10626 TCGv_i32 fp = tcg_temp_new_i32();
10627 TCGv_i32 fph = tcg_temp_new_i32();
10628 TCGLabel *l1 = gen_new_label();
10629 TCGLabel *l2 = gen_new_label();
10630
10631 gen_load_gpr(t0, fr);
10632 tcg_gen_andi_tl(t0, t0, 0x7);
10633
10634 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
10635 gen_load_fpr32(ctx, fp, fs);
10636 gen_load_fpr32h(ctx, fph, fs);
10637 gen_store_fpr32(ctx, fp, fd);
10638 gen_store_fpr32h(ctx, fph, fd);
10639 tcg_gen_br(l2);
10640 gen_set_label(l1);
10641 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
10642 if (disas_is_bigendian(ctx)) {
10643 gen_load_fpr32(ctx, fp, fs);
10644 gen_load_fpr32h(ctx, fph, ft);
10645 gen_store_fpr32h(ctx, fp, fd);
10646 gen_store_fpr32(ctx, fph, fd);
10647 } else {
10648 gen_load_fpr32h(ctx, fph, fs);
10649 gen_load_fpr32(ctx, fp, ft);
10650 gen_store_fpr32(ctx, fph, fd);
10651 gen_store_fpr32h(ctx, fp, fd);
10652 }
10653 gen_set_label(l2);
10654 }
10655 break;
10656 case OPC_MADD_S:
10657 check_cop1x(ctx);
10658 {
10659 TCGv_i32 fp0 = tcg_temp_new_i32();
10660 TCGv_i32 fp1 = tcg_temp_new_i32();
10661 TCGv_i32 fp2 = tcg_temp_new_i32();
10662
10663 gen_load_fpr32(ctx, fp0, fs);
10664 gen_load_fpr32(ctx, fp1, ft);
10665 gen_load_fpr32(ctx, fp2, fr);
10666 gen_helper_float_madd_s(fp2, tcg_env, fp0, fp1, fp2);
10667 gen_store_fpr32(ctx, fp2, fd);
10668 }
10669 break;
10670 case OPC_MADD_D:
10671 check_cop1x(ctx);
10672 check_cp1_registers(ctx, fd | fs | ft | fr);
10673 {
10674 TCGv_i64 fp0 = tcg_temp_new_i64();
10675 TCGv_i64 fp1 = tcg_temp_new_i64();
10676 TCGv_i64 fp2 = tcg_temp_new_i64();
10677
10678 gen_load_fpr64(ctx, fp0, fs);
10679 gen_load_fpr64(ctx, fp1, ft);
10680 gen_load_fpr64(ctx, fp2, fr);
10681 gen_helper_float_madd_d(fp2, tcg_env, fp0, fp1, fp2);
10682 gen_store_fpr64(ctx, fp2, fd);
10683 }
10684 break;
10685 case OPC_MADD_PS:
10686 check_ps(ctx);
10687 {
10688 TCGv_i64 fp0 = tcg_temp_new_i64();
10689 TCGv_i64 fp1 = tcg_temp_new_i64();
10690 TCGv_i64 fp2 = tcg_temp_new_i64();
10691
10692 gen_load_fpr64(ctx, fp0, fs);
10693 gen_load_fpr64(ctx, fp1, ft);
10694 gen_load_fpr64(ctx, fp2, fr);
10695 gen_helper_float_madd_ps(fp2, tcg_env, fp0, fp1, fp2);
10696 gen_store_fpr64(ctx, fp2, fd);
10697 }
10698 break;
10699 case OPC_MSUB_S:
10700 check_cop1x(ctx);
10701 {
10702 TCGv_i32 fp0 = tcg_temp_new_i32();
10703 TCGv_i32 fp1 = tcg_temp_new_i32();
10704 TCGv_i32 fp2 = tcg_temp_new_i32();
10705
10706 gen_load_fpr32(ctx, fp0, fs);
10707 gen_load_fpr32(ctx, fp1, ft);
10708 gen_load_fpr32(ctx, fp2, fr);
10709 gen_helper_float_msub_s(fp2, tcg_env, fp0, fp1, fp2);
10710 gen_store_fpr32(ctx, fp2, fd);
10711 }
10712 break;
10713 case OPC_MSUB_D:
10714 check_cop1x(ctx);
10715 check_cp1_registers(ctx, fd | fs | ft | fr);
10716 {
10717 TCGv_i64 fp0 = tcg_temp_new_i64();
10718 TCGv_i64 fp1 = tcg_temp_new_i64();
10719 TCGv_i64 fp2 = tcg_temp_new_i64();
10720
10721 gen_load_fpr64(ctx, fp0, fs);
10722 gen_load_fpr64(ctx, fp1, ft);
10723 gen_load_fpr64(ctx, fp2, fr);
10724 gen_helper_float_msub_d(fp2, tcg_env, fp0, fp1, fp2);
10725 gen_store_fpr64(ctx, fp2, fd);
10726 }
10727 break;
10728 case OPC_MSUB_PS:
10729 check_ps(ctx);
10730 {
10731 TCGv_i64 fp0 = tcg_temp_new_i64();
10732 TCGv_i64 fp1 = tcg_temp_new_i64();
10733 TCGv_i64 fp2 = tcg_temp_new_i64();
10734
10735 gen_load_fpr64(ctx, fp0, fs);
10736 gen_load_fpr64(ctx, fp1, ft);
10737 gen_load_fpr64(ctx, fp2, fr);
10738 gen_helper_float_msub_ps(fp2, tcg_env, fp0, fp1, fp2);
10739 gen_store_fpr64(ctx, fp2, fd);
10740 }
10741 break;
10742 case OPC_NMADD_S:
10743 check_cop1x(ctx);
10744 {
10745 TCGv_i32 fp0 = tcg_temp_new_i32();
10746 TCGv_i32 fp1 = tcg_temp_new_i32();
10747 TCGv_i32 fp2 = tcg_temp_new_i32();
10748
10749 gen_load_fpr32(ctx, fp0, fs);
10750 gen_load_fpr32(ctx, fp1, ft);
10751 gen_load_fpr32(ctx, fp2, fr);
10752 gen_helper_float_nmadd_s(fp2, tcg_env, fp0, fp1, fp2);
10753 gen_store_fpr32(ctx, fp2, fd);
10754 }
10755 break;
10756 case OPC_NMADD_D:
10757 check_cop1x(ctx);
10758 check_cp1_registers(ctx, fd | fs | ft | fr);
10759 {
10760 TCGv_i64 fp0 = tcg_temp_new_i64();
10761 TCGv_i64 fp1 = tcg_temp_new_i64();
10762 TCGv_i64 fp2 = tcg_temp_new_i64();
10763
10764 gen_load_fpr64(ctx, fp0, fs);
10765 gen_load_fpr64(ctx, fp1, ft);
10766 gen_load_fpr64(ctx, fp2, fr);
10767 gen_helper_float_nmadd_d(fp2, tcg_env, fp0, fp1, fp2);
10768 gen_store_fpr64(ctx, fp2, fd);
10769 }
10770 break;
10771 case OPC_NMADD_PS:
10772 check_ps(ctx);
10773 {
10774 TCGv_i64 fp0 = tcg_temp_new_i64();
10775 TCGv_i64 fp1 = tcg_temp_new_i64();
10776 TCGv_i64 fp2 = tcg_temp_new_i64();
10777
10778 gen_load_fpr64(ctx, fp0, fs);
10779 gen_load_fpr64(ctx, fp1, ft);
10780 gen_load_fpr64(ctx, fp2, fr);
10781 gen_helper_float_nmadd_ps(fp2, tcg_env, fp0, fp1, fp2);
10782 gen_store_fpr64(ctx, fp2, fd);
10783 }
10784 break;
10785 case OPC_NMSUB_S:
10786 check_cop1x(ctx);
10787 {
10788 TCGv_i32 fp0 = tcg_temp_new_i32();
10789 TCGv_i32 fp1 = tcg_temp_new_i32();
10790 TCGv_i32 fp2 = tcg_temp_new_i32();
10791
10792 gen_load_fpr32(ctx, fp0, fs);
10793 gen_load_fpr32(ctx, fp1, ft);
10794 gen_load_fpr32(ctx, fp2, fr);
10795 gen_helper_float_nmsub_s(fp2, tcg_env, fp0, fp1, fp2);
10796 gen_store_fpr32(ctx, fp2, fd);
10797 }
10798 break;
10799 case OPC_NMSUB_D:
10800 check_cop1x(ctx);
10801 check_cp1_registers(ctx, fd | fs | ft | fr);
10802 {
10803 TCGv_i64 fp0 = tcg_temp_new_i64();
10804 TCGv_i64 fp1 = tcg_temp_new_i64();
10805 TCGv_i64 fp2 = tcg_temp_new_i64();
10806
10807 gen_load_fpr64(ctx, fp0, fs);
10808 gen_load_fpr64(ctx, fp1, ft);
10809 gen_load_fpr64(ctx, fp2, fr);
10810 gen_helper_float_nmsub_d(fp2, tcg_env, fp0, fp1, fp2);
10811 gen_store_fpr64(ctx, fp2, fd);
10812 }
10813 break;
10814 case OPC_NMSUB_PS:
10815 check_ps(ctx);
10816 {
10817 TCGv_i64 fp0 = tcg_temp_new_i64();
10818 TCGv_i64 fp1 = tcg_temp_new_i64();
10819 TCGv_i64 fp2 = tcg_temp_new_i64();
10820
10821 gen_load_fpr64(ctx, fp0, fs);
10822 gen_load_fpr64(ctx, fp1, ft);
10823 gen_load_fpr64(ctx, fp2, fr);
10824 gen_helper_float_nmsub_ps(fp2, tcg_env, fp0, fp1, fp2);
10825 gen_store_fpr64(ctx, fp2, fd);
10826 }
10827 break;
10828 default:
10829 MIPS_INVAL("flt3_arith");
10830 gen_reserved_instruction(ctx);
10831 return;
10832 }
10833 }
10834
gen_rdhwr(DisasContext * ctx,int rt,int rd,int sel)10835 void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel)
10836 {
10837 TCGv t0;
10838
10839 #if !defined(CONFIG_USER_ONLY)
10840 /*
10841 * The Linux kernel will emulate rdhwr if it's not supported natively.
10842 * Therefore only check the ISA in system mode.
10843 */
10844 check_insn(ctx, ISA_MIPS_R2);
10845 #endif
10846 t0 = tcg_temp_new();
10847
10848 switch (rd) {
10849 case 0:
10850 gen_helper_rdhwr_cpunum(t0, tcg_env);
10851 gen_store_gpr(t0, rt);
10852 break;
10853 case 1:
10854 gen_helper_rdhwr_synci_step(t0, tcg_env);
10855 gen_store_gpr(t0, rt);
10856 break;
10857 case 2:
10858 translator_io_start(&ctx->base);
10859 gen_helper_rdhwr_cc(t0, tcg_env);
10860 gen_store_gpr(t0, rt);
10861 /*
10862 * Break the TB to be able to take timer interrupts immediately
10863 * after reading count. DISAS_STOP isn't sufficient, we need to ensure
10864 * we break completely out of translated code.
10865 */
10866 gen_save_pc(ctx->base.pc_next + 4);
10867 ctx->base.is_jmp = DISAS_EXIT;
10868 break;
10869 case 3:
10870 gen_helper_rdhwr_ccres(t0, tcg_env);
10871 gen_store_gpr(t0, rt);
10872 break;
10873 case 4:
10874 check_insn(ctx, ISA_MIPS_R6);
10875 if (sel != 0) {
10876 /*
10877 * Performance counter registers are not implemented other than
10878 * control register 0.
10879 */
10880 generate_exception(ctx, EXCP_RI);
10881 }
10882 gen_helper_rdhwr_performance(t0, tcg_env);
10883 gen_store_gpr(t0, rt);
10884 break;
10885 case 5:
10886 check_insn(ctx, ISA_MIPS_R6);
10887 gen_helper_rdhwr_xnp(t0, tcg_env);
10888 gen_store_gpr(t0, rt);
10889 break;
10890 case 29:
10891 #if defined(CONFIG_USER_ONLY)
10892 tcg_gen_ld_tl(t0, tcg_env,
10893 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10894 gen_store_gpr(t0, rt);
10895 break;
10896 #else
10897 if ((ctx->hflags & MIPS_HFLAG_CP0) ||
10898 (ctx->hflags & MIPS_HFLAG_HWRENA_ULR)) {
10899 tcg_gen_ld_tl(t0, tcg_env,
10900 offsetof(CPUMIPSState, active_tc.CP0_UserLocal));
10901 gen_store_gpr(t0, rt);
10902 } else {
10903 gen_reserved_instruction(ctx);
10904 }
10905 break;
10906 #endif
10907 default: /* Invalid */
10908 MIPS_INVAL("rdhwr");
10909 gen_reserved_instruction(ctx);
10910 break;
10911 }
10912 }
10913
clear_branch_hflags(DisasContext * ctx)10914 static inline void clear_branch_hflags(DisasContext *ctx)
10915 {
10916 ctx->hflags &= ~MIPS_HFLAG_BMASK;
10917 if (ctx->base.is_jmp == DISAS_NEXT) {
10918 save_cpu_state(ctx, 0);
10919 } else {
10920 /*
10921 * It is not safe to save ctx->hflags as hflags may be changed
10922 * in execution time by the instruction in delay / forbidden slot.
10923 */
10924 tcg_gen_andi_i32(hflags, hflags, ~MIPS_HFLAG_BMASK);
10925 }
10926 }
10927
gen_branch(DisasContext * ctx,int insn_bytes)10928 static void gen_branch(DisasContext *ctx, int insn_bytes)
10929 {
10930 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10931 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
10932 /* Branches completion */
10933 clear_branch_hflags(ctx);
10934 ctx->base.is_jmp = DISAS_NORETURN;
10935 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
10936 case MIPS_HFLAG_FBNSLOT:
10937 gen_goto_tb(ctx, 0, ctx->base.pc_next + insn_bytes);
10938 break;
10939 case MIPS_HFLAG_B:
10940 /* unconditional branch */
10941 if (proc_hflags & MIPS_HFLAG_BX) {
10942 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
10943 }
10944 gen_goto_tb(ctx, 0, ctx->btarget);
10945 break;
10946 case MIPS_HFLAG_BL:
10947 /* blikely taken case */
10948 gen_goto_tb(ctx, 0, ctx->btarget);
10949 break;
10950 case MIPS_HFLAG_BC:
10951 /* Conditional branch */
10952 {
10953 TCGLabel *l1 = gen_new_label();
10954
10955 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
10956 gen_goto_tb(ctx, 1, ctx->base.pc_next + insn_bytes);
10957 gen_set_label(l1);
10958 gen_goto_tb(ctx, 0, ctx->btarget);
10959 }
10960 break;
10961 case MIPS_HFLAG_BR:
10962 /* unconditional branch to register */
10963 if (ctx->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
10964 TCGv t0 = tcg_temp_new();
10965 TCGv_i32 t1 = tcg_temp_new_i32();
10966
10967 tcg_gen_andi_tl(t0, btarget, 0x1);
10968 tcg_gen_trunc_tl_i32(t1, t0);
10969 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
10970 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
10971 tcg_gen_or_i32(hflags, hflags, t1);
10972
10973 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
10974 } else {
10975 tcg_gen_mov_tl(cpu_PC, btarget);
10976 }
10977 tcg_gen_lookup_and_goto_ptr();
10978 break;
10979 default:
10980 LOG_DISAS("unknown branch 0x%x\n", proc_hflags);
10981 gen_reserved_instruction(ctx);
10982 }
10983 }
10984 }
10985
10986 /* Compact Branches */
gen_compute_compact_branch(DisasContext * ctx,uint32_t opc,int rs,int rt,int32_t offset)10987 static void gen_compute_compact_branch(DisasContext *ctx, uint32_t opc,
10988 int rs, int rt, int32_t offset)
10989 {
10990 int bcond_compute = 0;
10991 TCGv t0 = tcg_temp_new();
10992 TCGv t1 = tcg_temp_new();
10993 int m16_lowbit = (ctx->hflags & MIPS_HFLAG_M16) != 0;
10994
10995 if (ctx->hflags & MIPS_HFLAG_BMASK) {
10996 #ifdef MIPS_DEBUG_DISAS
10997 LOG_DISAS("Branch in delay / forbidden slot at PC 0x%016"
10998 VADDR_PRIx "\n", ctx->base.pc_next);
10999 #endif
11000 gen_reserved_instruction(ctx);
11001 return;
11002 }
11003
11004 /* Load needed operands and calculate btarget */
11005 switch (opc) {
11006 /* compact branch */
11007 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11008 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11009 gen_load_gpr(t0, rs);
11010 gen_load_gpr(t1, rt);
11011 bcond_compute = 1;
11012 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11013 if (rs <= rt && rs == 0) {
11014 /* OPC_BEQZALC, OPC_BNEZALC */
11015 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11016 }
11017 break;
11018 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11019 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11020 gen_load_gpr(t0, rs);
11021 gen_load_gpr(t1, rt);
11022 bcond_compute = 1;
11023 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11024 break;
11025 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11026 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11027 if (rs == 0 || rs == rt) {
11028 /* OPC_BLEZALC, OPC_BGEZALC */
11029 /* OPC_BGTZALC, OPC_BLTZALC */
11030 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11031 }
11032 gen_load_gpr(t0, rs);
11033 gen_load_gpr(t1, rt);
11034 bcond_compute = 1;
11035 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11036 break;
11037 case OPC_BC:
11038 case OPC_BALC:
11039 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11040 break;
11041 case OPC_BEQZC:
11042 case OPC_BNEZC:
11043 if (rs != 0) {
11044 /* OPC_BEQZC, OPC_BNEZC */
11045 gen_load_gpr(t0, rs);
11046 bcond_compute = 1;
11047 ctx->btarget = addr_add(ctx, ctx->base.pc_next + 4, offset);
11048 } else {
11049 /* OPC_JIC, OPC_JIALC */
11050 TCGv tbase = tcg_temp_new();
11051
11052 gen_load_gpr(tbase, rt);
11053 gen_op_addr_addi(ctx, btarget, tbase, offset);
11054 }
11055 break;
11056 default:
11057 MIPS_INVAL("Compact branch/jump");
11058 gen_reserved_instruction(ctx);
11059 return;
11060 }
11061
11062 if (bcond_compute == 0) {
11063 /* Unconditional compact branch */
11064 switch (opc) {
11065 case OPC_JIALC:
11066 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11067 /* Fallthrough */
11068 case OPC_JIC:
11069 ctx->hflags |= MIPS_HFLAG_BR;
11070 break;
11071 case OPC_BALC:
11072 tcg_gen_movi_tl(cpu_gpr[31], ctx->base.pc_next + 4 + m16_lowbit);
11073 /* Fallthrough */
11074 case OPC_BC:
11075 ctx->hflags |= MIPS_HFLAG_B;
11076 break;
11077 default:
11078 MIPS_INVAL("Compact branch/jump");
11079 gen_reserved_instruction(ctx);
11080 return;
11081 }
11082
11083 /* Generating branch here as compact branches don't have delay slot */
11084 gen_branch(ctx, 4);
11085 } else {
11086 /* Conditional compact branch */
11087 TCGLabel *fs = gen_new_label();
11088 save_cpu_state(ctx, 0);
11089
11090 switch (opc) {
11091 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC */
11092 if (rs == 0 && rt != 0) {
11093 /* OPC_BLEZALC */
11094 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11095 } else if (rs != 0 && rt != 0 && rs == rt) {
11096 /* OPC_BGEZALC */
11097 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11098 } else {
11099 /* OPC_BGEUC */
11100 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GEU), t0, t1, fs);
11101 }
11102 break;
11103 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC */
11104 if (rs == 0 && rt != 0) {
11105 /* OPC_BGTZALC */
11106 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11107 } else if (rs != 0 && rt != 0 && rs == rt) {
11108 /* OPC_BLTZALC */
11109 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11110 } else {
11111 /* OPC_BLTUC */
11112 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LTU), t0, t1, fs);
11113 }
11114 break;
11115 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC */
11116 if (rs == 0 && rt != 0) {
11117 /* OPC_BLEZC */
11118 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LE), t1, 0, fs);
11119 } else if (rs != 0 && rt != 0 && rs == rt) {
11120 /* OPC_BGEZC */
11121 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GE), t1, 0, fs);
11122 } else {
11123 /* OPC_BGEC */
11124 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_GE), t0, t1, fs);
11125 }
11126 break;
11127 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC */
11128 if (rs == 0 && rt != 0) {
11129 /* OPC_BGTZC */
11130 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_GT), t1, 0, fs);
11131 } else if (rs != 0 && rt != 0 && rs == rt) {
11132 /* OPC_BLTZC */
11133 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_LT), t1, 0, fs);
11134 } else {
11135 /* OPC_BLTC */
11136 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_LT), t0, t1, fs);
11137 }
11138 break;
11139 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC */
11140 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
11141 if (rs >= rt) {
11142 /* OPC_BOVC, OPC_BNVC */
11143 TCGv t2 = tcg_temp_new();
11144 TCGv t3 = tcg_temp_new();
11145 TCGv t4 = tcg_temp_new();
11146 TCGv input_overflow = tcg_temp_new();
11147
11148 gen_load_gpr(t0, rs);
11149 gen_load_gpr(t1, rt);
11150 tcg_gen_ext32s_tl(t2, t0);
11151 tcg_gen_setcond_tl(TCG_COND_NE, input_overflow, t2, t0);
11152 tcg_gen_ext32s_tl(t3, t1);
11153 tcg_gen_setcond_tl(TCG_COND_NE, t4, t3, t1);
11154 tcg_gen_or_tl(input_overflow, input_overflow, t4);
11155
11156 tcg_gen_add_tl(t4, t2, t3);
11157 tcg_gen_ext32s_tl(t4, t4);
11158 tcg_gen_xor_tl(t2, t2, t3);
11159 tcg_gen_xor_tl(t3, t4, t3);
11160 tcg_gen_andc_tl(t2, t3, t2);
11161 tcg_gen_setcondi_tl(TCG_COND_LT, t4, t2, 0);
11162 tcg_gen_or_tl(t4, t4, input_overflow);
11163 if (opc == OPC_BOVC) {
11164 /* OPC_BOVC */
11165 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t4, 0, fs);
11166 } else {
11167 /* OPC_BNVC */
11168 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t4, 0, fs);
11169 }
11170 } else if (rs < rt && rs == 0) {
11171 /* OPC_BEQZALC, OPC_BNEZALC */
11172 if (opc == OPC_BEQZALC) {
11173 /* OPC_BEQZALC */
11174 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t1, 0, fs);
11175 } else {
11176 /* OPC_BNEZALC */
11177 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t1, 0, fs);
11178 }
11179 } else {
11180 /* OPC_BEQC, OPC_BNEC */
11181 if (opc == OPC_BEQC) {
11182 /* OPC_BEQC */
11183 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_EQ), t0, t1, fs);
11184 } else {
11185 /* OPC_BNEC */
11186 tcg_gen_brcond_tl(tcg_invert_cond(TCG_COND_NE), t0, t1, fs);
11187 }
11188 }
11189 break;
11190 case OPC_BEQZC:
11191 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_EQ), t0, 0, fs);
11192 break;
11193 case OPC_BNEZC:
11194 tcg_gen_brcondi_tl(tcg_invert_cond(TCG_COND_NE), t0, 0, fs);
11195 break;
11196 default:
11197 MIPS_INVAL("Compact conditional branch/jump");
11198 gen_reserved_instruction(ctx);
11199 return;
11200 }
11201
11202 /* Generating branch here as compact branches don't have delay slot */
11203 gen_goto_tb(ctx, 1, ctx->btarget);
11204 gen_set_label(fs);
11205
11206 ctx->hflags |= MIPS_HFLAG_FBNSLOT;
11207 }
11208 }
11209
gen_addiupc(DisasContext * ctx,int rx,int imm,int is_64_bit,int extended)11210 void gen_addiupc(DisasContext *ctx, int rx, int imm,
11211 int is_64_bit, int extended)
11212 {
11213 target_ulong npc;
11214
11215 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
11216 gen_reserved_instruction(ctx);
11217 return;
11218 }
11219
11220 npc = pc_relative_pc(ctx) + imm;
11221 if (!is_64_bit) {
11222 npc = (int32_t)npc;
11223 }
11224 tcg_gen_movi_tl(cpu_gpr[rx], npc);
11225 }
11226
gen_cache_operation(DisasContext * ctx,uint32_t op,int base,int16_t offset)11227 static void gen_cache_operation(DisasContext *ctx, uint32_t op, int base,
11228 int16_t offset)
11229 {
11230 TCGv_i32 t0 = tcg_constant_i32(op);
11231 TCGv t1 = tcg_temp_new();
11232 gen_base_offset_addr(ctx, t1, base, offset);
11233 gen_helper_cache(tcg_env, t1, t0);
11234 }
11235
is_uhi(DisasContext * ctx,int sdbbp_code)11236 static inline bool is_uhi(DisasContext *ctx, int sdbbp_code)
11237 {
11238 #ifdef CONFIG_USER_ONLY
11239 return false;
11240 #else
11241 bool is_user = (ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM;
11242 return semihosting_enabled(is_user) && sdbbp_code == 1;
11243 #endif
11244 }
11245
gen_ldxs(DisasContext * ctx,int base,int index,int rd)11246 void gen_ldxs(DisasContext *ctx, int base, int index, int rd)
11247 {
11248 TCGv t0 = tcg_temp_new();
11249 TCGv t1 = tcg_temp_new();
11250
11251 gen_load_gpr(t0, base);
11252
11253 if (index != 0) {
11254 gen_load_gpr(t1, index);
11255 tcg_gen_shli_tl(t1, t1, 2);
11256 gen_op_addr_add(ctx, t0, t1, t0);
11257 }
11258
11259 tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
11260 gen_store_gpr(t1, rd);
11261 }
11262
gen_sync(int stype)11263 static void gen_sync(int stype)
11264 {
11265 TCGBar tcg_mo = TCG_BAR_SC;
11266
11267 switch (stype) {
11268 case 0x4: /* SYNC_WMB */
11269 tcg_mo |= TCG_MO_ST_ST;
11270 break;
11271 case 0x10: /* SYNC_MB */
11272 tcg_mo |= TCG_MO_ALL;
11273 break;
11274 case 0x11: /* SYNC_ACQUIRE */
11275 tcg_mo |= TCG_MO_LD_LD | TCG_MO_LD_ST;
11276 break;
11277 case 0x12: /* SYNC_RELEASE */
11278 tcg_mo |= TCG_MO_ST_ST | TCG_MO_LD_ST;
11279 break;
11280 case 0x13: /* SYNC_RMB */
11281 tcg_mo |= TCG_MO_LD_LD;
11282 break;
11283 default:
11284 tcg_mo |= TCG_MO_ALL;
11285 break;
11286 }
11287
11288 tcg_gen_mb(tcg_mo);
11289 }
11290
11291 /* ISA extensions (ASEs) */
11292
11293 /* MIPS16 extension to MIPS32 */
11294 #include "mips16e_translate.c.inc"
11295
11296 /* microMIPS extension to MIPS32/MIPS64 */
11297
11298 /*
11299 * Values for microMIPS fmt field. Variable-width, depending on which
11300 * formats the instruction supports.
11301 */
11302 enum {
11303 FMT_SD_S = 0,
11304 FMT_SD_D = 1,
11305
11306 FMT_SDPS_S = 0,
11307 FMT_SDPS_D = 1,
11308 FMT_SDPS_PS = 2,
11309
11310 FMT_SWL_S = 0,
11311 FMT_SWL_W = 1,
11312 FMT_SWL_L = 2,
11313
11314 FMT_DWL_D = 0,
11315 FMT_DWL_W = 1,
11316 FMT_DWL_L = 2
11317 };
11318
11319 #include "micromips_translate.c.inc"
11320
11321 #include "nanomips_translate.c.inc"
11322
11323 /* MIPSDSP functions. */
11324
11325 /* Indexed load is not for DSP only */
gen_mips_lx(DisasContext * ctx,uint32_t opc,int rd,int base,int offset)11326 static void gen_mips_lx(DisasContext *ctx, uint32_t opc,
11327 int rd, int base, int offset)
11328 {
11329 TCGv t0;
11330
11331 if (!(ctx->insn_flags & INSN_OCTEON)) {
11332 check_dsp(ctx);
11333 }
11334 t0 = tcg_temp_new();
11335
11336 if (base == 0) {
11337 gen_load_gpr(t0, offset);
11338 } else if (offset == 0) {
11339 gen_load_gpr(t0, base);
11340 } else {
11341 gen_op_addr_add(ctx, t0, cpu_gpr[base], cpu_gpr[offset]);
11342 }
11343
11344 switch (opc) {
11345 case OPC_LBUX:
11346 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_UB);
11347 gen_store_gpr(t0, rd);
11348 break;
11349 case OPC_LHX:
11350 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SW);
11351 gen_store_gpr(t0, rd);
11352 break;
11353 case OPC_LWX:
11354 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_SL);
11355 gen_store_gpr(t0, rd);
11356 break;
11357 #if defined(TARGET_MIPS64)
11358 case OPC_LDX:
11359 tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, mo_endian(ctx) | MO_UQ);
11360 gen_store_gpr(t0, rd);
11361 break;
11362 #endif
11363 }
11364 }
11365
gen_mipsdsp_arith(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2)11366 static void gen_mipsdsp_arith(DisasContext *ctx, uint32_t op1, uint32_t op2,
11367 int ret, int v1, int v2)
11368 {
11369 TCGv v1_t;
11370 TCGv v2_t;
11371
11372 if (ret == 0) {
11373 /* Treat as NOP. */
11374 return;
11375 }
11376
11377 v1_t = tcg_temp_new();
11378 v2_t = tcg_temp_new();
11379
11380 gen_load_gpr(v1_t, v1);
11381 gen_load_gpr(v2_t, v2);
11382
11383 switch (op1) {
11384 case OPC_ADDUH_QB_DSP:
11385 check_dsp_r2(ctx);
11386 switch (op2) {
11387 case OPC_ADDUH_QB:
11388 gen_helper_adduh_qb(cpu_gpr[ret], v1_t, v2_t);
11389 break;
11390 case OPC_ADDUH_R_QB:
11391 gen_helper_adduh_r_qb(cpu_gpr[ret], v1_t, v2_t);
11392 break;
11393 case OPC_ADDQH_PH:
11394 gen_helper_addqh_ph(cpu_gpr[ret], v1_t, v2_t);
11395 break;
11396 case OPC_ADDQH_R_PH:
11397 gen_helper_addqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
11398 break;
11399 case OPC_ADDQH_W:
11400 gen_helper_addqh_w(cpu_gpr[ret], v1_t, v2_t);
11401 break;
11402 case OPC_ADDQH_R_W:
11403 gen_helper_addqh_r_w(cpu_gpr[ret], v1_t, v2_t);
11404 break;
11405 case OPC_SUBUH_QB:
11406 gen_helper_subuh_qb(cpu_gpr[ret], v1_t, v2_t);
11407 break;
11408 case OPC_SUBUH_R_QB:
11409 gen_helper_subuh_r_qb(cpu_gpr[ret], v1_t, v2_t);
11410 break;
11411 case OPC_SUBQH_PH:
11412 gen_helper_subqh_ph(cpu_gpr[ret], v1_t, v2_t);
11413 break;
11414 case OPC_SUBQH_R_PH:
11415 gen_helper_subqh_r_ph(cpu_gpr[ret], v1_t, v2_t);
11416 break;
11417 case OPC_SUBQH_W:
11418 gen_helper_subqh_w(cpu_gpr[ret], v1_t, v2_t);
11419 break;
11420 case OPC_SUBQH_R_W:
11421 gen_helper_subqh_r_w(cpu_gpr[ret], v1_t, v2_t);
11422 break;
11423 }
11424 break;
11425 case OPC_ABSQ_S_PH_DSP:
11426 switch (op2) {
11427 case OPC_ABSQ_S_QB:
11428 check_dsp_r2(ctx);
11429 gen_helper_absq_s_qb(cpu_gpr[ret], v2_t, tcg_env);
11430 break;
11431 case OPC_ABSQ_S_PH:
11432 check_dsp(ctx);
11433 gen_helper_absq_s_ph(cpu_gpr[ret], v2_t, tcg_env);
11434 break;
11435 case OPC_ABSQ_S_W:
11436 check_dsp(ctx);
11437 gen_helper_absq_s_w(cpu_gpr[ret], v2_t, tcg_env);
11438 break;
11439 case OPC_PRECEQ_W_PHL:
11440 check_dsp(ctx);
11441 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFF0000);
11442 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
11443 break;
11444 case OPC_PRECEQ_W_PHR:
11445 check_dsp(ctx);
11446 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0x0000FFFF);
11447 tcg_gen_shli_tl(cpu_gpr[ret], cpu_gpr[ret], 16);
11448 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
11449 break;
11450 case OPC_PRECEQU_PH_QBL:
11451 check_dsp(ctx);
11452 gen_helper_precequ_ph_qbl(cpu_gpr[ret], v2_t);
11453 break;
11454 case OPC_PRECEQU_PH_QBR:
11455 check_dsp(ctx);
11456 gen_helper_precequ_ph_qbr(cpu_gpr[ret], v2_t);
11457 break;
11458 case OPC_PRECEQU_PH_QBLA:
11459 check_dsp(ctx);
11460 gen_helper_precequ_ph_qbla(cpu_gpr[ret], v2_t);
11461 break;
11462 case OPC_PRECEQU_PH_QBRA:
11463 check_dsp(ctx);
11464 gen_helper_precequ_ph_qbra(cpu_gpr[ret], v2_t);
11465 break;
11466 case OPC_PRECEU_PH_QBL:
11467 check_dsp(ctx);
11468 gen_helper_preceu_ph_qbl(cpu_gpr[ret], v2_t);
11469 break;
11470 case OPC_PRECEU_PH_QBR:
11471 check_dsp(ctx);
11472 gen_helper_preceu_ph_qbr(cpu_gpr[ret], v2_t);
11473 break;
11474 case OPC_PRECEU_PH_QBLA:
11475 check_dsp(ctx);
11476 gen_helper_preceu_ph_qbla(cpu_gpr[ret], v2_t);
11477 break;
11478 case OPC_PRECEU_PH_QBRA:
11479 check_dsp(ctx);
11480 gen_helper_preceu_ph_qbra(cpu_gpr[ret], v2_t);
11481 break;
11482 }
11483 break;
11484 case OPC_ADDU_QB_DSP:
11485 switch (op2) {
11486 case OPC_ADDQ_PH:
11487 check_dsp(ctx);
11488 gen_helper_addq_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11489 break;
11490 case OPC_ADDQ_S_PH:
11491 check_dsp(ctx);
11492 gen_helper_addq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11493 break;
11494 case OPC_ADDQ_S_W:
11495 check_dsp(ctx);
11496 gen_helper_addq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11497 break;
11498 case OPC_ADDU_QB:
11499 check_dsp(ctx);
11500 gen_helper_addu_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11501 break;
11502 case OPC_ADDU_S_QB:
11503 check_dsp(ctx);
11504 gen_helper_addu_s_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11505 break;
11506 case OPC_ADDU_PH:
11507 check_dsp_r2(ctx);
11508 gen_helper_addu_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11509 break;
11510 case OPC_ADDU_S_PH:
11511 check_dsp_r2(ctx);
11512 gen_helper_addu_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11513 break;
11514 case OPC_SUBQ_PH:
11515 check_dsp(ctx);
11516 gen_helper_subq_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11517 break;
11518 case OPC_SUBQ_S_PH:
11519 check_dsp(ctx);
11520 gen_helper_subq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11521 break;
11522 case OPC_SUBQ_S_W:
11523 check_dsp(ctx);
11524 gen_helper_subq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11525 break;
11526 case OPC_SUBU_QB:
11527 check_dsp(ctx);
11528 gen_helper_subu_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11529 break;
11530 case OPC_SUBU_S_QB:
11531 check_dsp(ctx);
11532 gen_helper_subu_s_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11533 break;
11534 case OPC_SUBU_PH:
11535 check_dsp_r2(ctx);
11536 gen_helper_subu_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11537 break;
11538 case OPC_SUBU_S_PH:
11539 check_dsp_r2(ctx);
11540 gen_helper_subu_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11541 break;
11542 case OPC_ADDSC:
11543 check_dsp(ctx);
11544 gen_helper_addsc(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11545 break;
11546 case OPC_ADDWC:
11547 check_dsp(ctx);
11548 gen_helper_addwc(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11549 break;
11550 case OPC_MODSUB:
11551 check_dsp(ctx);
11552 gen_helper_modsub(cpu_gpr[ret], v1_t, v2_t);
11553 break;
11554 case OPC_RADDU_W_QB:
11555 check_dsp(ctx);
11556 gen_helper_raddu_w_qb(cpu_gpr[ret], v1_t);
11557 break;
11558 }
11559 break;
11560 case OPC_CMPU_EQ_QB_DSP:
11561 switch (op2) {
11562 case OPC_PRECR_QB_PH:
11563 check_dsp_r2(ctx);
11564 gen_helper_precr_qb_ph(cpu_gpr[ret], v1_t, v2_t);
11565 break;
11566 case OPC_PRECRQ_QB_PH:
11567 check_dsp(ctx);
11568 gen_helper_precrq_qb_ph(cpu_gpr[ret], v1_t, v2_t);
11569 break;
11570 case OPC_PRECR_SRA_PH_W:
11571 check_dsp_r2(ctx);
11572 {
11573 TCGv_i32 sa_t = tcg_constant_i32(v2);
11574 gen_helper_precr_sra_ph_w(cpu_gpr[ret], sa_t, v1_t,
11575 cpu_gpr[ret]);
11576 break;
11577 }
11578 case OPC_PRECR_SRA_R_PH_W:
11579 check_dsp_r2(ctx);
11580 {
11581 TCGv_i32 sa_t = tcg_constant_i32(v2);
11582 gen_helper_precr_sra_r_ph_w(cpu_gpr[ret], sa_t, v1_t,
11583 cpu_gpr[ret]);
11584 break;
11585 }
11586 case OPC_PRECRQ_PH_W:
11587 check_dsp(ctx);
11588 gen_helper_precrq_ph_w(cpu_gpr[ret], v1_t, v2_t);
11589 break;
11590 case OPC_PRECRQ_RS_PH_W:
11591 check_dsp(ctx);
11592 gen_helper_precrq_rs_ph_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11593 break;
11594 case OPC_PRECRQU_S_QB_PH:
11595 check_dsp(ctx);
11596 gen_helper_precrqu_s_qb_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11597 break;
11598 }
11599 break;
11600 #ifdef TARGET_MIPS64
11601 case OPC_ABSQ_S_QH_DSP:
11602 switch (op2) {
11603 case OPC_PRECEQ_L_PWL:
11604 check_dsp(ctx);
11605 tcg_gen_andi_tl(cpu_gpr[ret], v2_t, 0xFFFFFFFF00000000ull);
11606 break;
11607 case OPC_PRECEQ_L_PWR:
11608 check_dsp(ctx);
11609 tcg_gen_shli_tl(cpu_gpr[ret], v2_t, 32);
11610 break;
11611 case OPC_PRECEQ_PW_QHL:
11612 check_dsp(ctx);
11613 gen_helper_preceq_pw_qhl(cpu_gpr[ret], v2_t);
11614 break;
11615 case OPC_PRECEQ_PW_QHR:
11616 check_dsp(ctx);
11617 gen_helper_preceq_pw_qhr(cpu_gpr[ret], v2_t);
11618 break;
11619 case OPC_PRECEQ_PW_QHLA:
11620 check_dsp(ctx);
11621 gen_helper_preceq_pw_qhla(cpu_gpr[ret], v2_t);
11622 break;
11623 case OPC_PRECEQ_PW_QHRA:
11624 check_dsp(ctx);
11625 gen_helper_preceq_pw_qhra(cpu_gpr[ret], v2_t);
11626 break;
11627 case OPC_PRECEQU_QH_OBL:
11628 check_dsp(ctx);
11629 gen_helper_precequ_qh_obl(cpu_gpr[ret], v2_t);
11630 break;
11631 case OPC_PRECEQU_QH_OBR:
11632 check_dsp(ctx);
11633 gen_helper_precequ_qh_obr(cpu_gpr[ret], v2_t);
11634 break;
11635 case OPC_PRECEQU_QH_OBLA:
11636 check_dsp(ctx);
11637 gen_helper_precequ_qh_obla(cpu_gpr[ret], v2_t);
11638 break;
11639 case OPC_PRECEQU_QH_OBRA:
11640 check_dsp(ctx);
11641 gen_helper_precequ_qh_obra(cpu_gpr[ret], v2_t);
11642 break;
11643 case OPC_PRECEU_QH_OBL:
11644 check_dsp(ctx);
11645 gen_helper_preceu_qh_obl(cpu_gpr[ret], v2_t);
11646 break;
11647 case OPC_PRECEU_QH_OBR:
11648 check_dsp(ctx);
11649 gen_helper_preceu_qh_obr(cpu_gpr[ret], v2_t);
11650 break;
11651 case OPC_PRECEU_QH_OBLA:
11652 check_dsp(ctx);
11653 gen_helper_preceu_qh_obla(cpu_gpr[ret], v2_t);
11654 break;
11655 case OPC_PRECEU_QH_OBRA:
11656 check_dsp(ctx);
11657 gen_helper_preceu_qh_obra(cpu_gpr[ret], v2_t);
11658 break;
11659 case OPC_ABSQ_S_OB:
11660 check_dsp_r2(ctx);
11661 gen_helper_absq_s_ob(cpu_gpr[ret], v2_t, tcg_env);
11662 break;
11663 case OPC_ABSQ_S_PW:
11664 check_dsp(ctx);
11665 gen_helper_absq_s_pw(cpu_gpr[ret], v2_t, tcg_env);
11666 break;
11667 case OPC_ABSQ_S_QH:
11668 check_dsp(ctx);
11669 gen_helper_absq_s_qh(cpu_gpr[ret], v2_t, tcg_env);
11670 break;
11671 }
11672 break;
11673 case OPC_ADDU_OB_DSP:
11674 switch (op2) {
11675 case OPC_RADDU_L_OB:
11676 check_dsp(ctx);
11677 gen_helper_raddu_l_ob(cpu_gpr[ret], v1_t);
11678 break;
11679 case OPC_SUBQ_PW:
11680 check_dsp(ctx);
11681 gen_helper_subq_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11682 break;
11683 case OPC_SUBQ_S_PW:
11684 check_dsp(ctx);
11685 gen_helper_subq_s_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11686 break;
11687 case OPC_SUBQ_QH:
11688 check_dsp(ctx);
11689 gen_helper_subq_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11690 break;
11691 case OPC_SUBQ_S_QH:
11692 check_dsp(ctx);
11693 gen_helper_subq_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11694 break;
11695 case OPC_SUBU_OB:
11696 check_dsp(ctx);
11697 gen_helper_subu_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11698 break;
11699 case OPC_SUBU_S_OB:
11700 check_dsp(ctx);
11701 gen_helper_subu_s_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11702 break;
11703 case OPC_SUBU_QH:
11704 check_dsp_r2(ctx);
11705 gen_helper_subu_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11706 break;
11707 case OPC_SUBU_S_QH:
11708 check_dsp_r2(ctx);
11709 gen_helper_subu_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11710 break;
11711 case OPC_SUBUH_OB:
11712 check_dsp_r2(ctx);
11713 gen_helper_subuh_ob(cpu_gpr[ret], v1_t, v2_t);
11714 break;
11715 case OPC_SUBUH_R_OB:
11716 check_dsp_r2(ctx);
11717 gen_helper_subuh_r_ob(cpu_gpr[ret], v1_t, v2_t);
11718 break;
11719 case OPC_ADDQ_PW:
11720 check_dsp(ctx);
11721 gen_helper_addq_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11722 break;
11723 case OPC_ADDQ_S_PW:
11724 check_dsp(ctx);
11725 gen_helper_addq_s_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11726 break;
11727 case OPC_ADDQ_QH:
11728 check_dsp(ctx);
11729 gen_helper_addq_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11730 break;
11731 case OPC_ADDQ_S_QH:
11732 check_dsp(ctx);
11733 gen_helper_addq_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11734 break;
11735 case OPC_ADDU_OB:
11736 check_dsp(ctx);
11737 gen_helper_addu_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11738 break;
11739 case OPC_ADDU_S_OB:
11740 check_dsp(ctx);
11741 gen_helper_addu_s_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11742 break;
11743 case OPC_ADDU_QH:
11744 check_dsp_r2(ctx);
11745 gen_helper_addu_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11746 break;
11747 case OPC_ADDU_S_QH:
11748 check_dsp_r2(ctx);
11749 gen_helper_addu_s_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11750 break;
11751 case OPC_ADDUH_OB:
11752 check_dsp_r2(ctx);
11753 gen_helper_adduh_ob(cpu_gpr[ret], v1_t, v2_t);
11754 break;
11755 case OPC_ADDUH_R_OB:
11756 check_dsp_r2(ctx);
11757 gen_helper_adduh_r_ob(cpu_gpr[ret], v1_t, v2_t);
11758 break;
11759 }
11760 break;
11761 case OPC_CMPU_EQ_OB_DSP:
11762 switch (op2) {
11763 case OPC_PRECR_OB_QH:
11764 check_dsp_r2(ctx);
11765 gen_helper_precr_ob_qh(cpu_gpr[ret], v1_t, v2_t);
11766 break;
11767 case OPC_PRECR_SRA_QH_PW:
11768 check_dsp_r2(ctx);
11769 {
11770 TCGv_i32 ret_t = tcg_constant_i32(ret);
11771 gen_helper_precr_sra_qh_pw(v2_t, v1_t, v2_t, ret_t);
11772 break;
11773 }
11774 case OPC_PRECR_SRA_R_QH_PW:
11775 check_dsp_r2(ctx);
11776 {
11777 TCGv_i32 sa_v = tcg_constant_i32(ret);
11778 gen_helper_precr_sra_r_qh_pw(v2_t, v1_t, v2_t, sa_v);
11779 break;
11780 }
11781 case OPC_PRECRQ_OB_QH:
11782 check_dsp(ctx);
11783 gen_helper_precrq_ob_qh(cpu_gpr[ret], v1_t, v2_t);
11784 break;
11785 case OPC_PRECRQ_PW_L:
11786 check_dsp(ctx);
11787 gen_helper_precrq_pw_l(cpu_gpr[ret], v1_t, v2_t);
11788 break;
11789 case OPC_PRECRQ_QH_PW:
11790 check_dsp(ctx);
11791 gen_helper_precrq_qh_pw(cpu_gpr[ret], v1_t, v2_t);
11792 break;
11793 case OPC_PRECRQ_RS_QH_PW:
11794 check_dsp(ctx);
11795 gen_helper_precrq_rs_qh_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11796 break;
11797 case OPC_PRECRQU_S_OB_QH:
11798 check_dsp(ctx);
11799 gen_helper_precrqu_s_ob_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11800 break;
11801 }
11802 break;
11803 #endif
11804 }
11805 }
11806
gen_mipsdsp_shift(DisasContext * ctx,uint32_t opc,int ret,int v1,int v2)11807 static void gen_mipsdsp_shift(DisasContext *ctx, uint32_t opc,
11808 int ret, int v1, int v2)
11809 {
11810 uint32_t op2;
11811 TCGv t0;
11812 TCGv v1_t;
11813 TCGv v2_t;
11814
11815 if (ret == 0) {
11816 /* Treat as NOP. */
11817 return;
11818 }
11819
11820 t0 = tcg_temp_new();
11821 v1_t = tcg_temp_new();
11822 v2_t = tcg_temp_new();
11823
11824 tcg_gen_movi_tl(t0, v1);
11825 gen_load_gpr(v1_t, v1);
11826 gen_load_gpr(v2_t, v2);
11827
11828 switch (opc) {
11829 case OPC_SHLL_QB_DSP:
11830 {
11831 op2 = MASK_SHLL_QB(ctx->opcode);
11832 switch (op2) {
11833 case OPC_SHLL_QB:
11834 check_dsp(ctx);
11835 gen_helper_shll_qb(cpu_gpr[ret], t0, v2_t, tcg_env);
11836 break;
11837 case OPC_SHLLV_QB:
11838 check_dsp(ctx);
11839 gen_helper_shll_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11840 break;
11841 case OPC_SHLL_PH:
11842 check_dsp(ctx);
11843 gen_helper_shll_ph(cpu_gpr[ret], t0, v2_t, tcg_env);
11844 break;
11845 case OPC_SHLLV_PH:
11846 check_dsp(ctx);
11847 gen_helper_shll_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11848 break;
11849 case OPC_SHLL_S_PH:
11850 check_dsp(ctx);
11851 gen_helper_shll_s_ph(cpu_gpr[ret], t0, v2_t, tcg_env);
11852 break;
11853 case OPC_SHLLV_S_PH:
11854 check_dsp(ctx);
11855 gen_helper_shll_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11856 break;
11857 case OPC_SHLL_S_W:
11858 check_dsp(ctx);
11859 gen_helper_shll_s_w(cpu_gpr[ret], t0, v2_t, tcg_env);
11860 break;
11861 case OPC_SHLLV_S_W:
11862 check_dsp(ctx);
11863 gen_helper_shll_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
11864 break;
11865 case OPC_SHRL_QB:
11866 check_dsp(ctx);
11867 gen_helper_shrl_qb(cpu_gpr[ret], t0, v2_t);
11868 break;
11869 case OPC_SHRLV_QB:
11870 check_dsp(ctx);
11871 gen_helper_shrl_qb(cpu_gpr[ret], v1_t, v2_t);
11872 break;
11873 case OPC_SHRL_PH:
11874 check_dsp_r2(ctx);
11875 gen_helper_shrl_ph(cpu_gpr[ret], t0, v2_t);
11876 break;
11877 case OPC_SHRLV_PH:
11878 check_dsp_r2(ctx);
11879 gen_helper_shrl_ph(cpu_gpr[ret], v1_t, v2_t);
11880 break;
11881 case OPC_SHRA_QB:
11882 check_dsp_r2(ctx);
11883 gen_helper_shra_qb(cpu_gpr[ret], t0, v2_t);
11884 break;
11885 case OPC_SHRA_R_QB:
11886 check_dsp_r2(ctx);
11887 gen_helper_shra_r_qb(cpu_gpr[ret], t0, v2_t);
11888 break;
11889 case OPC_SHRAV_QB:
11890 check_dsp_r2(ctx);
11891 gen_helper_shra_qb(cpu_gpr[ret], v1_t, v2_t);
11892 break;
11893 case OPC_SHRAV_R_QB:
11894 check_dsp_r2(ctx);
11895 gen_helper_shra_r_qb(cpu_gpr[ret], v1_t, v2_t);
11896 break;
11897 case OPC_SHRA_PH:
11898 check_dsp(ctx);
11899 gen_helper_shra_ph(cpu_gpr[ret], t0, v2_t);
11900 break;
11901 case OPC_SHRA_R_PH:
11902 check_dsp(ctx);
11903 gen_helper_shra_r_ph(cpu_gpr[ret], t0, v2_t);
11904 break;
11905 case OPC_SHRAV_PH:
11906 check_dsp(ctx);
11907 gen_helper_shra_ph(cpu_gpr[ret], v1_t, v2_t);
11908 break;
11909 case OPC_SHRAV_R_PH:
11910 check_dsp(ctx);
11911 gen_helper_shra_r_ph(cpu_gpr[ret], v1_t, v2_t);
11912 break;
11913 case OPC_SHRA_R_W:
11914 check_dsp(ctx);
11915 gen_helper_shra_r_w(cpu_gpr[ret], t0, v2_t);
11916 break;
11917 case OPC_SHRAV_R_W:
11918 check_dsp(ctx);
11919 gen_helper_shra_r_w(cpu_gpr[ret], v1_t, v2_t);
11920 break;
11921 default: /* Invalid */
11922 MIPS_INVAL("MASK SHLL.QB");
11923 gen_reserved_instruction(ctx);
11924 break;
11925 }
11926 break;
11927 }
11928 #ifdef TARGET_MIPS64
11929 case OPC_SHLL_OB_DSP:
11930 op2 = MASK_SHLL_OB(ctx->opcode);
11931 switch (op2) {
11932 case OPC_SHLL_PW:
11933 check_dsp(ctx);
11934 gen_helper_shll_pw(cpu_gpr[ret], v2_t, t0, tcg_env);
11935 break;
11936 case OPC_SHLLV_PW:
11937 check_dsp(ctx);
11938 gen_helper_shll_pw(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11939 break;
11940 case OPC_SHLL_S_PW:
11941 check_dsp(ctx);
11942 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, t0, tcg_env);
11943 break;
11944 case OPC_SHLLV_S_PW:
11945 check_dsp(ctx);
11946 gen_helper_shll_s_pw(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11947 break;
11948 case OPC_SHLL_OB:
11949 check_dsp(ctx);
11950 gen_helper_shll_ob(cpu_gpr[ret], v2_t, t0, tcg_env);
11951 break;
11952 case OPC_SHLLV_OB:
11953 check_dsp(ctx);
11954 gen_helper_shll_ob(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11955 break;
11956 case OPC_SHLL_QH:
11957 check_dsp(ctx);
11958 gen_helper_shll_qh(cpu_gpr[ret], v2_t, t0, tcg_env);
11959 break;
11960 case OPC_SHLLV_QH:
11961 check_dsp(ctx);
11962 gen_helper_shll_qh(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11963 break;
11964 case OPC_SHLL_S_QH:
11965 check_dsp(ctx);
11966 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, t0, tcg_env);
11967 break;
11968 case OPC_SHLLV_S_QH:
11969 check_dsp(ctx);
11970 gen_helper_shll_s_qh(cpu_gpr[ret], v2_t, v1_t, tcg_env);
11971 break;
11972 case OPC_SHRA_OB:
11973 check_dsp_r2(ctx);
11974 gen_helper_shra_ob(cpu_gpr[ret], v2_t, t0);
11975 break;
11976 case OPC_SHRAV_OB:
11977 check_dsp_r2(ctx);
11978 gen_helper_shra_ob(cpu_gpr[ret], v2_t, v1_t);
11979 break;
11980 case OPC_SHRA_R_OB:
11981 check_dsp_r2(ctx);
11982 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, t0);
11983 break;
11984 case OPC_SHRAV_R_OB:
11985 check_dsp_r2(ctx);
11986 gen_helper_shra_r_ob(cpu_gpr[ret], v2_t, v1_t);
11987 break;
11988 case OPC_SHRA_PW:
11989 check_dsp(ctx);
11990 gen_helper_shra_pw(cpu_gpr[ret], v2_t, t0);
11991 break;
11992 case OPC_SHRAV_PW:
11993 check_dsp(ctx);
11994 gen_helper_shra_pw(cpu_gpr[ret], v2_t, v1_t);
11995 break;
11996 case OPC_SHRA_R_PW:
11997 check_dsp(ctx);
11998 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, t0);
11999 break;
12000 case OPC_SHRAV_R_PW:
12001 check_dsp(ctx);
12002 gen_helper_shra_r_pw(cpu_gpr[ret], v2_t, v1_t);
12003 break;
12004 case OPC_SHRA_QH:
12005 check_dsp(ctx);
12006 gen_helper_shra_qh(cpu_gpr[ret], v2_t, t0);
12007 break;
12008 case OPC_SHRAV_QH:
12009 check_dsp(ctx);
12010 gen_helper_shra_qh(cpu_gpr[ret], v2_t, v1_t);
12011 break;
12012 case OPC_SHRA_R_QH:
12013 check_dsp(ctx);
12014 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, t0);
12015 break;
12016 case OPC_SHRAV_R_QH:
12017 check_dsp(ctx);
12018 gen_helper_shra_r_qh(cpu_gpr[ret], v2_t, v1_t);
12019 break;
12020 case OPC_SHRL_OB:
12021 check_dsp(ctx);
12022 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, t0);
12023 break;
12024 case OPC_SHRLV_OB:
12025 check_dsp(ctx);
12026 gen_helper_shrl_ob(cpu_gpr[ret], v2_t, v1_t);
12027 break;
12028 case OPC_SHRL_QH:
12029 check_dsp_r2(ctx);
12030 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, t0);
12031 break;
12032 case OPC_SHRLV_QH:
12033 check_dsp_r2(ctx);
12034 gen_helper_shrl_qh(cpu_gpr[ret], v2_t, v1_t);
12035 break;
12036 default: /* Invalid */
12037 MIPS_INVAL("MASK SHLL.OB");
12038 gen_reserved_instruction(ctx);
12039 break;
12040 }
12041 break;
12042 #endif
12043 }
12044 }
12045
gen_mipsdsp_multiply(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2,int check_ret)12046 static void gen_mipsdsp_multiply(DisasContext *ctx, uint32_t op1, uint32_t op2,
12047 int ret, int v1, int v2, int check_ret)
12048 {
12049 TCGv_i32 t0;
12050 TCGv v1_t;
12051 TCGv v2_t;
12052
12053 if ((ret == 0) && (check_ret == 1)) {
12054 /* Treat as NOP. */
12055 return;
12056 }
12057
12058 t0 = tcg_temp_new_i32();
12059 v1_t = tcg_temp_new();
12060 v2_t = tcg_temp_new();
12061
12062 tcg_gen_movi_i32(t0, ret);
12063 gen_load_gpr(v1_t, v1);
12064 gen_load_gpr(v2_t, v2);
12065
12066 switch (op1) {
12067 case OPC_MUL_PH_DSP:
12068 check_dsp_r2(ctx);
12069 switch (op2) {
12070 case OPC_MUL_PH:
12071 gen_helper_mul_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12072 break;
12073 case OPC_MUL_S_PH:
12074 gen_helper_mul_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12075 break;
12076 case OPC_MULQ_S_W:
12077 gen_helper_mulq_s_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12078 break;
12079 case OPC_MULQ_RS_W:
12080 gen_helper_mulq_rs_w(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12081 break;
12082 }
12083 break;
12084 case OPC_DPA_W_PH_DSP:
12085 switch (op2) {
12086 case OPC_DPAU_H_QBL:
12087 check_dsp(ctx);
12088 gen_helper_dpau_h_qbl(t0, v1_t, v2_t, tcg_env);
12089 break;
12090 case OPC_DPAU_H_QBR:
12091 check_dsp(ctx);
12092 gen_helper_dpau_h_qbr(t0, v1_t, v2_t, tcg_env);
12093 break;
12094 case OPC_DPSU_H_QBL:
12095 check_dsp(ctx);
12096 gen_helper_dpsu_h_qbl(t0, v1_t, v2_t, tcg_env);
12097 break;
12098 case OPC_DPSU_H_QBR:
12099 check_dsp(ctx);
12100 gen_helper_dpsu_h_qbr(t0, v1_t, v2_t, tcg_env);
12101 break;
12102 case OPC_DPA_W_PH:
12103 check_dsp_r2(ctx);
12104 gen_helper_dpa_w_ph(t0, v1_t, v2_t, tcg_env);
12105 break;
12106 case OPC_DPAX_W_PH:
12107 check_dsp_r2(ctx);
12108 gen_helper_dpax_w_ph(t0, v1_t, v2_t, tcg_env);
12109 break;
12110 case OPC_DPAQ_S_W_PH:
12111 check_dsp(ctx);
12112 gen_helper_dpaq_s_w_ph(t0, v1_t, v2_t, tcg_env);
12113 break;
12114 case OPC_DPAQX_S_W_PH:
12115 check_dsp_r2(ctx);
12116 gen_helper_dpaqx_s_w_ph(t0, v1_t, v2_t, tcg_env);
12117 break;
12118 case OPC_DPAQX_SA_W_PH:
12119 check_dsp_r2(ctx);
12120 gen_helper_dpaqx_sa_w_ph(t0, v1_t, v2_t, tcg_env);
12121 break;
12122 case OPC_DPS_W_PH:
12123 check_dsp_r2(ctx);
12124 gen_helper_dps_w_ph(t0, v1_t, v2_t, tcg_env);
12125 break;
12126 case OPC_DPSX_W_PH:
12127 check_dsp_r2(ctx);
12128 gen_helper_dpsx_w_ph(t0, v1_t, v2_t, tcg_env);
12129 break;
12130 case OPC_DPSQ_S_W_PH:
12131 check_dsp(ctx);
12132 gen_helper_dpsq_s_w_ph(t0, v1_t, v2_t, tcg_env);
12133 break;
12134 case OPC_DPSQX_S_W_PH:
12135 check_dsp_r2(ctx);
12136 gen_helper_dpsqx_s_w_ph(t0, v1_t, v2_t, tcg_env);
12137 break;
12138 case OPC_DPSQX_SA_W_PH:
12139 check_dsp_r2(ctx);
12140 gen_helper_dpsqx_sa_w_ph(t0, v1_t, v2_t, tcg_env);
12141 break;
12142 case OPC_MULSAQ_S_W_PH:
12143 check_dsp(ctx);
12144 gen_helper_mulsaq_s_w_ph(t0, v1_t, v2_t, tcg_env);
12145 break;
12146 case OPC_DPAQ_SA_L_W:
12147 check_dsp(ctx);
12148 gen_helper_dpaq_sa_l_w(t0, v1_t, v2_t, tcg_env);
12149 break;
12150 case OPC_DPSQ_SA_L_W:
12151 check_dsp(ctx);
12152 gen_helper_dpsq_sa_l_w(t0, v1_t, v2_t, tcg_env);
12153 break;
12154 case OPC_MAQ_S_W_PHL:
12155 check_dsp(ctx);
12156 gen_helper_maq_s_w_phl(t0, v1_t, v2_t, tcg_env);
12157 break;
12158 case OPC_MAQ_S_W_PHR:
12159 check_dsp(ctx);
12160 gen_helper_maq_s_w_phr(t0, v1_t, v2_t, tcg_env);
12161 break;
12162 case OPC_MAQ_SA_W_PHL:
12163 check_dsp(ctx);
12164 gen_helper_maq_sa_w_phl(t0, v1_t, v2_t, tcg_env);
12165 break;
12166 case OPC_MAQ_SA_W_PHR:
12167 check_dsp(ctx);
12168 gen_helper_maq_sa_w_phr(t0, v1_t, v2_t, tcg_env);
12169 break;
12170 case OPC_MULSA_W_PH:
12171 check_dsp_r2(ctx);
12172 gen_helper_mulsa_w_ph(t0, v1_t, v2_t, tcg_env);
12173 break;
12174 }
12175 break;
12176 #ifdef TARGET_MIPS64
12177 case OPC_DPAQ_W_QH_DSP:
12178 {
12179 int ac = ret & 0x03;
12180 tcg_gen_movi_i32(t0, ac);
12181
12182 switch (op2) {
12183 case OPC_DMADD:
12184 check_dsp(ctx);
12185 gen_helper_dmadd(v1_t, v2_t, t0, tcg_env);
12186 break;
12187 case OPC_DMADDU:
12188 check_dsp(ctx);
12189 gen_helper_dmaddu(v1_t, v2_t, t0, tcg_env);
12190 break;
12191 case OPC_DMSUB:
12192 check_dsp(ctx);
12193 gen_helper_dmsub(v1_t, v2_t, t0, tcg_env);
12194 break;
12195 case OPC_DMSUBU:
12196 check_dsp(ctx);
12197 gen_helper_dmsubu(v1_t, v2_t, t0, tcg_env);
12198 break;
12199 case OPC_DPA_W_QH:
12200 check_dsp_r2(ctx);
12201 gen_helper_dpa_w_qh(v1_t, v2_t, t0, tcg_env);
12202 break;
12203 case OPC_DPAQ_S_W_QH:
12204 check_dsp(ctx);
12205 gen_helper_dpaq_s_w_qh(v1_t, v2_t, t0, tcg_env);
12206 break;
12207 case OPC_DPAQ_SA_L_PW:
12208 check_dsp(ctx);
12209 gen_helper_dpaq_sa_l_pw(v1_t, v2_t, t0, tcg_env);
12210 break;
12211 case OPC_DPAU_H_OBL:
12212 check_dsp(ctx);
12213 gen_helper_dpau_h_obl(v1_t, v2_t, t0, tcg_env);
12214 break;
12215 case OPC_DPAU_H_OBR:
12216 check_dsp(ctx);
12217 gen_helper_dpau_h_obr(v1_t, v2_t, t0, tcg_env);
12218 break;
12219 case OPC_DPS_W_QH:
12220 check_dsp_r2(ctx);
12221 gen_helper_dps_w_qh(v1_t, v2_t, t0, tcg_env);
12222 break;
12223 case OPC_DPSQ_S_W_QH:
12224 check_dsp(ctx);
12225 gen_helper_dpsq_s_w_qh(v1_t, v2_t, t0, tcg_env);
12226 break;
12227 case OPC_DPSQ_SA_L_PW:
12228 check_dsp(ctx);
12229 gen_helper_dpsq_sa_l_pw(v1_t, v2_t, t0, tcg_env);
12230 break;
12231 case OPC_DPSU_H_OBL:
12232 check_dsp(ctx);
12233 gen_helper_dpsu_h_obl(v1_t, v2_t, t0, tcg_env);
12234 break;
12235 case OPC_DPSU_H_OBR:
12236 check_dsp(ctx);
12237 gen_helper_dpsu_h_obr(v1_t, v2_t, t0, tcg_env);
12238 break;
12239 case OPC_MAQ_S_L_PWL:
12240 check_dsp(ctx);
12241 gen_helper_maq_s_l_pwl(v1_t, v2_t, t0, tcg_env);
12242 break;
12243 case OPC_MAQ_S_L_PWR:
12244 check_dsp(ctx);
12245 gen_helper_maq_s_l_pwr(v1_t, v2_t, t0, tcg_env);
12246 break;
12247 case OPC_MAQ_S_W_QHLL:
12248 check_dsp(ctx);
12249 gen_helper_maq_s_w_qhll(v1_t, v2_t, t0, tcg_env);
12250 break;
12251 case OPC_MAQ_SA_W_QHLL:
12252 check_dsp(ctx);
12253 gen_helper_maq_sa_w_qhll(v1_t, v2_t, t0, tcg_env);
12254 break;
12255 case OPC_MAQ_S_W_QHLR:
12256 check_dsp(ctx);
12257 gen_helper_maq_s_w_qhlr(v1_t, v2_t, t0, tcg_env);
12258 break;
12259 case OPC_MAQ_SA_W_QHLR:
12260 check_dsp(ctx);
12261 gen_helper_maq_sa_w_qhlr(v1_t, v2_t, t0, tcg_env);
12262 break;
12263 case OPC_MAQ_S_W_QHRL:
12264 check_dsp(ctx);
12265 gen_helper_maq_s_w_qhrl(v1_t, v2_t, t0, tcg_env);
12266 break;
12267 case OPC_MAQ_SA_W_QHRL:
12268 check_dsp(ctx);
12269 gen_helper_maq_sa_w_qhrl(v1_t, v2_t, t0, tcg_env);
12270 break;
12271 case OPC_MAQ_S_W_QHRR:
12272 check_dsp(ctx);
12273 gen_helper_maq_s_w_qhrr(v1_t, v2_t, t0, tcg_env);
12274 break;
12275 case OPC_MAQ_SA_W_QHRR:
12276 check_dsp(ctx);
12277 gen_helper_maq_sa_w_qhrr(v1_t, v2_t, t0, tcg_env);
12278 break;
12279 case OPC_MULSAQ_S_L_PW:
12280 check_dsp(ctx);
12281 gen_helper_mulsaq_s_l_pw(v1_t, v2_t, t0, tcg_env);
12282 break;
12283 case OPC_MULSAQ_S_W_QH:
12284 check_dsp(ctx);
12285 gen_helper_mulsaq_s_w_qh(v1_t, v2_t, t0, tcg_env);
12286 break;
12287 }
12288 }
12289 break;
12290 #endif
12291 case OPC_ADDU_QB_DSP:
12292 switch (op2) {
12293 case OPC_MULEU_S_PH_QBL:
12294 check_dsp(ctx);
12295 gen_helper_muleu_s_ph_qbl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12296 break;
12297 case OPC_MULEU_S_PH_QBR:
12298 check_dsp(ctx);
12299 gen_helper_muleu_s_ph_qbr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12300 break;
12301 case OPC_MULQ_RS_PH:
12302 check_dsp(ctx);
12303 gen_helper_mulq_rs_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12304 break;
12305 case OPC_MULEQ_S_W_PHL:
12306 check_dsp(ctx);
12307 gen_helper_muleq_s_w_phl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12308 break;
12309 case OPC_MULEQ_S_W_PHR:
12310 check_dsp(ctx);
12311 gen_helper_muleq_s_w_phr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12312 break;
12313 case OPC_MULQ_S_PH:
12314 check_dsp_r2(ctx);
12315 gen_helper_mulq_s_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12316 break;
12317 }
12318 break;
12319 #ifdef TARGET_MIPS64
12320 case OPC_ADDU_OB_DSP:
12321 switch (op2) {
12322 case OPC_MULEQ_S_PW_QHL:
12323 check_dsp(ctx);
12324 gen_helper_muleq_s_pw_qhl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12325 break;
12326 case OPC_MULEQ_S_PW_QHR:
12327 check_dsp(ctx);
12328 gen_helper_muleq_s_pw_qhr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12329 break;
12330 case OPC_MULEU_S_QH_OBL:
12331 check_dsp(ctx);
12332 gen_helper_muleu_s_qh_obl(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12333 break;
12334 case OPC_MULEU_S_QH_OBR:
12335 check_dsp(ctx);
12336 gen_helper_muleu_s_qh_obr(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12337 break;
12338 case OPC_MULQ_RS_QH:
12339 check_dsp(ctx);
12340 gen_helper_mulq_rs_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12341 break;
12342 }
12343 break;
12344 #endif
12345 }
12346 }
12347
gen_mipsdsp_bitinsn(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int val)12348 static void gen_mipsdsp_bitinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
12349 int ret, int val)
12350 {
12351 int16_t imm;
12352 TCGv t0;
12353 TCGv val_t;
12354
12355 if (ret == 0) {
12356 /* Treat as NOP. */
12357 return;
12358 }
12359
12360 t0 = tcg_temp_new();
12361 val_t = tcg_temp_new();
12362 gen_load_gpr(val_t, val);
12363
12364 switch (op1) {
12365 case OPC_ABSQ_S_PH_DSP:
12366 switch (op2) {
12367 case OPC_BITREV:
12368 check_dsp(ctx);
12369 gen_helper_bitrev(cpu_gpr[ret], val_t);
12370 break;
12371 case OPC_REPL_QB:
12372 check_dsp(ctx);
12373 {
12374 target_long result;
12375 imm = (ctx->opcode >> 16) & 0xFF;
12376 result = (uint32_t)imm << 24 |
12377 (uint32_t)imm << 16 |
12378 (uint32_t)imm << 8 |
12379 (uint32_t)imm;
12380 result = (int32_t)result;
12381 tcg_gen_movi_tl(cpu_gpr[ret], result);
12382 }
12383 break;
12384 case OPC_REPLV_QB:
12385 check_dsp(ctx);
12386 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
12387 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
12388 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12389 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12390 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12391 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12392 break;
12393 case OPC_REPL_PH:
12394 check_dsp(ctx);
12395 {
12396 imm = (ctx->opcode >> 16) & 0x03FF;
12397 imm = (int16_t)(imm << 6) >> 6;
12398 tcg_gen_movi_tl(cpu_gpr[ret], \
12399 (target_long)((int32_t)imm << 16 | \
12400 (uint16_t)imm));
12401 }
12402 break;
12403 case OPC_REPLV_PH:
12404 check_dsp(ctx);
12405 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
12406 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12407 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12408 tcg_gen_ext32s_tl(cpu_gpr[ret], cpu_gpr[ret]);
12409 break;
12410 }
12411 break;
12412 #ifdef TARGET_MIPS64
12413 case OPC_ABSQ_S_QH_DSP:
12414 switch (op2) {
12415 case OPC_REPL_OB:
12416 check_dsp(ctx);
12417 {
12418 target_long temp;
12419
12420 imm = (ctx->opcode >> 16) & 0xFF;
12421 temp = ((uint64_t)imm << 8) | (uint64_t)imm;
12422 temp = (temp << 16) | temp;
12423 temp = (temp << 32) | temp;
12424 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12425 break;
12426 }
12427 case OPC_REPL_PW:
12428 check_dsp(ctx);
12429 {
12430 target_long temp;
12431
12432 imm = (ctx->opcode >> 16) & 0x03FF;
12433 imm = (int16_t)(imm << 6) >> 6;
12434 temp = ((target_long)imm << 32) \
12435 | ((target_long)imm & 0xFFFFFFFF);
12436 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12437 break;
12438 }
12439 case OPC_REPL_QH:
12440 check_dsp(ctx);
12441 {
12442 target_long temp;
12443
12444 imm = (ctx->opcode >> 16) & 0x03FF;
12445 imm = (int16_t)(imm << 6) >> 6;
12446
12447 temp = ((uint64_t)(uint16_t)imm << 48) |
12448 ((uint64_t)(uint16_t)imm << 32) |
12449 ((uint64_t)(uint16_t)imm << 16) |
12450 (uint64_t)(uint16_t)imm;
12451 tcg_gen_movi_tl(cpu_gpr[ret], temp);
12452 break;
12453 }
12454 case OPC_REPLV_OB:
12455 check_dsp(ctx);
12456 tcg_gen_ext8u_tl(cpu_gpr[ret], val_t);
12457 tcg_gen_shli_tl(t0, cpu_gpr[ret], 8);
12458 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12459 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12460 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12461 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12462 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12463 break;
12464 case OPC_REPLV_PW:
12465 check_dsp(ctx);
12466 tcg_gen_ext32u_i64(cpu_gpr[ret], val_t);
12467 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12468 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12469 break;
12470 case OPC_REPLV_QH:
12471 check_dsp(ctx);
12472 tcg_gen_ext16u_tl(cpu_gpr[ret], val_t);
12473 tcg_gen_shli_tl(t0, cpu_gpr[ret], 16);
12474 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12475 tcg_gen_shli_tl(t0, cpu_gpr[ret], 32);
12476 tcg_gen_or_tl(cpu_gpr[ret], cpu_gpr[ret], t0);
12477 break;
12478 }
12479 break;
12480 #endif
12481 }
12482 }
12483
gen_mipsdsp_add_cmp_pick(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2,int check_ret)12484 static void gen_mipsdsp_add_cmp_pick(DisasContext *ctx,
12485 uint32_t op1, uint32_t op2,
12486 int ret, int v1, int v2, int check_ret)
12487 {
12488 TCGv t1;
12489 TCGv v1_t;
12490 TCGv v2_t;
12491
12492 if ((ret == 0) && (check_ret == 1)) {
12493 /* Treat as NOP. */
12494 return;
12495 }
12496
12497 t1 = tcg_temp_new();
12498 v1_t = tcg_temp_new();
12499 v2_t = tcg_temp_new();
12500
12501 gen_load_gpr(v1_t, v1);
12502 gen_load_gpr(v2_t, v2);
12503
12504 switch (op1) {
12505 case OPC_CMPU_EQ_QB_DSP:
12506 switch (op2) {
12507 case OPC_CMPU_EQ_QB:
12508 check_dsp(ctx);
12509 gen_helper_cmpu_eq_qb(v1_t, v2_t, tcg_env);
12510 break;
12511 case OPC_CMPU_LT_QB:
12512 check_dsp(ctx);
12513 gen_helper_cmpu_lt_qb(v1_t, v2_t, tcg_env);
12514 break;
12515 case OPC_CMPU_LE_QB:
12516 check_dsp(ctx);
12517 gen_helper_cmpu_le_qb(v1_t, v2_t, tcg_env);
12518 break;
12519 case OPC_CMPGU_EQ_QB:
12520 check_dsp(ctx);
12521 gen_helper_cmpgu_eq_qb(cpu_gpr[ret], v1_t, v2_t);
12522 break;
12523 case OPC_CMPGU_LT_QB:
12524 check_dsp(ctx);
12525 gen_helper_cmpgu_lt_qb(cpu_gpr[ret], v1_t, v2_t);
12526 break;
12527 case OPC_CMPGU_LE_QB:
12528 check_dsp(ctx);
12529 gen_helper_cmpgu_le_qb(cpu_gpr[ret], v1_t, v2_t);
12530 break;
12531 case OPC_CMPGDU_EQ_QB:
12532 check_dsp_r2(ctx);
12533 gen_helper_cmpgu_eq_qb(t1, v1_t, v2_t);
12534 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12535 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12536 tcg_gen_shli_tl(t1, t1, 24);
12537 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12538 break;
12539 case OPC_CMPGDU_LT_QB:
12540 check_dsp_r2(ctx);
12541 gen_helper_cmpgu_lt_qb(t1, v1_t, v2_t);
12542 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12543 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12544 tcg_gen_shli_tl(t1, t1, 24);
12545 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12546 break;
12547 case OPC_CMPGDU_LE_QB:
12548 check_dsp_r2(ctx);
12549 gen_helper_cmpgu_le_qb(t1, v1_t, v2_t);
12550 tcg_gen_mov_tl(cpu_gpr[ret], t1);
12551 tcg_gen_andi_tl(cpu_dspctrl, cpu_dspctrl, 0xF0FFFFFF);
12552 tcg_gen_shli_tl(t1, t1, 24);
12553 tcg_gen_or_tl(cpu_dspctrl, cpu_dspctrl, t1);
12554 break;
12555 case OPC_CMP_EQ_PH:
12556 check_dsp(ctx);
12557 gen_helper_cmp_eq_ph(v1_t, v2_t, tcg_env);
12558 break;
12559 case OPC_CMP_LT_PH:
12560 check_dsp(ctx);
12561 gen_helper_cmp_lt_ph(v1_t, v2_t, tcg_env);
12562 break;
12563 case OPC_CMP_LE_PH:
12564 check_dsp(ctx);
12565 gen_helper_cmp_le_ph(v1_t, v2_t, tcg_env);
12566 break;
12567 case OPC_PICK_QB:
12568 check_dsp(ctx);
12569 gen_helper_pick_qb(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12570 break;
12571 case OPC_PICK_PH:
12572 check_dsp(ctx);
12573 gen_helper_pick_ph(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12574 break;
12575 case OPC_PACKRL_PH:
12576 check_dsp(ctx);
12577 gen_helper_packrl_ph(cpu_gpr[ret], v1_t, v2_t);
12578 break;
12579 }
12580 break;
12581 #ifdef TARGET_MIPS64
12582 case OPC_CMPU_EQ_OB_DSP:
12583 switch (op2) {
12584 case OPC_CMP_EQ_PW:
12585 check_dsp(ctx);
12586 gen_helper_cmp_eq_pw(v1_t, v2_t, tcg_env);
12587 break;
12588 case OPC_CMP_LT_PW:
12589 check_dsp(ctx);
12590 gen_helper_cmp_lt_pw(v1_t, v2_t, tcg_env);
12591 break;
12592 case OPC_CMP_LE_PW:
12593 check_dsp(ctx);
12594 gen_helper_cmp_le_pw(v1_t, v2_t, tcg_env);
12595 break;
12596 case OPC_CMP_EQ_QH:
12597 check_dsp(ctx);
12598 gen_helper_cmp_eq_qh(v1_t, v2_t, tcg_env);
12599 break;
12600 case OPC_CMP_LT_QH:
12601 check_dsp(ctx);
12602 gen_helper_cmp_lt_qh(v1_t, v2_t, tcg_env);
12603 break;
12604 case OPC_CMP_LE_QH:
12605 check_dsp(ctx);
12606 gen_helper_cmp_le_qh(v1_t, v2_t, tcg_env);
12607 break;
12608 case OPC_CMPGDU_EQ_OB:
12609 check_dsp_r2(ctx);
12610 gen_helper_cmpgdu_eq_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12611 break;
12612 case OPC_CMPGDU_LT_OB:
12613 check_dsp_r2(ctx);
12614 gen_helper_cmpgdu_lt_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12615 break;
12616 case OPC_CMPGDU_LE_OB:
12617 check_dsp_r2(ctx);
12618 gen_helper_cmpgdu_le_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12619 break;
12620 case OPC_CMPGU_EQ_OB:
12621 check_dsp(ctx);
12622 gen_helper_cmpgu_eq_ob(cpu_gpr[ret], v1_t, v2_t);
12623 break;
12624 case OPC_CMPGU_LT_OB:
12625 check_dsp(ctx);
12626 gen_helper_cmpgu_lt_ob(cpu_gpr[ret], v1_t, v2_t);
12627 break;
12628 case OPC_CMPGU_LE_OB:
12629 check_dsp(ctx);
12630 gen_helper_cmpgu_le_ob(cpu_gpr[ret], v1_t, v2_t);
12631 break;
12632 case OPC_CMPU_EQ_OB:
12633 check_dsp(ctx);
12634 gen_helper_cmpu_eq_ob(v1_t, v2_t, tcg_env);
12635 break;
12636 case OPC_CMPU_LT_OB:
12637 check_dsp(ctx);
12638 gen_helper_cmpu_lt_ob(v1_t, v2_t, tcg_env);
12639 break;
12640 case OPC_CMPU_LE_OB:
12641 check_dsp(ctx);
12642 gen_helper_cmpu_le_ob(v1_t, v2_t, tcg_env);
12643 break;
12644 case OPC_PACKRL_PW:
12645 check_dsp(ctx);
12646 gen_helper_packrl_pw(cpu_gpr[ret], v1_t, v2_t);
12647 break;
12648 case OPC_PICK_OB:
12649 check_dsp(ctx);
12650 gen_helper_pick_ob(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12651 break;
12652 case OPC_PICK_PW:
12653 check_dsp(ctx);
12654 gen_helper_pick_pw(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12655 break;
12656 case OPC_PICK_QH:
12657 check_dsp(ctx);
12658 gen_helper_pick_qh(cpu_gpr[ret], v1_t, v2_t, tcg_env);
12659 break;
12660 }
12661 break;
12662 #endif
12663 }
12664 }
12665
gen_mipsdsp_append(CPUMIPSState * env,DisasContext * ctx,uint32_t op1,int rt,int rs,int sa)12666 static void gen_mipsdsp_append(CPUMIPSState *env, DisasContext *ctx,
12667 uint32_t op1, int rt, int rs, int sa)
12668 {
12669 TCGv t0;
12670
12671 check_dsp_r2(ctx);
12672
12673 if (rt == 0) {
12674 /* Treat as NOP. */
12675 return;
12676 }
12677
12678 t0 = tcg_temp_new();
12679 gen_load_gpr(t0, rs);
12680
12681 switch (op1) {
12682 case OPC_APPEND_DSP:
12683 switch (MASK_APPEND(ctx->opcode)) {
12684 case OPC_APPEND:
12685 if (sa != 0) {
12686 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 32 - sa);
12687 }
12688 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12689 break;
12690 case OPC_PREPEND:
12691 if (sa != 0) {
12692 tcg_gen_ext32u_tl(cpu_gpr[rt], cpu_gpr[rt]);
12693 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
12694 tcg_gen_shli_tl(t0, t0, 32 - sa);
12695 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12696 }
12697 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12698 break;
12699 case OPC_BALIGN:
12700 sa &= 3;
12701 if (sa != 0 && sa != 2) {
12702 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
12703 tcg_gen_ext32u_tl(t0, t0);
12704 tcg_gen_shri_tl(t0, t0, 8 * (4 - sa));
12705 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12706 }
12707 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
12708 break;
12709 default: /* Invalid */
12710 MIPS_INVAL("MASK APPEND");
12711 gen_reserved_instruction(ctx);
12712 break;
12713 }
12714 break;
12715 #ifdef TARGET_MIPS64
12716 case OPC_DAPPEND_DSP:
12717 switch (MASK_DAPPEND(ctx->opcode)) {
12718 case OPC_DAPPEND:
12719 if (sa != 0) {
12720 tcg_gen_deposit_tl(cpu_gpr[rt], t0, cpu_gpr[rt], sa, 64 - sa);
12721 }
12722 break;
12723 case OPC_PREPENDD:
12724 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], 0x20 | sa);
12725 tcg_gen_shli_tl(t0, t0, 64 - (0x20 | sa));
12726 tcg_gen_or_tl(cpu_gpr[rt], t0, t0);
12727 break;
12728 case OPC_PREPENDW:
12729 if (sa != 0) {
12730 tcg_gen_shri_tl(cpu_gpr[rt], cpu_gpr[rt], sa);
12731 tcg_gen_shli_tl(t0, t0, 64 - sa);
12732 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12733 }
12734 break;
12735 case OPC_DBALIGN:
12736 sa &= 7;
12737 if (sa != 0 && sa != 2 && sa != 4) {
12738 tcg_gen_shli_tl(cpu_gpr[rt], cpu_gpr[rt], 8 * sa);
12739 tcg_gen_shri_tl(t0, t0, 8 * (8 - sa));
12740 tcg_gen_or_tl(cpu_gpr[rt], cpu_gpr[rt], t0);
12741 }
12742 break;
12743 default: /* Invalid */
12744 MIPS_INVAL("MASK DAPPEND");
12745 gen_reserved_instruction(ctx);
12746 break;
12747 }
12748 break;
12749 #endif
12750 }
12751 }
12752
gen_mipsdsp_accinsn(DisasContext * ctx,uint32_t op1,uint32_t op2,int ret,int v1,int v2,int check_ret)12753 static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
12754 int ret, int v1, int v2, int check_ret)
12755
12756 {
12757 TCGv t0;
12758 TCGv t1;
12759 TCGv v1_t;
12760 int16_t imm;
12761
12762 if ((ret == 0) && (check_ret == 1)) {
12763 /* Treat as NOP. */
12764 return;
12765 }
12766
12767 t0 = tcg_temp_new();
12768 t1 = tcg_temp_new();
12769 v1_t = tcg_temp_new();
12770
12771 gen_load_gpr(v1_t, v1);
12772
12773 switch (op1) {
12774 case OPC_EXTR_W_DSP:
12775 check_dsp(ctx);
12776 switch (op2) {
12777 case OPC_EXTR_W:
12778 tcg_gen_movi_tl(t0, v2);
12779 tcg_gen_movi_tl(t1, v1);
12780 gen_helper_extr_w(cpu_gpr[ret], t0, t1, tcg_env);
12781 break;
12782 case OPC_EXTR_R_W:
12783 tcg_gen_movi_tl(t0, v2);
12784 tcg_gen_movi_tl(t1, v1);
12785 gen_helper_extr_r_w(cpu_gpr[ret], t0, t1, tcg_env);
12786 break;
12787 case OPC_EXTR_RS_W:
12788 tcg_gen_movi_tl(t0, v2);
12789 tcg_gen_movi_tl(t1, v1);
12790 gen_helper_extr_rs_w(cpu_gpr[ret], t0, t1, tcg_env);
12791 break;
12792 case OPC_EXTR_S_H:
12793 tcg_gen_movi_tl(t0, v2);
12794 tcg_gen_movi_tl(t1, v1);
12795 gen_helper_extr_s_h(cpu_gpr[ret], t0, t1, tcg_env);
12796 break;
12797 case OPC_EXTRV_S_H:
12798 tcg_gen_movi_tl(t0, v2);
12799 gen_helper_extr_s_h(cpu_gpr[ret], t0, v1_t, tcg_env);
12800 break;
12801 case OPC_EXTRV_W:
12802 tcg_gen_movi_tl(t0, v2);
12803 gen_helper_extr_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12804 break;
12805 case OPC_EXTRV_R_W:
12806 tcg_gen_movi_tl(t0, v2);
12807 gen_helper_extr_r_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12808 break;
12809 case OPC_EXTRV_RS_W:
12810 tcg_gen_movi_tl(t0, v2);
12811 gen_helper_extr_rs_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12812 break;
12813 case OPC_EXTP:
12814 tcg_gen_movi_tl(t0, v2);
12815 tcg_gen_movi_tl(t1, v1);
12816 gen_helper_extp(cpu_gpr[ret], t0, t1, tcg_env);
12817 break;
12818 case OPC_EXTPV:
12819 tcg_gen_movi_tl(t0, v2);
12820 gen_helper_extp(cpu_gpr[ret], t0, v1_t, tcg_env);
12821 break;
12822 case OPC_EXTPDP:
12823 tcg_gen_movi_tl(t0, v2);
12824 tcg_gen_movi_tl(t1, v1);
12825 gen_helper_extpdp(cpu_gpr[ret], t0, t1, tcg_env);
12826 break;
12827 case OPC_EXTPDPV:
12828 tcg_gen_movi_tl(t0, v2);
12829 gen_helper_extpdp(cpu_gpr[ret], t0, v1_t, tcg_env);
12830 break;
12831 case OPC_SHILO:
12832 imm = (ctx->opcode >> 20) & 0x3F;
12833 tcg_gen_movi_tl(t0, ret);
12834 tcg_gen_movi_tl(t1, imm);
12835 gen_helper_shilo(t0, t1, tcg_env);
12836 break;
12837 case OPC_SHILOV:
12838 tcg_gen_movi_tl(t0, ret);
12839 gen_helper_shilo(t0, v1_t, tcg_env);
12840 break;
12841 case OPC_MTHLIP:
12842 tcg_gen_movi_tl(t0, ret);
12843 gen_helper_mthlip(t0, v1_t, tcg_env);
12844 break;
12845 case OPC_WRDSP:
12846 imm = (ctx->opcode >> 11) & 0x3FF;
12847 tcg_gen_movi_tl(t0, imm);
12848 gen_helper_wrdsp(v1_t, t0, tcg_env);
12849 break;
12850 case OPC_RDDSP:
12851 imm = (ctx->opcode >> 16) & 0x03FF;
12852 tcg_gen_movi_tl(t0, imm);
12853 gen_helper_rddsp(cpu_gpr[ret], t0, tcg_env);
12854 break;
12855 }
12856 break;
12857 #ifdef TARGET_MIPS64
12858 case OPC_DEXTR_W_DSP:
12859 check_dsp(ctx);
12860 switch (op2) {
12861 case OPC_DMTHLIP:
12862 tcg_gen_movi_tl(t0, ret);
12863 gen_helper_dmthlip(v1_t, t0, tcg_env);
12864 break;
12865 case OPC_DSHILO:
12866 {
12867 int shift = (ctx->opcode >> 19) & 0x7F;
12868 int ac = (ctx->opcode >> 11) & 0x03;
12869 tcg_gen_movi_tl(t0, shift);
12870 tcg_gen_movi_tl(t1, ac);
12871 gen_helper_dshilo(t0, t1, tcg_env);
12872 break;
12873 }
12874 case OPC_DSHILOV:
12875 {
12876 int ac = (ctx->opcode >> 11) & 0x03;
12877 tcg_gen_movi_tl(t0, ac);
12878 gen_helper_dshilo(v1_t, t0, tcg_env);
12879 break;
12880 }
12881 case OPC_DEXTP:
12882 tcg_gen_movi_tl(t0, v2);
12883 tcg_gen_movi_tl(t1, v1);
12884
12885 gen_helper_dextp(cpu_gpr[ret], t0, t1, tcg_env);
12886 break;
12887 case OPC_DEXTPV:
12888 tcg_gen_movi_tl(t0, v2);
12889 gen_helper_dextp(cpu_gpr[ret], t0, v1_t, tcg_env);
12890 break;
12891 case OPC_DEXTPDP:
12892 tcg_gen_movi_tl(t0, v2);
12893 tcg_gen_movi_tl(t1, v1);
12894 gen_helper_dextpdp(cpu_gpr[ret], t0, t1, tcg_env);
12895 break;
12896 case OPC_DEXTPDPV:
12897 tcg_gen_movi_tl(t0, v2);
12898 gen_helper_dextpdp(cpu_gpr[ret], t0, v1_t, tcg_env);
12899 break;
12900 case OPC_DEXTR_L:
12901 tcg_gen_movi_tl(t0, v2);
12902 tcg_gen_movi_tl(t1, v1);
12903 gen_helper_dextr_l(cpu_gpr[ret], t0, t1, tcg_env);
12904 break;
12905 case OPC_DEXTR_R_L:
12906 tcg_gen_movi_tl(t0, v2);
12907 tcg_gen_movi_tl(t1, v1);
12908 gen_helper_dextr_r_l(cpu_gpr[ret], t0, t1, tcg_env);
12909 break;
12910 case OPC_DEXTR_RS_L:
12911 tcg_gen_movi_tl(t0, v2);
12912 tcg_gen_movi_tl(t1, v1);
12913 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, t1, tcg_env);
12914 break;
12915 case OPC_DEXTR_W:
12916 tcg_gen_movi_tl(t0, v2);
12917 tcg_gen_movi_tl(t1, v1);
12918 gen_helper_dextr_w(cpu_gpr[ret], t0, t1, tcg_env);
12919 break;
12920 case OPC_DEXTR_R_W:
12921 tcg_gen_movi_tl(t0, v2);
12922 tcg_gen_movi_tl(t1, v1);
12923 gen_helper_dextr_r_w(cpu_gpr[ret], t0, t1, tcg_env);
12924 break;
12925 case OPC_DEXTR_RS_W:
12926 tcg_gen_movi_tl(t0, v2);
12927 tcg_gen_movi_tl(t1, v1);
12928 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, t1, tcg_env);
12929 break;
12930 case OPC_DEXTR_S_H:
12931 tcg_gen_movi_tl(t0, v2);
12932 tcg_gen_movi_tl(t1, v1);
12933 gen_helper_dextr_s_h(cpu_gpr[ret], t0, t1, tcg_env);
12934 break;
12935 case OPC_DEXTRV_S_H:
12936 tcg_gen_movi_tl(t0, v2);
12937 gen_helper_dextr_s_h(cpu_gpr[ret], t0, v1_t, tcg_env);
12938 break;
12939 case OPC_DEXTRV_L:
12940 tcg_gen_movi_tl(t0, v2);
12941 gen_helper_dextr_l(cpu_gpr[ret], t0, v1_t, tcg_env);
12942 break;
12943 case OPC_DEXTRV_R_L:
12944 tcg_gen_movi_tl(t0, v2);
12945 gen_helper_dextr_r_l(cpu_gpr[ret], t0, v1_t, tcg_env);
12946 break;
12947 case OPC_DEXTRV_RS_L:
12948 tcg_gen_movi_tl(t0, v2);
12949 gen_helper_dextr_rs_l(cpu_gpr[ret], t0, v1_t, tcg_env);
12950 break;
12951 case OPC_DEXTRV_W:
12952 tcg_gen_movi_tl(t0, v2);
12953 gen_helper_dextr_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12954 break;
12955 case OPC_DEXTRV_R_W:
12956 tcg_gen_movi_tl(t0, v2);
12957 gen_helper_dextr_r_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12958 break;
12959 case OPC_DEXTRV_RS_W:
12960 tcg_gen_movi_tl(t0, v2);
12961 gen_helper_dextr_rs_w(cpu_gpr[ret], t0, v1_t, tcg_env);
12962 break;
12963 }
12964 break;
12965 #endif
12966 }
12967 }
12968
12969 /* End MIPSDSP functions. */
12970
decode_opc_special_r6(CPUMIPSState * env,DisasContext * ctx)12971 static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
12972 {
12973 int rs, rt, rd, sa;
12974 uint32_t op1, op2;
12975
12976 rs = (ctx->opcode >> 21) & 0x1f;
12977 rt = (ctx->opcode >> 16) & 0x1f;
12978 rd = (ctx->opcode >> 11) & 0x1f;
12979 sa = (ctx->opcode >> 6) & 0x1f;
12980
12981 op1 = MASK_SPECIAL(ctx->opcode);
12982 switch (op1) {
12983 case OPC_MULT:
12984 case OPC_MULTU:
12985 case OPC_DIV:
12986 case OPC_DIVU:
12987 op2 = MASK_R6_MULDIV(ctx->opcode);
12988 switch (op2) {
12989 case R6_OPC_MUL:
12990 case R6_OPC_MUH:
12991 case R6_OPC_MULU:
12992 case R6_OPC_MUHU:
12993 case R6_OPC_DIV:
12994 case R6_OPC_MOD:
12995 case R6_OPC_DIVU:
12996 case R6_OPC_MODU:
12997 gen_r6_muldiv(ctx, op2, rd, rs, rt);
12998 break;
12999 default:
13000 MIPS_INVAL("special_r6 muldiv");
13001 gen_reserved_instruction(ctx);
13002 break;
13003 }
13004 break;
13005 case OPC_SELEQZ:
13006 case OPC_SELNEZ:
13007 gen_cond_move(ctx, op1, rd, rs, rt);
13008 break;
13009 case R6_OPC_CLO:
13010 case R6_OPC_CLZ:
13011 if (rt == 0 && sa == 1) {
13012 /*
13013 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13014 * We need additionally to check other fields.
13015 */
13016 gen_cl(ctx, op1, rd, rs);
13017 } else {
13018 gen_reserved_instruction(ctx);
13019 }
13020 break;
13021 case R6_OPC_SDBBP:
13022 if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) {
13023 ctx->base.is_jmp = DISAS_SEMIHOST;
13024 } else {
13025 if (ctx->hflags & MIPS_HFLAG_SBRI) {
13026 gen_reserved_instruction(ctx);
13027 } else {
13028 generate_exception_end(ctx, EXCP_DBp);
13029 }
13030 }
13031 break;
13032 #if defined(TARGET_MIPS64)
13033 case R6_OPC_DCLO:
13034 case R6_OPC_DCLZ:
13035 if (rt == 0 && sa == 1) {
13036 /*
13037 * Major opcode and function field is shared with preR6 MFHI/MTHI.
13038 * We need additionally to check other fields.
13039 */
13040 check_mips_64(ctx);
13041 gen_cl(ctx, op1, rd, rs);
13042 } else {
13043 gen_reserved_instruction(ctx);
13044 }
13045 break;
13046 case OPC_DMULT:
13047 case OPC_DMULTU:
13048 case OPC_DDIV:
13049 case OPC_DDIVU:
13050
13051 op2 = MASK_R6_MULDIV(ctx->opcode);
13052 switch (op2) {
13053 case R6_OPC_DMUL:
13054 case R6_OPC_DMUH:
13055 case R6_OPC_DMULU:
13056 case R6_OPC_DMUHU:
13057 case R6_OPC_DDIV:
13058 case R6_OPC_DMOD:
13059 case R6_OPC_DDIVU:
13060 case R6_OPC_DMODU:
13061 check_mips_64(ctx);
13062 gen_r6_muldiv(ctx, op2, rd, rs, rt);
13063 break;
13064 default:
13065 MIPS_INVAL("special_r6 muldiv");
13066 gen_reserved_instruction(ctx);
13067 break;
13068 }
13069 break;
13070 #endif
13071 default: /* Invalid */
13072 MIPS_INVAL("special_r6");
13073 gen_reserved_instruction(ctx);
13074 break;
13075 }
13076 }
13077
decode_opc_special_tx79(CPUMIPSState * env,DisasContext * ctx)13078 static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
13079 {
13080 int rs = extract32(ctx->opcode, 21, 5);
13081 int rt = extract32(ctx->opcode, 16, 5);
13082 int rd = extract32(ctx->opcode, 11, 5);
13083 uint32_t op1 = MASK_SPECIAL(ctx->opcode);
13084
13085 switch (op1) {
13086 case OPC_MOVN: /* Conditional move */
13087 case OPC_MOVZ:
13088 gen_cond_move(ctx, op1, rd, rs, rt);
13089 break;
13090 case OPC_MFHI: /* Move from HI/LO */
13091 case OPC_MFLO:
13092 gen_HILO(ctx, op1, 0, rd);
13093 break;
13094 case OPC_MTHI:
13095 case OPC_MTLO: /* Move to HI/LO */
13096 gen_HILO(ctx, op1, 0, rs);
13097 break;
13098 case OPC_MULT:
13099 case OPC_MULTU:
13100 gen_mul_txx9(ctx, op1, rd, rs, rt);
13101 break;
13102 case OPC_DIV:
13103 case OPC_DIVU:
13104 gen_muldiv(ctx, op1, 0, rs, rt);
13105 break;
13106 #if defined(TARGET_MIPS64)
13107 case OPC_DMULT:
13108 case OPC_DMULTU:
13109 case OPC_DDIV:
13110 case OPC_DDIVU:
13111 check_insn_opc_user_only(ctx, INSN_R5900);
13112 gen_muldiv(ctx, op1, 0, rs, rt);
13113 break;
13114 #endif
13115 case OPC_JR:
13116 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
13117 break;
13118 default: /* Invalid */
13119 MIPS_INVAL("special_tx79");
13120 gen_reserved_instruction(ctx);
13121 break;
13122 }
13123 }
13124
decode_opc_special_legacy(CPUMIPSState * env,DisasContext * ctx)13125 static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
13126 {
13127 int rs, rt, rd;
13128 uint32_t op1;
13129
13130 rs = (ctx->opcode >> 21) & 0x1f;
13131 rt = (ctx->opcode >> 16) & 0x1f;
13132 rd = (ctx->opcode >> 11) & 0x1f;
13133
13134 op1 = MASK_SPECIAL(ctx->opcode);
13135 switch (op1) {
13136 case OPC_MOVN: /* Conditional move */
13137 case OPC_MOVZ:
13138 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 |
13139 INSN_LOONGSON2E | INSN_LOONGSON2F);
13140 gen_cond_move(ctx, op1, rd, rs, rt);
13141 break;
13142 case OPC_MFHI: /* Move from HI/LO */
13143 case OPC_MFLO:
13144 gen_HILO(ctx, op1, rs & 3, rd);
13145 break;
13146 case OPC_MTHI:
13147 case OPC_MTLO: /* Move to HI/LO */
13148 gen_HILO(ctx, op1, rd & 3, rs);
13149 break;
13150 case OPC_MOVCI:
13151 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1);
13152 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
13153 check_cp1_enabled(ctx);
13154 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
13155 (ctx->opcode >> 16) & 1);
13156 } else {
13157 generate_exception_err(ctx, EXCP_CpU, 1);
13158 }
13159 break;
13160 case OPC_MULT:
13161 case OPC_MULTU:
13162 gen_muldiv(ctx, op1, rd & 3, rs, rt);
13163 break;
13164 case OPC_DIV:
13165 case OPC_DIVU:
13166 gen_muldiv(ctx, op1, 0, rs, rt);
13167 break;
13168 #if defined(TARGET_MIPS64)
13169 case OPC_DMULT:
13170 case OPC_DMULTU:
13171 case OPC_DDIV:
13172 case OPC_DDIVU:
13173 check_insn(ctx, ISA_MIPS3);
13174 check_mips_64(ctx);
13175 gen_muldiv(ctx, op1, 0, rs, rt);
13176 break;
13177 #endif
13178 case OPC_JR:
13179 gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
13180 break;
13181 case OPC_SPIM:
13182 #ifdef MIPS_STRICT_STANDARD
13183 MIPS_INVAL("SPIM");
13184 gen_reserved_instruction(ctx);
13185 #else
13186 /* Implemented as RI exception for now. */
13187 MIPS_INVAL("spim (unofficial)");
13188 gen_reserved_instruction(ctx);
13189 #endif
13190 break;
13191 default: /* Invalid */
13192 MIPS_INVAL("special_legacy");
13193 gen_reserved_instruction(ctx);
13194 break;
13195 }
13196 }
13197
decode_opc_special(CPUMIPSState * env,DisasContext * ctx)13198 static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
13199 {
13200 int rs, rt, rd, sa;
13201 uint32_t op1;
13202
13203 rs = (ctx->opcode >> 21) & 0x1f;
13204 rt = (ctx->opcode >> 16) & 0x1f;
13205 rd = (ctx->opcode >> 11) & 0x1f;
13206 sa = (ctx->opcode >> 6) & 0x1f;
13207
13208 op1 = MASK_SPECIAL(ctx->opcode);
13209 switch (op1) {
13210 case OPC_SLL: /* Shift with immediate */
13211 if (sa == 5 && rd == 0 &&
13212 rs == 0 && rt == 0) { /* PAUSE */
13213 if ((ctx->insn_flags & ISA_MIPS_R6) &&
13214 (ctx->hflags & MIPS_HFLAG_BMASK)) {
13215 gen_reserved_instruction(ctx);
13216 break;
13217 }
13218 }
13219 /* Fallthrough */
13220 case OPC_SRA:
13221 gen_shift_imm(ctx, op1, rd, rt, sa);
13222 break;
13223 case OPC_SRL:
13224 switch ((ctx->opcode >> 21) & 0x1f) {
13225 case 1:
13226 /* rotr is decoded as srl on non-R2 CPUs */
13227 if (ctx->insn_flags & ISA_MIPS_R2) {
13228 op1 = OPC_ROTR;
13229 }
13230 /* Fallthrough */
13231 case 0:
13232 gen_shift_imm(ctx, op1, rd, rt, sa);
13233 break;
13234 default:
13235 gen_reserved_instruction(ctx);
13236 break;
13237 }
13238 break;
13239 case OPC_ADD:
13240 case OPC_ADDU:
13241 case OPC_SUB:
13242 case OPC_SUBU:
13243 gen_arith(ctx, op1, rd, rs, rt);
13244 break;
13245 case OPC_SLLV: /* Shifts */
13246 case OPC_SRAV:
13247 gen_shift(ctx, op1, rd, rs, rt);
13248 break;
13249 case OPC_SRLV:
13250 switch ((ctx->opcode >> 6) & 0x1f) {
13251 case 1:
13252 /* rotrv is decoded as srlv on non-R2 CPUs */
13253 if (ctx->insn_flags & ISA_MIPS_R2) {
13254 op1 = OPC_ROTRV;
13255 }
13256 /* Fallthrough */
13257 case 0:
13258 gen_shift(ctx, op1, rd, rs, rt);
13259 break;
13260 default:
13261 gen_reserved_instruction(ctx);
13262 break;
13263 }
13264 break;
13265 case OPC_SLT: /* Set on less than */
13266 case OPC_SLTU:
13267 gen_slt(ctx, op1, rd, rs, rt);
13268 break;
13269 case OPC_AND: /* Logic*/
13270 case OPC_OR:
13271 case OPC_NOR:
13272 case OPC_XOR:
13273 gen_logic(ctx, op1, rd, rs, rt);
13274 break;
13275 case OPC_JALR:
13276 gen_compute_branch(ctx, op1, 4, rs, rd, sa, 4);
13277 break;
13278 case OPC_TGE: /* Traps */
13279 case OPC_TGEU:
13280 case OPC_TLT:
13281 case OPC_TLTU:
13282 case OPC_TEQ:
13283 case OPC_TNE:
13284 check_insn(ctx, ISA_MIPS2);
13285 gen_trap(ctx, op1, rs, rt, -1, extract32(ctx->opcode, 6, 10));
13286 break;
13287 case OPC_PMON:
13288 /* Pmon entry point, also R4010 selsl */
13289 #ifdef MIPS_STRICT_STANDARD
13290 MIPS_INVAL("PMON / selsl");
13291 gen_reserved_instruction(ctx);
13292 #else
13293 gen_helper_pmon(tcg_env, tcg_constant_i32(sa));
13294 #endif
13295 break;
13296 case OPC_SYSCALL:
13297 generate_exception_end(ctx, EXCP_SYSCALL);
13298 break;
13299 case OPC_BREAK:
13300 generate_exception_break(ctx, extract32(ctx->opcode, 6, 20));
13301 break;
13302 case OPC_SYNC:
13303 check_insn(ctx, ISA_MIPS2);
13304 gen_sync(extract32(ctx->opcode, 6, 5));
13305 break;
13306
13307 #if defined(TARGET_MIPS64)
13308 /* MIPS64 specific opcodes */
13309 case OPC_DSLL:
13310 case OPC_DSRA:
13311 case OPC_DSLL32:
13312 case OPC_DSRA32:
13313 check_insn(ctx, ISA_MIPS3);
13314 check_mips_64(ctx);
13315 gen_shift_imm(ctx, op1, rd, rt, sa);
13316 break;
13317 case OPC_DSRL:
13318 switch ((ctx->opcode >> 21) & 0x1f) {
13319 case 1:
13320 /* drotr is decoded as dsrl on non-R2 CPUs */
13321 if (ctx->insn_flags & ISA_MIPS_R2) {
13322 op1 = OPC_DROTR;
13323 }
13324 /* Fallthrough */
13325 case 0:
13326 check_insn(ctx, ISA_MIPS3);
13327 check_mips_64(ctx);
13328 gen_shift_imm(ctx, op1, rd, rt, sa);
13329 break;
13330 default:
13331 gen_reserved_instruction(ctx);
13332 break;
13333 }
13334 break;
13335 case OPC_DSRL32:
13336 switch ((ctx->opcode >> 21) & 0x1f) {
13337 case 1:
13338 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
13339 if (ctx->insn_flags & ISA_MIPS_R2) {
13340 op1 = OPC_DROTR32;
13341 }
13342 /* Fallthrough */
13343 case 0:
13344 check_insn(ctx, ISA_MIPS3);
13345 check_mips_64(ctx);
13346 gen_shift_imm(ctx, op1, rd, rt, sa);
13347 break;
13348 default:
13349 gen_reserved_instruction(ctx);
13350 break;
13351 }
13352 break;
13353 case OPC_DADD:
13354 case OPC_DADDU:
13355 case OPC_DSUB:
13356 case OPC_DSUBU:
13357 check_insn(ctx, ISA_MIPS3);
13358 check_mips_64(ctx);
13359 gen_arith(ctx, op1, rd, rs, rt);
13360 break;
13361 case OPC_DSLLV:
13362 case OPC_DSRAV:
13363 check_insn(ctx, ISA_MIPS3);
13364 check_mips_64(ctx);
13365 gen_shift(ctx, op1, rd, rs, rt);
13366 break;
13367 case OPC_DSRLV:
13368 switch ((ctx->opcode >> 6) & 0x1f) {
13369 case 1:
13370 /* drotrv is decoded as dsrlv on non-R2 CPUs */
13371 if (ctx->insn_flags & ISA_MIPS_R2) {
13372 op1 = OPC_DROTRV;
13373 }
13374 /* Fallthrough */
13375 case 0:
13376 check_insn(ctx, ISA_MIPS3);
13377 check_mips_64(ctx);
13378 gen_shift(ctx, op1, rd, rs, rt);
13379 break;
13380 default:
13381 gen_reserved_instruction(ctx);
13382 break;
13383 }
13384 break;
13385 #endif
13386 default:
13387 if (ctx->insn_flags & ISA_MIPS_R6) {
13388 decode_opc_special_r6(env, ctx);
13389 } else if (ctx->insn_flags & INSN_R5900) {
13390 decode_opc_special_tx79(env, ctx);
13391 } else {
13392 decode_opc_special_legacy(env, ctx);
13393 }
13394 }
13395 }
13396
13397
decode_opc_special2_legacy(CPUMIPSState * env,DisasContext * ctx)13398 static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
13399 {
13400 int rs, rt, rd;
13401 uint32_t op1;
13402
13403 rs = (ctx->opcode >> 21) & 0x1f;
13404 rt = (ctx->opcode >> 16) & 0x1f;
13405 rd = (ctx->opcode >> 11) & 0x1f;
13406
13407 op1 = MASK_SPECIAL2(ctx->opcode);
13408 switch (op1) {
13409 case OPC_MADD: /* Multiply and add/sub */
13410 case OPC_MADDU:
13411 case OPC_MSUB:
13412 case OPC_MSUBU:
13413 check_insn(ctx, ISA_MIPS_R1);
13414 gen_muldiv(ctx, op1, rd & 3, rs, rt);
13415 break;
13416 case OPC_MUL:
13417 gen_arith(ctx, op1, rd, rs, rt);
13418 break;
13419 case OPC_CLO:
13420 case OPC_CLZ:
13421 check_insn(ctx, ISA_MIPS_R1);
13422 gen_cl(ctx, op1, rd, rs);
13423 break;
13424 case OPC_SDBBP:
13425 if (is_uhi(ctx, extract32(ctx->opcode, 6, 20))) {
13426 ctx->base.is_jmp = DISAS_SEMIHOST;
13427 } else {
13428 /*
13429 * XXX: not clear which exception should be raised
13430 * when in debug mode...
13431 */
13432 check_insn(ctx, ISA_MIPS_R1);
13433 generate_exception_end(ctx, EXCP_DBp);
13434 }
13435 break;
13436 #if defined(TARGET_MIPS64)
13437 case OPC_DCLO:
13438 case OPC_DCLZ:
13439 check_insn(ctx, ISA_MIPS_R1);
13440 check_mips_64(ctx);
13441 gen_cl(ctx, op1, rd, rs);
13442 break;
13443 #endif
13444 default: /* Invalid */
13445 MIPS_INVAL("special2_legacy");
13446 gen_reserved_instruction(ctx);
13447 break;
13448 }
13449 }
13450
decode_opc_special3_r6(CPUMIPSState * env,DisasContext * ctx)13451 static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
13452 {
13453 int rs, rt, rd, sa;
13454 uint32_t op1, op2;
13455 int16_t imm;
13456
13457 rs = (ctx->opcode >> 21) & 0x1f;
13458 rt = (ctx->opcode >> 16) & 0x1f;
13459 rd = (ctx->opcode >> 11) & 0x1f;
13460 sa = (ctx->opcode >> 6) & 0x1f;
13461 imm = (int16_t)ctx->opcode >> 7;
13462
13463 op1 = MASK_SPECIAL3(ctx->opcode);
13464 switch (op1) {
13465 case R6_OPC_PREF:
13466 if (rt >= 24) {
13467 /* hint codes 24-31 are reserved and signal RI */
13468 gen_reserved_instruction(ctx);
13469 }
13470 /* Treat as NOP. */
13471 break;
13472 case R6_OPC_CACHE:
13473 check_cp0_enabled(ctx);
13474 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
13475 gen_cache_operation(ctx, rt, rs, imm);
13476 }
13477 break;
13478 case R6_OPC_SC:
13479 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, false);
13480 break;
13481 case R6_OPC_LL:
13482 gen_ld(ctx, op1, rt, rs, imm);
13483 break;
13484 case OPC_BSHFL:
13485 {
13486 if (rd == 0) {
13487 /* Treat as NOP. */
13488 break;
13489 }
13490 op2 = MASK_BSHFL(ctx->opcode);
13491 switch (op2) {
13492 case OPC_ALIGN:
13493 case OPC_ALIGN_1:
13494 case OPC_ALIGN_2:
13495 case OPC_ALIGN_3:
13496 gen_align(ctx, 32, rd, rs, rt, sa & 3);
13497 break;
13498 case OPC_BITSWAP:
13499 gen_bitswap(ctx, op2, rd, rt);
13500 break;
13501 }
13502 }
13503 break;
13504 #ifndef CONFIG_USER_ONLY
13505 case OPC_GINV:
13506 if (unlikely(ctx->gi <= 1)) {
13507 gen_reserved_instruction(ctx);
13508 }
13509 check_cp0_enabled(ctx);
13510 switch ((ctx->opcode >> 6) & 3) {
13511 case 0: /* GINVI */
13512 /* Treat as NOP. */
13513 break;
13514 case 2: /* GINVT */
13515 gen_helper_0e1i(ginvt, cpu_gpr[rs], extract32(ctx->opcode, 8, 2));
13516 break;
13517 default:
13518 gen_reserved_instruction(ctx);
13519 break;
13520 }
13521 break;
13522 #endif
13523 #if defined(TARGET_MIPS64)
13524 case R6_OPC_SCD:
13525 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_UQ, false);
13526 break;
13527 case R6_OPC_LLD:
13528 gen_ld(ctx, op1, rt, rs, imm);
13529 break;
13530 case OPC_DBSHFL:
13531 check_mips_64(ctx);
13532 {
13533 if (rd == 0) {
13534 /* Treat as NOP. */
13535 break;
13536 }
13537 op2 = MASK_DBSHFL(ctx->opcode);
13538 switch (op2) {
13539 case OPC_DALIGN:
13540 case OPC_DALIGN_1:
13541 case OPC_DALIGN_2:
13542 case OPC_DALIGN_3:
13543 case OPC_DALIGN_4:
13544 case OPC_DALIGN_5:
13545 case OPC_DALIGN_6:
13546 case OPC_DALIGN_7:
13547 gen_align(ctx, 64, rd, rs, rt, sa & 7);
13548 break;
13549 case OPC_DBITSWAP:
13550 gen_bitswap(ctx, op2, rd, rt);
13551 break;
13552 }
13553
13554 }
13555 break;
13556 #endif
13557 default: /* Invalid */
13558 MIPS_INVAL("special3_r6");
13559 gen_reserved_instruction(ctx);
13560 break;
13561 }
13562 }
13563
decode_opc_special3_legacy(CPUMIPSState * env,DisasContext * ctx)13564 static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
13565 {
13566 int rs, rt, rd;
13567 uint32_t op1, op2;
13568
13569 rs = (ctx->opcode >> 21) & 0x1f;
13570 rt = (ctx->opcode >> 16) & 0x1f;
13571 rd = (ctx->opcode >> 11) & 0x1f;
13572
13573 op1 = MASK_SPECIAL3(ctx->opcode);
13574 switch (op1) {
13575 case OPC_MUL_PH_DSP:
13576 /*
13577 * OPC_ADDUH_QB_DSP, OPC_MUL_PH_DSP have
13578 * the same mask and op1.
13579 */
13580 if ((ctx->insn_flags & ASE_DSP_R2) && (op1 == OPC_MUL_PH_DSP)) {
13581 op2 = MASK_ADDUH_QB(ctx->opcode);
13582 switch (op2) {
13583 case OPC_ADDUH_QB:
13584 case OPC_ADDUH_R_QB:
13585 case OPC_ADDQH_PH:
13586 case OPC_ADDQH_R_PH:
13587 case OPC_ADDQH_W:
13588 case OPC_ADDQH_R_W:
13589 case OPC_SUBUH_QB:
13590 case OPC_SUBUH_R_QB:
13591 case OPC_SUBQH_PH:
13592 case OPC_SUBQH_R_PH:
13593 case OPC_SUBQH_W:
13594 case OPC_SUBQH_R_W:
13595 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13596 break;
13597 case OPC_MUL_PH:
13598 case OPC_MUL_S_PH:
13599 case OPC_MULQ_S_W:
13600 case OPC_MULQ_RS_W:
13601 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
13602 break;
13603 default:
13604 MIPS_INVAL("MASK ADDUH.QB");
13605 gen_reserved_instruction(ctx);
13606 break;
13607 }
13608 } else {
13609 gen_reserved_instruction(ctx);
13610 }
13611 break;
13612 case OPC_LX_DSP:
13613 op2 = MASK_LX(ctx->opcode);
13614 switch (op2) {
13615 #if defined(TARGET_MIPS64)
13616 case OPC_LDX:
13617 #endif
13618 case OPC_LBUX:
13619 case OPC_LHX:
13620 case OPC_LWX:
13621 gen_mips_lx(ctx, op2, rd, rs, rt);
13622 break;
13623 default: /* Invalid */
13624 MIPS_INVAL("MASK LX");
13625 gen_reserved_instruction(ctx);
13626 break;
13627 }
13628 break;
13629 case OPC_ABSQ_S_PH_DSP:
13630 op2 = MASK_ABSQ_S_PH(ctx->opcode);
13631 switch (op2) {
13632 case OPC_ABSQ_S_QB:
13633 case OPC_ABSQ_S_PH:
13634 case OPC_ABSQ_S_W:
13635 case OPC_PRECEQ_W_PHL:
13636 case OPC_PRECEQ_W_PHR:
13637 case OPC_PRECEQU_PH_QBL:
13638 case OPC_PRECEQU_PH_QBR:
13639 case OPC_PRECEQU_PH_QBLA:
13640 case OPC_PRECEQU_PH_QBRA:
13641 case OPC_PRECEU_PH_QBL:
13642 case OPC_PRECEU_PH_QBR:
13643 case OPC_PRECEU_PH_QBLA:
13644 case OPC_PRECEU_PH_QBRA:
13645 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13646 break;
13647 case OPC_BITREV:
13648 case OPC_REPL_QB:
13649 case OPC_REPLV_QB:
13650 case OPC_REPL_PH:
13651 case OPC_REPLV_PH:
13652 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
13653 break;
13654 default:
13655 MIPS_INVAL("MASK ABSQ_S.PH");
13656 gen_reserved_instruction(ctx);
13657 break;
13658 }
13659 break;
13660 case OPC_ADDU_QB_DSP:
13661 op2 = MASK_ADDU_QB(ctx->opcode);
13662 switch (op2) {
13663 case OPC_ADDQ_PH:
13664 case OPC_ADDQ_S_PH:
13665 case OPC_ADDQ_S_W:
13666 case OPC_ADDU_QB:
13667 case OPC_ADDU_S_QB:
13668 case OPC_ADDU_PH:
13669 case OPC_ADDU_S_PH:
13670 case OPC_SUBQ_PH:
13671 case OPC_SUBQ_S_PH:
13672 case OPC_SUBQ_S_W:
13673 case OPC_SUBU_QB:
13674 case OPC_SUBU_S_QB:
13675 case OPC_SUBU_PH:
13676 case OPC_SUBU_S_PH:
13677 case OPC_ADDSC:
13678 case OPC_ADDWC:
13679 case OPC_MODSUB:
13680 case OPC_RADDU_W_QB:
13681 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13682 break;
13683 case OPC_MULEU_S_PH_QBL:
13684 case OPC_MULEU_S_PH_QBR:
13685 case OPC_MULQ_RS_PH:
13686 case OPC_MULEQ_S_W_PHL:
13687 case OPC_MULEQ_S_W_PHR:
13688 case OPC_MULQ_S_PH:
13689 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
13690 break;
13691 default: /* Invalid */
13692 MIPS_INVAL("MASK ADDU.QB");
13693 gen_reserved_instruction(ctx);
13694 break;
13695
13696 }
13697 break;
13698 case OPC_CMPU_EQ_QB_DSP:
13699 op2 = MASK_CMPU_EQ_QB(ctx->opcode);
13700 switch (op2) {
13701 case OPC_PRECR_SRA_PH_W:
13702 case OPC_PRECR_SRA_R_PH_W:
13703 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
13704 break;
13705 case OPC_PRECR_QB_PH:
13706 case OPC_PRECRQ_QB_PH:
13707 case OPC_PRECRQ_PH_W:
13708 case OPC_PRECRQ_RS_PH_W:
13709 case OPC_PRECRQU_S_QB_PH:
13710 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13711 break;
13712 case OPC_CMPU_EQ_QB:
13713 case OPC_CMPU_LT_QB:
13714 case OPC_CMPU_LE_QB:
13715 case OPC_CMP_EQ_PH:
13716 case OPC_CMP_LT_PH:
13717 case OPC_CMP_LE_PH:
13718 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
13719 break;
13720 case OPC_CMPGU_EQ_QB:
13721 case OPC_CMPGU_LT_QB:
13722 case OPC_CMPGU_LE_QB:
13723 case OPC_CMPGDU_EQ_QB:
13724 case OPC_CMPGDU_LT_QB:
13725 case OPC_CMPGDU_LE_QB:
13726 case OPC_PICK_QB:
13727 case OPC_PICK_PH:
13728 case OPC_PACKRL_PH:
13729 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
13730 break;
13731 default: /* Invalid */
13732 MIPS_INVAL("MASK CMPU.EQ.QB");
13733 gen_reserved_instruction(ctx);
13734 break;
13735 }
13736 break;
13737 case OPC_SHLL_QB_DSP:
13738 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
13739 break;
13740 case OPC_DPA_W_PH_DSP:
13741 op2 = MASK_DPA_W_PH(ctx->opcode);
13742 switch (op2) {
13743 case OPC_DPAU_H_QBL:
13744 case OPC_DPAU_H_QBR:
13745 case OPC_DPSU_H_QBL:
13746 case OPC_DPSU_H_QBR:
13747 case OPC_DPA_W_PH:
13748 case OPC_DPAX_W_PH:
13749 case OPC_DPAQ_S_W_PH:
13750 case OPC_DPAQX_S_W_PH:
13751 case OPC_DPAQX_SA_W_PH:
13752 case OPC_DPS_W_PH:
13753 case OPC_DPSX_W_PH:
13754 case OPC_DPSQ_S_W_PH:
13755 case OPC_DPSQX_S_W_PH:
13756 case OPC_DPSQX_SA_W_PH:
13757 case OPC_MULSAQ_S_W_PH:
13758 case OPC_DPAQ_SA_L_W:
13759 case OPC_DPSQ_SA_L_W:
13760 case OPC_MAQ_S_W_PHL:
13761 case OPC_MAQ_S_W_PHR:
13762 case OPC_MAQ_SA_W_PHL:
13763 case OPC_MAQ_SA_W_PHR:
13764 case OPC_MULSA_W_PH:
13765 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
13766 break;
13767 default: /* Invalid */
13768 MIPS_INVAL("MASK DPAW.PH");
13769 gen_reserved_instruction(ctx);
13770 break;
13771 }
13772 break;
13773 case OPC_INSV_DSP:
13774 op2 = MASK_INSV(ctx->opcode);
13775 switch (op2) {
13776 case OPC_INSV:
13777 check_dsp(ctx);
13778 {
13779 TCGv t0, t1;
13780
13781 if (rt == 0) {
13782 break;
13783 }
13784
13785 t0 = tcg_temp_new();
13786 t1 = tcg_temp_new();
13787
13788 gen_load_gpr(t0, rt);
13789 gen_load_gpr(t1, rs);
13790
13791 gen_helper_insv(cpu_gpr[rt], tcg_env, t1, t0);
13792 break;
13793 }
13794 default: /* Invalid */
13795 MIPS_INVAL("MASK INSV");
13796 gen_reserved_instruction(ctx);
13797 break;
13798 }
13799 break;
13800 case OPC_APPEND_DSP:
13801 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
13802 break;
13803 case OPC_EXTR_W_DSP:
13804 op2 = MASK_EXTR_W(ctx->opcode);
13805 switch (op2) {
13806 case OPC_EXTR_W:
13807 case OPC_EXTR_R_W:
13808 case OPC_EXTR_RS_W:
13809 case OPC_EXTR_S_H:
13810 case OPC_EXTRV_S_H:
13811 case OPC_EXTRV_W:
13812 case OPC_EXTRV_R_W:
13813 case OPC_EXTRV_RS_W:
13814 case OPC_EXTP:
13815 case OPC_EXTPV:
13816 case OPC_EXTPDP:
13817 case OPC_EXTPDPV:
13818 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
13819 break;
13820 case OPC_RDDSP:
13821 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 1);
13822 break;
13823 case OPC_SHILO:
13824 case OPC_SHILOV:
13825 case OPC_MTHLIP:
13826 case OPC_WRDSP:
13827 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
13828 break;
13829 default: /* Invalid */
13830 MIPS_INVAL("MASK EXTR.W");
13831 gen_reserved_instruction(ctx);
13832 break;
13833 }
13834 break;
13835 #if defined(TARGET_MIPS64)
13836 case OPC_ABSQ_S_QH_DSP:
13837 op2 = MASK_ABSQ_S_QH(ctx->opcode);
13838 switch (op2) {
13839 case OPC_PRECEQ_L_PWL:
13840 case OPC_PRECEQ_L_PWR:
13841 case OPC_PRECEQ_PW_QHL:
13842 case OPC_PRECEQ_PW_QHR:
13843 case OPC_PRECEQ_PW_QHLA:
13844 case OPC_PRECEQ_PW_QHRA:
13845 case OPC_PRECEQU_QH_OBL:
13846 case OPC_PRECEQU_QH_OBR:
13847 case OPC_PRECEQU_QH_OBLA:
13848 case OPC_PRECEQU_QH_OBRA:
13849 case OPC_PRECEU_QH_OBL:
13850 case OPC_PRECEU_QH_OBR:
13851 case OPC_PRECEU_QH_OBLA:
13852 case OPC_PRECEU_QH_OBRA:
13853 case OPC_ABSQ_S_OB:
13854 case OPC_ABSQ_S_PW:
13855 case OPC_ABSQ_S_QH:
13856 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13857 break;
13858 case OPC_REPL_OB:
13859 case OPC_REPL_PW:
13860 case OPC_REPL_QH:
13861 case OPC_REPLV_OB:
13862 case OPC_REPLV_PW:
13863 case OPC_REPLV_QH:
13864 gen_mipsdsp_bitinsn(ctx, op1, op2, rd, rt);
13865 break;
13866 default: /* Invalid */
13867 MIPS_INVAL("MASK ABSQ_S.QH");
13868 gen_reserved_instruction(ctx);
13869 break;
13870 }
13871 break;
13872 case OPC_ADDU_OB_DSP:
13873 op2 = MASK_ADDU_OB(ctx->opcode);
13874 switch (op2) {
13875 case OPC_RADDU_L_OB:
13876 case OPC_SUBQ_PW:
13877 case OPC_SUBQ_S_PW:
13878 case OPC_SUBQ_QH:
13879 case OPC_SUBQ_S_QH:
13880 case OPC_SUBU_OB:
13881 case OPC_SUBU_S_OB:
13882 case OPC_SUBU_QH:
13883 case OPC_SUBU_S_QH:
13884 case OPC_SUBUH_OB:
13885 case OPC_SUBUH_R_OB:
13886 case OPC_ADDQ_PW:
13887 case OPC_ADDQ_S_PW:
13888 case OPC_ADDQ_QH:
13889 case OPC_ADDQ_S_QH:
13890 case OPC_ADDU_OB:
13891 case OPC_ADDU_S_OB:
13892 case OPC_ADDU_QH:
13893 case OPC_ADDU_S_QH:
13894 case OPC_ADDUH_OB:
13895 case OPC_ADDUH_R_OB:
13896 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13897 break;
13898 case OPC_MULEQ_S_PW_QHL:
13899 case OPC_MULEQ_S_PW_QHR:
13900 case OPC_MULEU_S_QH_OBL:
13901 case OPC_MULEU_S_QH_OBR:
13902 case OPC_MULQ_RS_QH:
13903 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 1);
13904 break;
13905 default: /* Invalid */
13906 MIPS_INVAL("MASK ADDU.OB");
13907 gen_reserved_instruction(ctx);
13908 break;
13909 }
13910 break;
13911 case OPC_CMPU_EQ_OB_DSP:
13912 op2 = MASK_CMPU_EQ_OB(ctx->opcode);
13913 switch (op2) {
13914 case OPC_PRECR_SRA_QH_PW:
13915 case OPC_PRECR_SRA_R_QH_PW:
13916 /* Return value is rt. */
13917 gen_mipsdsp_arith(ctx, op1, op2, rt, rs, rd);
13918 break;
13919 case OPC_PRECR_OB_QH:
13920 case OPC_PRECRQ_OB_QH:
13921 case OPC_PRECRQ_PW_L:
13922 case OPC_PRECRQ_QH_PW:
13923 case OPC_PRECRQ_RS_QH_PW:
13924 case OPC_PRECRQU_S_OB_QH:
13925 gen_mipsdsp_arith(ctx, op1, op2, rd, rs, rt);
13926 break;
13927 case OPC_CMPU_EQ_OB:
13928 case OPC_CMPU_LT_OB:
13929 case OPC_CMPU_LE_OB:
13930 case OPC_CMP_EQ_QH:
13931 case OPC_CMP_LT_QH:
13932 case OPC_CMP_LE_QH:
13933 case OPC_CMP_EQ_PW:
13934 case OPC_CMP_LT_PW:
13935 case OPC_CMP_LE_PW:
13936 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 0);
13937 break;
13938 case OPC_CMPGDU_EQ_OB:
13939 case OPC_CMPGDU_LT_OB:
13940 case OPC_CMPGDU_LE_OB:
13941 case OPC_CMPGU_EQ_OB:
13942 case OPC_CMPGU_LT_OB:
13943 case OPC_CMPGU_LE_OB:
13944 case OPC_PACKRL_PW:
13945 case OPC_PICK_OB:
13946 case OPC_PICK_PW:
13947 case OPC_PICK_QH:
13948 gen_mipsdsp_add_cmp_pick(ctx, op1, op2, rd, rs, rt, 1);
13949 break;
13950 default: /* Invalid */
13951 MIPS_INVAL("MASK CMPU_EQ.OB");
13952 gen_reserved_instruction(ctx);
13953 break;
13954 }
13955 break;
13956 case OPC_DAPPEND_DSP:
13957 gen_mipsdsp_append(env, ctx, op1, rt, rs, rd);
13958 break;
13959 case OPC_DEXTR_W_DSP:
13960 op2 = MASK_DEXTR_W(ctx->opcode);
13961 switch (op2) {
13962 case OPC_DEXTP:
13963 case OPC_DEXTPDP:
13964 case OPC_DEXTPDPV:
13965 case OPC_DEXTPV:
13966 case OPC_DEXTR_L:
13967 case OPC_DEXTR_R_L:
13968 case OPC_DEXTR_RS_L:
13969 case OPC_DEXTR_W:
13970 case OPC_DEXTR_R_W:
13971 case OPC_DEXTR_RS_W:
13972 case OPC_DEXTR_S_H:
13973 case OPC_DEXTRV_L:
13974 case OPC_DEXTRV_R_L:
13975 case OPC_DEXTRV_RS_L:
13976 case OPC_DEXTRV_S_H:
13977 case OPC_DEXTRV_W:
13978 case OPC_DEXTRV_R_W:
13979 case OPC_DEXTRV_RS_W:
13980 gen_mipsdsp_accinsn(ctx, op1, op2, rt, rs, rd, 1);
13981 break;
13982 case OPC_DMTHLIP:
13983 case OPC_DSHILO:
13984 case OPC_DSHILOV:
13985 gen_mipsdsp_accinsn(ctx, op1, op2, rd, rs, rt, 0);
13986 break;
13987 default: /* Invalid */
13988 MIPS_INVAL("MASK EXTR.W");
13989 gen_reserved_instruction(ctx);
13990 break;
13991 }
13992 break;
13993 case OPC_DPAQ_W_QH_DSP:
13994 op2 = MASK_DPAQ_W_QH(ctx->opcode);
13995 switch (op2) {
13996 case OPC_DPAU_H_OBL:
13997 case OPC_DPAU_H_OBR:
13998 case OPC_DPSU_H_OBL:
13999 case OPC_DPSU_H_OBR:
14000 case OPC_DPA_W_QH:
14001 case OPC_DPAQ_S_W_QH:
14002 case OPC_DPS_W_QH:
14003 case OPC_DPSQ_S_W_QH:
14004 case OPC_MULSAQ_S_W_QH:
14005 case OPC_DPAQ_SA_L_PW:
14006 case OPC_DPSQ_SA_L_PW:
14007 case OPC_MULSAQ_S_L_PW:
14008 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14009 break;
14010 case OPC_MAQ_S_W_QHLL:
14011 case OPC_MAQ_S_W_QHLR:
14012 case OPC_MAQ_S_W_QHRL:
14013 case OPC_MAQ_S_W_QHRR:
14014 case OPC_MAQ_SA_W_QHLL:
14015 case OPC_MAQ_SA_W_QHLR:
14016 case OPC_MAQ_SA_W_QHRL:
14017 case OPC_MAQ_SA_W_QHRR:
14018 case OPC_MAQ_S_L_PWL:
14019 case OPC_MAQ_S_L_PWR:
14020 case OPC_DMADD:
14021 case OPC_DMADDU:
14022 case OPC_DMSUB:
14023 case OPC_DMSUBU:
14024 gen_mipsdsp_multiply(ctx, op1, op2, rd, rs, rt, 0);
14025 break;
14026 default: /* Invalid */
14027 MIPS_INVAL("MASK DPAQ.W.QH");
14028 gen_reserved_instruction(ctx);
14029 break;
14030 }
14031 break;
14032 case OPC_DINSV_DSP:
14033 op2 = MASK_INSV(ctx->opcode);
14034 switch (op2) {
14035 case OPC_DINSV:
14036 {
14037 TCGv t0, t1;
14038
14039 check_dsp(ctx);
14040
14041 if (rt == 0) {
14042 break;
14043 }
14044
14045 t0 = tcg_temp_new();
14046 t1 = tcg_temp_new();
14047
14048 gen_load_gpr(t0, rt);
14049 gen_load_gpr(t1, rs);
14050
14051 gen_helper_dinsv(cpu_gpr[rt], tcg_env, t1, t0);
14052 break;
14053 }
14054 default: /* Invalid */
14055 MIPS_INVAL("MASK DINSV");
14056 gen_reserved_instruction(ctx);
14057 break;
14058 }
14059 break;
14060 case OPC_SHLL_OB_DSP:
14061 gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
14062 break;
14063 #endif
14064 default: /* Invalid */
14065 MIPS_INVAL("special3_legacy");
14066 gen_reserved_instruction(ctx);
14067 break;
14068 }
14069 }
14070
14071
14072 #if defined(TARGET_MIPS64)
14073
decode_mmi(CPUMIPSState * env,DisasContext * ctx)14074 static void decode_mmi(CPUMIPSState *env, DisasContext *ctx)
14075 {
14076 uint32_t opc = MASK_MMI(ctx->opcode);
14077 int rs = extract32(ctx->opcode, 21, 5);
14078 int rt = extract32(ctx->opcode, 16, 5);
14079 int rd = extract32(ctx->opcode, 11, 5);
14080
14081 switch (opc) {
14082 case MMI_OPC_MULT1:
14083 case MMI_OPC_MULTU1:
14084 case MMI_OPC_MADD:
14085 case MMI_OPC_MADDU:
14086 case MMI_OPC_MADD1:
14087 case MMI_OPC_MADDU1:
14088 gen_mul_txx9(ctx, opc, rd, rs, rt);
14089 break;
14090 case MMI_OPC_DIV1:
14091 case MMI_OPC_DIVU1:
14092 gen_div1_tx79(ctx, opc, rs, rt);
14093 break;
14094 default:
14095 MIPS_INVAL("TX79 MMI class");
14096 gen_reserved_instruction(ctx);
14097 break;
14098 }
14099 }
14100
gen_mmi_sq(DisasContext * ctx,int base,int rt,int offset)14101 static void gen_mmi_sq(DisasContext *ctx, int base, int rt, int offset)
14102 {
14103 gen_reserved_instruction(ctx); /* TODO: MMI_OPC_SQ */
14104 }
14105
14106 /*
14107 * The TX79-specific instruction Store Quadword
14108 *
14109 * +--------+-------+-------+------------------------+
14110 * | 011111 | base | rt | offset | SQ
14111 * +--------+-------+-------+------------------------+
14112 * 6 5 5 16
14113 *
14114 * has the same opcode as the Read Hardware Register instruction
14115 *
14116 * +--------+-------+-------+-------+-------+--------+
14117 * | 011111 | 00000 | rt | rd | 00000 | 111011 | RDHWR
14118 * +--------+-------+-------+-------+-------+--------+
14119 * 6 5 5 5 5 6
14120 *
14121 * that is required, trapped and emulated by the Linux kernel. However, all
14122 * RDHWR encodings yield address error exceptions on the TX79 since the SQ
14123 * offset is odd. Therefore all valid SQ instructions can execute normally.
14124 * In user mode, QEMU must verify the upper and lower 11 bits to distinguish
14125 * between SQ and RDHWR, as the Linux kernel does.
14126 */
decode_mmi_sq(CPUMIPSState * env,DisasContext * ctx)14127 static void decode_mmi_sq(CPUMIPSState *env, DisasContext *ctx)
14128 {
14129 int base = extract32(ctx->opcode, 21, 5);
14130 int rt = extract32(ctx->opcode, 16, 5);
14131 int offset = extract32(ctx->opcode, 0, 16);
14132
14133 #ifdef CONFIG_USER_ONLY
14134 uint32_t op1 = MASK_SPECIAL3(ctx->opcode);
14135 uint32_t op2 = extract32(ctx->opcode, 6, 5);
14136
14137 if (base == 0 && op2 == 0 && op1 == OPC_RDHWR) {
14138 int rd = extract32(ctx->opcode, 11, 5);
14139
14140 gen_rdhwr(ctx, rt, rd, 0);
14141 return;
14142 }
14143 #endif
14144
14145 gen_mmi_sq(ctx, base, rt, offset);
14146 }
14147
14148 #endif
14149
decode_opc_special3(CPUMIPSState * env,DisasContext * ctx)14150 static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
14151 {
14152 int rs, rt, rd, sa;
14153 uint32_t op1, op2;
14154 int16_t imm;
14155
14156 rs = (ctx->opcode >> 21) & 0x1f;
14157 rt = (ctx->opcode >> 16) & 0x1f;
14158 rd = (ctx->opcode >> 11) & 0x1f;
14159 sa = (ctx->opcode >> 6) & 0x1f;
14160 imm = sextract32(ctx->opcode, 7, 9);
14161
14162 op1 = MASK_SPECIAL3(ctx->opcode);
14163
14164 /*
14165 * EVA loads and stores overlap Loongson 2E instructions decoded by
14166 * decode_opc_special3_legacy(), so be careful to allow their decoding when
14167 * EVA is absent.
14168 */
14169 if (ctx->eva) {
14170 switch (op1) {
14171 case OPC_LWLE:
14172 case OPC_LWRE:
14173 case OPC_LBUE:
14174 case OPC_LHUE:
14175 case OPC_LBE:
14176 case OPC_LHE:
14177 case OPC_LLE:
14178 case OPC_LWE:
14179 check_cp0_enabled(ctx);
14180 gen_ld(ctx, op1, rt, rs, imm);
14181 return;
14182 case OPC_SWLE:
14183 case OPC_SWRE:
14184 case OPC_SBE:
14185 case OPC_SHE:
14186 case OPC_SWE:
14187 check_cp0_enabled(ctx);
14188 gen_st(ctx, op1, rt, rs, imm);
14189 return;
14190 case OPC_SCE:
14191 check_cp0_enabled(ctx);
14192 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, true);
14193 return;
14194 case OPC_CACHEE:
14195 check_eva(ctx);
14196 check_cp0_enabled(ctx);
14197 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14198 gen_cache_operation(ctx, rt, rs, imm);
14199 }
14200 return;
14201 case OPC_PREFE:
14202 check_cp0_enabled(ctx);
14203 /* Treat as NOP. */
14204 return;
14205 }
14206 }
14207
14208 switch (op1) {
14209 case OPC_EXT:
14210 case OPC_INS:
14211 check_insn(ctx, ISA_MIPS_R2);
14212 gen_bitops(ctx, op1, rt, rs, sa, rd);
14213 break;
14214 case OPC_BSHFL:
14215 op2 = MASK_BSHFL(ctx->opcode);
14216 switch (op2) {
14217 case OPC_ALIGN:
14218 case OPC_ALIGN_1:
14219 case OPC_ALIGN_2:
14220 case OPC_ALIGN_3:
14221 case OPC_BITSWAP:
14222 check_insn(ctx, ISA_MIPS_R6);
14223 decode_opc_special3_r6(env, ctx);
14224 break;
14225 default:
14226 check_insn(ctx, ISA_MIPS_R2);
14227 gen_bshfl(ctx, op2, rt, rd);
14228 break;
14229 }
14230 break;
14231 #if defined(TARGET_MIPS64)
14232 case OPC_DEXTM:
14233 case OPC_DEXTU:
14234 case OPC_DEXT:
14235 case OPC_DINSM:
14236 case OPC_DINSU:
14237 case OPC_DINS:
14238 check_insn(ctx, ISA_MIPS_R2);
14239 check_mips_64(ctx);
14240 gen_bitops(ctx, op1, rt, rs, sa, rd);
14241 break;
14242 case OPC_DBSHFL:
14243 op2 = MASK_DBSHFL(ctx->opcode);
14244 switch (op2) {
14245 case OPC_DALIGN:
14246 case OPC_DALIGN_1:
14247 case OPC_DALIGN_2:
14248 case OPC_DALIGN_3:
14249 case OPC_DALIGN_4:
14250 case OPC_DALIGN_5:
14251 case OPC_DALIGN_6:
14252 case OPC_DALIGN_7:
14253 case OPC_DBITSWAP:
14254 check_insn(ctx, ISA_MIPS_R6);
14255 decode_opc_special3_r6(env, ctx);
14256 break;
14257 default:
14258 check_insn(ctx, ISA_MIPS_R2);
14259 check_mips_64(ctx);
14260 op2 = MASK_DBSHFL(ctx->opcode);
14261 gen_bshfl(ctx, op2, rt, rd);
14262 break;
14263 }
14264 break;
14265 #endif
14266 case OPC_RDHWR:
14267 gen_rdhwr(ctx, rt, rd, extract32(ctx->opcode, 6, 3));
14268 break;
14269 case OPC_FORK:
14270 check_mt(ctx);
14271 {
14272 TCGv t0 = tcg_temp_new();
14273 TCGv t1 = tcg_temp_new();
14274
14275 gen_load_gpr(t0, rt);
14276 gen_load_gpr(t1, rs);
14277 gen_helper_fork(t0, t1);
14278 }
14279 break;
14280 case OPC_YIELD:
14281 check_mt(ctx);
14282 {
14283 TCGv t0 = tcg_temp_new();
14284
14285 gen_load_gpr(t0, rs);
14286 gen_helper_yield(t0, tcg_env, t0);
14287 gen_store_gpr(t0, rd);
14288 }
14289 break;
14290 default:
14291 if (ctx->insn_flags & ISA_MIPS_R6) {
14292 decode_opc_special3_r6(env, ctx);
14293 } else {
14294 decode_opc_special3_legacy(env, ctx);
14295 }
14296 }
14297 }
14298
decode_opc_legacy(CPUMIPSState * env,DisasContext * ctx)14299 static bool decode_opc_legacy(CPUMIPSState *env, DisasContext *ctx)
14300 {
14301 int32_t offset;
14302 int rs, rt, rd, sa;
14303 uint32_t op, op1;
14304 int16_t imm;
14305
14306 op = MASK_OP_MAJOR(ctx->opcode);
14307 rs = (ctx->opcode >> 21) & 0x1f;
14308 rt = (ctx->opcode >> 16) & 0x1f;
14309 rd = (ctx->opcode >> 11) & 0x1f;
14310 sa = (ctx->opcode >> 6) & 0x1f;
14311 imm = (int16_t)ctx->opcode;
14312 switch (op) {
14313 case OPC_SPECIAL:
14314 decode_opc_special(env, ctx);
14315 break;
14316 case OPC_SPECIAL2:
14317 #if defined(TARGET_MIPS64)
14318 if ((ctx->insn_flags & INSN_R5900) && (ctx->insn_flags & ASE_MMI)) {
14319 decode_mmi(env, ctx);
14320 break;
14321 }
14322 #endif
14323 if (TARGET_LONG_BITS == 32 && (ctx->insn_flags & ASE_MXU)) {
14324 if (decode_ase_mxu(ctx, ctx->opcode)) {
14325 break;
14326 }
14327 }
14328 decode_opc_special2_legacy(env, ctx);
14329 break;
14330 case OPC_SPECIAL3:
14331 #if defined(TARGET_MIPS64)
14332 if (ctx->insn_flags & INSN_R5900) {
14333 decode_mmi_sq(env, ctx); /* MMI_OPC_SQ */
14334 } else {
14335 decode_opc_special3(env, ctx);
14336 }
14337 #else
14338 decode_opc_special3(env, ctx);
14339 #endif
14340 break;
14341 case OPC_REGIMM:
14342 op1 = MASK_REGIMM(ctx->opcode);
14343 switch (op1) {
14344 case OPC_BLTZL: /* REGIMM branches */
14345 case OPC_BGEZL:
14346 case OPC_BLTZALL:
14347 case OPC_BGEZALL:
14348 check_insn(ctx, ISA_MIPS2);
14349 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14350 /* Fallthrough */
14351 case OPC_BLTZ:
14352 case OPC_BGEZ:
14353 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
14354 break;
14355 case OPC_BLTZAL:
14356 case OPC_BGEZAL:
14357 if (ctx->insn_flags & ISA_MIPS_R6) {
14358 if (rs == 0) {
14359 /* OPC_NAL, OPC_BAL */
14360 gen_compute_branch(ctx, op1, 4, 0, -1, imm << 2, 4);
14361 } else {
14362 gen_reserved_instruction(ctx);
14363 }
14364 } else {
14365 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2, 4);
14366 }
14367 break;
14368 case OPC_TGEI: /* REGIMM traps */
14369 case OPC_TGEIU:
14370 case OPC_TLTI:
14371 case OPC_TLTIU:
14372 case OPC_TEQI:
14373 case OPC_TNEI:
14374 check_insn(ctx, ISA_MIPS2);
14375 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14376 gen_trap(ctx, op1, rs, -1, imm, 0);
14377 break;
14378 case OPC_SIGRIE:
14379 check_insn(ctx, ISA_MIPS_R6);
14380 gen_reserved_instruction(ctx);
14381 break;
14382 case OPC_SYNCI:
14383 check_insn(ctx, ISA_MIPS_R2);
14384 /*
14385 * Break the TB to be able to sync copied instructions
14386 * immediately.
14387 */
14388 ctx->base.is_jmp = DISAS_STOP;
14389 break;
14390 case OPC_BPOSGE32: /* MIPS DSP branch */
14391 #if defined(TARGET_MIPS64)
14392 case OPC_BPOSGE64:
14393 #endif
14394 check_dsp(ctx);
14395 gen_compute_branch(ctx, op1, 4, -1, -2, (int32_t)imm << 2, 4);
14396 break;
14397 #if defined(TARGET_MIPS64)
14398 case OPC_DAHI:
14399 check_insn(ctx, ISA_MIPS_R6);
14400 check_mips_64(ctx);
14401 if (rs != 0) {
14402 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 32);
14403 }
14404 break;
14405 case OPC_DATI:
14406 check_insn(ctx, ISA_MIPS_R6);
14407 check_mips_64(ctx);
14408 if (rs != 0) {
14409 tcg_gen_addi_tl(cpu_gpr[rs], cpu_gpr[rs], (int64_t)imm << 48);
14410 }
14411 break;
14412 #endif
14413 default: /* Invalid */
14414 MIPS_INVAL("regimm");
14415 gen_reserved_instruction(ctx);
14416 break;
14417 }
14418 break;
14419 case OPC_CP0:
14420 check_cp0_enabled(ctx);
14421 op1 = MASK_CP0(ctx->opcode);
14422 switch (op1) {
14423 case OPC_MFC0:
14424 case OPC_MTC0:
14425 case OPC_MFTR:
14426 case OPC_MTTR:
14427 case OPC_MFHC0:
14428 case OPC_MTHC0:
14429 #if defined(TARGET_MIPS64)
14430 case OPC_DMFC0:
14431 case OPC_DMTC0:
14432 #endif
14433 #ifndef CONFIG_USER_ONLY
14434 gen_cp0(env, ctx, op1, rt, rd);
14435 #endif /* !CONFIG_USER_ONLY */
14436 break;
14437 case OPC_C0:
14438 case OPC_C0_1:
14439 case OPC_C0_2:
14440 case OPC_C0_3:
14441 case OPC_C0_4:
14442 case OPC_C0_5:
14443 case OPC_C0_6:
14444 case OPC_C0_7:
14445 case OPC_C0_8:
14446 case OPC_C0_9:
14447 case OPC_C0_A:
14448 case OPC_C0_B:
14449 case OPC_C0_C:
14450 case OPC_C0_D:
14451 case OPC_C0_E:
14452 case OPC_C0_F:
14453 #ifndef CONFIG_USER_ONLY
14454 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
14455 #endif /* !CONFIG_USER_ONLY */
14456 break;
14457 case OPC_MFMC0:
14458 #ifndef CONFIG_USER_ONLY
14459 {
14460 uint32_t op2;
14461 TCGv t0 = tcg_temp_new();
14462
14463 op2 = MASK_MFMC0(ctx->opcode);
14464 switch (op2) {
14465 case OPC_DMT:
14466 check_cp0_mt(ctx);
14467 gen_helper_dmt(t0);
14468 gen_store_gpr(t0, rt);
14469 break;
14470 case OPC_EMT:
14471 check_cp0_mt(ctx);
14472 gen_helper_emt(t0);
14473 gen_store_gpr(t0, rt);
14474 break;
14475 case OPC_DVPE:
14476 check_cp0_mt(ctx);
14477 gen_helper_dvpe(t0, tcg_env);
14478 gen_store_gpr(t0, rt);
14479 break;
14480 case OPC_EVPE:
14481 check_cp0_mt(ctx);
14482 gen_helper_evpe(t0, tcg_env);
14483 gen_store_gpr(t0, rt);
14484 break;
14485 case OPC_DVP:
14486 check_insn(ctx, ISA_MIPS_R6);
14487 if (ctx->vp) {
14488 gen_helper_dvp(t0, tcg_env);
14489 gen_store_gpr(t0, rt);
14490 }
14491 break;
14492 case OPC_EVP:
14493 check_insn(ctx, ISA_MIPS_R6);
14494 if (ctx->vp) {
14495 gen_helper_evp(t0, tcg_env);
14496 gen_store_gpr(t0, rt);
14497 }
14498 break;
14499 case OPC_DI:
14500 check_insn(ctx, ISA_MIPS_R2);
14501 save_cpu_state(ctx, 1);
14502 gen_helper_di(t0, tcg_env);
14503 gen_store_gpr(t0, rt);
14504 /*
14505 * Stop translation as we may have switched
14506 * the execution mode.
14507 */
14508 ctx->base.is_jmp = DISAS_STOP;
14509 break;
14510 case OPC_EI:
14511 check_insn(ctx, ISA_MIPS_R2);
14512 save_cpu_state(ctx, 1);
14513 gen_helper_ei(t0, tcg_env);
14514 gen_store_gpr(t0, rt);
14515 /*
14516 * DISAS_STOP isn't sufficient, we need to ensure we break
14517 * out of translated code to check for pending interrupts.
14518 */
14519 gen_save_pc(ctx->base.pc_next + 4);
14520 ctx->base.is_jmp = DISAS_EXIT;
14521 break;
14522 default: /* Invalid */
14523 MIPS_INVAL("mfmc0");
14524 gen_reserved_instruction(ctx);
14525 break;
14526 }
14527 }
14528 #endif /* !CONFIG_USER_ONLY */
14529 break;
14530 case OPC_RDPGPR:
14531 check_insn(ctx, ISA_MIPS_R2);
14532 gen_load_srsgpr(rt, rd);
14533 break;
14534 case OPC_WRPGPR:
14535 check_insn(ctx, ISA_MIPS_R2);
14536 gen_store_srsgpr(rt, rd);
14537 break;
14538 default:
14539 MIPS_INVAL("cp0");
14540 gen_reserved_instruction(ctx);
14541 break;
14542 }
14543 break;
14544 case OPC_BOVC: /* OPC_BEQZALC, OPC_BEQC, OPC_ADDI */
14545 if (ctx->insn_flags & ISA_MIPS_R6) {
14546 /* OPC_BOVC, OPC_BEQZALC, OPC_BEQC */
14547 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14548 } else {
14549 /* OPC_ADDI */
14550 /* Arithmetic with immediate opcode */
14551 gen_arith_imm(ctx, op, rt, rs, imm);
14552 }
14553 break;
14554 case OPC_ADDIU:
14555 gen_arith_imm(ctx, op, rt, rs, imm);
14556 break;
14557 case OPC_SLTI: /* Set on less than with immediate opcode */
14558 case OPC_SLTIU:
14559 gen_slt_imm(ctx, op, rt, rs, imm);
14560 break;
14561 case OPC_ANDI: /* Arithmetic with immediate opcode */
14562 case OPC_LUI: /* OPC_AUI */
14563 case OPC_ORI:
14564 case OPC_XORI:
14565 gen_logic_imm(ctx, op, rt, rs, imm);
14566 break;
14567 case OPC_J: /* Jump */
14568 case OPC_JAL:
14569 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14570 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
14571 break;
14572 /* Branch */
14573 case OPC_BLEZC: /* OPC_BGEZC, OPC_BGEC, OPC_BLEZL */
14574 if (ctx->insn_flags & ISA_MIPS_R6) {
14575 if (rt == 0) {
14576 gen_reserved_instruction(ctx);
14577 break;
14578 }
14579 /* OPC_BLEZC, OPC_BGEZC, OPC_BGEC */
14580 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14581 } else {
14582 /* OPC_BLEZL */
14583 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14584 }
14585 break;
14586 case OPC_BGTZC: /* OPC_BLTZC, OPC_BLTC, OPC_BGTZL */
14587 if (ctx->insn_flags & ISA_MIPS_R6) {
14588 if (rt == 0) {
14589 gen_reserved_instruction(ctx);
14590 break;
14591 }
14592 /* OPC_BGTZC, OPC_BLTZC, OPC_BLTC */
14593 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14594 } else {
14595 /* OPC_BGTZL */
14596 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14597 }
14598 break;
14599 case OPC_BLEZALC: /* OPC_BGEZALC, OPC_BGEUC, OPC_BLEZ */
14600 if (rt == 0) {
14601 /* OPC_BLEZ */
14602 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14603 } else {
14604 check_insn(ctx, ISA_MIPS_R6);
14605 /* OPC_BLEZALC, OPC_BGEZALC, OPC_BGEUC */
14606 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14607 }
14608 break;
14609 case OPC_BGTZALC: /* OPC_BLTZALC, OPC_BLTUC, OPC_BGTZ */
14610 if (rt == 0) {
14611 /* OPC_BGTZ */
14612 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14613 } else {
14614 check_insn(ctx, ISA_MIPS_R6);
14615 /* OPC_BGTZALC, OPC_BLTZALC, OPC_BLTUC */
14616 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14617 }
14618 break;
14619 case OPC_BEQL:
14620 case OPC_BNEL:
14621 check_insn(ctx, ISA_MIPS2);
14622 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14623 /* Fallthrough */
14624 case OPC_BEQ:
14625 case OPC_BNE:
14626 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2, 4);
14627 break;
14628 case OPC_LL: /* Load and stores */
14629 check_insn(ctx, ISA_MIPS2);
14630 if (ctx->insn_flags & INSN_R5900) {
14631 check_insn_opc_user_only(ctx, INSN_R5900);
14632 }
14633 /* Fallthrough */
14634 case OPC_LWL:
14635 case OPC_LWR:
14636 case OPC_LB:
14637 case OPC_LH:
14638 case OPC_LW:
14639 case OPC_LWPC:
14640 case OPC_LBU:
14641 case OPC_LHU:
14642 gen_ld(ctx, op, rt, rs, imm);
14643 break;
14644 case OPC_SWL:
14645 case OPC_SWR:
14646 case OPC_SB:
14647 case OPC_SH:
14648 case OPC_SW:
14649 gen_st(ctx, op, rt, rs, imm);
14650 break;
14651 case OPC_SC:
14652 check_insn(ctx, ISA_MIPS2);
14653 if (ctx->insn_flags & INSN_R5900) {
14654 check_insn_opc_user_only(ctx, INSN_R5900);
14655 }
14656 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_SL, false);
14657 break;
14658 case OPC_CACHE:
14659 check_cp0_enabled(ctx);
14660 check_insn(ctx, ISA_MIPS3 | ISA_MIPS_R1);
14661 if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
14662 gen_cache_operation(ctx, rt, rs, imm);
14663 }
14664 /* Treat as NOP. */
14665 break;
14666 case OPC_PREF:
14667 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R1 | INSN_R5900);
14668 /* Treat as NOP. */
14669 break;
14670
14671 /* Floating point (COP1). */
14672 case OPC_LWC1:
14673 case OPC_LDC1:
14674 case OPC_SWC1:
14675 case OPC_SDC1:
14676 gen_cop1_ldst(ctx, op, rt, rs, imm);
14677 break;
14678
14679 case OPC_CP1:
14680 op1 = MASK_CP1(ctx->opcode);
14681
14682 switch (op1) {
14683 case OPC_MFHC1:
14684 case OPC_MTHC1:
14685 check_cp1_enabled(ctx);
14686 check_insn(ctx, ISA_MIPS_R2);
14687 /* fall through */
14688 case OPC_MFC1:
14689 case OPC_CFC1:
14690 case OPC_MTC1:
14691 case OPC_CTC1:
14692 check_cp1_enabled(ctx);
14693 gen_cp1(ctx, op1, rt, rd);
14694 break;
14695 #if defined(TARGET_MIPS64)
14696 case OPC_DMFC1:
14697 case OPC_DMTC1:
14698 check_cp1_enabled(ctx);
14699 check_insn(ctx, ISA_MIPS3);
14700 check_mips_64(ctx);
14701 gen_cp1(ctx, op1, rt, rd);
14702 break;
14703 #endif
14704 case OPC_BC1EQZ: /* OPC_BC1ANY2 */
14705 check_cp1_enabled(ctx);
14706 if (ctx->insn_flags & ISA_MIPS_R6) {
14707 /* OPC_BC1EQZ */
14708 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
14709 rt, imm << 2, 4);
14710 } else {
14711 /* OPC_BC1ANY2 */
14712 check_cop1x(ctx);
14713 if (!ase_3d_available(env)) {
14714 return false;
14715 }
14716 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
14717 (rt >> 2) & 0x7, imm << 2);
14718 }
14719 break;
14720 case OPC_BC1NEZ:
14721 check_cp1_enabled(ctx);
14722 check_insn(ctx, ISA_MIPS_R6);
14723 gen_compute_branch1_r6(ctx, MASK_CP1(ctx->opcode),
14724 rt, imm << 2, 4);
14725 break;
14726 case OPC_BC1ANY4:
14727 check_cp1_enabled(ctx);
14728 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14729 check_cop1x(ctx);
14730 if (!ase_3d_available(env)) {
14731 return false;
14732 }
14733 /* fall through */
14734 case OPC_BC1:
14735 check_cp1_enabled(ctx);
14736 check_insn_opc_removed(ctx, ISA_MIPS_R6);
14737 gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
14738 (rt >> 2) & 0x7, imm << 2);
14739 break;
14740 case OPC_PS_FMT:
14741 check_ps(ctx);
14742 /* fall through */
14743 case OPC_S_FMT:
14744 case OPC_D_FMT:
14745 check_cp1_enabled(ctx);
14746 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
14747 (imm >> 8) & 0x7);
14748 break;
14749 case OPC_W_FMT:
14750 case OPC_L_FMT:
14751 {
14752 int r6_op = ctx->opcode & FOP(0x3f, 0x1f);
14753 check_cp1_enabled(ctx);
14754 if (ctx->insn_flags & ISA_MIPS_R6) {
14755 switch (r6_op) {
14756 case R6_OPC_CMP_AF_S:
14757 case R6_OPC_CMP_UN_S:
14758 case R6_OPC_CMP_EQ_S:
14759 case R6_OPC_CMP_UEQ_S:
14760 case R6_OPC_CMP_LT_S:
14761 case R6_OPC_CMP_ULT_S:
14762 case R6_OPC_CMP_LE_S:
14763 case R6_OPC_CMP_ULE_S:
14764 case R6_OPC_CMP_SAF_S:
14765 case R6_OPC_CMP_SUN_S:
14766 case R6_OPC_CMP_SEQ_S:
14767 case R6_OPC_CMP_SEUQ_S:
14768 case R6_OPC_CMP_SLT_S:
14769 case R6_OPC_CMP_SULT_S:
14770 case R6_OPC_CMP_SLE_S:
14771 case R6_OPC_CMP_SULE_S:
14772 case R6_OPC_CMP_OR_S:
14773 case R6_OPC_CMP_UNE_S:
14774 case R6_OPC_CMP_NE_S:
14775 case R6_OPC_CMP_SOR_S:
14776 case R6_OPC_CMP_SUNE_S:
14777 case R6_OPC_CMP_SNE_S:
14778 gen_r6_cmp_s(ctx, ctx->opcode & 0x1f, rt, rd, sa);
14779 break;
14780 case R6_OPC_CMP_AF_D:
14781 case R6_OPC_CMP_UN_D:
14782 case R6_OPC_CMP_EQ_D:
14783 case R6_OPC_CMP_UEQ_D:
14784 case R6_OPC_CMP_LT_D:
14785 case R6_OPC_CMP_ULT_D:
14786 case R6_OPC_CMP_LE_D:
14787 case R6_OPC_CMP_ULE_D:
14788 case R6_OPC_CMP_SAF_D:
14789 case R6_OPC_CMP_SUN_D:
14790 case R6_OPC_CMP_SEQ_D:
14791 case R6_OPC_CMP_SEUQ_D:
14792 case R6_OPC_CMP_SLT_D:
14793 case R6_OPC_CMP_SULT_D:
14794 case R6_OPC_CMP_SLE_D:
14795 case R6_OPC_CMP_SULE_D:
14796 case R6_OPC_CMP_OR_D:
14797 case R6_OPC_CMP_UNE_D:
14798 case R6_OPC_CMP_NE_D:
14799 case R6_OPC_CMP_SOR_D:
14800 case R6_OPC_CMP_SUNE_D:
14801 case R6_OPC_CMP_SNE_D:
14802 gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
14803 break;
14804 default:
14805 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
14806 rt, rd, sa, (imm >> 8) & 0x7);
14807
14808 break;
14809 }
14810 } else {
14811 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
14812 (imm >> 8) & 0x7);
14813 }
14814 break;
14815 }
14816 default:
14817 MIPS_INVAL("cp1");
14818 gen_reserved_instruction(ctx);
14819 break;
14820 }
14821 break;
14822
14823 /* Compact branches [R6] and COP2 [non-R6] */
14824 case OPC_BC: /* OPC_LWC2 */
14825 case OPC_BALC: /* OPC_SWC2 */
14826 if (ctx->insn_flags & ISA_MIPS_R6) {
14827 /* OPC_BC, OPC_BALC */
14828 gen_compute_compact_branch(ctx, op, 0, 0,
14829 sextract32(ctx->opcode << 2, 0, 28));
14830 } else if (ctx->insn_flags & ASE_LEXT) {
14831 gen_loongson_lswc2(ctx, rt, rs, rd);
14832 } else {
14833 /* OPC_LWC2, OPC_SWC2 */
14834 /* COP2: Not implemented. */
14835 generate_exception_err(ctx, EXCP_CpU, 2);
14836 }
14837 break;
14838 case OPC_BEQZC: /* OPC_JIC, OPC_LDC2 */
14839 case OPC_BNEZC: /* OPC_JIALC, OPC_SDC2 */
14840 if (ctx->insn_flags & ISA_MIPS_R6) {
14841 if (rs != 0) {
14842 /* OPC_BEQZC, OPC_BNEZC */
14843 gen_compute_compact_branch(ctx, op, rs, 0,
14844 sextract32(ctx->opcode << 2, 0, 23));
14845 } else {
14846 /* OPC_JIC, OPC_JIALC */
14847 gen_compute_compact_branch(ctx, op, 0, rt, imm);
14848 }
14849 } else if (ctx->insn_flags & ASE_LEXT) {
14850 gen_loongson_lsdc2(ctx, rt, rs, rd);
14851 } else {
14852 /* OPC_LWC2, OPC_SWC2 */
14853 /* COP2: Not implemented. */
14854 generate_exception_err(ctx, EXCP_CpU, 2);
14855 }
14856 break;
14857 case OPC_CP2:
14858 check_insn(ctx, ASE_LMMI);
14859 /* Note that these instructions use different fields. */
14860 gen_loongson_multimedia(ctx, sa, rd, rt);
14861 break;
14862
14863 case OPC_CP3:
14864 if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
14865 check_cp1_enabled(ctx);
14866 op1 = MASK_CP3(ctx->opcode);
14867 switch (op1) {
14868 case OPC_LUXC1:
14869 case OPC_SUXC1:
14870 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
14871 /* Fallthrough */
14872 case OPC_LWXC1:
14873 case OPC_LDXC1:
14874 case OPC_SWXC1:
14875 case OPC_SDXC1:
14876 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
14877 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
14878 break;
14879 case OPC_PREFX:
14880 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
14881 /* Treat as NOP. */
14882 break;
14883 case OPC_ALNV_PS:
14884 check_insn(ctx, ISA_MIPS5 | ISA_MIPS_R2);
14885 /* Fallthrough */
14886 case OPC_MADD_S:
14887 case OPC_MADD_D:
14888 case OPC_MADD_PS:
14889 case OPC_MSUB_S:
14890 case OPC_MSUB_D:
14891 case OPC_MSUB_PS:
14892 case OPC_NMADD_S:
14893 case OPC_NMADD_D:
14894 case OPC_NMADD_PS:
14895 case OPC_NMSUB_S:
14896 case OPC_NMSUB_D:
14897 case OPC_NMSUB_PS:
14898 check_insn(ctx, ISA_MIPS4 | ISA_MIPS_R2);
14899 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
14900 break;
14901 default:
14902 MIPS_INVAL("cp3");
14903 gen_reserved_instruction(ctx);
14904 break;
14905 }
14906 } else {
14907 generate_exception_err(ctx, EXCP_CpU, 1);
14908 }
14909 break;
14910
14911 #if defined(TARGET_MIPS64)
14912 /* MIPS64 opcodes */
14913 case OPC_LLD:
14914 if (ctx->insn_flags & INSN_R5900) {
14915 check_insn_opc_user_only(ctx, INSN_R5900);
14916 }
14917 /* fall through */
14918 case OPC_LDL:
14919 case OPC_LDR:
14920 case OPC_LWU:
14921 case OPC_LD:
14922 check_insn(ctx, ISA_MIPS3);
14923 check_mips_64(ctx);
14924 gen_ld(ctx, op, rt, rs, imm);
14925 break;
14926 case OPC_SDL:
14927 case OPC_SDR:
14928 case OPC_SD:
14929 check_insn(ctx, ISA_MIPS3);
14930 check_mips_64(ctx);
14931 gen_st(ctx, op, rt, rs, imm);
14932 break;
14933 case OPC_SCD:
14934 check_insn(ctx, ISA_MIPS3);
14935 if (ctx->insn_flags & INSN_R5900) {
14936 check_insn_opc_user_only(ctx, INSN_R5900);
14937 }
14938 check_mips_64(ctx);
14939 gen_st_cond(ctx, rt, rs, imm, mo_endian(ctx) | MO_UQ, false);
14940 break;
14941 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC, OPC_DADDI */
14942 if (ctx->insn_flags & ISA_MIPS_R6) {
14943 /* OPC_BNVC, OPC_BNEZALC, OPC_BNEC */
14944 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14945 } else {
14946 /* OPC_DADDI */
14947 check_insn(ctx, ISA_MIPS3);
14948 check_mips_64(ctx);
14949 gen_arith_imm(ctx, op, rt, rs, imm);
14950 }
14951 break;
14952 case OPC_DADDIU:
14953 check_insn(ctx, ISA_MIPS3);
14954 check_mips_64(ctx);
14955 gen_arith_imm(ctx, op, rt, rs, imm);
14956 break;
14957 #else
14958 case OPC_BNVC: /* OPC_BNEZALC, OPC_BNEC */
14959 if (ctx->insn_flags & ISA_MIPS_R6) {
14960 gen_compute_compact_branch(ctx, op, rs, rt, imm << 2);
14961 } else {
14962 MIPS_INVAL("major opcode");
14963 gen_reserved_instruction(ctx);
14964 }
14965 break;
14966 #endif
14967 case OPC_DAUI: /* OPC_JALX */
14968 if (ctx->insn_flags & ISA_MIPS_R6) {
14969 #if defined(TARGET_MIPS64)
14970 /* OPC_DAUI */
14971 check_mips_64(ctx);
14972 if (rs == 0) {
14973 generate_exception(ctx, EXCP_RI);
14974 } else if (rt != 0) {
14975 TCGv t0 = tcg_temp_new();
14976 gen_load_gpr(t0, rs);
14977 tcg_gen_addi_tl(cpu_gpr[rt], t0, imm << 16);
14978 }
14979 #else
14980 gen_reserved_instruction(ctx);
14981 MIPS_INVAL("major opcode");
14982 #endif
14983 } else {
14984 /* OPC_JALX */
14985 check_insn(ctx, ASE_MIPS16 | ASE_MICROMIPS);
14986 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
14987 gen_compute_branch(ctx, op, 4, rs, rt, offset, 4);
14988 }
14989 break;
14990 case OPC_MDMX:
14991 /* MDMX: Not implemented. */
14992 break;
14993 case OPC_PCREL:
14994 check_insn(ctx, ISA_MIPS_R6);
14995 gen_pcrel(ctx, ctx->opcode, ctx->base.pc_next, rs);
14996 break;
14997 default: /* Invalid */
14998 MIPS_INVAL("major opcode");
14999 return false;
15000 }
15001 return true;
15002 }
15003
decode_opc(CPUMIPSState * env,DisasContext * ctx)15004 static void decode_opc(CPUMIPSState *env, DisasContext *ctx)
15005 {
15006 /* make sure instructions are on a word boundary */
15007 if (ctx->base.pc_next & 0x3) {
15008 env->CP0_BadVAddr = ctx->base.pc_next;
15009 generate_exception_err(ctx, EXCP_AdEL, EXCP_INST_NOTAVAIL);
15010 return;
15011 }
15012
15013 /* Handle blikely not taken case */
15014 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
15015 TCGLabel *l1 = gen_new_label();
15016
15017 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
15018 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
15019 gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
15020 gen_set_label(l1);
15021 }
15022
15023 /* Transition to the auto-generated decoder. */
15024
15025 /* Vendor specific extensions */
15026 if (cpu_supports_isa(env, INSN_R5900) && decode_ext_txx9(ctx, ctx->opcode)) {
15027 return;
15028 }
15029 if (cpu_supports_isa(env, INSN_VR54XX) && decode_ext_vr54xx(ctx, ctx->opcode)) {
15030 return;
15031 }
15032 if (TARGET_LONG_BITS == 64 && decode_ext_loongson(ctx, ctx->opcode)) {
15033 return;
15034 }
15035 #if defined(TARGET_MIPS64)
15036 if (ase_lcsr_available(env) && decode_ase_lcsr(ctx, ctx->opcode)) {
15037 return;
15038 }
15039 if (cpu_supports_isa(env, INSN_OCTEON) && decode_ext_octeon(ctx, ctx->opcode)) {
15040 return;
15041 }
15042 #endif
15043
15044 /* ISA extensions */
15045 if (ase_msa_available(env) && decode_ase_msa(ctx, ctx->opcode)) {
15046 return;
15047 }
15048
15049 /* ISA (from latest to oldest) */
15050 if (cpu_supports_isa(env, ISA_MIPS_R6) && decode_isa_rel6(ctx, ctx->opcode)) {
15051 return;
15052 }
15053
15054 if (decode_opc_legacy(env, ctx)) {
15055 return;
15056 }
15057
15058 gen_reserved_instruction(ctx);
15059 }
15060
mips_tr_init_disas_context(DisasContextBase * dcbase,CPUState * cs)15061 static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
15062 {
15063 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15064 CPUMIPSState *env = cpu_env(cs);
15065
15066 ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
15067 ctx->saved_pc = -1;
15068 ctx->insn_flags = env->insn_flags;
15069 ctx->CP0_Config0 = env->CP0_Config0;
15070 ctx->CP0_Config1 = env->CP0_Config1;
15071 ctx->CP0_Config2 = env->CP0_Config2;
15072 ctx->CP0_Config3 = env->CP0_Config3;
15073 ctx->CP0_Config5 = env->CP0_Config5;
15074 ctx->btarget = 0;
15075 ctx->kscrexist = (env->CP0_Config4 >> CP0C4_KScrExist) & 0xff;
15076 ctx->rxi = (env->CP0_Config3 >> CP0C3_RXI) & 1;
15077 ctx->ie = (env->CP0_Config4 >> CP0C4_IE) & 3;
15078 ctx->bi = (env->CP0_Config3 >> CP0C3_BI) & 1;
15079 ctx->bp = (env->CP0_Config3 >> CP0C3_BP) & 1;
15080 ctx->PAMask = env->PAMask;
15081 ctx->mvh = (env->CP0_Config5 >> CP0C5_MVH) & 1;
15082 ctx->eva = (env->CP0_Config5 >> CP0C5_EVA) & 1;
15083 ctx->sc = (env->CP0_Config3 >> CP0C3_SC) & 1;
15084 ctx->CP0_LLAddr_shift = env->CP0_LLAddr_shift;
15085 ctx->cmgcr = (env->CP0_Config3 >> CP0C3_CMGCR) & 1;
15086 /* Restore delay slot state from the tb context. */
15087 ctx->hflags = (uint32_t)ctx->base.tb->flags; /* FIXME: maybe use 64 bits? */
15088 ctx->ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
15089 ctx->ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
15090 (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
15091 ctx->vp = (env->CP0_Config5 >> CP0C5_VP) & 1;
15092 ctx->mrp = (env->CP0_Config5 >> CP0C5_MRP) & 1;
15093 ctx->nan2008 = (env->active_fpu.fcr31 >> FCR31_NAN2008) & 1;
15094 ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
15095 ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
15096 ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
15097 restore_cpu_state(env, ctx);
15098 #ifdef CONFIG_USER_ONLY
15099 ctx->mem_idx = MIPS_HFLAG_UM;
15100 #else
15101 ctx->mem_idx = hflags_mmu_index(ctx->hflags);
15102 #endif
15103 ctx->default_tcg_memop_mask = (!(ctx->insn_flags & ISA_NANOMIPS32) &&
15104 (ctx->insn_flags & (ISA_MIPS_R6 |
15105 INSN_LOONGSON3A))) ? MO_UNALN : MO_ALIGN;
15106
15107 /*
15108 * Execute a branch and its delay slot as a single instruction.
15109 * This is what GDB expects and is consistent with what the
15110 * hardware does (e.g. if a delay slot instruction faults, the
15111 * reported PC is the PC of the branch).
15112 */
15113 if ((tb_cflags(ctx->base.tb) & CF_SINGLE_STEP) &&
15114 (ctx->hflags & MIPS_HFLAG_BMASK)) {
15115 ctx->base.max_insns = 2;
15116 }
15117
15118 LOG_DISAS("\ntb %p idx %d hflags %04x\n", ctx->base.tb, ctx->mem_idx,
15119 ctx->hflags);
15120 }
15121
mips_tr_tb_start(DisasContextBase * dcbase,CPUState * cs)15122 static void mips_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
15123 {
15124 }
15125
mips_tr_insn_start(DisasContextBase * dcbase,CPUState * cs)15126 static void mips_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
15127 {
15128 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15129
15130 tcg_gen_insn_start(ctx->base.pc_next, ctx->hflags & MIPS_HFLAG_BMASK,
15131 ctx->btarget);
15132 }
15133
mips_tr_translate_insn(DisasContextBase * dcbase,CPUState * cs)15134 static void mips_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
15135 {
15136 CPUMIPSState *env = cpu_env(cs);
15137 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15138 int insn_bytes;
15139 int is_slot;
15140
15141 is_slot = ctx->hflags & MIPS_HFLAG_BMASK;
15142 if (ctx->insn_flags & ISA_NANOMIPS32) {
15143 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
15144 insn_bytes = decode_isa_nanomips(env, ctx);
15145 } else if (!(ctx->hflags & MIPS_HFLAG_M16)) {
15146 ctx->opcode = translator_ldl(env, &ctx->base, ctx->base.pc_next);
15147 insn_bytes = 4;
15148 decode_opc(env, ctx);
15149 } else if (ctx->insn_flags & ASE_MICROMIPS) {
15150 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
15151 insn_bytes = decode_isa_micromips(env, ctx);
15152 } else if (ctx->insn_flags & ASE_MIPS16) {
15153 ctx->opcode = translator_lduw(env, &ctx->base, ctx->base.pc_next);
15154 insn_bytes = decode_ase_mips16e(env, ctx);
15155 } else {
15156 gen_reserved_instruction(ctx);
15157 g_assert(ctx->base.is_jmp == DISAS_NORETURN);
15158 return;
15159 }
15160
15161 if (ctx->hflags & MIPS_HFLAG_BMASK) {
15162 if (!(ctx->hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
15163 MIPS_HFLAG_FBNSLOT))) {
15164 /*
15165 * Force to generate branch as there is neither delay nor
15166 * forbidden slot.
15167 */
15168 is_slot = 1;
15169 }
15170 if ((ctx->hflags & MIPS_HFLAG_M16) &&
15171 (ctx->hflags & MIPS_HFLAG_FBNSLOT)) {
15172 /*
15173 * Force to generate branch as microMIPS R6 doesn't restrict
15174 * branches in the forbidden slot.
15175 */
15176 is_slot = 1;
15177 }
15178 }
15179 if (is_slot) {
15180 gen_branch(ctx, insn_bytes);
15181 }
15182 if (ctx->base.is_jmp == DISAS_SEMIHOST) {
15183 generate_exception_err(ctx, EXCP_SEMIHOST, insn_bytes);
15184 }
15185 ctx->base.pc_next += insn_bytes;
15186
15187 if (ctx->base.is_jmp != DISAS_NEXT) {
15188 return;
15189 }
15190
15191 /*
15192 * End the TB on (most) page crossings.
15193 * See mips_tr_init_disas_context about single-stepping a branch
15194 * together with its delay slot.
15195 */
15196 if (ctx->base.pc_next - ctx->page_start >= TARGET_PAGE_SIZE
15197 && !(tb_cflags(ctx->base.tb) & CF_SINGLE_STEP)) {
15198 ctx->base.is_jmp = DISAS_TOO_MANY;
15199 }
15200 }
15201
mips_tr_tb_stop(DisasContextBase * dcbase,CPUState * cs)15202 static void mips_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
15203 {
15204 DisasContext *ctx = container_of(dcbase, DisasContext, base);
15205
15206 switch (ctx->base.is_jmp) {
15207 case DISAS_STOP:
15208 gen_save_pc(ctx->base.pc_next);
15209 tcg_gen_lookup_and_goto_ptr();
15210 break;
15211 case DISAS_NEXT:
15212 case DISAS_TOO_MANY:
15213 save_cpu_state(ctx, 0);
15214 gen_goto_tb(ctx, 0, ctx->base.pc_next);
15215 break;
15216 case DISAS_EXIT:
15217 tcg_gen_exit_tb(NULL, 0);
15218 break;
15219 case DISAS_NORETURN:
15220 break;
15221 default:
15222 g_assert_not_reached();
15223 }
15224 }
15225
15226 static const TranslatorOps mips_tr_ops = {
15227 .init_disas_context = mips_tr_init_disas_context,
15228 .tb_start = mips_tr_tb_start,
15229 .insn_start = mips_tr_insn_start,
15230 .translate_insn = mips_tr_translate_insn,
15231 .tb_stop = mips_tr_tb_stop,
15232 };
15233
gen_intermediate_code(CPUState * cs,TranslationBlock * tb,int * max_insns,vaddr pc,void * host_pc)15234 void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int *max_insns,
15235 vaddr pc, void *host_pc)
15236 {
15237 DisasContext ctx;
15238
15239 translator_loop(cs, tb, max_insns, pc, host_pc, &mips_tr_ops, &ctx.base);
15240 }
15241
mips_tcg_init(void)15242 void mips_tcg_init(void)
15243 {
15244 cpu_gpr[0] = NULL;
15245 for (unsigned i = 1; i < 32; i++)
15246 cpu_gpr[i] = tcg_global_mem_new(tcg_env,
15247 offsetof(CPUMIPSState,
15248 active_tc.gpr[i]),
15249 regnames[i]);
15250 #if defined(TARGET_MIPS64)
15251 cpu_gpr_hi[0] = NULL;
15252
15253 for (unsigned i = 1; i < 32; i++) {
15254 g_autofree char *rname = g_strdup_printf("%s[hi]", regnames[i]);
15255
15256 cpu_gpr_hi[i] = tcg_global_mem_new_i64(tcg_env,
15257 offsetof(CPUMIPSState,
15258 active_tc.gpr_hi[i]),
15259 rname);
15260 }
15261 #endif /* !TARGET_MIPS64 */
15262 for (unsigned i = 0; i < 32; i++) {
15263 int off = offsetof(CPUMIPSState, active_fpu.fpr[i].wr.d[0]);
15264
15265 fpu_f64[i] = tcg_global_mem_new_i64(tcg_env, off, fregnames[i]);
15266 }
15267 msa_translate_init();
15268 cpu_PC = tcg_global_mem_new(tcg_env,
15269 offsetof(CPUMIPSState, active_tc.PC), "PC");
15270 for (unsigned i = 0; i < MIPS_DSP_ACC; i++) {
15271 cpu_HI[i] = tcg_global_mem_new(tcg_env,
15272 offsetof(CPUMIPSState, active_tc.HI[i]),
15273 regnames_HI[i]);
15274 cpu_LO[i] = tcg_global_mem_new(tcg_env,
15275 offsetof(CPUMIPSState, active_tc.LO[i]),
15276 regnames_LO[i]);
15277 }
15278 cpu_dspctrl = tcg_global_mem_new(tcg_env,
15279 offsetof(CPUMIPSState,
15280 active_tc.DSPControl),
15281 "DSPControl");
15282 bcond = tcg_global_mem_new(tcg_env,
15283 offsetof(CPUMIPSState, bcond), "bcond");
15284 btarget = tcg_global_mem_new(tcg_env,
15285 offsetof(CPUMIPSState, btarget), "btarget");
15286 hflags = tcg_global_mem_new_i32(tcg_env,
15287 offsetof(CPUMIPSState, hflags), "hflags");
15288
15289 fpu_fcr0 = tcg_global_mem_new_i32(tcg_env,
15290 offsetof(CPUMIPSState, active_fpu.fcr0),
15291 "fcr0");
15292 fpu_fcr31 = tcg_global_mem_new_i32(tcg_env,
15293 offsetof(CPUMIPSState, active_fpu.fcr31),
15294 "fcr31");
15295 cpu_lladdr = tcg_global_mem_new(tcg_env, offsetof(CPUMIPSState, lladdr),
15296 "lladdr");
15297 cpu_llval = tcg_global_mem_new(tcg_env, offsetof(CPUMIPSState, llval),
15298 "llval");
15299
15300 if (TARGET_LONG_BITS == 32) {
15301 mxu_translate_init();
15302 }
15303 }
15304
mips_restore_state_to_opc(CPUState * cs,const TranslationBlock * tb,const uint64_t * data)15305 void mips_restore_state_to_opc(CPUState *cs,
15306 const TranslationBlock *tb,
15307 const uint64_t *data)
15308 {
15309 CPUMIPSState *env = cpu_env(cs);
15310
15311 env->active_tc.PC = data[0];
15312 env->hflags &= ~MIPS_HFLAG_BMASK;
15313 env->hflags |= data[1];
15314 switch (env->hflags & MIPS_HFLAG_BMASK_BASE) {
15315 case MIPS_HFLAG_BR:
15316 break;
15317 case MIPS_HFLAG_BC:
15318 case MIPS_HFLAG_BL:
15319 case MIPS_HFLAG_B:
15320 env->btarget = data[2];
15321 break;
15322 }
15323 }
15324