Merge remote-tracking branch 'stefanha/trivial-patches' into staging
[qemu/opensuse.git] / target-mips / translate.c
bloba663b743c1b3ef2a886dbf6de6779f5b3ca7f674
1 /*
2 * MIPS32 emulation for qemu: main translation routines.
4 * Copyright (c) 2004-2005 Jocelyn Mayer
5 * Copyright (c) 2006 Marius Groeger (FPU operations)
6 * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
7 * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
23 #include "cpu.h"
24 #include "disas.h"
25 #include "tcg-op.h"
27 #include "helper.h"
28 #define GEN_HELPER 1
29 #include "helper.h"
31 //#define MIPS_DEBUG_DISAS
32 //#define MIPS_DEBUG_SIGN_EXTENSIONS
34 /* MIPS major opcodes */
35 #define MASK_OP_MAJOR(op) (op & (0x3F << 26))
37 enum {
38 /* indirect opcode tables */
39 OPC_SPECIAL = (0x00 << 26),
40 OPC_REGIMM = (0x01 << 26),
41 OPC_CP0 = (0x10 << 26),
42 OPC_CP1 = (0x11 << 26),
43 OPC_CP2 = (0x12 << 26),
44 OPC_CP3 = (0x13 << 26),
45 OPC_SPECIAL2 = (0x1C << 26),
46 OPC_SPECIAL3 = (0x1F << 26),
47 /* arithmetic with immediate */
48 OPC_ADDI = (0x08 << 26),
49 OPC_ADDIU = (0x09 << 26),
50 OPC_SLTI = (0x0A << 26),
51 OPC_SLTIU = (0x0B << 26),
52 /* logic with immediate */
53 OPC_ANDI = (0x0C << 26),
54 OPC_ORI = (0x0D << 26),
55 OPC_XORI = (0x0E << 26),
56 OPC_LUI = (0x0F << 26),
57 /* arithmetic with immediate */
58 OPC_DADDI = (0x18 << 26),
59 OPC_DADDIU = (0x19 << 26),
60 /* Jump and branches */
61 OPC_J = (0x02 << 26),
62 OPC_JAL = (0x03 << 26),
63 OPC_JALS = OPC_JAL | 0x5,
64 OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
65 OPC_BEQL = (0x14 << 26),
66 OPC_BNE = (0x05 << 26),
67 OPC_BNEL = (0x15 << 26),
68 OPC_BLEZ = (0x06 << 26),
69 OPC_BLEZL = (0x16 << 26),
70 OPC_BGTZ = (0x07 << 26),
71 OPC_BGTZL = (0x17 << 26),
72 OPC_JALX = (0x1D << 26), /* MIPS 16 only */
73 OPC_JALXS = OPC_JALX | 0x5,
74 /* Load and stores */
75 OPC_LDL = (0x1A << 26),
76 OPC_LDR = (0x1B << 26),
77 OPC_LB = (0x20 << 26),
78 OPC_LH = (0x21 << 26),
79 OPC_LWL = (0x22 << 26),
80 OPC_LW = (0x23 << 26),
81 OPC_LWPC = OPC_LW | 0x5,
82 OPC_LBU = (0x24 << 26),
83 OPC_LHU = (0x25 << 26),
84 OPC_LWR = (0x26 << 26),
85 OPC_LWU = (0x27 << 26),
86 OPC_SB = (0x28 << 26),
87 OPC_SH = (0x29 << 26),
88 OPC_SWL = (0x2A << 26),
89 OPC_SW = (0x2B << 26),
90 OPC_SDL = (0x2C << 26),
91 OPC_SDR = (0x2D << 26),
92 OPC_SWR = (0x2E << 26),
93 OPC_LL = (0x30 << 26),
94 OPC_LLD = (0x34 << 26),
95 OPC_LD = (0x37 << 26),
96 OPC_LDPC = OPC_LD | 0x5,
97 OPC_SC = (0x38 << 26),
98 OPC_SCD = (0x3C << 26),
99 OPC_SD = (0x3F << 26),
100 /* Floating point load/store */
101 OPC_LWC1 = (0x31 << 26),
102 OPC_LWC2 = (0x32 << 26),
103 OPC_LDC1 = (0x35 << 26),
104 OPC_LDC2 = (0x36 << 26),
105 OPC_SWC1 = (0x39 << 26),
106 OPC_SWC2 = (0x3A << 26),
107 OPC_SDC1 = (0x3D << 26),
108 OPC_SDC2 = (0x3E << 26),
109 /* MDMX ASE specific */
110 OPC_MDMX = (0x1E << 26),
111 /* Cache and prefetch */
112 OPC_CACHE = (0x2F << 26),
113 OPC_PREF = (0x33 << 26),
114 /* Reserved major opcode */
115 OPC_MAJOR3B_RESERVED = (0x3B << 26),
118 /* MIPS special opcodes */
119 #define MASK_SPECIAL(op) MASK_OP_MAJOR(op) | (op & 0x3F)
121 enum {
122 /* Shifts */
123 OPC_SLL = 0x00 | OPC_SPECIAL,
124 /* NOP is SLL r0, r0, 0 */
125 /* SSNOP is SLL r0, r0, 1 */
126 /* EHB is SLL r0, r0, 3 */
127 OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
128 OPC_ROTR = OPC_SRL | (1 << 21),
129 OPC_SRA = 0x03 | OPC_SPECIAL,
130 OPC_SLLV = 0x04 | OPC_SPECIAL,
131 OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
132 OPC_ROTRV = OPC_SRLV | (1 << 6),
133 OPC_SRAV = 0x07 | OPC_SPECIAL,
134 OPC_DSLLV = 0x14 | OPC_SPECIAL,
135 OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
136 OPC_DROTRV = OPC_DSRLV | (1 << 6),
137 OPC_DSRAV = 0x17 | OPC_SPECIAL,
138 OPC_DSLL = 0x38 | OPC_SPECIAL,
139 OPC_DSRL = 0x3A | OPC_SPECIAL, /* also DROTR */
140 OPC_DROTR = OPC_DSRL | (1 << 21),
141 OPC_DSRA = 0x3B | OPC_SPECIAL,
142 OPC_DSLL32 = 0x3C | OPC_SPECIAL,
143 OPC_DSRL32 = 0x3E | OPC_SPECIAL, /* also DROTR32 */
144 OPC_DROTR32 = OPC_DSRL32 | (1 << 21),
145 OPC_DSRA32 = 0x3F | OPC_SPECIAL,
146 /* Multiplication / division */
147 OPC_MULT = 0x18 | OPC_SPECIAL,
148 OPC_MULTU = 0x19 | OPC_SPECIAL,
149 OPC_DIV = 0x1A | OPC_SPECIAL,
150 OPC_DIVU = 0x1B | OPC_SPECIAL,
151 OPC_DMULT = 0x1C | OPC_SPECIAL,
152 OPC_DMULTU = 0x1D | OPC_SPECIAL,
153 OPC_DDIV = 0x1E | OPC_SPECIAL,
154 OPC_DDIVU = 0x1F | OPC_SPECIAL,
155 /* 2 registers arithmetic / logic */
156 OPC_ADD = 0x20 | OPC_SPECIAL,
157 OPC_ADDU = 0x21 | OPC_SPECIAL,
158 OPC_SUB = 0x22 | OPC_SPECIAL,
159 OPC_SUBU = 0x23 | OPC_SPECIAL,
160 OPC_AND = 0x24 | OPC_SPECIAL,
161 OPC_OR = 0x25 | OPC_SPECIAL,
162 OPC_XOR = 0x26 | OPC_SPECIAL,
163 OPC_NOR = 0x27 | OPC_SPECIAL,
164 OPC_SLT = 0x2A | OPC_SPECIAL,
165 OPC_SLTU = 0x2B | OPC_SPECIAL,
166 OPC_DADD = 0x2C | OPC_SPECIAL,
167 OPC_DADDU = 0x2D | OPC_SPECIAL,
168 OPC_DSUB = 0x2E | OPC_SPECIAL,
169 OPC_DSUBU = 0x2F | OPC_SPECIAL,
170 /* Jumps */
171 OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
172 OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
173 OPC_JALRC = OPC_JALR | (0x5 << 6),
174 OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
175 /* Traps */
176 OPC_TGE = 0x30 | OPC_SPECIAL,
177 OPC_TGEU = 0x31 | OPC_SPECIAL,
178 OPC_TLT = 0x32 | OPC_SPECIAL,
179 OPC_TLTU = 0x33 | OPC_SPECIAL,
180 OPC_TEQ = 0x34 | OPC_SPECIAL,
181 OPC_TNE = 0x36 | OPC_SPECIAL,
182 /* HI / LO registers load & stores */
183 OPC_MFHI = 0x10 | OPC_SPECIAL,
184 OPC_MTHI = 0x11 | OPC_SPECIAL,
185 OPC_MFLO = 0x12 | OPC_SPECIAL,
186 OPC_MTLO = 0x13 | OPC_SPECIAL,
187 /* Conditional moves */
188 OPC_MOVZ = 0x0A | OPC_SPECIAL,
189 OPC_MOVN = 0x0B | OPC_SPECIAL,
191 OPC_MOVCI = 0x01 | OPC_SPECIAL,
193 /* Special */
194 OPC_PMON = 0x05 | OPC_SPECIAL, /* unofficial */
195 OPC_SYSCALL = 0x0C | OPC_SPECIAL,
196 OPC_BREAK = 0x0D | OPC_SPECIAL,
197 OPC_SPIM = 0x0E | OPC_SPECIAL, /* unofficial */
198 OPC_SYNC = 0x0F | OPC_SPECIAL,
200 OPC_SPECIAL15_RESERVED = 0x15 | OPC_SPECIAL,
201 OPC_SPECIAL28_RESERVED = 0x28 | OPC_SPECIAL,
202 OPC_SPECIAL29_RESERVED = 0x29 | OPC_SPECIAL,
203 OPC_SPECIAL35_RESERVED = 0x35 | OPC_SPECIAL,
204 OPC_SPECIAL37_RESERVED = 0x37 | OPC_SPECIAL,
205 OPC_SPECIAL39_RESERVED = 0x39 | OPC_SPECIAL,
206 OPC_SPECIAL3D_RESERVED = 0x3D | OPC_SPECIAL,
209 /* Multiplication variants of the vr54xx. */
210 #define MASK_MUL_VR54XX(op) MASK_SPECIAL(op) | (op & (0x1F << 6))
212 enum {
213 OPC_VR54XX_MULS = (0x03 << 6) | OPC_MULT,
214 OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU,
215 OPC_VR54XX_MACC = (0x05 << 6) | OPC_MULT,
216 OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU,
217 OPC_VR54XX_MSAC = (0x07 << 6) | OPC_MULT,
218 OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU,
219 OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT,
220 OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU,
221 OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT,
222 OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU,
223 OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT,
224 OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
225 OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT,
226 OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU,
229 /* REGIMM (rt field) opcodes */
230 #define MASK_REGIMM(op) MASK_OP_MAJOR(op) | (op & (0x1F << 16))
232 enum {
233 OPC_BLTZ = (0x00 << 16) | OPC_REGIMM,
234 OPC_BLTZL = (0x02 << 16) | OPC_REGIMM,
235 OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
236 OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
237 OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
238 OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
239 OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
240 OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
241 OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
242 OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
243 OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
244 OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
245 OPC_TLTI = (0x0A << 16) | OPC_REGIMM,
246 OPC_TLTIU = (0x0B << 16) | OPC_REGIMM,
247 OPC_TEQI = (0x0C << 16) | OPC_REGIMM,
248 OPC_TNEI = (0x0E << 16) | OPC_REGIMM,
249 OPC_SYNCI = (0x1F << 16) | OPC_REGIMM,
252 /* Special2 opcodes */
253 #define MASK_SPECIAL2(op) MASK_OP_MAJOR(op) | (op & 0x3F)
255 enum {
256 /* Multiply & xxx operations */
257 OPC_MADD = 0x00 | OPC_SPECIAL2,
258 OPC_MADDU = 0x01 | OPC_SPECIAL2,
259 OPC_MUL = 0x02 | OPC_SPECIAL2,
260 OPC_MSUB = 0x04 | OPC_SPECIAL2,
261 OPC_MSUBU = 0x05 | OPC_SPECIAL2,
262 /* Loongson 2F */
263 OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2,
264 OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2,
265 OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2,
266 OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2,
267 OPC_DIV_G_2F = 0x14 | OPC_SPECIAL2,
268 OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2,
269 OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2,
270 OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2,
271 OPC_MOD_G_2F = 0x1c | OPC_SPECIAL2,
272 OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2,
273 OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2,
274 OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2,
275 /* Misc */
276 OPC_CLZ = 0x20 | OPC_SPECIAL2,
277 OPC_CLO = 0x21 | OPC_SPECIAL2,
278 OPC_DCLZ = 0x24 | OPC_SPECIAL2,
279 OPC_DCLO = 0x25 | OPC_SPECIAL2,
280 /* Special */
281 OPC_SDBBP = 0x3F | OPC_SPECIAL2,
284 /* Special3 opcodes */
285 #define MASK_SPECIAL3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
287 enum {
288 OPC_EXT = 0x00 | OPC_SPECIAL3,
289 OPC_DEXTM = 0x01 | OPC_SPECIAL3,
290 OPC_DEXTU = 0x02 | OPC_SPECIAL3,
291 OPC_DEXT = 0x03 | OPC_SPECIAL3,
292 OPC_INS = 0x04 | OPC_SPECIAL3,
293 OPC_DINSM = 0x05 | OPC_SPECIAL3,
294 OPC_DINSU = 0x06 | OPC_SPECIAL3,
295 OPC_DINS = 0x07 | OPC_SPECIAL3,
296 OPC_FORK = 0x08 | OPC_SPECIAL3,
297 OPC_YIELD = 0x09 | OPC_SPECIAL3,
298 OPC_BSHFL = 0x20 | OPC_SPECIAL3,
299 OPC_DBSHFL = 0x24 | OPC_SPECIAL3,
300 OPC_RDHWR = 0x3B | OPC_SPECIAL3,
302 /* Loongson 2E */
303 OPC_MULT_G_2E = 0x18 | OPC_SPECIAL3,
304 OPC_MULTU_G_2E = 0x19 | OPC_SPECIAL3,
305 OPC_DIV_G_2E = 0x1A | OPC_SPECIAL3,
306 OPC_DIVU_G_2E = 0x1B | OPC_SPECIAL3,
307 OPC_DMULT_G_2E = 0x1C | OPC_SPECIAL3,
308 OPC_DMULTU_G_2E = 0x1D | OPC_SPECIAL3,
309 OPC_DDIV_G_2E = 0x1E | OPC_SPECIAL3,
310 OPC_DDIVU_G_2E = 0x1F | OPC_SPECIAL3,
311 OPC_MOD_G_2E = 0x22 | OPC_SPECIAL3,
312 OPC_MODU_G_2E = 0x23 | OPC_SPECIAL3,
313 OPC_DMOD_G_2E = 0x26 | OPC_SPECIAL3,
314 OPC_DMODU_G_2E = 0x27 | OPC_SPECIAL3,
317 /* BSHFL opcodes */
318 #define MASK_BSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
320 enum {
321 OPC_WSBH = (0x02 << 6) | OPC_BSHFL,
322 OPC_SEB = (0x10 << 6) | OPC_BSHFL,
323 OPC_SEH = (0x18 << 6) | OPC_BSHFL,
326 /* DBSHFL opcodes */
327 #define MASK_DBSHFL(op) MASK_SPECIAL3(op) | (op & (0x1F << 6))
329 enum {
330 OPC_DSBH = (0x02 << 6) | OPC_DBSHFL,
331 OPC_DSHD = (0x05 << 6) | OPC_DBSHFL,
334 /* Coprocessor 0 (rs field) */
335 #define MASK_CP0(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
337 enum {
338 OPC_MFC0 = (0x00 << 21) | OPC_CP0,
339 OPC_DMFC0 = (0x01 << 21) | OPC_CP0,
340 OPC_MTC0 = (0x04 << 21) | OPC_CP0,
341 OPC_DMTC0 = (0x05 << 21) | OPC_CP0,
342 OPC_MFTR = (0x08 << 21) | OPC_CP0,
343 OPC_RDPGPR = (0x0A << 21) | OPC_CP0,
344 OPC_MFMC0 = (0x0B << 21) | OPC_CP0,
345 OPC_MTTR = (0x0C << 21) | OPC_CP0,
346 OPC_WRPGPR = (0x0E << 21) | OPC_CP0,
347 OPC_C0 = (0x10 << 21) | OPC_CP0,
348 OPC_C0_FIRST = (0x10 << 21) | OPC_CP0,
349 OPC_C0_LAST = (0x1F << 21) | OPC_CP0,
352 /* MFMC0 opcodes */
353 #define MASK_MFMC0(op) MASK_CP0(op) | (op & 0xFFFF)
355 enum {
356 OPC_DMT = 0x01 | (0 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
357 OPC_EMT = 0x01 | (1 << 5) | (0x0F << 6) | (0x01 << 11) | OPC_MFMC0,
358 OPC_DVPE = 0x01 | (0 << 5) | OPC_MFMC0,
359 OPC_EVPE = 0x01 | (1 << 5) | OPC_MFMC0,
360 OPC_DI = (0 << 5) | (0x0C << 11) | OPC_MFMC0,
361 OPC_EI = (1 << 5) | (0x0C << 11) | OPC_MFMC0,
364 /* Coprocessor 0 (with rs == C0) */
365 #define MASK_C0(op) MASK_CP0(op) | (op & 0x3F)
367 enum {
368 OPC_TLBR = 0x01 | OPC_C0,
369 OPC_TLBWI = 0x02 | OPC_C0,
370 OPC_TLBWR = 0x06 | OPC_C0,
371 OPC_TLBP = 0x08 | OPC_C0,
372 OPC_RFE = 0x10 | OPC_C0,
373 OPC_ERET = 0x18 | OPC_C0,
374 OPC_DERET = 0x1F | OPC_C0,
375 OPC_WAIT = 0x20 | OPC_C0,
378 /* Coprocessor 1 (rs field) */
379 #define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
381 /* Values for the fmt field in FP instructions */
382 enum {
383 /* 0 - 15 are reserved */
384 FMT_S = 16, /* single fp */
385 FMT_D = 17, /* double fp */
386 FMT_E = 18, /* extended fp */
387 FMT_Q = 19, /* quad fp */
388 FMT_W = 20, /* 32-bit fixed */
389 FMT_L = 21, /* 64-bit fixed */
390 FMT_PS = 22, /* paired single fp */
391 /* 23 - 31 are reserved */
394 enum {
395 OPC_MFC1 = (0x00 << 21) | OPC_CP1,
396 OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
397 OPC_CFC1 = (0x02 << 21) | OPC_CP1,
398 OPC_MFHC1 = (0x03 << 21) | OPC_CP1,
399 OPC_MTC1 = (0x04 << 21) | OPC_CP1,
400 OPC_DMTC1 = (0x05 << 21) | OPC_CP1,
401 OPC_CTC1 = (0x06 << 21) | OPC_CP1,
402 OPC_MTHC1 = (0x07 << 21) | OPC_CP1,
403 OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
404 OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
405 OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
406 OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
407 OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
408 OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
409 OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
410 OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
411 OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
412 OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
415 #define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
416 #define MASK_BC1(op) MASK_CP1(op) | (op & (0x3 << 16))
418 enum {
419 OPC_BC1F = (0x00 << 16) | OPC_BC1,
420 OPC_BC1T = (0x01 << 16) | OPC_BC1,
421 OPC_BC1FL = (0x02 << 16) | OPC_BC1,
422 OPC_BC1TL = (0x03 << 16) | OPC_BC1,
425 enum {
426 OPC_BC1FANY2 = (0x00 << 16) | OPC_BC1ANY2,
427 OPC_BC1TANY2 = (0x01 << 16) | OPC_BC1ANY2,
430 enum {
431 OPC_BC1FANY4 = (0x00 << 16) | OPC_BC1ANY4,
432 OPC_BC1TANY4 = (0x01 << 16) | OPC_BC1ANY4,
435 #define MASK_CP2(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
437 enum {
438 OPC_MFC2 = (0x00 << 21) | OPC_CP2,
439 OPC_DMFC2 = (0x01 << 21) | OPC_CP2,
440 OPC_CFC2 = (0x02 << 21) | OPC_CP2,
441 OPC_MFHC2 = (0x03 << 21) | OPC_CP2,
442 OPC_MTC2 = (0x04 << 21) | OPC_CP2,
443 OPC_DMTC2 = (0x05 << 21) | OPC_CP2,
444 OPC_CTC2 = (0x06 << 21) | OPC_CP2,
445 OPC_MTHC2 = (0x07 << 21) | OPC_CP2,
446 OPC_BC2 = (0x08 << 21) | OPC_CP2,
449 #define MASK_CP3(op) MASK_OP_MAJOR(op) | (op & 0x3F)
451 enum {
452 OPC_LWXC1 = 0x00 | OPC_CP3,
453 OPC_LDXC1 = 0x01 | OPC_CP3,
454 OPC_LUXC1 = 0x05 | OPC_CP3,
455 OPC_SWXC1 = 0x08 | OPC_CP3,
456 OPC_SDXC1 = 0x09 | OPC_CP3,
457 OPC_SUXC1 = 0x0D | OPC_CP3,
458 OPC_PREFX = 0x0F | OPC_CP3,
459 OPC_ALNV_PS = 0x1E | OPC_CP3,
460 OPC_MADD_S = 0x20 | OPC_CP3,
461 OPC_MADD_D = 0x21 | OPC_CP3,
462 OPC_MADD_PS = 0x26 | OPC_CP3,
463 OPC_MSUB_S = 0x28 | OPC_CP3,
464 OPC_MSUB_D = 0x29 | OPC_CP3,
465 OPC_MSUB_PS = 0x2E | OPC_CP3,
466 OPC_NMADD_S = 0x30 | OPC_CP3,
467 OPC_NMADD_D = 0x31 | OPC_CP3,
468 OPC_NMADD_PS= 0x36 | OPC_CP3,
469 OPC_NMSUB_S = 0x38 | OPC_CP3,
470 OPC_NMSUB_D = 0x39 | OPC_CP3,
471 OPC_NMSUB_PS= 0x3E | OPC_CP3,
474 /* global register indices */
475 static TCGv_ptr cpu_env;
476 static TCGv cpu_gpr[32], cpu_PC;
477 static TCGv cpu_HI[MIPS_DSP_ACC], cpu_LO[MIPS_DSP_ACC], cpu_ACX[MIPS_DSP_ACC];
478 static TCGv cpu_dspctrl, btarget, bcond;
479 static TCGv_i32 hflags;
480 static TCGv_i32 fpu_fcr0, fpu_fcr31;
482 static uint32_t gen_opc_hflags[OPC_BUF_SIZE];
484 #include "gen-icount.h"
486 #define gen_helper_0i(name, arg) do { \
487 TCGv_i32 helper_tmp = tcg_const_i32(arg); \
488 gen_helper_##name(helper_tmp); \
489 tcg_temp_free_i32(helper_tmp); \
490 } while(0)
492 #define gen_helper_1i(name, arg1, arg2) do { \
493 TCGv_i32 helper_tmp = tcg_const_i32(arg2); \
494 gen_helper_##name(arg1, helper_tmp); \
495 tcg_temp_free_i32(helper_tmp); \
496 } while(0)
498 #define gen_helper_2i(name, arg1, arg2, arg3) do { \
499 TCGv_i32 helper_tmp = tcg_const_i32(arg3); \
500 gen_helper_##name(arg1, arg2, helper_tmp); \
501 tcg_temp_free_i32(helper_tmp); \
502 } while(0)
504 #define gen_helper_3i(name, arg1, arg2, arg3, arg4) do { \
505 TCGv_i32 helper_tmp = tcg_const_i32(arg4); \
506 gen_helper_##name(arg1, arg2, arg3, helper_tmp); \
507 tcg_temp_free_i32(helper_tmp); \
508 } while(0)
510 typedef struct DisasContext {
511 struct TranslationBlock *tb;
512 target_ulong pc, saved_pc;
513 uint32_t opcode;
514 int singlestep_enabled;
515 /* Routine used to access memory */
516 int mem_idx;
517 uint32_t hflags, saved_hflags;
518 int bstate;
519 target_ulong btarget;
520 } DisasContext;
522 enum {
523 BS_NONE = 0, /* We go out of the TB without reaching a branch or an
524 * exception condition */
525 BS_STOP = 1, /* We want to stop translation for any reason */
526 BS_BRANCH = 2, /* We reached a branch condition */
527 BS_EXCP = 3, /* We reached an exception condition */
530 static const char *regnames[] =
531 { "r0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
532 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
533 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
534 "t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra", };
536 static const char *regnames_HI[] =
537 { "HI0", "HI1", "HI2", "HI3", };
539 static const char *regnames_LO[] =
540 { "LO0", "LO1", "LO2", "LO3", };
542 static const char *regnames_ACX[] =
543 { "ACX0", "ACX1", "ACX2", "ACX3", };
545 static const char *fregnames[] =
546 { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
547 "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
548 "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
549 "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", };
551 #ifdef MIPS_DEBUG_DISAS
552 #define MIPS_DEBUG(fmt, ...) \
553 qemu_log_mask(CPU_LOG_TB_IN_ASM, \
554 TARGET_FMT_lx ": %08x " fmt "\n", \
555 ctx->pc, ctx->opcode , ## __VA_ARGS__)
556 #define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
557 #else
558 #define MIPS_DEBUG(fmt, ...) do { } while(0)
559 #define LOG_DISAS(...) do { } while (0)
560 #endif
562 #define MIPS_INVAL(op) \
563 do { \
564 MIPS_DEBUG("Invalid %s %03x %03x %03x", op, ctx->opcode >> 26, \
565 ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
566 } while (0)
568 /* General purpose registers moves. */
569 static inline void gen_load_gpr (TCGv t, int reg)
571 if (reg == 0)
572 tcg_gen_movi_tl(t, 0);
573 else
574 tcg_gen_mov_tl(t, cpu_gpr[reg]);
577 static inline void gen_store_gpr (TCGv t, int reg)
579 if (reg != 0)
580 tcg_gen_mov_tl(cpu_gpr[reg], t);
583 /* Moves to/from ACX register. */
584 static inline void gen_load_ACX (TCGv t, int reg)
586 tcg_gen_mov_tl(t, cpu_ACX[reg]);
589 static inline void gen_store_ACX (TCGv t, int reg)
591 tcg_gen_mov_tl(cpu_ACX[reg], t);
594 /* Moves to/from shadow registers. */
595 static inline void gen_load_srsgpr (int from, int to)
597 TCGv t0 = tcg_temp_new();
599 if (from == 0)
600 tcg_gen_movi_tl(t0, 0);
601 else {
602 TCGv_i32 t2 = tcg_temp_new_i32();
603 TCGv_ptr addr = tcg_temp_new_ptr();
605 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
606 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
607 tcg_gen_andi_i32(t2, t2, 0xf);
608 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
609 tcg_gen_ext_i32_ptr(addr, t2);
610 tcg_gen_add_ptr(addr, cpu_env, addr);
612 tcg_gen_ld_tl(t0, addr, sizeof(target_ulong) * from);
613 tcg_temp_free_ptr(addr);
614 tcg_temp_free_i32(t2);
616 gen_store_gpr(t0, to);
617 tcg_temp_free(t0);
620 static inline void gen_store_srsgpr (int from, int to)
622 if (to != 0) {
623 TCGv t0 = tcg_temp_new();
624 TCGv_i32 t2 = tcg_temp_new_i32();
625 TCGv_ptr addr = tcg_temp_new_ptr();
627 gen_load_gpr(t0, from);
628 tcg_gen_ld_i32(t2, cpu_env, offsetof(CPUMIPSState, CP0_SRSCtl));
629 tcg_gen_shri_i32(t2, t2, CP0SRSCtl_PSS);
630 tcg_gen_andi_i32(t2, t2, 0xf);
631 tcg_gen_muli_i32(t2, t2, sizeof(target_ulong) * 32);
632 tcg_gen_ext_i32_ptr(addr, t2);
633 tcg_gen_add_ptr(addr, cpu_env, addr);
635 tcg_gen_st_tl(t0, addr, sizeof(target_ulong) * to);
636 tcg_temp_free_ptr(addr);
637 tcg_temp_free_i32(t2);
638 tcg_temp_free(t0);
642 /* Floating point register moves. */
643 static inline void gen_load_fpr32 (TCGv_i32 t, int reg)
645 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
648 static inline void gen_store_fpr32 (TCGv_i32 t, int reg)
650 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[FP_ENDIAN_IDX]));
653 static inline void gen_load_fpr32h (TCGv_i32 t, int reg)
655 tcg_gen_ld_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
658 static inline void gen_store_fpr32h (TCGv_i32 t, int reg)
660 tcg_gen_st_i32(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].w[!FP_ENDIAN_IDX]));
663 static inline void gen_load_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
665 if (ctx->hflags & MIPS_HFLAG_F64) {
666 tcg_gen_ld_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
667 } else {
668 TCGv_i32 t0 = tcg_temp_new_i32();
669 TCGv_i32 t1 = tcg_temp_new_i32();
670 gen_load_fpr32(t0, reg & ~1);
671 gen_load_fpr32(t1, reg | 1);
672 tcg_gen_concat_i32_i64(t, t0, t1);
673 tcg_temp_free_i32(t0);
674 tcg_temp_free_i32(t1);
678 static inline void gen_store_fpr64 (DisasContext *ctx, TCGv_i64 t, int reg)
680 if (ctx->hflags & MIPS_HFLAG_F64) {
681 tcg_gen_st_i64(t, cpu_env, offsetof(CPUMIPSState, active_fpu.fpr[reg].d));
682 } else {
683 TCGv_i64 t0 = tcg_temp_new_i64();
684 TCGv_i32 t1 = tcg_temp_new_i32();
685 tcg_gen_trunc_i64_i32(t1, t);
686 gen_store_fpr32(t1, reg & ~1);
687 tcg_gen_shri_i64(t0, t, 32);
688 tcg_gen_trunc_i64_i32(t1, t0);
689 gen_store_fpr32(t1, reg | 1);
690 tcg_temp_free_i32(t1);
691 tcg_temp_free_i64(t0);
695 static inline int get_fp_bit (int cc)
697 if (cc)
698 return 24 + cc;
699 else
700 return 23;
703 /* Tests */
704 static inline void gen_save_pc(target_ulong pc)
706 tcg_gen_movi_tl(cpu_PC, pc);
709 static inline void save_cpu_state (DisasContext *ctx, int do_save_pc)
711 LOG_DISAS("hflags %08x saved %08x\n", ctx->hflags, ctx->saved_hflags);
712 if (do_save_pc && ctx->pc != ctx->saved_pc) {
713 gen_save_pc(ctx->pc);
714 ctx->saved_pc = ctx->pc;
716 if (ctx->hflags != ctx->saved_hflags) {
717 tcg_gen_movi_i32(hflags, ctx->hflags);
718 ctx->saved_hflags = ctx->hflags;
719 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
720 case MIPS_HFLAG_BR:
721 break;
722 case MIPS_HFLAG_BC:
723 case MIPS_HFLAG_BL:
724 case MIPS_HFLAG_B:
725 tcg_gen_movi_tl(btarget, ctx->btarget);
726 break;
731 static inline void restore_cpu_state (CPUMIPSState *env, DisasContext *ctx)
733 ctx->saved_hflags = ctx->hflags;
734 switch (ctx->hflags & MIPS_HFLAG_BMASK_BASE) {
735 case MIPS_HFLAG_BR:
736 break;
737 case MIPS_HFLAG_BC:
738 case MIPS_HFLAG_BL:
739 case MIPS_HFLAG_B:
740 ctx->btarget = env->btarget;
741 break;
745 static inline void
746 generate_exception_err (DisasContext *ctx, int excp, int err)
748 TCGv_i32 texcp = tcg_const_i32(excp);
749 TCGv_i32 terr = tcg_const_i32(err);
750 save_cpu_state(ctx, 1);
751 gen_helper_raise_exception_err(texcp, terr);
752 tcg_temp_free_i32(terr);
753 tcg_temp_free_i32(texcp);
756 static inline void
757 generate_exception (DisasContext *ctx, int excp)
759 save_cpu_state(ctx, 1);
760 gen_helper_0i(raise_exception, excp);
763 /* Addresses computation */
764 static inline void gen_op_addr_add (DisasContext *ctx, TCGv ret, TCGv arg0, TCGv arg1)
766 tcg_gen_add_tl(ret, arg0, arg1);
768 #if defined(TARGET_MIPS64)
769 /* For compatibility with 32-bit code, data reference in user mode
770 with Status_UX = 0 should be casted to 32-bit and sign extended.
771 See the MIPS64 PRA manual, section 4.10. */
772 if (((ctx->hflags & MIPS_HFLAG_KSU) == MIPS_HFLAG_UM) &&
773 !(ctx->hflags & MIPS_HFLAG_UX)) {
774 tcg_gen_ext32s_i64(ret, ret);
776 #endif
779 static inline void check_cp0_enabled(DisasContext *ctx)
781 if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
782 generate_exception_err(ctx, EXCP_CpU, 0);
785 static inline void check_cp1_enabled(DisasContext *ctx)
787 if (unlikely(!(ctx->hflags & MIPS_HFLAG_FPU)))
788 generate_exception_err(ctx, EXCP_CpU, 1);
791 /* Verify that the processor is running with COP1X instructions enabled.
792 This is associated with the nabla symbol in the MIPS32 and MIPS64
793 opcode tables. */
795 static inline void check_cop1x(DisasContext *ctx)
797 if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
798 generate_exception(ctx, EXCP_RI);
801 /* Verify that the processor is running with 64-bit floating-point
802 operations enabled. */
804 static inline void check_cp1_64bitmode(DisasContext *ctx)
806 if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
807 generate_exception(ctx, EXCP_RI);
811 * Verify if floating point register is valid; an operation is not defined
812 * if bit 0 of any register specification is set and the FR bit in the
813 * Status register equals zero, since the register numbers specify an
814 * even-odd pair of adjacent coprocessor general registers. When the FR bit
815 * in the Status register equals one, both even and odd register numbers
816 * are valid. This limitation exists only for 64 bit wide (d,l,ps) registers.
818 * Multiple 64 bit wide registers can be checked by calling
819 * gen_op_cp1_registers(freg1 | freg2 | ... | fregN);
821 static inline void check_cp1_registers(DisasContext *ctx, int regs)
823 if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64) && (regs & 1)))
824 generate_exception(ctx, EXCP_RI);
827 /* This code generates a "reserved instruction" exception if the
828 CPU does not support the instruction set corresponding to flags. */
829 static inline void check_insn(CPUMIPSState *env, DisasContext *ctx, int flags)
831 if (unlikely(!(env->insn_flags & flags)))
832 generate_exception(ctx, EXCP_RI);
835 /* This code generates a "reserved instruction" exception if 64-bit
836 instructions are not enabled. */
837 static inline void check_mips_64(DisasContext *ctx)
839 if (unlikely(!(ctx->hflags & MIPS_HFLAG_64)))
840 generate_exception(ctx, EXCP_RI);
843 /* Define small wrappers for gen_load_fpr* so that we have a uniform
844 calling interface for 32 and 64-bit FPRs. No sense in changing
845 all callers for gen_load_fpr32 when we need the CTX parameter for
846 this one use. */
847 #define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
848 #define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
849 #define FOP_CONDS(type, abs, fmt, ifmt, bits) \
850 static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
851 int ft, int fs, int cc) \
853 TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
854 TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
855 switch (ifmt) { \
856 case FMT_PS: \
857 check_cp1_64bitmode(ctx); \
858 break; \
859 case FMT_D: \
860 if (abs) { \
861 check_cop1x(ctx); \
863 check_cp1_registers(ctx, fs | ft); \
864 break; \
865 case FMT_S: \
866 if (abs) { \
867 check_cop1x(ctx); \
869 break; \
871 gen_ldcmp_fpr##bits (ctx, fp0, fs); \
872 gen_ldcmp_fpr##bits (ctx, fp1, ft); \
873 switch (n) { \
874 case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
875 case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
876 case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
877 case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
878 case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
879 case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
880 case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
881 case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
882 case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
883 case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
884 case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
885 case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
886 case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
887 case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
888 case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
889 case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
890 default: abort(); \
892 tcg_temp_free_i##bits (fp0); \
893 tcg_temp_free_i##bits (fp1); \
896 FOP_CONDS(, 0, d, FMT_D, 64)
897 FOP_CONDS(abs, 1, d, FMT_D, 64)
898 FOP_CONDS(, 0, s, FMT_S, 32)
899 FOP_CONDS(abs, 1, s, FMT_S, 32)
900 FOP_CONDS(, 0, ps, FMT_PS, 64)
901 FOP_CONDS(abs, 1, ps, FMT_PS, 64)
902 #undef FOP_CONDS
903 #undef gen_ldcmp_fpr32
904 #undef gen_ldcmp_fpr64
906 /* load/store instructions. */
907 #define OP_LD(insn,fname) \
908 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
910 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
912 OP_LD(lb,ld8s);
913 OP_LD(lbu,ld8u);
914 OP_LD(lh,ld16s);
915 OP_LD(lhu,ld16u);
916 OP_LD(lw,ld32s);
917 #if defined(TARGET_MIPS64)
918 OP_LD(lwu,ld32u);
919 OP_LD(ld,ld64);
920 #endif
921 #undef OP_LD
923 #define OP_ST(insn,fname) \
924 static inline void op_st_##insn(TCGv arg1, TCGv arg2, DisasContext *ctx) \
926 tcg_gen_qemu_##fname(arg1, arg2, ctx->mem_idx); \
928 OP_ST(sb,st8);
929 OP_ST(sh,st16);
930 OP_ST(sw,st32);
931 #if defined(TARGET_MIPS64)
932 OP_ST(sd,st64);
933 #endif
934 #undef OP_ST
936 #ifdef CONFIG_USER_ONLY
937 #define OP_LD_ATOMIC(insn,fname) \
938 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
940 TCGv t0 = tcg_temp_new(); \
941 tcg_gen_mov_tl(t0, arg1); \
942 tcg_gen_qemu_##fname(ret, arg1, ctx->mem_idx); \
943 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
944 tcg_gen_st_tl(ret, cpu_env, offsetof(CPUMIPSState, llval)); \
945 tcg_temp_free(t0); \
947 #else
948 #define OP_LD_ATOMIC(insn,fname) \
949 static inline void op_ld_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
951 gen_helper_2i(insn, ret, arg1, ctx->mem_idx); \
953 #endif
954 OP_LD_ATOMIC(ll,ld32s);
955 #if defined(TARGET_MIPS64)
956 OP_LD_ATOMIC(lld,ld64);
957 #endif
958 #undef OP_LD_ATOMIC
960 #ifdef CONFIG_USER_ONLY
961 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
962 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
964 TCGv t0 = tcg_temp_new(); \
965 int l1 = gen_new_label(); \
966 int l2 = gen_new_label(); \
968 tcg_gen_andi_tl(t0, arg2, almask); \
969 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1); \
970 tcg_gen_st_tl(arg2, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr)); \
971 generate_exception(ctx, EXCP_AdES); \
972 gen_set_label(l1); \
973 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, lladdr)); \
974 tcg_gen_brcond_tl(TCG_COND_NE, arg2, t0, l2); \
975 tcg_gen_movi_tl(t0, rt | ((almask << 3) & 0x20)); \
976 tcg_gen_st_tl(t0, cpu_env, offsetof(CPUMIPSState, llreg)); \
977 tcg_gen_st_tl(arg1, cpu_env, offsetof(CPUMIPSState, llnewval)); \
978 gen_helper_0i(raise_exception, EXCP_SC); \
979 gen_set_label(l2); \
980 tcg_gen_movi_tl(t0, 0); \
981 gen_store_gpr(t0, rt); \
982 tcg_temp_free(t0); \
984 #else
985 #define OP_ST_ATOMIC(insn,fname,ldname,almask) \
986 static inline void op_st_##insn(TCGv arg1, TCGv arg2, int rt, DisasContext *ctx) \
988 TCGv t0 = tcg_temp_new(); \
989 gen_helper_3i(insn, t0, arg1, arg2, ctx->mem_idx); \
990 gen_store_gpr(t0, rt); \
991 tcg_temp_free(t0); \
993 #endif
994 OP_ST_ATOMIC(sc,st32,ld32s,0x3);
995 #if defined(TARGET_MIPS64)
996 OP_ST_ATOMIC(scd,st64,ld64,0x7);
997 #endif
998 #undef OP_ST_ATOMIC
1000 static void gen_base_offset_addr (DisasContext *ctx, TCGv addr,
1001 int base, int16_t offset)
1003 if (base == 0) {
1004 tcg_gen_movi_tl(addr, offset);
1005 } else if (offset == 0) {
1006 gen_load_gpr(addr, base);
1007 } else {
1008 tcg_gen_movi_tl(addr, offset);
1009 gen_op_addr_add(ctx, addr, cpu_gpr[base], addr);
1013 static target_ulong pc_relative_pc (DisasContext *ctx)
1015 target_ulong pc = ctx->pc;
1017 if (ctx->hflags & MIPS_HFLAG_BMASK) {
1018 int branch_bytes = ctx->hflags & MIPS_HFLAG_BDS16 ? 2 : 4;
1020 pc -= branch_bytes;
1023 pc &= ~(target_ulong)3;
1024 return pc;
1027 /* Load */
1028 static void gen_ld (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1029 int rt, int base, int16_t offset)
1031 const char *opn = "ld";
1032 TCGv t0, t1;
1034 if (rt == 0 && env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F)) {
1035 /* Loongson CPU uses a load to zero register for prefetch.
1036 We emulate it as a NOP. On other CPU we must perform the
1037 actual memory access. */
1038 MIPS_DEBUG("NOP");
1039 return;
1042 t0 = tcg_temp_new();
1043 t1 = tcg_temp_new();
1044 gen_base_offset_addr(ctx, t0, base, offset);
1046 switch (opc) {
1047 #if defined(TARGET_MIPS64)
1048 case OPC_LWU:
1049 save_cpu_state(ctx, 0);
1050 op_ld_lwu(t0, t0, ctx);
1051 gen_store_gpr(t0, rt);
1052 opn = "lwu";
1053 break;
1054 case OPC_LD:
1055 save_cpu_state(ctx, 0);
1056 op_ld_ld(t0, t0, ctx);
1057 gen_store_gpr(t0, rt);
1058 opn = "ld";
1059 break;
1060 case OPC_LLD:
1061 save_cpu_state(ctx, 1);
1062 op_ld_lld(t0, t0, ctx);
1063 gen_store_gpr(t0, rt);
1064 opn = "lld";
1065 break;
1066 case OPC_LDL:
1067 save_cpu_state(ctx, 1);
1068 gen_load_gpr(t1, rt);
1069 gen_helper_3i(ldl, t1, t1, t0, ctx->mem_idx);
1070 gen_store_gpr(t1, rt);
1071 opn = "ldl";
1072 break;
1073 case OPC_LDR:
1074 save_cpu_state(ctx, 1);
1075 gen_load_gpr(t1, rt);
1076 gen_helper_3i(ldr, t1, t1, t0, ctx->mem_idx);
1077 gen_store_gpr(t1, rt);
1078 opn = "ldr";
1079 break;
1080 case OPC_LDPC:
1081 save_cpu_state(ctx, 0);
1082 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1083 gen_op_addr_add(ctx, t0, t0, t1);
1084 op_ld_ld(t0, t0, ctx);
1085 gen_store_gpr(t0, rt);
1086 opn = "ldpc";
1087 break;
1088 #endif
1089 case OPC_LWPC:
1090 save_cpu_state(ctx, 0);
1091 tcg_gen_movi_tl(t1, pc_relative_pc(ctx));
1092 gen_op_addr_add(ctx, t0, t0, t1);
1093 op_ld_lw(t0, t0, ctx);
1094 gen_store_gpr(t0, rt);
1095 opn = "lwpc";
1096 break;
1097 case OPC_LW:
1098 save_cpu_state(ctx, 0);
1099 op_ld_lw(t0, t0, ctx);
1100 gen_store_gpr(t0, rt);
1101 opn = "lw";
1102 break;
1103 case OPC_LH:
1104 save_cpu_state(ctx, 0);
1105 op_ld_lh(t0, t0, ctx);
1106 gen_store_gpr(t0, rt);
1107 opn = "lh";
1108 break;
1109 case OPC_LHU:
1110 save_cpu_state(ctx, 0);
1111 op_ld_lhu(t0, t0, ctx);
1112 gen_store_gpr(t0, rt);
1113 opn = "lhu";
1114 break;
1115 case OPC_LB:
1116 save_cpu_state(ctx, 0);
1117 op_ld_lb(t0, t0, ctx);
1118 gen_store_gpr(t0, rt);
1119 opn = "lb";
1120 break;
1121 case OPC_LBU:
1122 save_cpu_state(ctx, 0);
1123 op_ld_lbu(t0, t0, ctx);
1124 gen_store_gpr(t0, rt);
1125 opn = "lbu";
1126 break;
1127 case OPC_LWL:
1128 save_cpu_state(ctx, 1);
1129 gen_load_gpr(t1, rt);
1130 gen_helper_3i(lwl, t1, t1, t0, ctx->mem_idx);
1131 gen_store_gpr(t1, rt);
1132 opn = "lwl";
1133 break;
1134 case OPC_LWR:
1135 save_cpu_state(ctx, 1);
1136 gen_load_gpr(t1, rt);
1137 gen_helper_3i(lwr, t1, t1, t0, ctx->mem_idx);
1138 gen_store_gpr(t1, rt);
1139 opn = "lwr";
1140 break;
1141 case OPC_LL:
1142 save_cpu_state(ctx, 1);
1143 op_ld_ll(t0, t0, ctx);
1144 gen_store_gpr(t0, rt);
1145 opn = "ll";
1146 break;
1148 (void)opn; /* avoid a compiler warning */
1149 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1150 tcg_temp_free(t0);
1151 tcg_temp_free(t1);
1154 /* Store */
1155 static void gen_st (DisasContext *ctx, uint32_t opc, int rt,
1156 int base, int16_t offset)
1158 const char *opn = "st";
1159 TCGv t0 = tcg_temp_new();
1160 TCGv t1 = tcg_temp_new();
1162 gen_base_offset_addr(ctx, t0, base, offset);
1163 gen_load_gpr(t1, rt);
1164 switch (opc) {
1165 #if defined(TARGET_MIPS64)
1166 case OPC_SD:
1167 save_cpu_state(ctx, 0);
1168 op_st_sd(t1, t0, ctx);
1169 opn = "sd";
1170 break;
1171 case OPC_SDL:
1172 save_cpu_state(ctx, 1);
1173 gen_helper_2i(sdl, t1, t0, ctx->mem_idx);
1174 opn = "sdl";
1175 break;
1176 case OPC_SDR:
1177 save_cpu_state(ctx, 1);
1178 gen_helper_2i(sdr, t1, t0, ctx->mem_idx);
1179 opn = "sdr";
1180 break;
1181 #endif
1182 case OPC_SW:
1183 save_cpu_state(ctx, 0);
1184 op_st_sw(t1, t0, ctx);
1185 opn = "sw";
1186 break;
1187 case OPC_SH:
1188 save_cpu_state(ctx, 0);
1189 op_st_sh(t1, t0, ctx);
1190 opn = "sh";
1191 break;
1192 case OPC_SB:
1193 save_cpu_state(ctx, 0);
1194 op_st_sb(t1, t0, ctx);
1195 opn = "sb";
1196 break;
1197 case OPC_SWL:
1198 save_cpu_state(ctx, 1);
1199 gen_helper_2i(swl, t1, t0, ctx->mem_idx);
1200 opn = "swl";
1201 break;
1202 case OPC_SWR:
1203 save_cpu_state(ctx, 1);
1204 gen_helper_2i(swr, t1, t0, ctx->mem_idx);
1205 opn = "swr";
1206 break;
1208 (void)opn; /* avoid a compiler warning */
1209 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1210 tcg_temp_free(t0);
1211 tcg_temp_free(t1);
1215 /* Store conditional */
1216 static void gen_st_cond (DisasContext *ctx, uint32_t opc, int rt,
1217 int base, int16_t offset)
1219 const char *opn = "st_cond";
1220 TCGv t0, t1;
1222 t0 = tcg_temp_local_new();
1224 gen_base_offset_addr(ctx, t0, base, offset);
1225 /* Don't do NOP if destination is zero: we must perform the actual
1226 memory access. */
1228 t1 = tcg_temp_local_new();
1229 gen_load_gpr(t1, rt);
1230 switch (opc) {
1231 #if defined(TARGET_MIPS64)
1232 case OPC_SCD:
1233 save_cpu_state(ctx, 1);
1234 op_st_scd(t1, t0, rt, ctx);
1235 opn = "scd";
1236 break;
1237 #endif
1238 case OPC_SC:
1239 save_cpu_state(ctx, 1);
1240 op_st_sc(t1, t0, rt, ctx);
1241 opn = "sc";
1242 break;
1244 (void)opn; /* avoid a compiler warning */
1245 MIPS_DEBUG("%s %s, %d(%s)", opn, regnames[rt], offset, regnames[base]);
1246 tcg_temp_free(t1);
1247 tcg_temp_free(t0);
1250 /* Load and store */
1251 static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
1252 int base, int16_t offset)
1254 const char *opn = "flt_ldst";
1255 TCGv t0 = tcg_temp_new();
1257 gen_base_offset_addr(ctx, t0, base, offset);
1258 /* Don't do NOP if destination is zero: we must perform the actual
1259 memory access. */
1260 switch (opc) {
1261 case OPC_LWC1:
1263 TCGv_i32 fp0 = tcg_temp_new_i32();
1265 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
1266 tcg_gen_trunc_tl_i32(fp0, t0);
1267 gen_store_fpr32(fp0, ft);
1268 tcg_temp_free_i32(fp0);
1270 opn = "lwc1";
1271 break;
1272 case OPC_SWC1:
1274 TCGv_i32 fp0 = tcg_temp_new_i32();
1275 TCGv t1 = tcg_temp_new();
1277 gen_load_fpr32(fp0, ft);
1278 tcg_gen_extu_i32_tl(t1, fp0);
1279 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
1280 tcg_temp_free(t1);
1281 tcg_temp_free_i32(fp0);
1283 opn = "swc1";
1284 break;
1285 case OPC_LDC1:
1287 TCGv_i64 fp0 = tcg_temp_new_i64();
1289 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
1290 gen_store_fpr64(ctx, fp0, ft);
1291 tcg_temp_free_i64(fp0);
1293 opn = "ldc1";
1294 break;
1295 case OPC_SDC1:
1297 TCGv_i64 fp0 = tcg_temp_new_i64();
1299 gen_load_fpr64(ctx, fp0, ft);
1300 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
1301 tcg_temp_free_i64(fp0);
1303 opn = "sdc1";
1304 break;
1305 default:
1306 MIPS_INVAL(opn);
1307 generate_exception(ctx, EXCP_RI);
1308 goto out;
1310 (void)opn; /* avoid a compiler warning */
1311 MIPS_DEBUG("%s %s, %d(%s)", opn, fregnames[ft], offset, regnames[base]);
1312 out:
1313 tcg_temp_free(t0);
1316 static void gen_cop1_ldst(CPUMIPSState *env, DisasContext *ctx,
1317 uint32_t op, int rt, int rs, int16_t imm)
1319 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
1320 check_cp1_enabled(ctx);
1321 gen_flt_ldst(ctx, op, rt, rs, imm);
1322 } else {
1323 generate_exception_err(ctx, EXCP_CpU, 1);
1327 /* Arithmetic with immediate operand */
1328 static void gen_arith_imm (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1329 int rt, int rs, int16_t imm)
1331 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1332 const char *opn = "imm arith";
1334 if (rt == 0 && opc != OPC_ADDI && opc != OPC_DADDI) {
1335 /* If no destination, treat it as a NOP.
1336 For addi, we must generate the overflow exception when needed. */
1337 MIPS_DEBUG("NOP");
1338 return;
1340 switch (opc) {
1341 case OPC_ADDI:
1343 TCGv t0 = tcg_temp_local_new();
1344 TCGv t1 = tcg_temp_new();
1345 TCGv t2 = tcg_temp_new();
1346 int l1 = gen_new_label();
1348 gen_load_gpr(t1, rs);
1349 tcg_gen_addi_tl(t0, t1, uimm);
1350 tcg_gen_ext32s_tl(t0, t0);
1352 tcg_gen_xori_tl(t1, t1, ~uimm);
1353 tcg_gen_xori_tl(t2, t0, uimm);
1354 tcg_gen_and_tl(t1, t1, t2);
1355 tcg_temp_free(t2);
1356 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1357 tcg_temp_free(t1);
1358 /* operands of same sign, result different sign */
1359 generate_exception(ctx, EXCP_OVERFLOW);
1360 gen_set_label(l1);
1361 tcg_gen_ext32s_tl(t0, t0);
1362 gen_store_gpr(t0, rt);
1363 tcg_temp_free(t0);
1365 opn = "addi";
1366 break;
1367 case OPC_ADDIU:
1368 if (rs != 0) {
1369 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1370 tcg_gen_ext32s_tl(cpu_gpr[rt], cpu_gpr[rt]);
1371 } else {
1372 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1374 opn = "addiu";
1375 break;
1376 #if defined(TARGET_MIPS64)
1377 case OPC_DADDI:
1379 TCGv t0 = tcg_temp_local_new();
1380 TCGv t1 = tcg_temp_new();
1381 TCGv t2 = tcg_temp_new();
1382 int l1 = gen_new_label();
1384 gen_load_gpr(t1, rs);
1385 tcg_gen_addi_tl(t0, t1, uimm);
1387 tcg_gen_xori_tl(t1, t1, ~uimm);
1388 tcg_gen_xori_tl(t2, t0, uimm);
1389 tcg_gen_and_tl(t1, t1, t2);
1390 tcg_temp_free(t2);
1391 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1392 tcg_temp_free(t1);
1393 /* operands of same sign, result different sign */
1394 generate_exception(ctx, EXCP_OVERFLOW);
1395 gen_set_label(l1);
1396 gen_store_gpr(t0, rt);
1397 tcg_temp_free(t0);
1399 opn = "daddi";
1400 break;
1401 case OPC_DADDIU:
1402 if (rs != 0) {
1403 tcg_gen_addi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1404 } else {
1405 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1407 opn = "daddiu";
1408 break;
1409 #endif
1411 (void)opn; /* avoid a compiler warning */
1412 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1415 /* Logic with immediate operand */
1416 static void gen_logic_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
1418 target_ulong uimm;
1419 const char *opn = "imm logic";
1421 if (rt == 0) {
1422 /* If no destination, treat it as a NOP. */
1423 MIPS_DEBUG("NOP");
1424 return;
1426 uimm = (uint16_t)imm;
1427 switch (opc) {
1428 case OPC_ANDI:
1429 if (likely(rs != 0))
1430 tcg_gen_andi_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1431 else
1432 tcg_gen_movi_tl(cpu_gpr[rt], 0);
1433 opn = "andi";
1434 break;
1435 case OPC_ORI:
1436 if (rs != 0)
1437 tcg_gen_ori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1438 else
1439 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1440 opn = "ori";
1441 break;
1442 case OPC_XORI:
1443 if (likely(rs != 0))
1444 tcg_gen_xori_tl(cpu_gpr[rt], cpu_gpr[rs], uimm);
1445 else
1446 tcg_gen_movi_tl(cpu_gpr[rt], uimm);
1447 opn = "xori";
1448 break;
1449 case OPC_LUI:
1450 tcg_gen_movi_tl(cpu_gpr[rt], imm << 16);
1451 opn = "lui";
1452 break;
1454 (void)opn; /* avoid a compiler warning */
1455 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1458 /* Set on less than with immediate operand */
1459 static void gen_slt_imm (CPUMIPSState *env, uint32_t opc, int rt, int rs, int16_t imm)
1461 target_ulong uimm = (target_long)imm; /* Sign extend to 32/64 bits */
1462 const char *opn = "imm arith";
1463 TCGv t0;
1465 if (rt == 0) {
1466 /* If no destination, treat it as a NOP. */
1467 MIPS_DEBUG("NOP");
1468 return;
1470 t0 = tcg_temp_new();
1471 gen_load_gpr(t0, rs);
1472 switch (opc) {
1473 case OPC_SLTI:
1474 tcg_gen_setcondi_tl(TCG_COND_LT, cpu_gpr[rt], t0, uimm);
1475 opn = "slti";
1476 break;
1477 case OPC_SLTIU:
1478 tcg_gen_setcondi_tl(TCG_COND_LTU, cpu_gpr[rt], t0, uimm);
1479 opn = "sltiu";
1480 break;
1482 (void)opn; /* avoid a compiler warning */
1483 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1484 tcg_temp_free(t0);
1487 /* Shifts with immediate operand */
1488 static void gen_shift_imm(CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1489 int rt, int rs, int16_t imm)
1491 target_ulong uimm = ((uint16_t)imm) & 0x1f;
1492 const char *opn = "imm shift";
1493 TCGv t0;
1495 if (rt == 0) {
1496 /* If no destination, treat it as a NOP. */
1497 MIPS_DEBUG("NOP");
1498 return;
1501 t0 = tcg_temp_new();
1502 gen_load_gpr(t0, rs);
1503 switch (opc) {
1504 case OPC_SLL:
1505 tcg_gen_shli_tl(t0, t0, uimm);
1506 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1507 opn = "sll";
1508 break;
1509 case OPC_SRA:
1510 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1511 opn = "sra";
1512 break;
1513 case OPC_SRL:
1514 if (uimm != 0) {
1515 tcg_gen_ext32u_tl(t0, t0);
1516 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1517 } else {
1518 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1520 opn = "srl";
1521 break;
1522 case OPC_ROTR:
1523 if (uimm != 0) {
1524 TCGv_i32 t1 = tcg_temp_new_i32();
1526 tcg_gen_trunc_tl_i32(t1, t0);
1527 tcg_gen_rotri_i32(t1, t1, uimm);
1528 tcg_gen_ext_i32_tl(cpu_gpr[rt], t1);
1529 tcg_temp_free_i32(t1);
1530 } else {
1531 tcg_gen_ext32s_tl(cpu_gpr[rt], t0);
1533 opn = "rotr";
1534 break;
1535 #if defined(TARGET_MIPS64)
1536 case OPC_DSLL:
1537 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm);
1538 opn = "dsll";
1539 break;
1540 case OPC_DSRA:
1541 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm);
1542 opn = "dsra";
1543 break;
1544 case OPC_DSRL:
1545 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm);
1546 opn = "dsrl";
1547 break;
1548 case OPC_DROTR:
1549 if (uimm != 0) {
1550 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm);
1551 } else {
1552 tcg_gen_mov_tl(cpu_gpr[rt], t0);
1554 opn = "drotr";
1555 break;
1556 case OPC_DSLL32:
1557 tcg_gen_shli_tl(cpu_gpr[rt], t0, uimm + 32);
1558 opn = "dsll32";
1559 break;
1560 case OPC_DSRA32:
1561 tcg_gen_sari_tl(cpu_gpr[rt], t0, uimm + 32);
1562 opn = "dsra32";
1563 break;
1564 case OPC_DSRL32:
1565 tcg_gen_shri_tl(cpu_gpr[rt], t0, uimm + 32);
1566 opn = "dsrl32";
1567 break;
1568 case OPC_DROTR32:
1569 tcg_gen_rotri_tl(cpu_gpr[rt], t0, uimm + 32);
1570 opn = "drotr32";
1571 break;
1572 #endif
1574 (void)opn; /* avoid a compiler warning */
1575 MIPS_DEBUG("%s %s, %s, " TARGET_FMT_lx, opn, regnames[rt], regnames[rs], uimm);
1576 tcg_temp_free(t0);
1579 /* Arithmetic */
1580 static void gen_arith (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1581 int rd, int rs, int rt)
1583 const char *opn = "arith";
1585 if (rd == 0 && opc != OPC_ADD && opc != OPC_SUB
1586 && opc != OPC_DADD && opc != OPC_DSUB) {
1587 /* If no destination, treat it as a NOP.
1588 For add & sub, we must generate the overflow exception when needed. */
1589 MIPS_DEBUG("NOP");
1590 return;
1593 switch (opc) {
1594 case OPC_ADD:
1596 TCGv t0 = tcg_temp_local_new();
1597 TCGv t1 = tcg_temp_new();
1598 TCGv t2 = tcg_temp_new();
1599 int l1 = gen_new_label();
1601 gen_load_gpr(t1, rs);
1602 gen_load_gpr(t2, rt);
1603 tcg_gen_add_tl(t0, t1, t2);
1604 tcg_gen_ext32s_tl(t0, t0);
1605 tcg_gen_xor_tl(t1, t1, t2);
1606 tcg_gen_xor_tl(t2, t0, t2);
1607 tcg_gen_andc_tl(t1, t2, t1);
1608 tcg_temp_free(t2);
1609 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1610 tcg_temp_free(t1);
1611 /* operands of same sign, result different sign */
1612 generate_exception(ctx, EXCP_OVERFLOW);
1613 gen_set_label(l1);
1614 gen_store_gpr(t0, rd);
1615 tcg_temp_free(t0);
1617 opn = "add";
1618 break;
1619 case OPC_ADDU:
1620 if (rs != 0 && rt != 0) {
1621 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1622 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1623 } else if (rs == 0 && rt != 0) {
1624 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1625 } else if (rs != 0 && rt == 0) {
1626 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1627 } else {
1628 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1630 opn = "addu";
1631 break;
1632 case OPC_SUB:
1634 TCGv t0 = tcg_temp_local_new();
1635 TCGv t1 = tcg_temp_new();
1636 TCGv t2 = tcg_temp_new();
1637 int l1 = gen_new_label();
1639 gen_load_gpr(t1, rs);
1640 gen_load_gpr(t2, rt);
1641 tcg_gen_sub_tl(t0, t1, t2);
1642 tcg_gen_ext32s_tl(t0, t0);
1643 tcg_gen_xor_tl(t2, t1, t2);
1644 tcg_gen_xor_tl(t1, t0, t1);
1645 tcg_gen_and_tl(t1, t1, t2);
1646 tcg_temp_free(t2);
1647 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1648 tcg_temp_free(t1);
1649 /* operands of different sign, first operand and result different sign */
1650 generate_exception(ctx, EXCP_OVERFLOW);
1651 gen_set_label(l1);
1652 gen_store_gpr(t0, rd);
1653 tcg_temp_free(t0);
1655 opn = "sub";
1656 break;
1657 case OPC_SUBU:
1658 if (rs != 0 && rt != 0) {
1659 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1660 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1661 } else if (rs == 0 && rt != 0) {
1662 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1663 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1664 } else if (rs != 0 && rt == 0) {
1665 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1666 } else {
1667 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1669 opn = "subu";
1670 break;
1671 #if defined(TARGET_MIPS64)
1672 case OPC_DADD:
1674 TCGv t0 = tcg_temp_local_new();
1675 TCGv t1 = tcg_temp_new();
1676 TCGv t2 = tcg_temp_new();
1677 int l1 = gen_new_label();
1679 gen_load_gpr(t1, rs);
1680 gen_load_gpr(t2, rt);
1681 tcg_gen_add_tl(t0, t1, t2);
1682 tcg_gen_xor_tl(t1, t1, t2);
1683 tcg_gen_xor_tl(t2, t0, t2);
1684 tcg_gen_andc_tl(t1, t2, t1);
1685 tcg_temp_free(t2);
1686 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1687 tcg_temp_free(t1);
1688 /* operands of same sign, result different sign */
1689 generate_exception(ctx, EXCP_OVERFLOW);
1690 gen_set_label(l1);
1691 gen_store_gpr(t0, rd);
1692 tcg_temp_free(t0);
1694 opn = "dadd";
1695 break;
1696 case OPC_DADDU:
1697 if (rs != 0 && rt != 0) {
1698 tcg_gen_add_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1699 } else if (rs == 0 && rt != 0) {
1700 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1701 } else if (rs != 0 && rt == 0) {
1702 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1703 } else {
1704 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1706 opn = "daddu";
1707 break;
1708 case OPC_DSUB:
1710 TCGv t0 = tcg_temp_local_new();
1711 TCGv t1 = tcg_temp_new();
1712 TCGv t2 = tcg_temp_new();
1713 int l1 = gen_new_label();
1715 gen_load_gpr(t1, rs);
1716 gen_load_gpr(t2, rt);
1717 tcg_gen_sub_tl(t0, t1, t2);
1718 tcg_gen_xor_tl(t2, t1, t2);
1719 tcg_gen_xor_tl(t1, t0, t1);
1720 tcg_gen_and_tl(t1, t1, t2);
1721 tcg_temp_free(t2);
1722 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
1723 tcg_temp_free(t1);
1724 /* operands of different sign, first operand and result different sign */
1725 generate_exception(ctx, EXCP_OVERFLOW);
1726 gen_set_label(l1);
1727 gen_store_gpr(t0, rd);
1728 tcg_temp_free(t0);
1730 opn = "dsub";
1731 break;
1732 case OPC_DSUBU:
1733 if (rs != 0 && rt != 0) {
1734 tcg_gen_sub_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1735 } else if (rs == 0 && rt != 0) {
1736 tcg_gen_neg_tl(cpu_gpr[rd], cpu_gpr[rt]);
1737 } else if (rs != 0 && rt == 0) {
1738 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1739 } else {
1740 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1742 opn = "dsubu";
1743 break;
1744 #endif
1745 case OPC_MUL:
1746 if (likely(rs != 0 && rt != 0)) {
1747 tcg_gen_mul_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1748 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
1749 } else {
1750 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1752 opn = "mul";
1753 break;
1755 (void)opn; /* avoid a compiler warning */
1756 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1759 /* Conditional move */
1760 static void gen_cond_move (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1762 const char *opn = "cond move";
1763 int l1;
1765 if (rd == 0) {
1766 /* If no destination, treat it as a NOP.
1767 For add & sub, we must generate the overflow exception when needed. */
1768 MIPS_DEBUG("NOP");
1769 return;
1772 l1 = gen_new_label();
1773 switch (opc) {
1774 case OPC_MOVN:
1775 if (likely(rt != 0))
1776 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[rt], 0, l1);
1777 else
1778 tcg_gen_br(l1);
1779 opn = "movn";
1780 break;
1781 case OPC_MOVZ:
1782 if (likely(rt != 0))
1783 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rt], 0, l1);
1784 opn = "movz";
1785 break;
1787 if (rs != 0)
1788 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1789 else
1790 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1791 gen_set_label(l1);
1793 (void)opn; /* avoid a compiler warning */
1794 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1797 /* Logic */
1798 static void gen_logic (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1800 const char *opn = "logic";
1802 if (rd == 0) {
1803 /* If no destination, treat it as a NOP. */
1804 MIPS_DEBUG("NOP");
1805 return;
1808 switch (opc) {
1809 case OPC_AND:
1810 if (likely(rs != 0 && rt != 0)) {
1811 tcg_gen_and_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1812 } else {
1813 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1815 opn = "and";
1816 break;
1817 case OPC_NOR:
1818 if (rs != 0 && rt != 0) {
1819 tcg_gen_nor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1820 } else if (rs == 0 && rt != 0) {
1821 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rt]);
1822 } else if (rs != 0 && rt == 0) {
1823 tcg_gen_not_tl(cpu_gpr[rd], cpu_gpr[rs]);
1824 } else {
1825 tcg_gen_movi_tl(cpu_gpr[rd], ~((target_ulong)0));
1827 opn = "nor";
1828 break;
1829 case OPC_OR:
1830 if (likely(rs != 0 && rt != 0)) {
1831 tcg_gen_or_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1832 } else if (rs == 0 && rt != 0) {
1833 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1834 } else if (rs != 0 && rt == 0) {
1835 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1836 } else {
1837 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1839 opn = "or";
1840 break;
1841 case OPC_XOR:
1842 if (likely(rs != 0 && rt != 0)) {
1843 tcg_gen_xor_tl(cpu_gpr[rd], cpu_gpr[rs], cpu_gpr[rt]);
1844 } else if (rs == 0 && rt != 0) {
1845 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rt]);
1846 } else if (rs != 0 && rt == 0) {
1847 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
1848 } else {
1849 tcg_gen_movi_tl(cpu_gpr[rd], 0);
1851 opn = "xor";
1852 break;
1854 (void)opn; /* avoid a compiler warning */
1855 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1858 /* Set on lower than */
1859 static void gen_slt (CPUMIPSState *env, uint32_t opc, int rd, int rs, int rt)
1861 const char *opn = "slt";
1862 TCGv t0, t1;
1864 if (rd == 0) {
1865 /* If no destination, treat it as a NOP. */
1866 MIPS_DEBUG("NOP");
1867 return;
1870 t0 = tcg_temp_new();
1871 t1 = tcg_temp_new();
1872 gen_load_gpr(t0, rs);
1873 gen_load_gpr(t1, rt);
1874 switch (opc) {
1875 case OPC_SLT:
1876 tcg_gen_setcond_tl(TCG_COND_LT, cpu_gpr[rd], t0, t1);
1877 opn = "slt";
1878 break;
1879 case OPC_SLTU:
1880 tcg_gen_setcond_tl(TCG_COND_LTU, cpu_gpr[rd], t0, t1);
1881 opn = "sltu";
1882 break;
1884 (void)opn; /* avoid a compiler warning */
1885 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1886 tcg_temp_free(t0);
1887 tcg_temp_free(t1);
1890 /* Shifts */
1891 static void gen_shift (CPUMIPSState *env, DisasContext *ctx, uint32_t opc,
1892 int rd, int rs, int rt)
1894 const char *opn = "shifts";
1895 TCGv t0, t1;
1897 if (rd == 0) {
1898 /* If no destination, treat it as a NOP.
1899 For add & sub, we must generate the overflow exception when needed. */
1900 MIPS_DEBUG("NOP");
1901 return;
1904 t0 = tcg_temp_new();
1905 t1 = tcg_temp_new();
1906 gen_load_gpr(t0, rs);
1907 gen_load_gpr(t1, rt);
1908 switch (opc) {
1909 case OPC_SLLV:
1910 tcg_gen_andi_tl(t0, t0, 0x1f);
1911 tcg_gen_shl_tl(t0, t1, t0);
1912 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1913 opn = "sllv";
1914 break;
1915 case OPC_SRAV:
1916 tcg_gen_andi_tl(t0, t0, 0x1f);
1917 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1918 opn = "srav";
1919 break;
1920 case OPC_SRLV:
1921 tcg_gen_ext32u_tl(t1, t1);
1922 tcg_gen_andi_tl(t0, t0, 0x1f);
1923 tcg_gen_shr_tl(t0, t1, t0);
1924 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
1925 opn = "srlv";
1926 break;
1927 case OPC_ROTRV:
1929 TCGv_i32 t2 = tcg_temp_new_i32();
1930 TCGv_i32 t3 = tcg_temp_new_i32();
1932 tcg_gen_trunc_tl_i32(t2, t0);
1933 tcg_gen_trunc_tl_i32(t3, t1);
1934 tcg_gen_andi_i32(t2, t2, 0x1f);
1935 tcg_gen_rotr_i32(t2, t3, t2);
1936 tcg_gen_ext_i32_tl(cpu_gpr[rd], t2);
1937 tcg_temp_free_i32(t2);
1938 tcg_temp_free_i32(t3);
1939 opn = "rotrv";
1941 break;
1942 #if defined(TARGET_MIPS64)
1943 case OPC_DSLLV:
1944 tcg_gen_andi_tl(t0, t0, 0x3f);
1945 tcg_gen_shl_tl(cpu_gpr[rd], t1, t0);
1946 opn = "dsllv";
1947 break;
1948 case OPC_DSRAV:
1949 tcg_gen_andi_tl(t0, t0, 0x3f);
1950 tcg_gen_sar_tl(cpu_gpr[rd], t1, t0);
1951 opn = "dsrav";
1952 break;
1953 case OPC_DSRLV:
1954 tcg_gen_andi_tl(t0, t0, 0x3f);
1955 tcg_gen_shr_tl(cpu_gpr[rd], t1, t0);
1956 opn = "dsrlv";
1957 break;
1958 case OPC_DROTRV:
1959 tcg_gen_andi_tl(t0, t0, 0x3f);
1960 tcg_gen_rotr_tl(cpu_gpr[rd], t1, t0);
1961 opn = "drotrv";
1962 break;
1963 #endif
1965 (void)opn; /* avoid a compiler warning */
1966 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
1967 tcg_temp_free(t0);
1968 tcg_temp_free(t1);
1971 /* Arithmetic on HI/LO registers */
1972 static void gen_HILO (DisasContext *ctx, uint32_t opc, int reg)
1974 const char *opn = "hilo";
1976 if (reg == 0 && (opc == OPC_MFHI || opc == OPC_MFLO)) {
1977 /* Treat as NOP. */
1978 MIPS_DEBUG("NOP");
1979 return;
1981 switch (opc) {
1982 case OPC_MFHI:
1983 tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[0]);
1984 opn = "mfhi";
1985 break;
1986 case OPC_MFLO:
1987 tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[0]);
1988 opn = "mflo";
1989 break;
1990 case OPC_MTHI:
1991 if (reg != 0)
1992 tcg_gen_mov_tl(cpu_HI[0], cpu_gpr[reg]);
1993 else
1994 tcg_gen_movi_tl(cpu_HI[0], 0);
1995 opn = "mthi";
1996 break;
1997 case OPC_MTLO:
1998 if (reg != 0)
1999 tcg_gen_mov_tl(cpu_LO[0], cpu_gpr[reg]);
2000 else
2001 tcg_gen_movi_tl(cpu_LO[0], 0);
2002 opn = "mtlo";
2003 break;
2005 (void)opn; /* avoid a compiler warning */
2006 MIPS_DEBUG("%s %s", opn, regnames[reg]);
2009 static void gen_muldiv (DisasContext *ctx, uint32_t opc,
2010 int rs, int rt)
2012 const char *opn = "mul/div";
2013 TCGv t0, t1;
2015 switch (opc) {
2016 case OPC_DIV:
2017 case OPC_DIVU:
2018 #if defined(TARGET_MIPS64)
2019 case OPC_DDIV:
2020 case OPC_DDIVU:
2021 #endif
2022 t0 = tcg_temp_local_new();
2023 t1 = tcg_temp_local_new();
2024 break;
2025 default:
2026 t0 = tcg_temp_new();
2027 t1 = tcg_temp_new();
2028 break;
2031 gen_load_gpr(t0, rs);
2032 gen_load_gpr(t1, rt);
2033 switch (opc) {
2034 case OPC_DIV:
2036 int l1 = gen_new_label();
2037 int l2 = gen_new_label();
2039 tcg_gen_ext32s_tl(t0, t0);
2040 tcg_gen_ext32s_tl(t1, t1);
2041 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2042 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2043 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2045 tcg_gen_mov_tl(cpu_LO[0], t0);
2046 tcg_gen_movi_tl(cpu_HI[0], 0);
2047 tcg_gen_br(l1);
2048 gen_set_label(l2);
2049 tcg_gen_div_tl(cpu_LO[0], t0, t1);
2050 tcg_gen_rem_tl(cpu_HI[0], t0, t1);
2051 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2052 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2053 gen_set_label(l1);
2055 opn = "div";
2056 break;
2057 case OPC_DIVU:
2059 int l1 = gen_new_label();
2061 tcg_gen_ext32u_tl(t0, t0);
2062 tcg_gen_ext32u_tl(t1, t1);
2063 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2064 tcg_gen_divu_tl(cpu_LO[0], t0, t1);
2065 tcg_gen_remu_tl(cpu_HI[0], t0, t1);
2066 tcg_gen_ext32s_tl(cpu_LO[0], cpu_LO[0]);
2067 tcg_gen_ext32s_tl(cpu_HI[0], cpu_HI[0]);
2068 gen_set_label(l1);
2070 opn = "divu";
2071 break;
2072 case OPC_MULT:
2074 TCGv_i64 t2 = tcg_temp_new_i64();
2075 TCGv_i64 t3 = tcg_temp_new_i64();
2077 tcg_gen_ext_tl_i64(t2, t0);
2078 tcg_gen_ext_tl_i64(t3, t1);
2079 tcg_gen_mul_i64(t2, t2, t3);
2080 tcg_temp_free_i64(t3);
2081 tcg_gen_trunc_i64_tl(t0, t2);
2082 tcg_gen_shri_i64(t2, t2, 32);
2083 tcg_gen_trunc_i64_tl(t1, t2);
2084 tcg_temp_free_i64(t2);
2085 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2086 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2088 opn = "mult";
2089 break;
2090 case OPC_MULTU:
2092 TCGv_i64 t2 = tcg_temp_new_i64();
2093 TCGv_i64 t3 = tcg_temp_new_i64();
2095 tcg_gen_ext32u_tl(t0, t0);
2096 tcg_gen_ext32u_tl(t1, t1);
2097 tcg_gen_extu_tl_i64(t2, t0);
2098 tcg_gen_extu_tl_i64(t3, t1);
2099 tcg_gen_mul_i64(t2, t2, t3);
2100 tcg_temp_free_i64(t3);
2101 tcg_gen_trunc_i64_tl(t0, t2);
2102 tcg_gen_shri_i64(t2, t2, 32);
2103 tcg_gen_trunc_i64_tl(t1, t2);
2104 tcg_temp_free_i64(t2);
2105 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2106 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2108 opn = "multu";
2109 break;
2110 #if defined(TARGET_MIPS64)
2111 case OPC_DDIV:
2113 int l1 = gen_new_label();
2114 int l2 = gen_new_label();
2116 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2117 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2118 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2119 tcg_gen_mov_tl(cpu_LO[0], t0);
2120 tcg_gen_movi_tl(cpu_HI[0], 0);
2121 tcg_gen_br(l1);
2122 gen_set_label(l2);
2123 tcg_gen_div_i64(cpu_LO[0], t0, t1);
2124 tcg_gen_rem_i64(cpu_HI[0], t0, t1);
2125 gen_set_label(l1);
2127 opn = "ddiv";
2128 break;
2129 case OPC_DDIVU:
2131 int l1 = gen_new_label();
2133 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2134 tcg_gen_divu_i64(cpu_LO[0], t0, t1);
2135 tcg_gen_remu_i64(cpu_HI[0], t0, t1);
2136 gen_set_label(l1);
2138 opn = "ddivu";
2139 break;
2140 case OPC_DMULT:
2141 gen_helper_dmult(t0, t1);
2142 opn = "dmult";
2143 break;
2144 case OPC_DMULTU:
2145 gen_helper_dmultu(t0, t1);
2146 opn = "dmultu";
2147 break;
2148 #endif
2149 case OPC_MADD:
2151 TCGv_i64 t2 = tcg_temp_new_i64();
2152 TCGv_i64 t3 = tcg_temp_new_i64();
2154 tcg_gen_ext_tl_i64(t2, t0);
2155 tcg_gen_ext_tl_i64(t3, t1);
2156 tcg_gen_mul_i64(t2, t2, t3);
2157 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2158 tcg_gen_add_i64(t2, t2, t3);
2159 tcg_temp_free_i64(t3);
2160 tcg_gen_trunc_i64_tl(t0, t2);
2161 tcg_gen_shri_i64(t2, t2, 32);
2162 tcg_gen_trunc_i64_tl(t1, t2);
2163 tcg_temp_free_i64(t2);
2164 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2165 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2167 opn = "madd";
2168 break;
2169 case OPC_MADDU:
2171 TCGv_i64 t2 = tcg_temp_new_i64();
2172 TCGv_i64 t3 = tcg_temp_new_i64();
2174 tcg_gen_ext32u_tl(t0, t0);
2175 tcg_gen_ext32u_tl(t1, t1);
2176 tcg_gen_extu_tl_i64(t2, t0);
2177 tcg_gen_extu_tl_i64(t3, t1);
2178 tcg_gen_mul_i64(t2, t2, t3);
2179 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2180 tcg_gen_add_i64(t2, t2, t3);
2181 tcg_temp_free_i64(t3);
2182 tcg_gen_trunc_i64_tl(t0, t2);
2183 tcg_gen_shri_i64(t2, t2, 32);
2184 tcg_gen_trunc_i64_tl(t1, t2);
2185 tcg_temp_free_i64(t2);
2186 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2187 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2189 opn = "maddu";
2190 break;
2191 case OPC_MSUB:
2193 TCGv_i64 t2 = tcg_temp_new_i64();
2194 TCGv_i64 t3 = tcg_temp_new_i64();
2196 tcg_gen_ext_tl_i64(t2, t0);
2197 tcg_gen_ext_tl_i64(t3, t1);
2198 tcg_gen_mul_i64(t2, t2, t3);
2199 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2200 tcg_gen_sub_i64(t2, t3, t2);
2201 tcg_temp_free_i64(t3);
2202 tcg_gen_trunc_i64_tl(t0, t2);
2203 tcg_gen_shri_i64(t2, t2, 32);
2204 tcg_gen_trunc_i64_tl(t1, t2);
2205 tcg_temp_free_i64(t2);
2206 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2207 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2209 opn = "msub";
2210 break;
2211 case OPC_MSUBU:
2213 TCGv_i64 t2 = tcg_temp_new_i64();
2214 TCGv_i64 t3 = tcg_temp_new_i64();
2216 tcg_gen_ext32u_tl(t0, t0);
2217 tcg_gen_ext32u_tl(t1, t1);
2218 tcg_gen_extu_tl_i64(t2, t0);
2219 tcg_gen_extu_tl_i64(t3, t1);
2220 tcg_gen_mul_i64(t2, t2, t3);
2221 tcg_gen_concat_tl_i64(t3, cpu_LO[0], cpu_HI[0]);
2222 tcg_gen_sub_i64(t2, t3, t2);
2223 tcg_temp_free_i64(t3);
2224 tcg_gen_trunc_i64_tl(t0, t2);
2225 tcg_gen_shri_i64(t2, t2, 32);
2226 tcg_gen_trunc_i64_tl(t1, t2);
2227 tcg_temp_free_i64(t2);
2228 tcg_gen_ext32s_tl(cpu_LO[0], t0);
2229 tcg_gen_ext32s_tl(cpu_HI[0], t1);
2231 opn = "msubu";
2232 break;
2233 default:
2234 MIPS_INVAL(opn);
2235 generate_exception(ctx, EXCP_RI);
2236 goto out;
2238 (void)opn; /* avoid a compiler warning */
2239 MIPS_DEBUG("%s %s %s", opn, regnames[rs], regnames[rt]);
2240 out:
2241 tcg_temp_free(t0);
2242 tcg_temp_free(t1);
2245 static void gen_mul_vr54xx (DisasContext *ctx, uint32_t opc,
2246 int rd, int rs, int rt)
2248 const char *opn = "mul vr54xx";
2249 TCGv t0 = tcg_temp_new();
2250 TCGv t1 = tcg_temp_new();
2252 gen_load_gpr(t0, rs);
2253 gen_load_gpr(t1, rt);
2255 switch (opc) {
2256 case OPC_VR54XX_MULS:
2257 gen_helper_muls(t0, t0, t1);
2258 opn = "muls";
2259 break;
2260 case OPC_VR54XX_MULSU:
2261 gen_helper_mulsu(t0, t0, t1);
2262 opn = "mulsu";
2263 break;
2264 case OPC_VR54XX_MACC:
2265 gen_helper_macc(t0, t0, t1);
2266 opn = "macc";
2267 break;
2268 case OPC_VR54XX_MACCU:
2269 gen_helper_maccu(t0, t0, t1);
2270 opn = "maccu";
2271 break;
2272 case OPC_VR54XX_MSAC:
2273 gen_helper_msac(t0, t0, t1);
2274 opn = "msac";
2275 break;
2276 case OPC_VR54XX_MSACU:
2277 gen_helper_msacu(t0, t0, t1);
2278 opn = "msacu";
2279 break;
2280 case OPC_VR54XX_MULHI:
2281 gen_helper_mulhi(t0, t0, t1);
2282 opn = "mulhi";
2283 break;
2284 case OPC_VR54XX_MULHIU:
2285 gen_helper_mulhiu(t0, t0, t1);
2286 opn = "mulhiu";
2287 break;
2288 case OPC_VR54XX_MULSHI:
2289 gen_helper_mulshi(t0, t0, t1);
2290 opn = "mulshi";
2291 break;
2292 case OPC_VR54XX_MULSHIU:
2293 gen_helper_mulshiu(t0, t0, t1);
2294 opn = "mulshiu";
2295 break;
2296 case OPC_VR54XX_MACCHI:
2297 gen_helper_macchi(t0, t0, t1);
2298 opn = "macchi";
2299 break;
2300 case OPC_VR54XX_MACCHIU:
2301 gen_helper_macchiu(t0, t0, t1);
2302 opn = "macchiu";
2303 break;
2304 case OPC_VR54XX_MSACHI:
2305 gen_helper_msachi(t0, t0, t1);
2306 opn = "msachi";
2307 break;
2308 case OPC_VR54XX_MSACHIU:
2309 gen_helper_msachiu(t0, t0, t1);
2310 opn = "msachiu";
2311 break;
2312 default:
2313 MIPS_INVAL("mul vr54xx");
2314 generate_exception(ctx, EXCP_RI);
2315 goto out;
2317 gen_store_gpr(t0, rd);
2318 (void)opn; /* avoid a compiler warning */
2319 MIPS_DEBUG("%s %s, %s, %s", opn, regnames[rd], regnames[rs], regnames[rt]);
2321 out:
2322 tcg_temp_free(t0);
2323 tcg_temp_free(t1);
2326 static void gen_cl (DisasContext *ctx, uint32_t opc,
2327 int rd, int rs)
2329 const char *opn = "CLx";
2330 TCGv t0;
2332 if (rd == 0) {
2333 /* Treat as NOP. */
2334 MIPS_DEBUG("NOP");
2335 return;
2337 t0 = tcg_temp_new();
2338 gen_load_gpr(t0, rs);
2339 switch (opc) {
2340 case OPC_CLO:
2341 gen_helper_clo(cpu_gpr[rd], t0);
2342 opn = "clo";
2343 break;
2344 case OPC_CLZ:
2345 gen_helper_clz(cpu_gpr[rd], t0);
2346 opn = "clz";
2347 break;
2348 #if defined(TARGET_MIPS64)
2349 case OPC_DCLO:
2350 gen_helper_dclo(cpu_gpr[rd], t0);
2351 opn = "dclo";
2352 break;
2353 case OPC_DCLZ:
2354 gen_helper_dclz(cpu_gpr[rd], t0);
2355 opn = "dclz";
2356 break;
2357 #endif
2359 (void)opn; /* avoid a compiler warning */
2360 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2361 tcg_temp_free(t0);
2364 /* Godson integer instructions */
2365 static void gen_loongson_integer (DisasContext *ctx, uint32_t opc,
2366 int rd, int rs, int rt)
2368 const char *opn = "loongson";
2369 TCGv t0, t1;
2371 if (rd == 0) {
2372 /* Treat as NOP. */
2373 MIPS_DEBUG("NOP");
2374 return;
2377 switch (opc) {
2378 case OPC_MULT_G_2E:
2379 case OPC_MULT_G_2F:
2380 case OPC_MULTU_G_2E:
2381 case OPC_MULTU_G_2F:
2382 #if defined(TARGET_MIPS64)
2383 case OPC_DMULT_G_2E:
2384 case OPC_DMULT_G_2F:
2385 case OPC_DMULTU_G_2E:
2386 case OPC_DMULTU_G_2F:
2387 #endif
2388 t0 = tcg_temp_new();
2389 t1 = tcg_temp_new();
2390 break;
2391 default:
2392 t0 = tcg_temp_local_new();
2393 t1 = tcg_temp_local_new();
2394 break;
2397 gen_load_gpr(t0, rs);
2398 gen_load_gpr(t1, rt);
2400 switch (opc) {
2401 case OPC_MULT_G_2E:
2402 case OPC_MULT_G_2F:
2403 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2404 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2405 opn = "mult.g";
2406 break;
2407 case OPC_MULTU_G_2E:
2408 case OPC_MULTU_G_2F:
2409 tcg_gen_ext32u_tl(t0, t0);
2410 tcg_gen_ext32u_tl(t1, t1);
2411 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2412 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2413 opn = "multu.g";
2414 break;
2415 case OPC_DIV_G_2E:
2416 case OPC_DIV_G_2F:
2418 int l1 = gen_new_label();
2419 int l2 = gen_new_label();
2420 int l3 = gen_new_label();
2421 tcg_gen_ext32s_tl(t0, t0);
2422 tcg_gen_ext32s_tl(t1, t1);
2423 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2424 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2425 tcg_gen_br(l3);
2426 gen_set_label(l1);
2427 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2428 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2429 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2430 tcg_gen_br(l3);
2431 gen_set_label(l2);
2432 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2433 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2434 gen_set_label(l3);
2436 opn = "div.g";
2437 break;
2438 case OPC_DIVU_G_2E:
2439 case OPC_DIVU_G_2F:
2441 int l1 = gen_new_label();
2442 int l2 = gen_new_label();
2443 tcg_gen_ext32u_tl(t0, t0);
2444 tcg_gen_ext32u_tl(t1, t1);
2445 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2446 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2447 tcg_gen_br(l2);
2448 gen_set_label(l1);
2449 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2450 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2451 gen_set_label(l2);
2453 opn = "divu.g";
2454 break;
2455 case OPC_MOD_G_2E:
2456 case OPC_MOD_G_2F:
2458 int l1 = gen_new_label();
2459 int l2 = gen_new_label();
2460 int l3 = gen_new_label();
2461 tcg_gen_ext32u_tl(t0, t0);
2462 tcg_gen_ext32u_tl(t1, t1);
2463 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2464 tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2);
2465 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2);
2466 gen_set_label(l1);
2467 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2468 tcg_gen_br(l3);
2469 gen_set_label(l2);
2470 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2471 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2472 gen_set_label(l3);
2474 opn = "mod.g";
2475 break;
2476 case OPC_MODU_G_2E:
2477 case OPC_MODU_G_2F:
2479 int l1 = gen_new_label();
2480 int l2 = gen_new_label();
2481 tcg_gen_ext32u_tl(t0, t0);
2482 tcg_gen_ext32u_tl(t1, t1);
2483 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2484 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2485 tcg_gen_br(l2);
2486 gen_set_label(l1);
2487 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2488 tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]);
2489 gen_set_label(l2);
2491 opn = "modu.g";
2492 break;
2493 #if defined(TARGET_MIPS64)
2494 case OPC_DMULT_G_2E:
2495 case OPC_DMULT_G_2F:
2496 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2497 opn = "dmult.g";
2498 break;
2499 case OPC_DMULTU_G_2E:
2500 case OPC_DMULTU_G_2F:
2501 tcg_gen_mul_tl(cpu_gpr[rd], t0, t1);
2502 opn = "dmultu.g";
2503 break;
2504 case OPC_DDIV_G_2E:
2505 case OPC_DDIV_G_2F:
2507 int l1 = gen_new_label();
2508 int l2 = gen_new_label();
2509 int l3 = gen_new_label();
2510 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2511 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2512 tcg_gen_br(l3);
2513 gen_set_label(l1);
2514 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2515 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2516 tcg_gen_mov_tl(cpu_gpr[rd], t0);
2517 tcg_gen_br(l3);
2518 gen_set_label(l2);
2519 tcg_gen_div_tl(cpu_gpr[rd], t0, t1);
2520 gen_set_label(l3);
2522 opn = "ddiv.g";
2523 break;
2524 case OPC_DDIVU_G_2E:
2525 case OPC_DDIVU_G_2F:
2527 int l1 = gen_new_label();
2528 int l2 = gen_new_label();
2529 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2530 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2531 tcg_gen_br(l2);
2532 gen_set_label(l1);
2533 tcg_gen_divu_tl(cpu_gpr[rd], t0, t1);
2534 gen_set_label(l2);
2536 opn = "ddivu.g";
2537 break;
2538 case OPC_DMOD_G_2E:
2539 case OPC_DMOD_G_2F:
2541 int l1 = gen_new_label();
2542 int l2 = gen_new_label();
2543 int l3 = gen_new_label();
2544 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
2545 tcg_gen_brcondi_tl(TCG_COND_NE, t0, -1LL << 63, l2);
2546 tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1LL, l2);
2547 gen_set_label(l1);
2548 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2549 tcg_gen_br(l3);
2550 gen_set_label(l2);
2551 tcg_gen_rem_tl(cpu_gpr[rd], t0, t1);
2552 gen_set_label(l3);
2554 opn = "dmod.g";
2555 break;
2556 case OPC_DMODU_G_2E:
2557 case OPC_DMODU_G_2F:
2559 int l1 = gen_new_label();
2560 int l2 = gen_new_label();
2561 tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1);
2562 tcg_gen_movi_tl(cpu_gpr[rd], 0);
2563 tcg_gen_br(l2);
2564 gen_set_label(l1);
2565 tcg_gen_remu_tl(cpu_gpr[rd], t0, t1);
2566 gen_set_label(l2);
2568 opn = "dmodu.g";
2569 break;
2570 #endif
2573 (void)opn; /* avoid a compiler warning */
2574 MIPS_DEBUG("%s %s, %s", opn, regnames[rd], regnames[rs]);
2575 tcg_temp_free(t0);
2576 tcg_temp_free(t1);
2579 /* Traps */
2580 static void gen_trap (DisasContext *ctx, uint32_t opc,
2581 int rs, int rt, int16_t imm)
2583 int cond;
2584 TCGv t0 = tcg_temp_new();
2585 TCGv t1 = tcg_temp_new();
2587 cond = 0;
2588 /* Load needed operands */
2589 switch (opc) {
2590 case OPC_TEQ:
2591 case OPC_TGE:
2592 case OPC_TGEU:
2593 case OPC_TLT:
2594 case OPC_TLTU:
2595 case OPC_TNE:
2596 /* Compare two registers */
2597 if (rs != rt) {
2598 gen_load_gpr(t0, rs);
2599 gen_load_gpr(t1, rt);
2600 cond = 1;
2602 break;
2603 case OPC_TEQI:
2604 case OPC_TGEI:
2605 case OPC_TGEIU:
2606 case OPC_TLTI:
2607 case OPC_TLTIU:
2608 case OPC_TNEI:
2609 /* Compare register to immediate */
2610 if (rs != 0 || imm != 0) {
2611 gen_load_gpr(t0, rs);
2612 tcg_gen_movi_tl(t1, (int32_t)imm);
2613 cond = 1;
2615 break;
2617 if (cond == 0) {
2618 switch (opc) {
2619 case OPC_TEQ: /* rs == rs */
2620 case OPC_TEQI: /* r0 == 0 */
2621 case OPC_TGE: /* rs >= rs */
2622 case OPC_TGEI: /* r0 >= 0 */
2623 case OPC_TGEU: /* rs >= rs unsigned */
2624 case OPC_TGEIU: /* r0 >= 0 unsigned */
2625 /* Always trap */
2626 generate_exception(ctx, EXCP_TRAP);
2627 break;
2628 case OPC_TLT: /* rs < rs */
2629 case OPC_TLTI: /* r0 < 0 */
2630 case OPC_TLTU: /* rs < rs unsigned */
2631 case OPC_TLTIU: /* r0 < 0 unsigned */
2632 case OPC_TNE: /* rs != rs */
2633 case OPC_TNEI: /* r0 != 0 */
2634 /* Never trap: treat as NOP. */
2635 break;
2637 } else {
2638 int l1 = gen_new_label();
2640 switch (opc) {
2641 case OPC_TEQ:
2642 case OPC_TEQI:
2643 tcg_gen_brcond_tl(TCG_COND_NE, t0, t1, l1);
2644 break;
2645 case OPC_TGE:
2646 case OPC_TGEI:
2647 tcg_gen_brcond_tl(TCG_COND_LT, t0, t1, l1);
2648 break;
2649 case OPC_TGEU:
2650 case OPC_TGEIU:
2651 tcg_gen_brcond_tl(TCG_COND_LTU, t0, t1, l1);
2652 break;
2653 case OPC_TLT:
2654 case OPC_TLTI:
2655 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
2656 break;
2657 case OPC_TLTU:
2658 case OPC_TLTIU:
2659 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
2660 break;
2661 case OPC_TNE:
2662 case OPC_TNEI:
2663 tcg_gen_brcond_tl(TCG_COND_EQ, t0, t1, l1);
2664 break;
2666 generate_exception(ctx, EXCP_TRAP);
2667 gen_set_label(l1);
2669 tcg_temp_free(t0);
2670 tcg_temp_free(t1);
2673 static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
2675 TranslationBlock *tb;
2676 tb = ctx->tb;
2677 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2678 likely(!ctx->singlestep_enabled)) {
2679 tcg_gen_goto_tb(n);
2680 gen_save_pc(dest);
2681 tcg_gen_exit_tb((tcg_target_long)tb + n);
2682 } else {
2683 gen_save_pc(dest);
2684 if (ctx->singlestep_enabled) {
2685 save_cpu_state(ctx, 0);
2686 gen_helper_0i(raise_exception, EXCP_DEBUG);
2688 tcg_gen_exit_tb(0);
2692 /* Branches (before delay slot) */
2693 static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
2694 int insn_bytes,
2695 int rs, int rt, int32_t offset)
2697 target_ulong btgt = -1;
2698 int blink = 0;
2699 int bcond_compute = 0;
2700 TCGv t0 = tcg_temp_new();
2701 TCGv t1 = tcg_temp_new();
2703 if (ctx->hflags & MIPS_HFLAG_BMASK) {
2704 #ifdef MIPS_DEBUG_DISAS
2705 LOG_DISAS("Branch in delay slot at PC 0x" TARGET_FMT_lx "\n", ctx->pc);
2706 #endif
2707 generate_exception(ctx, EXCP_RI);
2708 goto out;
2711 /* Load needed operands */
2712 switch (opc) {
2713 case OPC_BEQ:
2714 case OPC_BEQL:
2715 case OPC_BNE:
2716 case OPC_BNEL:
2717 /* Compare two registers */
2718 if (rs != rt) {
2719 gen_load_gpr(t0, rs);
2720 gen_load_gpr(t1, rt);
2721 bcond_compute = 1;
2723 btgt = ctx->pc + insn_bytes + offset;
2724 break;
2725 case OPC_BGEZ:
2726 case OPC_BGEZAL:
2727 case OPC_BGEZALS:
2728 case OPC_BGEZALL:
2729 case OPC_BGEZL:
2730 case OPC_BGTZ:
2731 case OPC_BGTZL:
2732 case OPC_BLEZ:
2733 case OPC_BLEZL:
2734 case OPC_BLTZ:
2735 case OPC_BLTZAL:
2736 case OPC_BLTZALS:
2737 case OPC_BLTZALL:
2738 case OPC_BLTZL:
2739 /* Compare to zero */
2740 if (rs != 0) {
2741 gen_load_gpr(t0, rs);
2742 bcond_compute = 1;
2744 btgt = ctx->pc + insn_bytes + offset;
2745 break;
2746 case OPC_J:
2747 case OPC_JAL:
2748 case OPC_JALX:
2749 case OPC_JALS:
2750 case OPC_JALXS:
2751 /* Jump to immediate */
2752 btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
2753 break;
2754 case OPC_JR:
2755 case OPC_JALR:
2756 case OPC_JALRC:
2757 case OPC_JALRS:
2758 /* Jump to register */
2759 if (offset != 0 && offset != 16) {
2760 /* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
2761 others are reserved. */
2762 MIPS_INVAL("jump hint");
2763 generate_exception(ctx, EXCP_RI);
2764 goto out;
2766 gen_load_gpr(btarget, rs);
2767 break;
2768 default:
2769 MIPS_INVAL("branch/jump");
2770 generate_exception(ctx, EXCP_RI);
2771 goto out;
2773 if (bcond_compute == 0) {
2774 /* No condition to be computed */
2775 switch (opc) {
2776 case OPC_BEQ: /* rx == rx */
2777 case OPC_BEQL: /* rx == rx likely */
2778 case OPC_BGEZ: /* 0 >= 0 */
2779 case OPC_BGEZL: /* 0 >= 0 likely */
2780 case OPC_BLEZ: /* 0 <= 0 */
2781 case OPC_BLEZL: /* 0 <= 0 likely */
2782 /* Always take */
2783 ctx->hflags |= MIPS_HFLAG_B;
2784 MIPS_DEBUG("balways");
2785 break;
2786 case OPC_BGEZALS:
2787 case OPC_BGEZAL: /* 0 >= 0 */
2788 case OPC_BGEZALL: /* 0 >= 0 likely */
2789 ctx->hflags |= (opc == OPC_BGEZALS
2790 ? MIPS_HFLAG_BDS16
2791 : MIPS_HFLAG_BDS32);
2792 /* Always take and link */
2793 blink = 31;
2794 ctx->hflags |= MIPS_HFLAG_B;
2795 MIPS_DEBUG("balways and link");
2796 break;
2797 case OPC_BNE: /* rx != rx */
2798 case OPC_BGTZ: /* 0 > 0 */
2799 case OPC_BLTZ: /* 0 < 0 */
2800 /* Treat as NOP. */
2801 MIPS_DEBUG("bnever (NOP)");
2802 goto out;
2803 case OPC_BLTZALS:
2804 case OPC_BLTZAL: /* 0 < 0 */
2805 ctx->hflags |= (opc == OPC_BLTZALS
2806 ? MIPS_HFLAG_BDS16
2807 : MIPS_HFLAG_BDS32);
2808 /* Handle as an unconditional branch to get correct delay
2809 slot checking. */
2810 blink = 31;
2811 btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
2812 ctx->hflags |= MIPS_HFLAG_B;
2813 MIPS_DEBUG("bnever and link");
2814 break;
2815 case OPC_BLTZALL: /* 0 < 0 likely */
2816 tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
2817 /* Skip the instruction in the delay slot */
2818 MIPS_DEBUG("bnever, link and skip");
2819 ctx->pc += 4;
2820 goto out;
2821 case OPC_BNEL: /* rx != rx likely */
2822 case OPC_BGTZL: /* 0 > 0 likely */
2823 case OPC_BLTZL: /* 0 < 0 likely */
2824 /* Skip the instruction in the delay slot */
2825 MIPS_DEBUG("bnever and skip");
2826 ctx->pc += 4;
2827 goto out;
2828 case OPC_J:
2829 ctx->hflags |= MIPS_HFLAG_B;
2830 MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
2831 break;
2832 case OPC_JALXS:
2833 case OPC_JALX:
2834 ctx->hflags |= MIPS_HFLAG_BX;
2835 /* Fallthrough */
2836 case OPC_JALS:
2837 case OPC_JAL:
2838 blink = 31;
2839 ctx->hflags |= MIPS_HFLAG_B;
2840 ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
2841 ? MIPS_HFLAG_BDS16
2842 : MIPS_HFLAG_BDS32);
2843 MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
2844 break;
2845 case OPC_JR:
2846 ctx->hflags |= MIPS_HFLAG_BR;
2847 if (insn_bytes == 4)
2848 ctx->hflags |= MIPS_HFLAG_BDS32;
2849 MIPS_DEBUG("jr %s", regnames[rs]);
2850 break;
2851 case OPC_JALRS:
2852 case OPC_JALR:
2853 case OPC_JALRC:
2854 blink = rt;
2855 ctx->hflags |= MIPS_HFLAG_BR;
2856 ctx->hflags |= (opc == OPC_JALRS
2857 ? MIPS_HFLAG_BDS16
2858 : MIPS_HFLAG_BDS32);
2859 MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
2860 break;
2861 default:
2862 MIPS_INVAL("branch/jump");
2863 generate_exception(ctx, EXCP_RI);
2864 goto out;
2866 } else {
2867 switch (opc) {
2868 case OPC_BEQ:
2869 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2870 MIPS_DEBUG("beq %s, %s, " TARGET_FMT_lx,
2871 regnames[rs], regnames[rt], btgt);
2872 goto not_likely;
2873 case OPC_BEQL:
2874 tcg_gen_setcond_tl(TCG_COND_EQ, bcond, t0, t1);
2875 MIPS_DEBUG("beql %s, %s, " TARGET_FMT_lx,
2876 regnames[rs], regnames[rt], btgt);
2877 goto likely;
2878 case OPC_BNE:
2879 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2880 MIPS_DEBUG("bne %s, %s, " TARGET_FMT_lx,
2881 regnames[rs], regnames[rt], btgt);
2882 goto not_likely;
2883 case OPC_BNEL:
2884 tcg_gen_setcond_tl(TCG_COND_NE, bcond, t0, t1);
2885 MIPS_DEBUG("bnel %s, %s, " TARGET_FMT_lx,
2886 regnames[rs], regnames[rt], btgt);
2887 goto likely;
2888 case OPC_BGEZ:
2889 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2890 MIPS_DEBUG("bgez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2891 goto not_likely;
2892 case OPC_BGEZL:
2893 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2894 MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2895 goto likely;
2896 case OPC_BGEZALS:
2897 case OPC_BGEZAL:
2898 ctx->hflags |= (opc == OPC_BGEZALS
2899 ? MIPS_HFLAG_BDS16
2900 : MIPS_HFLAG_BDS32);
2901 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2902 MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2903 blink = 31;
2904 goto not_likely;
2905 case OPC_BGEZALL:
2906 tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
2907 blink = 31;
2908 MIPS_DEBUG("bgezall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2909 goto likely;
2910 case OPC_BGTZ:
2911 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2912 MIPS_DEBUG("bgtz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2913 goto not_likely;
2914 case OPC_BGTZL:
2915 tcg_gen_setcondi_tl(TCG_COND_GT, bcond, t0, 0);
2916 MIPS_DEBUG("bgtzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2917 goto likely;
2918 case OPC_BLEZ:
2919 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2920 MIPS_DEBUG("blez %s, " TARGET_FMT_lx, regnames[rs], btgt);
2921 goto not_likely;
2922 case OPC_BLEZL:
2923 tcg_gen_setcondi_tl(TCG_COND_LE, bcond, t0, 0);
2924 MIPS_DEBUG("blezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2925 goto likely;
2926 case OPC_BLTZ:
2927 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2928 MIPS_DEBUG("bltz %s, " TARGET_FMT_lx, regnames[rs], btgt);
2929 goto not_likely;
2930 case OPC_BLTZL:
2931 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2932 MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
2933 goto likely;
2934 case OPC_BLTZALS:
2935 case OPC_BLTZAL:
2936 ctx->hflags |= (opc == OPC_BLTZALS
2937 ? MIPS_HFLAG_BDS16
2938 : MIPS_HFLAG_BDS32);
2939 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2940 blink = 31;
2941 MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
2942 not_likely:
2943 ctx->hflags |= MIPS_HFLAG_BC;
2944 break;
2945 case OPC_BLTZALL:
2946 tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
2947 blink = 31;
2948 MIPS_DEBUG("bltzall %s, " TARGET_FMT_lx, regnames[rs], btgt);
2949 likely:
2950 ctx->hflags |= MIPS_HFLAG_BL;
2951 break;
2952 default:
2953 MIPS_INVAL("conditional branch/jump");
2954 generate_exception(ctx, EXCP_RI);
2955 goto out;
2958 MIPS_DEBUG("enter ds: link %d cond %02x target " TARGET_FMT_lx,
2959 blink, ctx->hflags, btgt);
2961 ctx->btarget = btgt;
2962 if (blink > 0) {
2963 int post_delay = insn_bytes;
2964 int lowbit = !!(ctx->hflags & MIPS_HFLAG_M16);
2966 if (opc != OPC_JALRC)
2967 post_delay += ((ctx->hflags & MIPS_HFLAG_BDS16) ? 2 : 4);
2969 tcg_gen_movi_tl(cpu_gpr[blink], ctx->pc + post_delay + lowbit);
2972 out:
2973 if (insn_bytes == 2)
2974 ctx->hflags |= MIPS_HFLAG_B16;
2975 tcg_temp_free(t0);
2976 tcg_temp_free(t1);
2979 /* special3 bitfield operations */
2980 static void gen_bitops (DisasContext *ctx, uint32_t opc, int rt,
2981 int rs, int lsb, int msb)
2983 TCGv t0 = tcg_temp_new();
2984 TCGv t1 = tcg_temp_new();
2985 target_ulong mask;
2987 gen_load_gpr(t1, rs);
2988 switch (opc) {
2989 case OPC_EXT:
2990 if (lsb + msb > 31)
2991 goto fail;
2992 tcg_gen_shri_tl(t0, t1, lsb);
2993 if (msb != 31) {
2994 tcg_gen_andi_tl(t0, t0, (1 << (msb + 1)) - 1);
2995 } else {
2996 tcg_gen_ext32s_tl(t0, t0);
2998 break;
2999 #if defined(TARGET_MIPS64)
3000 case OPC_DEXTM:
3001 tcg_gen_shri_tl(t0, t1, lsb);
3002 if (msb != 31) {
3003 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1 + 32)) - 1);
3005 break;
3006 case OPC_DEXTU:
3007 tcg_gen_shri_tl(t0, t1, lsb + 32);
3008 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3009 break;
3010 case OPC_DEXT:
3011 tcg_gen_shri_tl(t0, t1, lsb);
3012 tcg_gen_andi_tl(t0, t0, (1ULL << (msb + 1)) - 1);
3013 break;
3014 #endif
3015 case OPC_INS:
3016 if (lsb > msb)
3017 goto fail;
3018 mask = ((msb - lsb + 1 < 32) ? ((1 << (msb - lsb + 1)) - 1) : ~0) << lsb;
3019 gen_load_gpr(t0, rt);
3020 tcg_gen_andi_tl(t0, t0, ~mask);
3021 tcg_gen_shli_tl(t1, t1, lsb);
3022 tcg_gen_andi_tl(t1, t1, mask);
3023 tcg_gen_or_tl(t0, t0, t1);
3024 tcg_gen_ext32s_tl(t0, t0);
3025 break;
3026 #if defined(TARGET_MIPS64)
3027 case OPC_DINSM:
3028 if (lsb > msb)
3029 goto fail;
3030 mask = ((msb - lsb + 1 + 32 < 64) ? ((1ULL << (msb - lsb + 1 + 32)) - 1) : ~0ULL) << lsb;
3031 gen_load_gpr(t0, rt);
3032 tcg_gen_andi_tl(t0, t0, ~mask);
3033 tcg_gen_shli_tl(t1, t1, lsb);
3034 tcg_gen_andi_tl(t1, t1, mask);
3035 tcg_gen_or_tl(t0, t0, t1);
3036 break;
3037 case OPC_DINSU:
3038 if (lsb > msb)
3039 goto fail;
3040 mask = ((1ULL << (msb - lsb + 1)) - 1) << (lsb + 32);
3041 gen_load_gpr(t0, rt);
3042 tcg_gen_andi_tl(t0, t0, ~mask);
3043 tcg_gen_shli_tl(t1, t1, lsb + 32);
3044 tcg_gen_andi_tl(t1, t1, mask);
3045 tcg_gen_or_tl(t0, t0, t1);
3046 break;
3047 case OPC_DINS:
3048 if (lsb > msb)
3049 goto fail;
3050 gen_load_gpr(t0, rt);
3051 mask = ((1ULL << (msb - lsb + 1)) - 1) << lsb;
3052 gen_load_gpr(t0, rt);
3053 tcg_gen_andi_tl(t0, t0, ~mask);
3054 tcg_gen_shli_tl(t1, t1, lsb);
3055 tcg_gen_andi_tl(t1, t1, mask);
3056 tcg_gen_or_tl(t0, t0, t1);
3057 break;
3058 #endif
3059 default:
3060 fail:
3061 MIPS_INVAL("bitops");
3062 generate_exception(ctx, EXCP_RI);
3063 tcg_temp_free(t0);
3064 tcg_temp_free(t1);
3065 return;
3067 gen_store_gpr(t0, rt);
3068 tcg_temp_free(t0);
3069 tcg_temp_free(t1);
3072 static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
3074 TCGv t0;
3076 if (rd == 0) {
3077 /* If no destination, treat it as a NOP. */
3078 MIPS_DEBUG("NOP");
3079 return;
3082 t0 = tcg_temp_new();
3083 gen_load_gpr(t0, rt);
3084 switch (op2) {
3085 case OPC_WSBH:
3087 TCGv t1 = tcg_temp_new();
3089 tcg_gen_shri_tl(t1, t0, 8);
3090 tcg_gen_andi_tl(t1, t1, 0x00FF00FF);
3091 tcg_gen_shli_tl(t0, t0, 8);
3092 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF);
3093 tcg_gen_or_tl(t0, t0, t1);
3094 tcg_temp_free(t1);
3095 tcg_gen_ext32s_tl(cpu_gpr[rd], t0);
3097 break;
3098 case OPC_SEB:
3099 tcg_gen_ext8s_tl(cpu_gpr[rd], t0);
3100 break;
3101 case OPC_SEH:
3102 tcg_gen_ext16s_tl(cpu_gpr[rd], t0);
3103 break;
3104 #if defined(TARGET_MIPS64)
3105 case OPC_DSBH:
3107 TCGv t1 = tcg_temp_new();
3109 tcg_gen_shri_tl(t1, t0, 8);
3110 tcg_gen_andi_tl(t1, t1, 0x00FF00FF00FF00FFULL);
3111 tcg_gen_shli_tl(t0, t0, 8);
3112 tcg_gen_andi_tl(t0, t0, ~0x00FF00FF00FF00FFULL);
3113 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3114 tcg_temp_free(t1);
3116 break;
3117 case OPC_DSHD:
3119 TCGv t1 = tcg_temp_new();
3121 tcg_gen_shri_tl(t1, t0, 16);
3122 tcg_gen_andi_tl(t1, t1, 0x0000FFFF0000FFFFULL);
3123 tcg_gen_shli_tl(t0, t0, 16);
3124 tcg_gen_andi_tl(t0, t0, ~0x0000FFFF0000FFFFULL);
3125 tcg_gen_or_tl(t0, t0, t1);
3126 tcg_gen_shri_tl(t1, t0, 32);
3127 tcg_gen_shli_tl(t0, t0, 32);
3128 tcg_gen_or_tl(cpu_gpr[rd], t0, t1);
3129 tcg_temp_free(t1);
3131 break;
3132 #endif
3133 default:
3134 MIPS_INVAL("bsfhl");
3135 generate_exception(ctx, EXCP_RI);
3136 tcg_temp_free(t0);
3137 return;
3139 tcg_temp_free(t0);
3142 #ifndef CONFIG_USER_ONLY
3143 /* CP0 (MMU and control) */
3144 static inline void gen_mfc0_load32 (TCGv arg, target_ulong off)
3146 TCGv_i32 t0 = tcg_temp_new_i32();
3148 tcg_gen_ld_i32(t0, cpu_env, off);
3149 tcg_gen_ext_i32_tl(arg, t0);
3150 tcg_temp_free_i32(t0);
3153 static inline void gen_mfc0_load64 (TCGv arg, target_ulong off)
3155 tcg_gen_ld_tl(arg, cpu_env, off);
3156 tcg_gen_ext32s_tl(arg, arg);
3159 static inline void gen_mtc0_store32 (TCGv arg, target_ulong off)
3161 TCGv_i32 t0 = tcg_temp_new_i32();
3163 tcg_gen_trunc_tl_i32(t0, arg);
3164 tcg_gen_st_i32(t0, cpu_env, off);
3165 tcg_temp_free_i32(t0);
3168 static inline void gen_mtc0_store64 (TCGv arg, target_ulong off)
3170 tcg_gen_ext32s_tl(arg, arg);
3171 tcg_gen_st_tl(arg, cpu_env, off);
3174 static void gen_mfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3176 const char *rn = "invalid";
3178 if (sel != 0)
3179 check_insn(env, ctx, ISA_MIPS32);
3181 switch (reg) {
3182 case 0:
3183 switch (sel) {
3184 case 0:
3185 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
3186 rn = "Index";
3187 break;
3188 case 1:
3189 check_insn(env, ctx, ASE_MT);
3190 gen_helper_mfc0_mvpcontrol(arg);
3191 rn = "MVPControl";
3192 break;
3193 case 2:
3194 check_insn(env, ctx, ASE_MT);
3195 gen_helper_mfc0_mvpconf0(arg);
3196 rn = "MVPConf0";
3197 break;
3198 case 3:
3199 check_insn(env, ctx, ASE_MT);
3200 gen_helper_mfc0_mvpconf1(arg);
3201 rn = "MVPConf1";
3202 break;
3203 default:
3204 goto die;
3206 break;
3207 case 1:
3208 switch (sel) {
3209 case 0:
3210 gen_helper_mfc0_random(arg);
3211 rn = "Random";
3212 break;
3213 case 1:
3214 check_insn(env, ctx, ASE_MT);
3215 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
3216 rn = "VPEControl";
3217 break;
3218 case 2:
3219 check_insn(env, ctx, ASE_MT);
3220 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
3221 rn = "VPEConf0";
3222 break;
3223 case 3:
3224 check_insn(env, ctx, ASE_MT);
3225 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
3226 rn = "VPEConf1";
3227 break;
3228 case 4:
3229 check_insn(env, ctx, ASE_MT);
3230 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_YQMask));
3231 rn = "YQMask";
3232 break;
3233 case 5:
3234 check_insn(env, ctx, ASE_MT);
3235 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
3236 rn = "VPESchedule";
3237 break;
3238 case 6:
3239 check_insn(env, ctx, ASE_MT);
3240 gen_mfc0_load64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
3241 rn = "VPEScheFBack";
3242 break;
3243 case 7:
3244 check_insn(env, ctx, ASE_MT);
3245 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
3246 rn = "VPEOpt";
3247 break;
3248 default:
3249 goto die;
3251 break;
3252 case 2:
3253 switch (sel) {
3254 case 0:
3255 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
3256 tcg_gen_ext32s_tl(arg, arg);
3257 rn = "EntryLo0";
3258 break;
3259 case 1:
3260 check_insn(env, ctx, ASE_MT);
3261 gen_helper_mfc0_tcstatus(arg);
3262 rn = "TCStatus";
3263 break;
3264 case 2:
3265 check_insn(env, ctx, ASE_MT);
3266 gen_helper_mfc0_tcbind(arg);
3267 rn = "TCBind";
3268 break;
3269 case 3:
3270 check_insn(env, ctx, ASE_MT);
3271 gen_helper_mfc0_tcrestart(arg);
3272 rn = "TCRestart";
3273 break;
3274 case 4:
3275 check_insn(env, ctx, ASE_MT);
3276 gen_helper_mfc0_tchalt(arg);
3277 rn = "TCHalt";
3278 break;
3279 case 5:
3280 check_insn(env, ctx, ASE_MT);
3281 gen_helper_mfc0_tccontext(arg);
3282 rn = "TCContext";
3283 break;
3284 case 6:
3285 check_insn(env, ctx, ASE_MT);
3286 gen_helper_mfc0_tcschedule(arg);
3287 rn = "TCSchedule";
3288 break;
3289 case 7:
3290 check_insn(env, ctx, ASE_MT);
3291 gen_helper_mfc0_tcschefback(arg);
3292 rn = "TCScheFBack";
3293 break;
3294 default:
3295 goto die;
3297 break;
3298 case 3:
3299 switch (sel) {
3300 case 0:
3301 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
3302 tcg_gen_ext32s_tl(arg, arg);
3303 rn = "EntryLo1";
3304 break;
3305 default:
3306 goto die;
3308 break;
3309 case 4:
3310 switch (sel) {
3311 case 0:
3312 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
3313 tcg_gen_ext32s_tl(arg, arg);
3314 rn = "Context";
3315 break;
3316 case 1:
3317 // gen_helper_mfc0_contextconfig(arg); /* SmartMIPS ASE */
3318 rn = "ContextConfig";
3319 // break;
3320 default:
3321 goto die;
3323 break;
3324 case 5:
3325 switch (sel) {
3326 case 0:
3327 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
3328 rn = "PageMask";
3329 break;
3330 case 1:
3331 check_insn(env, ctx, ISA_MIPS32R2);
3332 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
3333 rn = "PageGrain";
3334 break;
3335 default:
3336 goto die;
3338 break;
3339 case 6:
3340 switch (sel) {
3341 case 0:
3342 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
3343 rn = "Wired";
3344 break;
3345 case 1:
3346 check_insn(env, ctx, ISA_MIPS32R2);
3347 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
3348 rn = "SRSConf0";
3349 break;
3350 case 2:
3351 check_insn(env, ctx, ISA_MIPS32R2);
3352 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
3353 rn = "SRSConf1";
3354 break;
3355 case 3:
3356 check_insn(env, ctx, ISA_MIPS32R2);
3357 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
3358 rn = "SRSConf2";
3359 break;
3360 case 4:
3361 check_insn(env, ctx, ISA_MIPS32R2);
3362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
3363 rn = "SRSConf3";
3364 break;
3365 case 5:
3366 check_insn(env, ctx, ISA_MIPS32R2);
3367 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
3368 rn = "SRSConf4";
3369 break;
3370 default:
3371 goto die;
3373 break;
3374 case 7:
3375 switch (sel) {
3376 case 0:
3377 check_insn(env, ctx, ISA_MIPS32R2);
3378 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
3379 rn = "HWREna";
3380 break;
3381 default:
3382 goto die;
3384 break;
3385 case 8:
3386 switch (sel) {
3387 case 0:
3388 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
3389 tcg_gen_ext32s_tl(arg, arg);
3390 rn = "BadVAddr";
3391 break;
3392 default:
3393 goto die;
3395 break;
3396 case 9:
3397 switch (sel) {
3398 case 0:
3399 /* Mark as an IO operation because we read the time. */
3400 if (use_icount)
3401 gen_io_start();
3402 gen_helper_mfc0_count(arg);
3403 if (use_icount) {
3404 gen_io_end();
3406 /* Break the TB to be able to take timer interrupts immediately
3407 after reading count. */
3408 ctx->bstate = BS_STOP;
3409 rn = "Count";
3410 break;
3411 /* 6,7 are implementation dependent */
3412 default:
3413 goto die;
3415 break;
3416 case 10:
3417 switch (sel) {
3418 case 0:
3419 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
3420 tcg_gen_ext32s_tl(arg, arg);
3421 rn = "EntryHi";
3422 break;
3423 default:
3424 goto die;
3426 break;
3427 case 11:
3428 switch (sel) {
3429 case 0:
3430 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
3431 rn = "Compare";
3432 break;
3433 /* 6,7 are implementation dependent */
3434 default:
3435 goto die;
3437 break;
3438 case 12:
3439 switch (sel) {
3440 case 0:
3441 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
3442 rn = "Status";
3443 break;
3444 case 1:
3445 check_insn(env, ctx, ISA_MIPS32R2);
3446 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
3447 rn = "IntCtl";
3448 break;
3449 case 2:
3450 check_insn(env, ctx, ISA_MIPS32R2);
3451 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
3452 rn = "SRSCtl";
3453 break;
3454 case 3:
3455 check_insn(env, ctx, ISA_MIPS32R2);
3456 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
3457 rn = "SRSMap";
3458 break;
3459 default:
3460 goto die;
3462 break;
3463 case 13:
3464 switch (sel) {
3465 case 0:
3466 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
3467 rn = "Cause";
3468 break;
3469 default:
3470 goto die;
3472 break;
3473 case 14:
3474 switch (sel) {
3475 case 0:
3476 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
3477 tcg_gen_ext32s_tl(arg, arg);
3478 rn = "EPC";
3479 break;
3480 default:
3481 goto die;
3483 break;
3484 case 15:
3485 switch (sel) {
3486 case 0:
3487 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
3488 rn = "PRid";
3489 break;
3490 case 1:
3491 check_insn(env, ctx, ISA_MIPS32R2);
3492 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
3493 rn = "EBase";
3494 break;
3495 default:
3496 goto die;
3498 break;
3499 case 16:
3500 switch (sel) {
3501 case 0:
3502 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
3503 rn = "Config";
3504 break;
3505 case 1:
3506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
3507 rn = "Config1";
3508 break;
3509 case 2:
3510 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
3511 rn = "Config2";
3512 break;
3513 case 3:
3514 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
3515 rn = "Config3";
3516 break;
3517 /* 4,5 are reserved */
3518 /* 6,7 are implementation dependent */
3519 case 6:
3520 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
3521 rn = "Config6";
3522 break;
3523 case 7:
3524 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
3525 rn = "Config7";
3526 break;
3527 default:
3528 goto die;
3530 break;
3531 case 17:
3532 switch (sel) {
3533 case 0:
3534 gen_helper_mfc0_lladdr(arg);
3535 rn = "LLAddr";
3536 break;
3537 default:
3538 goto die;
3540 break;
3541 case 18:
3542 switch (sel) {
3543 case 0 ... 7:
3544 gen_helper_1i(mfc0_watchlo, arg, sel);
3545 rn = "WatchLo";
3546 break;
3547 default:
3548 goto die;
3550 break;
3551 case 19:
3552 switch (sel) {
3553 case 0 ...7:
3554 gen_helper_1i(mfc0_watchhi, arg, sel);
3555 rn = "WatchHi";
3556 break;
3557 default:
3558 goto die;
3560 break;
3561 case 20:
3562 switch (sel) {
3563 case 0:
3564 #if defined(TARGET_MIPS64)
3565 check_insn(env, ctx, ISA_MIPS3);
3566 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
3567 tcg_gen_ext32s_tl(arg, arg);
3568 rn = "XContext";
3569 break;
3570 #endif
3571 default:
3572 goto die;
3574 break;
3575 case 21:
3576 /* Officially reserved, but sel 0 is used for R1x000 framemask */
3577 switch (sel) {
3578 case 0:
3579 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
3580 rn = "Framemask";
3581 break;
3582 default:
3583 goto die;
3585 break;
3586 case 22:
3587 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3588 rn = "'Diagnostic"; /* implementation dependent */
3589 break;
3590 case 23:
3591 switch (sel) {
3592 case 0:
3593 gen_helper_mfc0_debug(arg); /* EJTAG support */
3594 rn = "Debug";
3595 break;
3596 case 1:
3597 // gen_helper_mfc0_tracecontrol(arg); /* PDtrace support */
3598 rn = "TraceControl";
3599 // break;
3600 case 2:
3601 // gen_helper_mfc0_tracecontrol2(arg); /* PDtrace support */
3602 rn = "TraceControl2";
3603 // break;
3604 case 3:
3605 // gen_helper_mfc0_usertracedata(arg); /* PDtrace support */
3606 rn = "UserTraceData";
3607 // break;
3608 case 4:
3609 // gen_helper_mfc0_tracebpc(arg); /* PDtrace support */
3610 rn = "TraceBPC";
3611 // break;
3612 default:
3613 goto die;
3615 break;
3616 case 24:
3617 switch (sel) {
3618 case 0:
3619 /* EJTAG support */
3620 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
3621 tcg_gen_ext32s_tl(arg, arg);
3622 rn = "DEPC";
3623 break;
3624 default:
3625 goto die;
3627 break;
3628 case 25:
3629 switch (sel) {
3630 case 0:
3631 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
3632 rn = "Performance0";
3633 break;
3634 case 1:
3635 // gen_helper_mfc0_performance1(arg);
3636 rn = "Performance1";
3637 // break;
3638 case 2:
3639 // gen_helper_mfc0_performance2(arg);
3640 rn = "Performance2";
3641 // break;
3642 case 3:
3643 // gen_helper_mfc0_performance3(arg);
3644 rn = "Performance3";
3645 // break;
3646 case 4:
3647 // gen_helper_mfc0_performance4(arg);
3648 rn = "Performance4";
3649 // break;
3650 case 5:
3651 // gen_helper_mfc0_performance5(arg);
3652 rn = "Performance5";
3653 // break;
3654 case 6:
3655 // gen_helper_mfc0_performance6(arg);
3656 rn = "Performance6";
3657 // break;
3658 case 7:
3659 // gen_helper_mfc0_performance7(arg);
3660 rn = "Performance7";
3661 // break;
3662 default:
3663 goto die;
3665 break;
3666 case 26:
3667 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3668 rn = "ECC";
3669 break;
3670 case 27:
3671 switch (sel) {
3672 case 0 ... 3:
3673 tcg_gen_movi_tl(arg, 0); /* unimplemented */
3674 rn = "CacheErr";
3675 break;
3676 default:
3677 goto die;
3679 break;
3680 case 28:
3681 switch (sel) {
3682 case 0:
3683 case 2:
3684 case 4:
3685 case 6:
3686 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
3687 rn = "TagLo";
3688 break;
3689 case 1:
3690 case 3:
3691 case 5:
3692 case 7:
3693 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
3694 rn = "DataLo";
3695 break;
3696 default:
3697 goto die;
3699 break;
3700 case 29:
3701 switch (sel) {
3702 case 0:
3703 case 2:
3704 case 4:
3705 case 6:
3706 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
3707 rn = "TagHi";
3708 break;
3709 case 1:
3710 case 3:
3711 case 5:
3712 case 7:
3713 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
3714 rn = "DataHi";
3715 break;
3716 default:
3717 goto die;
3719 break;
3720 case 30:
3721 switch (sel) {
3722 case 0:
3723 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
3724 tcg_gen_ext32s_tl(arg, arg);
3725 rn = "ErrorEPC";
3726 break;
3727 default:
3728 goto die;
3730 break;
3731 case 31:
3732 switch (sel) {
3733 case 0:
3734 /* EJTAG support */
3735 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
3736 rn = "DESAVE";
3737 break;
3738 default:
3739 goto die;
3741 break;
3742 default:
3743 goto die;
3745 (void)rn; /* avoid a compiler warning */
3746 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3747 return;
3749 die:
3750 LOG_DISAS("mfc0 %s (reg %d sel %d)\n", rn, reg, sel);
3751 generate_exception(ctx, EXCP_RI);
3754 static void gen_mtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
3756 const char *rn = "invalid";
3758 if (sel != 0)
3759 check_insn(env, ctx, ISA_MIPS32);
3761 if (use_icount)
3762 gen_io_start();
3764 switch (reg) {
3765 case 0:
3766 switch (sel) {
3767 case 0:
3768 gen_helper_mtc0_index(arg);
3769 rn = "Index";
3770 break;
3771 case 1:
3772 check_insn(env, ctx, ASE_MT);
3773 gen_helper_mtc0_mvpcontrol(arg);
3774 rn = "MVPControl";
3775 break;
3776 case 2:
3777 check_insn(env, ctx, ASE_MT);
3778 /* ignored */
3779 rn = "MVPConf0";
3780 break;
3781 case 3:
3782 check_insn(env, ctx, ASE_MT);
3783 /* ignored */
3784 rn = "MVPConf1";
3785 break;
3786 default:
3787 goto die;
3789 break;
3790 case 1:
3791 switch (sel) {
3792 case 0:
3793 /* ignored */
3794 rn = "Random";
3795 break;
3796 case 1:
3797 check_insn(env, ctx, ASE_MT);
3798 gen_helper_mtc0_vpecontrol(arg);
3799 rn = "VPEControl";
3800 break;
3801 case 2:
3802 check_insn(env, ctx, ASE_MT);
3803 gen_helper_mtc0_vpeconf0(arg);
3804 rn = "VPEConf0";
3805 break;
3806 case 3:
3807 check_insn(env, ctx, ASE_MT);
3808 gen_helper_mtc0_vpeconf1(arg);
3809 rn = "VPEConf1";
3810 break;
3811 case 4:
3812 check_insn(env, ctx, ASE_MT);
3813 gen_helper_mtc0_yqmask(arg);
3814 rn = "YQMask";
3815 break;
3816 case 5:
3817 check_insn(env, ctx, ASE_MT);
3818 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPESchedule));
3819 rn = "VPESchedule";
3820 break;
3821 case 6:
3822 check_insn(env, ctx, ASE_MT);
3823 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_VPEScheFBack));
3824 rn = "VPEScheFBack";
3825 break;
3826 case 7:
3827 check_insn(env, ctx, ASE_MT);
3828 gen_helper_mtc0_vpeopt(arg);
3829 rn = "VPEOpt";
3830 break;
3831 default:
3832 goto die;
3834 break;
3835 case 2:
3836 switch (sel) {
3837 case 0:
3838 gen_helper_mtc0_entrylo0(arg);
3839 rn = "EntryLo0";
3840 break;
3841 case 1:
3842 check_insn(env, ctx, ASE_MT);
3843 gen_helper_mtc0_tcstatus(arg);
3844 rn = "TCStatus";
3845 break;
3846 case 2:
3847 check_insn(env, ctx, ASE_MT);
3848 gen_helper_mtc0_tcbind(arg);
3849 rn = "TCBind";
3850 break;
3851 case 3:
3852 check_insn(env, ctx, ASE_MT);
3853 gen_helper_mtc0_tcrestart(arg);
3854 rn = "TCRestart";
3855 break;
3856 case 4:
3857 check_insn(env, ctx, ASE_MT);
3858 gen_helper_mtc0_tchalt(arg);
3859 rn = "TCHalt";
3860 break;
3861 case 5:
3862 check_insn(env, ctx, ASE_MT);
3863 gen_helper_mtc0_tccontext(arg);
3864 rn = "TCContext";
3865 break;
3866 case 6:
3867 check_insn(env, ctx, ASE_MT);
3868 gen_helper_mtc0_tcschedule(arg);
3869 rn = "TCSchedule";
3870 break;
3871 case 7:
3872 check_insn(env, ctx, ASE_MT);
3873 gen_helper_mtc0_tcschefback(arg);
3874 rn = "TCScheFBack";
3875 break;
3876 default:
3877 goto die;
3879 break;
3880 case 3:
3881 switch (sel) {
3882 case 0:
3883 gen_helper_mtc0_entrylo1(arg);
3884 rn = "EntryLo1";
3885 break;
3886 default:
3887 goto die;
3889 break;
3890 case 4:
3891 switch (sel) {
3892 case 0:
3893 gen_helper_mtc0_context(arg);
3894 rn = "Context";
3895 break;
3896 case 1:
3897 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
3898 rn = "ContextConfig";
3899 // break;
3900 default:
3901 goto die;
3903 break;
3904 case 5:
3905 switch (sel) {
3906 case 0:
3907 gen_helper_mtc0_pagemask(arg);
3908 rn = "PageMask";
3909 break;
3910 case 1:
3911 check_insn(env, ctx, ISA_MIPS32R2);
3912 gen_helper_mtc0_pagegrain(arg);
3913 rn = "PageGrain";
3914 break;
3915 default:
3916 goto die;
3918 break;
3919 case 6:
3920 switch (sel) {
3921 case 0:
3922 gen_helper_mtc0_wired(arg);
3923 rn = "Wired";
3924 break;
3925 case 1:
3926 check_insn(env, ctx, ISA_MIPS32R2);
3927 gen_helper_mtc0_srsconf0(arg);
3928 rn = "SRSConf0";
3929 break;
3930 case 2:
3931 check_insn(env, ctx, ISA_MIPS32R2);
3932 gen_helper_mtc0_srsconf1(arg);
3933 rn = "SRSConf1";
3934 break;
3935 case 3:
3936 check_insn(env, ctx, ISA_MIPS32R2);
3937 gen_helper_mtc0_srsconf2(arg);
3938 rn = "SRSConf2";
3939 break;
3940 case 4:
3941 check_insn(env, ctx, ISA_MIPS32R2);
3942 gen_helper_mtc0_srsconf3(arg);
3943 rn = "SRSConf3";
3944 break;
3945 case 5:
3946 check_insn(env, ctx, ISA_MIPS32R2);
3947 gen_helper_mtc0_srsconf4(arg);
3948 rn = "SRSConf4";
3949 break;
3950 default:
3951 goto die;
3953 break;
3954 case 7:
3955 switch (sel) {
3956 case 0:
3957 check_insn(env, ctx, ISA_MIPS32R2);
3958 gen_helper_mtc0_hwrena(arg);
3959 rn = "HWREna";
3960 break;
3961 default:
3962 goto die;
3964 break;
3965 case 8:
3966 /* ignored */
3967 rn = "BadVAddr";
3968 break;
3969 case 9:
3970 switch (sel) {
3971 case 0:
3972 gen_helper_mtc0_count(arg);
3973 rn = "Count";
3974 break;
3975 /* 6,7 are implementation dependent */
3976 default:
3977 goto die;
3979 break;
3980 case 10:
3981 switch (sel) {
3982 case 0:
3983 gen_helper_mtc0_entryhi(arg);
3984 rn = "EntryHi";
3985 break;
3986 default:
3987 goto die;
3989 break;
3990 case 11:
3991 switch (sel) {
3992 case 0:
3993 gen_helper_mtc0_compare(arg);
3994 rn = "Compare";
3995 break;
3996 /* 6,7 are implementation dependent */
3997 default:
3998 goto die;
4000 break;
4001 case 12:
4002 switch (sel) {
4003 case 0:
4004 save_cpu_state(ctx, 1);
4005 gen_helper_mtc0_status(arg);
4006 /* BS_STOP isn't good enough here, hflags may have changed. */
4007 gen_save_pc(ctx->pc + 4);
4008 ctx->bstate = BS_EXCP;
4009 rn = "Status";
4010 break;
4011 case 1:
4012 check_insn(env, ctx, ISA_MIPS32R2);
4013 gen_helper_mtc0_intctl(arg);
4014 /* Stop translation as we may have switched the execution mode */
4015 ctx->bstate = BS_STOP;
4016 rn = "IntCtl";
4017 break;
4018 case 2:
4019 check_insn(env, ctx, ISA_MIPS32R2);
4020 gen_helper_mtc0_srsctl(arg);
4021 /* Stop translation as we may have switched the execution mode */
4022 ctx->bstate = BS_STOP;
4023 rn = "SRSCtl";
4024 break;
4025 case 3:
4026 check_insn(env, ctx, ISA_MIPS32R2);
4027 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4028 /* Stop translation as we may have switched the execution mode */
4029 ctx->bstate = BS_STOP;
4030 rn = "SRSMap";
4031 break;
4032 default:
4033 goto die;
4035 break;
4036 case 13:
4037 switch (sel) {
4038 case 0:
4039 save_cpu_state(ctx, 1);
4040 gen_helper_mtc0_cause(arg);
4041 rn = "Cause";
4042 break;
4043 default:
4044 goto die;
4046 break;
4047 case 14:
4048 switch (sel) {
4049 case 0:
4050 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_EPC));
4051 rn = "EPC";
4052 break;
4053 default:
4054 goto die;
4056 break;
4057 case 15:
4058 switch (sel) {
4059 case 0:
4060 /* ignored */
4061 rn = "PRid";
4062 break;
4063 case 1:
4064 check_insn(env, ctx, ISA_MIPS32R2);
4065 gen_helper_mtc0_ebase(arg);
4066 rn = "EBase";
4067 break;
4068 default:
4069 goto die;
4071 break;
4072 case 16:
4073 switch (sel) {
4074 case 0:
4075 gen_helper_mtc0_config0(arg);
4076 rn = "Config";
4077 /* Stop translation as we may have switched the execution mode */
4078 ctx->bstate = BS_STOP;
4079 break;
4080 case 1:
4081 /* ignored, read only */
4082 rn = "Config1";
4083 break;
4084 case 2:
4085 gen_helper_mtc0_config2(arg);
4086 rn = "Config2";
4087 /* Stop translation as we may have switched the execution mode */
4088 ctx->bstate = BS_STOP;
4089 break;
4090 case 3:
4091 /* ignored, read only */
4092 rn = "Config3";
4093 break;
4094 /* 4,5 are reserved */
4095 /* 6,7 are implementation dependent */
4096 case 6:
4097 /* ignored */
4098 rn = "Config6";
4099 break;
4100 case 7:
4101 /* ignored */
4102 rn = "Config7";
4103 break;
4104 default:
4105 rn = "Invalid config selector";
4106 goto die;
4108 break;
4109 case 17:
4110 switch (sel) {
4111 case 0:
4112 gen_helper_mtc0_lladdr(arg);
4113 rn = "LLAddr";
4114 break;
4115 default:
4116 goto die;
4118 break;
4119 case 18:
4120 switch (sel) {
4121 case 0 ... 7:
4122 gen_helper_1i(mtc0_watchlo, arg, sel);
4123 rn = "WatchLo";
4124 break;
4125 default:
4126 goto die;
4128 break;
4129 case 19:
4130 switch (sel) {
4131 case 0 ... 7:
4132 gen_helper_1i(mtc0_watchhi, arg, sel);
4133 rn = "WatchHi";
4134 break;
4135 default:
4136 goto die;
4138 break;
4139 case 20:
4140 switch (sel) {
4141 case 0:
4142 #if defined(TARGET_MIPS64)
4143 check_insn(env, ctx, ISA_MIPS3);
4144 gen_helper_mtc0_xcontext(arg);
4145 rn = "XContext";
4146 break;
4147 #endif
4148 default:
4149 goto die;
4151 break;
4152 case 21:
4153 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4154 switch (sel) {
4155 case 0:
4156 gen_helper_mtc0_framemask(arg);
4157 rn = "Framemask";
4158 break;
4159 default:
4160 goto die;
4162 break;
4163 case 22:
4164 /* ignored */
4165 rn = "Diagnostic"; /* implementation dependent */
4166 break;
4167 case 23:
4168 switch (sel) {
4169 case 0:
4170 gen_helper_mtc0_debug(arg); /* EJTAG support */
4171 /* BS_STOP isn't good enough here, hflags may have changed. */
4172 gen_save_pc(ctx->pc + 4);
4173 ctx->bstate = BS_EXCP;
4174 rn = "Debug";
4175 break;
4176 case 1:
4177 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
4178 rn = "TraceControl";
4179 /* Stop translation as we may have switched the execution mode */
4180 ctx->bstate = BS_STOP;
4181 // break;
4182 case 2:
4183 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
4184 rn = "TraceControl2";
4185 /* Stop translation as we may have switched the execution mode */
4186 ctx->bstate = BS_STOP;
4187 // break;
4188 case 3:
4189 /* Stop translation as we may have switched the execution mode */
4190 ctx->bstate = BS_STOP;
4191 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
4192 rn = "UserTraceData";
4193 /* Stop translation as we may have switched the execution mode */
4194 ctx->bstate = BS_STOP;
4195 // break;
4196 case 4:
4197 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
4198 /* Stop translation as we may have switched the execution mode */
4199 ctx->bstate = BS_STOP;
4200 rn = "TraceBPC";
4201 // break;
4202 default:
4203 goto die;
4205 break;
4206 case 24:
4207 switch (sel) {
4208 case 0:
4209 /* EJTAG support */
4210 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_DEPC));
4211 rn = "DEPC";
4212 break;
4213 default:
4214 goto die;
4216 break;
4217 case 25:
4218 switch (sel) {
4219 case 0:
4220 gen_helper_mtc0_performance0(arg);
4221 rn = "Performance0";
4222 break;
4223 case 1:
4224 // gen_helper_mtc0_performance1(arg);
4225 rn = "Performance1";
4226 // break;
4227 case 2:
4228 // gen_helper_mtc0_performance2(arg);
4229 rn = "Performance2";
4230 // break;
4231 case 3:
4232 // gen_helper_mtc0_performance3(arg);
4233 rn = "Performance3";
4234 // break;
4235 case 4:
4236 // gen_helper_mtc0_performance4(arg);
4237 rn = "Performance4";
4238 // break;
4239 case 5:
4240 // gen_helper_mtc0_performance5(arg);
4241 rn = "Performance5";
4242 // break;
4243 case 6:
4244 // gen_helper_mtc0_performance6(arg);
4245 rn = "Performance6";
4246 // break;
4247 case 7:
4248 // gen_helper_mtc0_performance7(arg);
4249 rn = "Performance7";
4250 // break;
4251 default:
4252 goto die;
4254 break;
4255 case 26:
4256 /* ignored */
4257 rn = "ECC";
4258 break;
4259 case 27:
4260 switch (sel) {
4261 case 0 ... 3:
4262 /* ignored */
4263 rn = "CacheErr";
4264 break;
4265 default:
4266 goto die;
4268 break;
4269 case 28:
4270 switch (sel) {
4271 case 0:
4272 case 2:
4273 case 4:
4274 case 6:
4275 gen_helper_mtc0_taglo(arg);
4276 rn = "TagLo";
4277 break;
4278 case 1:
4279 case 3:
4280 case 5:
4281 case 7:
4282 gen_helper_mtc0_datalo(arg);
4283 rn = "DataLo";
4284 break;
4285 default:
4286 goto die;
4288 break;
4289 case 29:
4290 switch (sel) {
4291 case 0:
4292 case 2:
4293 case 4:
4294 case 6:
4295 gen_helper_mtc0_taghi(arg);
4296 rn = "TagHi";
4297 break;
4298 case 1:
4299 case 3:
4300 case 5:
4301 case 7:
4302 gen_helper_mtc0_datahi(arg);
4303 rn = "DataHi";
4304 break;
4305 default:
4306 rn = "invalid sel";
4307 goto die;
4309 break;
4310 case 30:
4311 switch (sel) {
4312 case 0:
4313 gen_mtc0_store64(arg, offsetof(CPUMIPSState, CP0_ErrorEPC));
4314 rn = "ErrorEPC";
4315 break;
4316 default:
4317 goto die;
4319 break;
4320 case 31:
4321 switch (sel) {
4322 case 0:
4323 /* EJTAG support */
4324 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4325 rn = "DESAVE";
4326 break;
4327 default:
4328 goto die;
4330 /* Stop translation as we may have switched the execution mode */
4331 ctx->bstate = BS_STOP;
4332 break;
4333 default:
4334 goto die;
4336 (void)rn; /* avoid a compiler warning */
4337 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4338 /* For simplicity assume that all writes can cause interrupts. */
4339 if (use_icount) {
4340 gen_io_end();
4341 ctx->bstate = BS_STOP;
4343 return;
4345 die:
4346 LOG_DISAS("mtc0 %s (reg %d sel %d)\n", rn, reg, sel);
4347 generate_exception(ctx, EXCP_RI);
4350 #if defined(TARGET_MIPS64)
4351 static void gen_dmfc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4353 const char *rn = "invalid";
4355 if (sel != 0)
4356 check_insn(env, ctx, ISA_MIPS64);
4358 switch (reg) {
4359 case 0:
4360 switch (sel) {
4361 case 0:
4362 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Index));
4363 rn = "Index";
4364 break;
4365 case 1:
4366 check_insn(env, ctx, ASE_MT);
4367 gen_helper_mfc0_mvpcontrol(arg);
4368 rn = "MVPControl";
4369 break;
4370 case 2:
4371 check_insn(env, ctx, ASE_MT);
4372 gen_helper_mfc0_mvpconf0(arg);
4373 rn = "MVPConf0";
4374 break;
4375 case 3:
4376 check_insn(env, ctx, ASE_MT);
4377 gen_helper_mfc0_mvpconf1(arg);
4378 rn = "MVPConf1";
4379 break;
4380 default:
4381 goto die;
4383 break;
4384 case 1:
4385 switch (sel) {
4386 case 0:
4387 gen_helper_mfc0_random(arg);
4388 rn = "Random";
4389 break;
4390 case 1:
4391 check_insn(env, ctx, ASE_MT);
4392 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEControl));
4393 rn = "VPEControl";
4394 break;
4395 case 2:
4396 check_insn(env, ctx, ASE_MT);
4397 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf0));
4398 rn = "VPEConf0";
4399 break;
4400 case 3:
4401 check_insn(env, ctx, ASE_MT);
4402 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEConf1));
4403 rn = "VPEConf1";
4404 break;
4405 case 4:
4406 check_insn(env, ctx, ASE_MT);
4407 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_YQMask));
4408 rn = "YQMask";
4409 break;
4410 case 5:
4411 check_insn(env, ctx, ASE_MT);
4412 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
4413 rn = "VPESchedule";
4414 break;
4415 case 6:
4416 check_insn(env, ctx, ASE_MT);
4417 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4418 rn = "VPEScheFBack";
4419 break;
4420 case 7:
4421 check_insn(env, ctx, ASE_MT);
4422 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_VPEOpt));
4423 rn = "VPEOpt";
4424 break;
4425 default:
4426 goto die;
4428 break;
4429 case 2:
4430 switch (sel) {
4431 case 0:
4432 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo0));
4433 rn = "EntryLo0";
4434 break;
4435 case 1:
4436 check_insn(env, ctx, ASE_MT);
4437 gen_helper_mfc0_tcstatus(arg);
4438 rn = "TCStatus";
4439 break;
4440 case 2:
4441 check_insn(env, ctx, ASE_MT);
4442 gen_helper_mfc0_tcbind(arg);
4443 rn = "TCBind";
4444 break;
4445 case 3:
4446 check_insn(env, ctx, ASE_MT);
4447 gen_helper_dmfc0_tcrestart(arg);
4448 rn = "TCRestart";
4449 break;
4450 case 4:
4451 check_insn(env, ctx, ASE_MT);
4452 gen_helper_dmfc0_tchalt(arg);
4453 rn = "TCHalt";
4454 break;
4455 case 5:
4456 check_insn(env, ctx, ASE_MT);
4457 gen_helper_dmfc0_tccontext(arg);
4458 rn = "TCContext";
4459 break;
4460 case 6:
4461 check_insn(env, ctx, ASE_MT);
4462 gen_helper_dmfc0_tcschedule(arg);
4463 rn = "TCSchedule";
4464 break;
4465 case 7:
4466 check_insn(env, ctx, ASE_MT);
4467 gen_helper_dmfc0_tcschefback(arg);
4468 rn = "TCScheFBack";
4469 break;
4470 default:
4471 goto die;
4473 break;
4474 case 3:
4475 switch (sel) {
4476 case 0:
4477 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryLo1));
4478 rn = "EntryLo1";
4479 break;
4480 default:
4481 goto die;
4483 break;
4484 case 4:
4485 switch (sel) {
4486 case 0:
4487 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_Context));
4488 rn = "Context";
4489 break;
4490 case 1:
4491 // gen_helper_dmfc0_contextconfig(arg); /* SmartMIPS ASE */
4492 rn = "ContextConfig";
4493 // break;
4494 default:
4495 goto die;
4497 break;
4498 case 5:
4499 switch (sel) {
4500 case 0:
4501 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageMask));
4502 rn = "PageMask";
4503 break;
4504 case 1:
4505 check_insn(env, ctx, ISA_MIPS32R2);
4506 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PageGrain));
4507 rn = "PageGrain";
4508 break;
4509 default:
4510 goto die;
4512 break;
4513 case 6:
4514 switch (sel) {
4515 case 0:
4516 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Wired));
4517 rn = "Wired";
4518 break;
4519 case 1:
4520 check_insn(env, ctx, ISA_MIPS32R2);
4521 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf0));
4522 rn = "SRSConf0";
4523 break;
4524 case 2:
4525 check_insn(env, ctx, ISA_MIPS32R2);
4526 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf1));
4527 rn = "SRSConf1";
4528 break;
4529 case 3:
4530 check_insn(env, ctx, ISA_MIPS32R2);
4531 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf2));
4532 rn = "SRSConf2";
4533 break;
4534 case 4:
4535 check_insn(env, ctx, ISA_MIPS32R2);
4536 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf3));
4537 rn = "SRSConf3";
4538 break;
4539 case 5:
4540 check_insn(env, ctx, ISA_MIPS32R2);
4541 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSConf4));
4542 rn = "SRSConf4";
4543 break;
4544 default:
4545 goto die;
4547 break;
4548 case 7:
4549 switch (sel) {
4550 case 0:
4551 check_insn(env, ctx, ISA_MIPS32R2);
4552 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_HWREna));
4553 rn = "HWREna";
4554 break;
4555 default:
4556 goto die;
4558 break;
4559 case 8:
4560 switch (sel) {
4561 case 0:
4562 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_BadVAddr));
4563 rn = "BadVAddr";
4564 break;
4565 default:
4566 goto die;
4568 break;
4569 case 9:
4570 switch (sel) {
4571 case 0:
4572 /* Mark as an IO operation because we read the time. */
4573 if (use_icount)
4574 gen_io_start();
4575 gen_helper_mfc0_count(arg);
4576 if (use_icount) {
4577 gen_io_end();
4579 /* Break the TB to be able to take timer interrupts immediately
4580 after reading count. */
4581 ctx->bstate = BS_STOP;
4582 rn = "Count";
4583 break;
4584 /* 6,7 are implementation dependent */
4585 default:
4586 goto die;
4588 break;
4589 case 10:
4590 switch (sel) {
4591 case 0:
4592 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EntryHi));
4593 rn = "EntryHi";
4594 break;
4595 default:
4596 goto die;
4598 break;
4599 case 11:
4600 switch (sel) {
4601 case 0:
4602 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Compare));
4603 rn = "Compare";
4604 break;
4605 /* 6,7 are implementation dependent */
4606 default:
4607 goto die;
4609 break;
4610 case 12:
4611 switch (sel) {
4612 case 0:
4613 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Status));
4614 rn = "Status";
4615 break;
4616 case 1:
4617 check_insn(env, ctx, ISA_MIPS32R2);
4618 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_IntCtl));
4619 rn = "IntCtl";
4620 break;
4621 case 2:
4622 check_insn(env, ctx, ISA_MIPS32R2);
4623 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSCtl));
4624 rn = "SRSCtl";
4625 break;
4626 case 3:
4627 check_insn(env, ctx, ISA_MIPS32R2);
4628 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
4629 rn = "SRSMap";
4630 break;
4631 default:
4632 goto die;
4634 break;
4635 case 13:
4636 switch (sel) {
4637 case 0:
4638 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Cause));
4639 rn = "Cause";
4640 break;
4641 default:
4642 goto die;
4644 break;
4645 case 14:
4646 switch (sel) {
4647 case 0:
4648 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
4649 rn = "EPC";
4650 break;
4651 default:
4652 goto die;
4654 break;
4655 case 15:
4656 switch (sel) {
4657 case 0:
4658 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_PRid));
4659 rn = "PRid";
4660 break;
4661 case 1:
4662 check_insn(env, ctx, ISA_MIPS32R2);
4663 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_EBase));
4664 rn = "EBase";
4665 break;
4666 default:
4667 goto die;
4669 break;
4670 case 16:
4671 switch (sel) {
4672 case 0:
4673 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config0));
4674 rn = "Config";
4675 break;
4676 case 1:
4677 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config1));
4678 rn = "Config1";
4679 break;
4680 case 2:
4681 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config2));
4682 rn = "Config2";
4683 break;
4684 case 3:
4685 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config3));
4686 rn = "Config3";
4687 break;
4688 /* 6,7 are implementation dependent */
4689 case 6:
4690 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config6));
4691 rn = "Config6";
4692 break;
4693 case 7:
4694 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Config7));
4695 rn = "Config7";
4696 break;
4697 default:
4698 goto die;
4700 break;
4701 case 17:
4702 switch (sel) {
4703 case 0:
4704 gen_helper_dmfc0_lladdr(arg);
4705 rn = "LLAddr";
4706 break;
4707 default:
4708 goto die;
4710 break;
4711 case 18:
4712 switch (sel) {
4713 case 0 ... 7:
4714 gen_helper_1i(dmfc0_watchlo, arg, sel);
4715 rn = "WatchLo";
4716 break;
4717 default:
4718 goto die;
4720 break;
4721 case 19:
4722 switch (sel) {
4723 case 0 ... 7:
4724 gen_helper_1i(mfc0_watchhi, arg, sel);
4725 rn = "WatchHi";
4726 break;
4727 default:
4728 goto die;
4730 break;
4731 case 20:
4732 switch (sel) {
4733 case 0:
4734 check_insn(env, ctx, ISA_MIPS3);
4735 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_XContext));
4736 rn = "XContext";
4737 break;
4738 default:
4739 goto die;
4741 break;
4742 case 21:
4743 /* Officially reserved, but sel 0 is used for R1x000 framemask */
4744 switch (sel) {
4745 case 0:
4746 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Framemask));
4747 rn = "Framemask";
4748 break;
4749 default:
4750 goto die;
4752 break;
4753 case 22:
4754 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4755 rn = "'Diagnostic"; /* implementation dependent */
4756 break;
4757 case 23:
4758 switch (sel) {
4759 case 0:
4760 gen_helper_mfc0_debug(arg); /* EJTAG support */
4761 rn = "Debug";
4762 break;
4763 case 1:
4764 // gen_helper_dmfc0_tracecontrol(arg); /* PDtrace support */
4765 rn = "TraceControl";
4766 // break;
4767 case 2:
4768 // gen_helper_dmfc0_tracecontrol2(arg); /* PDtrace support */
4769 rn = "TraceControl2";
4770 // break;
4771 case 3:
4772 // gen_helper_dmfc0_usertracedata(arg); /* PDtrace support */
4773 rn = "UserTraceData";
4774 // break;
4775 case 4:
4776 // gen_helper_dmfc0_tracebpc(arg); /* PDtrace support */
4777 rn = "TraceBPC";
4778 // break;
4779 default:
4780 goto die;
4782 break;
4783 case 24:
4784 switch (sel) {
4785 case 0:
4786 /* EJTAG support */
4787 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
4788 rn = "DEPC";
4789 break;
4790 default:
4791 goto die;
4793 break;
4794 case 25:
4795 switch (sel) {
4796 case 0:
4797 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_Performance0));
4798 rn = "Performance0";
4799 break;
4800 case 1:
4801 // gen_helper_dmfc0_performance1(arg);
4802 rn = "Performance1";
4803 // break;
4804 case 2:
4805 // gen_helper_dmfc0_performance2(arg);
4806 rn = "Performance2";
4807 // break;
4808 case 3:
4809 // gen_helper_dmfc0_performance3(arg);
4810 rn = "Performance3";
4811 // break;
4812 case 4:
4813 // gen_helper_dmfc0_performance4(arg);
4814 rn = "Performance4";
4815 // break;
4816 case 5:
4817 // gen_helper_dmfc0_performance5(arg);
4818 rn = "Performance5";
4819 // break;
4820 case 6:
4821 // gen_helper_dmfc0_performance6(arg);
4822 rn = "Performance6";
4823 // break;
4824 case 7:
4825 // gen_helper_dmfc0_performance7(arg);
4826 rn = "Performance7";
4827 // break;
4828 default:
4829 goto die;
4831 break;
4832 case 26:
4833 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4834 rn = "ECC";
4835 break;
4836 case 27:
4837 switch (sel) {
4838 /* ignored */
4839 case 0 ... 3:
4840 tcg_gen_movi_tl(arg, 0); /* unimplemented */
4841 rn = "CacheErr";
4842 break;
4843 default:
4844 goto die;
4846 break;
4847 case 28:
4848 switch (sel) {
4849 case 0:
4850 case 2:
4851 case 4:
4852 case 6:
4853 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagLo));
4854 rn = "TagLo";
4855 break;
4856 case 1:
4857 case 3:
4858 case 5:
4859 case 7:
4860 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataLo));
4861 rn = "DataLo";
4862 break;
4863 default:
4864 goto die;
4866 break;
4867 case 29:
4868 switch (sel) {
4869 case 0:
4870 case 2:
4871 case 4:
4872 case 6:
4873 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_TagHi));
4874 rn = "TagHi";
4875 break;
4876 case 1:
4877 case 3:
4878 case 5:
4879 case 7:
4880 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DataHi));
4881 rn = "DataHi";
4882 break;
4883 default:
4884 goto die;
4886 break;
4887 case 30:
4888 switch (sel) {
4889 case 0:
4890 tcg_gen_ld_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
4891 rn = "ErrorEPC";
4892 break;
4893 default:
4894 goto die;
4896 break;
4897 case 31:
4898 switch (sel) {
4899 case 0:
4900 /* EJTAG support */
4901 gen_mfc0_load32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
4902 rn = "DESAVE";
4903 break;
4904 default:
4905 goto die;
4907 break;
4908 default:
4909 goto die;
4911 (void)rn; /* avoid a compiler warning */
4912 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4913 return;
4915 die:
4916 LOG_DISAS("dmfc0 %s (reg %d sel %d)\n", rn, reg, sel);
4917 generate_exception(ctx, EXCP_RI);
4920 static void gen_dmtc0 (CPUMIPSState *env, DisasContext *ctx, TCGv arg, int reg, int sel)
4922 const char *rn = "invalid";
4924 if (sel != 0)
4925 check_insn(env, ctx, ISA_MIPS64);
4927 if (use_icount)
4928 gen_io_start();
4930 switch (reg) {
4931 case 0:
4932 switch (sel) {
4933 case 0:
4934 gen_helper_mtc0_index(arg);
4935 rn = "Index";
4936 break;
4937 case 1:
4938 check_insn(env, ctx, ASE_MT);
4939 gen_helper_mtc0_mvpcontrol(arg);
4940 rn = "MVPControl";
4941 break;
4942 case 2:
4943 check_insn(env, ctx, ASE_MT);
4944 /* ignored */
4945 rn = "MVPConf0";
4946 break;
4947 case 3:
4948 check_insn(env, ctx, ASE_MT);
4949 /* ignored */
4950 rn = "MVPConf1";
4951 break;
4952 default:
4953 goto die;
4955 break;
4956 case 1:
4957 switch (sel) {
4958 case 0:
4959 /* ignored */
4960 rn = "Random";
4961 break;
4962 case 1:
4963 check_insn(env, ctx, ASE_MT);
4964 gen_helper_mtc0_vpecontrol(arg);
4965 rn = "VPEControl";
4966 break;
4967 case 2:
4968 check_insn(env, ctx, ASE_MT);
4969 gen_helper_mtc0_vpeconf0(arg);
4970 rn = "VPEConf0";
4971 break;
4972 case 3:
4973 check_insn(env, ctx, ASE_MT);
4974 gen_helper_mtc0_vpeconf1(arg);
4975 rn = "VPEConf1";
4976 break;
4977 case 4:
4978 check_insn(env, ctx, ASE_MT);
4979 gen_helper_mtc0_yqmask(arg);
4980 rn = "YQMask";
4981 break;
4982 case 5:
4983 check_insn(env, ctx, ASE_MT);
4984 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPESchedule));
4985 rn = "VPESchedule";
4986 break;
4987 case 6:
4988 check_insn(env, ctx, ASE_MT);
4989 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_VPEScheFBack));
4990 rn = "VPEScheFBack";
4991 break;
4992 case 7:
4993 check_insn(env, ctx, ASE_MT);
4994 gen_helper_mtc0_vpeopt(arg);
4995 rn = "VPEOpt";
4996 break;
4997 default:
4998 goto die;
5000 break;
5001 case 2:
5002 switch (sel) {
5003 case 0:
5004 gen_helper_mtc0_entrylo0(arg);
5005 rn = "EntryLo0";
5006 break;
5007 case 1:
5008 check_insn(env, ctx, ASE_MT);
5009 gen_helper_mtc0_tcstatus(arg);
5010 rn = "TCStatus";
5011 break;
5012 case 2:
5013 check_insn(env, ctx, ASE_MT);
5014 gen_helper_mtc0_tcbind(arg);
5015 rn = "TCBind";
5016 break;
5017 case 3:
5018 check_insn(env, ctx, ASE_MT);
5019 gen_helper_mtc0_tcrestart(arg);
5020 rn = "TCRestart";
5021 break;
5022 case 4:
5023 check_insn(env, ctx, ASE_MT);
5024 gen_helper_mtc0_tchalt(arg);
5025 rn = "TCHalt";
5026 break;
5027 case 5:
5028 check_insn(env, ctx, ASE_MT);
5029 gen_helper_mtc0_tccontext(arg);
5030 rn = "TCContext";
5031 break;
5032 case 6:
5033 check_insn(env, ctx, ASE_MT);
5034 gen_helper_mtc0_tcschedule(arg);
5035 rn = "TCSchedule";
5036 break;
5037 case 7:
5038 check_insn(env, ctx, ASE_MT);
5039 gen_helper_mtc0_tcschefback(arg);
5040 rn = "TCScheFBack";
5041 break;
5042 default:
5043 goto die;
5045 break;
5046 case 3:
5047 switch (sel) {
5048 case 0:
5049 gen_helper_mtc0_entrylo1(arg);
5050 rn = "EntryLo1";
5051 break;
5052 default:
5053 goto die;
5055 break;
5056 case 4:
5057 switch (sel) {
5058 case 0:
5059 gen_helper_mtc0_context(arg);
5060 rn = "Context";
5061 break;
5062 case 1:
5063 // gen_helper_mtc0_contextconfig(arg); /* SmartMIPS ASE */
5064 rn = "ContextConfig";
5065 // break;
5066 default:
5067 goto die;
5069 break;
5070 case 5:
5071 switch (sel) {
5072 case 0:
5073 gen_helper_mtc0_pagemask(arg);
5074 rn = "PageMask";
5075 break;
5076 case 1:
5077 check_insn(env, ctx, ISA_MIPS32R2);
5078 gen_helper_mtc0_pagegrain(arg);
5079 rn = "PageGrain";
5080 break;
5081 default:
5082 goto die;
5084 break;
5085 case 6:
5086 switch (sel) {
5087 case 0:
5088 gen_helper_mtc0_wired(arg);
5089 rn = "Wired";
5090 break;
5091 case 1:
5092 check_insn(env, ctx, ISA_MIPS32R2);
5093 gen_helper_mtc0_srsconf0(arg);
5094 rn = "SRSConf0";
5095 break;
5096 case 2:
5097 check_insn(env, ctx, ISA_MIPS32R2);
5098 gen_helper_mtc0_srsconf1(arg);
5099 rn = "SRSConf1";
5100 break;
5101 case 3:
5102 check_insn(env, ctx, ISA_MIPS32R2);
5103 gen_helper_mtc0_srsconf2(arg);
5104 rn = "SRSConf2";
5105 break;
5106 case 4:
5107 check_insn(env, ctx, ISA_MIPS32R2);
5108 gen_helper_mtc0_srsconf3(arg);
5109 rn = "SRSConf3";
5110 break;
5111 case 5:
5112 check_insn(env, ctx, ISA_MIPS32R2);
5113 gen_helper_mtc0_srsconf4(arg);
5114 rn = "SRSConf4";
5115 break;
5116 default:
5117 goto die;
5119 break;
5120 case 7:
5121 switch (sel) {
5122 case 0:
5123 check_insn(env, ctx, ISA_MIPS32R2);
5124 gen_helper_mtc0_hwrena(arg);
5125 rn = "HWREna";
5126 break;
5127 default:
5128 goto die;
5130 break;
5131 case 8:
5132 /* ignored */
5133 rn = "BadVAddr";
5134 break;
5135 case 9:
5136 switch (sel) {
5137 case 0:
5138 gen_helper_mtc0_count(arg);
5139 rn = "Count";
5140 break;
5141 /* 6,7 are implementation dependent */
5142 default:
5143 goto die;
5145 /* Stop translation as we may have switched the execution mode */
5146 ctx->bstate = BS_STOP;
5147 break;
5148 case 10:
5149 switch (sel) {
5150 case 0:
5151 gen_helper_mtc0_entryhi(arg);
5152 rn = "EntryHi";
5153 break;
5154 default:
5155 goto die;
5157 break;
5158 case 11:
5159 switch (sel) {
5160 case 0:
5161 gen_helper_mtc0_compare(arg);
5162 rn = "Compare";
5163 break;
5164 /* 6,7 are implementation dependent */
5165 default:
5166 goto die;
5168 /* Stop translation as we may have switched the execution mode */
5169 ctx->bstate = BS_STOP;
5170 break;
5171 case 12:
5172 switch (sel) {
5173 case 0:
5174 save_cpu_state(ctx, 1);
5175 gen_helper_mtc0_status(arg);
5176 /* BS_STOP isn't good enough here, hflags may have changed. */
5177 gen_save_pc(ctx->pc + 4);
5178 ctx->bstate = BS_EXCP;
5179 rn = "Status";
5180 break;
5181 case 1:
5182 check_insn(env, ctx, ISA_MIPS32R2);
5183 gen_helper_mtc0_intctl(arg);
5184 /* Stop translation as we may have switched the execution mode */
5185 ctx->bstate = BS_STOP;
5186 rn = "IntCtl";
5187 break;
5188 case 2:
5189 check_insn(env, ctx, ISA_MIPS32R2);
5190 gen_helper_mtc0_srsctl(arg);
5191 /* Stop translation as we may have switched the execution mode */
5192 ctx->bstate = BS_STOP;
5193 rn = "SRSCtl";
5194 break;
5195 case 3:
5196 check_insn(env, ctx, ISA_MIPS32R2);
5197 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_SRSMap));
5198 /* Stop translation as we may have switched the execution mode */
5199 ctx->bstate = BS_STOP;
5200 rn = "SRSMap";
5201 break;
5202 default:
5203 goto die;
5205 break;
5206 case 13:
5207 switch (sel) {
5208 case 0:
5209 save_cpu_state(ctx, 1);
5210 /* Mark as an IO operation because we may trigger a software
5211 interrupt. */
5212 if (use_icount) {
5213 gen_io_start();
5215 gen_helper_mtc0_cause(arg);
5216 if (use_icount) {
5217 gen_io_end();
5219 /* Stop translation as we may have triggered an intetrupt */
5220 ctx->bstate = BS_STOP;
5221 rn = "Cause";
5222 break;
5223 default:
5224 goto die;
5226 break;
5227 case 14:
5228 switch (sel) {
5229 case 0:
5230 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_EPC));
5231 rn = "EPC";
5232 break;
5233 default:
5234 goto die;
5236 break;
5237 case 15:
5238 switch (sel) {
5239 case 0:
5240 /* ignored */
5241 rn = "PRid";
5242 break;
5243 case 1:
5244 check_insn(env, ctx, ISA_MIPS32R2);
5245 gen_helper_mtc0_ebase(arg);
5246 rn = "EBase";
5247 break;
5248 default:
5249 goto die;
5251 break;
5252 case 16:
5253 switch (sel) {
5254 case 0:
5255 gen_helper_mtc0_config0(arg);
5256 rn = "Config";
5257 /* Stop translation as we may have switched the execution mode */
5258 ctx->bstate = BS_STOP;
5259 break;
5260 case 1:
5261 /* ignored, read only */
5262 rn = "Config1";
5263 break;
5264 case 2:
5265 gen_helper_mtc0_config2(arg);
5266 rn = "Config2";
5267 /* Stop translation as we may have switched the execution mode */
5268 ctx->bstate = BS_STOP;
5269 break;
5270 case 3:
5271 /* ignored */
5272 rn = "Config3";
5273 break;
5274 /* 6,7 are implementation dependent */
5275 default:
5276 rn = "Invalid config selector";
5277 goto die;
5279 break;
5280 case 17:
5281 switch (sel) {
5282 case 0:
5283 gen_helper_mtc0_lladdr(arg);
5284 rn = "LLAddr";
5285 break;
5286 default:
5287 goto die;
5289 break;
5290 case 18:
5291 switch (sel) {
5292 case 0 ... 7:
5293 gen_helper_1i(mtc0_watchlo, arg, sel);
5294 rn = "WatchLo";
5295 break;
5296 default:
5297 goto die;
5299 break;
5300 case 19:
5301 switch (sel) {
5302 case 0 ... 7:
5303 gen_helper_1i(mtc0_watchhi, arg, sel);
5304 rn = "WatchHi";
5305 break;
5306 default:
5307 goto die;
5309 break;
5310 case 20:
5311 switch (sel) {
5312 case 0:
5313 check_insn(env, ctx, ISA_MIPS3);
5314 gen_helper_mtc0_xcontext(arg);
5315 rn = "XContext";
5316 break;
5317 default:
5318 goto die;
5320 break;
5321 case 21:
5322 /* Officially reserved, but sel 0 is used for R1x000 framemask */
5323 switch (sel) {
5324 case 0:
5325 gen_helper_mtc0_framemask(arg);
5326 rn = "Framemask";
5327 break;
5328 default:
5329 goto die;
5331 break;
5332 case 22:
5333 /* ignored */
5334 rn = "Diagnostic"; /* implementation dependent */
5335 break;
5336 case 23:
5337 switch (sel) {
5338 case 0:
5339 gen_helper_mtc0_debug(arg); /* EJTAG support */
5340 /* BS_STOP isn't good enough here, hflags may have changed. */
5341 gen_save_pc(ctx->pc + 4);
5342 ctx->bstate = BS_EXCP;
5343 rn = "Debug";
5344 break;
5345 case 1:
5346 // gen_helper_mtc0_tracecontrol(arg); /* PDtrace support */
5347 /* Stop translation as we may have switched the execution mode */
5348 ctx->bstate = BS_STOP;
5349 rn = "TraceControl";
5350 // break;
5351 case 2:
5352 // gen_helper_mtc0_tracecontrol2(arg); /* PDtrace support */
5353 /* Stop translation as we may have switched the execution mode */
5354 ctx->bstate = BS_STOP;
5355 rn = "TraceControl2";
5356 // break;
5357 case 3:
5358 // gen_helper_mtc0_usertracedata(arg); /* PDtrace support */
5359 /* Stop translation as we may have switched the execution mode */
5360 ctx->bstate = BS_STOP;
5361 rn = "UserTraceData";
5362 // break;
5363 case 4:
5364 // gen_helper_mtc0_tracebpc(arg); /* PDtrace support */
5365 /* Stop translation as we may have switched the execution mode */
5366 ctx->bstate = BS_STOP;
5367 rn = "TraceBPC";
5368 // break;
5369 default:
5370 goto die;
5372 break;
5373 case 24:
5374 switch (sel) {
5375 case 0:
5376 /* EJTAG support */
5377 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_DEPC));
5378 rn = "DEPC";
5379 break;
5380 default:
5381 goto die;
5383 break;
5384 case 25:
5385 switch (sel) {
5386 case 0:
5387 gen_helper_mtc0_performance0(arg);
5388 rn = "Performance0";
5389 break;
5390 case 1:
5391 // gen_helper_mtc0_performance1(arg);
5392 rn = "Performance1";
5393 // break;
5394 case 2:
5395 // gen_helper_mtc0_performance2(arg);
5396 rn = "Performance2";
5397 // break;
5398 case 3:
5399 // gen_helper_mtc0_performance3(arg);
5400 rn = "Performance3";
5401 // break;
5402 case 4:
5403 // gen_helper_mtc0_performance4(arg);
5404 rn = "Performance4";
5405 // break;
5406 case 5:
5407 // gen_helper_mtc0_performance5(arg);
5408 rn = "Performance5";
5409 // break;
5410 case 6:
5411 // gen_helper_mtc0_performance6(arg);
5412 rn = "Performance6";
5413 // break;
5414 case 7:
5415 // gen_helper_mtc0_performance7(arg);
5416 rn = "Performance7";
5417 // break;
5418 default:
5419 goto die;
5421 break;
5422 case 26:
5423 /* ignored */
5424 rn = "ECC";
5425 break;
5426 case 27:
5427 switch (sel) {
5428 case 0 ... 3:
5429 /* ignored */
5430 rn = "CacheErr";
5431 break;
5432 default:
5433 goto die;
5435 break;
5436 case 28:
5437 switch (sel) {
5438 case 0:
5439 case 2:
5440 case 4:
5441 case 6:
5442 gen_helper_mtc0_taglo(arg);
5443 rn = "TagLo";
5444 break;
5445 case 1:
5446 case 3:
5447 case 5:
5448 case 7:
5449 gen_helper_mtc0_datalo(arg);
5450 rn = "DataLo";
5451 break;
5452 default:
5453 goto die;
5455 break;
5456 case 29:
5457 switch (sel) {
5458 case 0:
5459 case 2:
5460 case 4:
5461 case 6:
5462 gen_helper_mtc0_taghi(arg);
5463 rn = "TagHi";
5464 break;
5465 case 1:
5466 case 3:
5467 case 5:
5468 case 7:
5469 gen_helper_mtc0_datahi(arg);
5470 rn = "DataHi";
5471 break;
5472 default:
5473 rn = "invalid sel";
5474 goto die;
5476 break;
5477 case 30:
5478 switch (sel) {
5479 case 0:
5480 tcg_gen_st_tl(arg, cpu_env, offsetof(CPUMIPSState, CP0_ErrorEPC));
5481 rn = "ErrorEPC";
5482 break;
5483 default:
5484 goto die;
5486 break;
5487 case 31:
5488 switch (sel) {
5489 case 0:
5490 /* EJTAG support */
5491 gen_mtc0_store32(arg, offsetof(CPUMIPSState, CP0_DESAVE));
5492 rn = "DESAVE";
5493 break;
5494 default:
5495 goto die;
5497 /* Stop translation as we may have switched the execution mode */
5498 ctx->bstate = BS_STOP;
5499 break;
5500 default:
5501 goto die;
5503 (void)rn; /* avoid a compiler warning */
5504 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5505 /* For simplicity assume that all writes can cause interrupts. */
5506 if (use_icount) {
5507 gen_io_end();
5508 ctx->bstate = BS_STOP;
5510 return;
5512 die:
5513 LOG_DISAS("dmtc0 %s (reg %d sel %d)\n", rn, reg, sel);
5514 generate_exception(ctx, EXCP_RI);
5516 #endif /* TARGET_MIPS64 */
5518 static void gen_mftr(CPUMIPSState *env, DisasContext *ctx, int rt, int rd,
5519 int u, int sel, int h)
5521 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5522 TCGv t0 = tcg_temp_local_new();
5524 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5525 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5526 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5527 tcg_gen_movi_tl(t0, -1);
5528 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5529 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5530 tcg_gen_movi_tl(t0, -1);
5531 else if (u == 0) {
5532 switch (rt) {
5533 case 1:
5534 switch (sel) {
5535 case 1:
5536 gen_helper_mftc0_vpecontrol(t0);
5537 break;
5538 case 2:
5539 gen_helper_mftc0_vpeconf0(t0);
5540 break;
5541 default:
5542 goto die;
5543 break;
5545 break;
5546 case 2:
5547 switch (sel) {
5548 case 1:
5549 gen_helper_mftc0_tcstatus(t0);
5550 break;
5551 case 2:
5552 gen_helper_mftc0_tcbind(t0);
5553 break;
5554 case 3:
5555 gen_helper_mftc0_tcrestart(t0);
5556 break;
5557 case 4:
5558 gen_helper_mftc0_tchalt(t0);
5559 break;
5560 case 5:
5561 gen_helper_mftc0_tccontext(t0);
5562 break;
5563 case 6:
5564 gen_helper_mftc0_tcschedule(t0);
5565 break;
5566 case 7:
5567 gen_helper_mftc0_tcschefback(t0);
5568 break;
5569 default:
5570 gen_mfc0(env, ctx, t0, rt, sel);
5571 break;
5573 break;
5574 case 10:
5575 switch (sel) {
5576 case 0:
5577 gen_helper_mftc0_entryhi(t0);
5578 break;
5579 default:
5580 gen_mfc0(env, ctx, t0, rt, sel);
5581 break;
5583 case 12:
5584 switch (sel) {
5585 case 0:
5586 gen_helper_mftc0_status(t0);
5587 break;
5588 default:
5589 gen_mfc0(env, ctx, t0, rt, sel);
5590 break;
5592 case 13:
5593 switch (sel) {
5594 case 0:
5595 gen_helper_mftc0_cause(t0);
5596 break;
5597 default:
5598 goto die;
5599 break;
5601 break;
5602 case 14:
5603 switch (sel) {
5604 case 0:
5605 gen_helper_mftc0_epc(t0);
5606 break;
5607 default:
5608 goto die;
5609 break;
5611 break;
5612 case 15:
5613 switch (sel) {
5614 case 1:
5615 gen_helper_mftc0_ebase(t0);
5616 break;
5617 default:
5618 goto die;
5619 break;
5621 break;
5622 case 16:
5623 switch (sel) {
5624 case 0 ... 7:
5625 gen_helper_mftc0_configx(t0, tcg_const_tl(sel));
5626 break;
5627 default:
5628 goto die;
5629 break;
5631 break;
5632 case 23:
5633 switch (sel) {
5634 case 0:
5635 gen_helper_mftc0_debug(t0);
5636 break;
5637 default:
5638 gen_mfc0(env, ctx, t0, rt, sel);
5639 break;
5641 break;
5642 default:
5643 gen_mfc0(env, ctx, t0, rt, sel);
5645 } else switch (sel) {
5646 /* GPR registers. */
5647 case 0:
5648 gen_helper_1i(mftgpr, t0, rt);
5649 break;
5650 /* Auxiliary CPU registers */
5651 case 1:
5652 switch (rt) {
5653 case 0:
5654 gen_helper_1i(mftlo, t0, 0);
5655 break;
5656 case 1:
5657 gen_helper_1i(mfthi, t0, 0);
5658 break;
5659 case 2:
5660 gen_helper_1i(mftacx, t0, 0);
5661 break;
5662 case 4:
5663 gen_helper_1i(mftlo, t0, 1);
5664 break;
5665 case 5:
5666 gen_helper_1i(mfthi, t0, 1);
5667 break;
5668 case 6:
5669 gen_helper_1i(mftacx, t0, 1);
5670 break;
5671 case 8:
5672 gen_helper_1i(mftlo, t0, 2);
5673 break;
5674 case 9:
5675 gen_helper_1i(mfthi, t0, 2);
5676 break;
5677 case 10:
5678 gen_helper_1i(mftacx, t0, 2);
5679 break;
5680 case 12:
5681 gen_helper_1i(mftlo, t0, 3);
5682 break;
5683 case 13:
5684 gen_helper_1i(mfthi, t0, 3);
5685 break;
5686 case 14:
5687 gen_helper_1i(mftacx, t0, 3);
5688 break;
5689 case 16:
5690 gen_helper_mftdsp(t0);
5691 break;
5692 default:
5693 goto die;
5695 break;
5696 /* Floating point (COP1). */
5697 case 2:
5698 /* XXX: For now we support only a single FPU context. */
5699 if (h == 0) {
5700 TCGv_i32 fp0 = tcg_temp_new_i32();
5702 gen_load_fpr32(fp0, rt);
5703 tcg_gen_ext_i32_tl(t0, fp0);
5704 tcg_temp_free_i32(fp0);
5705 } else {
5706 TCGv_i32 fp0 = tcg_temp_new_i32();
5708 gen_load_fpr32h(fp0, rt);
5709 tcg_gen_ext_i32_tl(t0, fp0);
5710 tcg_temp_free_i32(fp0);
5712 break;
5713 case 3:
5714 /* XXX: For now we support only a single FPU context. */
5715 gen_helper_1i(cfc1, t0, rt);
5716 break;
5717 /* COP2: Not implemented. */
5718 case 4:
5719 case 5:
5720 /* fall through */
5721 default:
5722 goto die;
5724 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5725 gen_store_gpr(t0, rd);
5726 tcg_temp_free(t0);
5727 return;
5729 die:
5730 tcg_temp_free(t0);
5731 LOG_DISAS("mftr (reg %d u %d sel %d h %d)\n", rt, u, sel, h);
5732 generate_exception(ctx, EXCP_RI);
5735 static void gen_mttr(CPUMIPSState *env, DisasContext *ctx, int rd, int rt,
5736 int u, int sel, int h)
5738 int other_tc = env->CP0_VPEControl & (0xff << CP0VPECo_TargTC);
5739 TCGv t0 = tcg_temp_local_new();
5741 gen_load_gpr(t0, rt);
5742 if ((env->CP0_VPEConf0 & (1 << CP0VPEC0_MVP)) == 0 &&
5743 ((env->tcs[other_tc].CP0_TCBind & (0xf << CP0TCBd_CurVPE)) !=
5744 (env->active_tc.CP0_TCBind & (0xf << CP0TCBd_CurVPE))))
5745 /* NOP */ ;
5746 else if ((env->CP0_VPEControl & (0xff << CP0VPECo_TargTC)) >
5747 (env->mvp->CP0_MVPConf0 & (0xff << CP0MVPC0_PTC)))
5748 /* NOP */ ;
5749 else if (u == 0) {
5750 switch (rd) {
5751 case 1:
5752 switch (sel) {
5753 case 1:
5754 gen_helper_mttc0_vpecontrol(t0);
5755 break;
5756 case 2:
5757 gen_helper_mttc0_vpeconf0(t0);
5758 break;
5759 default:
5760 goto die;
5761 break;
5763 break;
5764 case 2:
5765 switch (sel) {
5766 case 1:
5767 gen_helper_mttc0_tcstatus(t0);
5768 break;
5769 case 2:
5770 gen_helper_mttc0_tcbind(t0);
5771 break;
5772 case 3:
5773 gen_helper_mttc0_tcrestart(t0);
5774 break;
5775 case 4:
5776 gen_helper_mttc0_tchalt(t0);
5777 break;
5778 case 5:
5779 gen_helper_mttc0_tccontext(t0);
5780 break;
5781 case 6:
5782 gen_helper_mttc0_tcschedule(t0);
5783 break;
5784 case 7:
5785 gen_helper_mttc0_tcschefback(t0);
5786 break;
5787 default:
5788 gen_mtc0(env, ctx, t0, rd, sel);
5789 break;
5791 break;
5792 case 10:
5793 switch (sel) {
5794 case 0:
5795 gen_helper_mttc0_entryhi(t0);
5796 break;
5797 default:
5798 gen_mtc0(env, ctx, t0, rd, sel);
5799 break;
5801 case 12:
5802 switch (sel) {
5803 case 0:
5804 gen_helper_mttc0_status(t0);
5805 break;
5806 default:
5807 gen_mtc0(env, ctx, t0, rd, sel);
5808 break;
5810 case 13:
5811 switch (sel) {
5812 case 0:
5813 gen_helper_mttc0_cause(t0);
5814 break;
5815 default:
5816 goto die;
5817 break;
5819 break;
5820 case 15:
5821 switch (sel) {
5822 case 1:
5823 gen_helper_mttc0_ebase(t0);
5824 break;
5825 default:
5826 goto die;
5827 break;
5829 break;
5830 case 23:
5831 switch (sel) {
5832 case 0:
5833 gen_helper_mttc0_debug(t0);
5834 break;
5835 default:
5836 gen_mtc0(env, ctx, t0, rd, sel);
5837 break;
5839 break;
5840 default:
5841 gen_mtc0(env, ctx, t0, rd, sel);
5843 } else switch (sel) {
5844 /* GPR registers. */
5845 case 0:
5846 gen_helper_1i(mttgpr, t0, rd);
5847 break;
5848 /* Auxiliary CPU registers */
5849 case 1:
5850 switch (rd) {
5851 case 0:
5852 gen_helper_1i(mttlo, t0, 0);
5853 break;
5854 case 1:
5855 gen_helper_1i(mtthi, t0, 0);
5856 break;
5857 case 2:
5858 gen_helper_1i(mttacx, t0, 0);
5859 break;
5860 case 4:
5861 gen_helper_1i(mttlo, t0, 1);
5862 break;
5863 case 5:
5864 gen_helper_1i(mtthi, t0, 1);
5865 break;
5866 case 6:
5867 gen_helper_1i(mttacx, t0, 1);
5868 break;
5869 case 8:
5870 gen_helper_1i(mttlo, t0, 2);
5871 break;
5872 case 9:
5873 gen_helper_1i(mtthi, t0, 2);
5874 break;
5875 case 10:
5876 gen_helper_1i(mttacx, t0, 2);
5877 break;
5878 case 12:
5879 gen_helper_1i(mttlo, t0, 3);
5880 break;
5881 case 13:
5882 gen_helper_1i(mtthi, t0, 3);
5883 break;
5884 case 14:
5885 gen_helper_1i(mttacx, t0, 3);
5886 break;
5887 case 16:
5888 gen_helper_mttdsp(t0);
5889 break;
5890 default:
5891 goto die;
5893 break;
5894 /* Floating point (COP1). */
5895 case 2:
5896 /* XXX: For now we support only a single FPU context. */
5897 if (h == 0) {
5898 TCGv_i32 fp0 = tcg_temp_new_i32();
5900 tcg_gen_trunc_tl_i32(fp0, t0);
5901 gen_store_fpr32(fp0, rd);
5902 tcg_temp_free_i32(fp0);
5903 } else {
5904 TCGv_i32 fp0 = tcg_temp_new_i32();
5906 tcg_gen_trunc_tl_i32(fp0, t0);
5907 gen_store_fpr32h(fp0, rd);
5908 tcg_temp_free_i32(fp0);
5910 break;
5911 case 3:
5912 /* XXX: For now we support only a single FPU context. */
5913 gen_helper_1i(ctc1, t0, rd);
5914 break;
5915 /* COP2: Not implemented. */
5916 case 4:
5917 case 5:
5918 /* fall through */
5919 default:
5920 goto die;
5922 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5923 tcg_temp_free(t0);
5924 return;
5926 die:
5927 tcg_temp_free(t0);
5928 LOG_DISAS("mttr (reg %d u %d sel %d h %d)\n", rd, u, sel, h);
5929 generate_exception(ctx, EXCP_RI);
5932 static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt, int rd)
5934 const char *opn = "ldst";
5936 switch (opc) {
5937 case OPC_MFC0:
5938 if (rt == 0) {
5939 /* Treat as NOP. */
5940 return;
5942 gen_mfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5943 opn = "mfc0";
5944 break;
5945 case OPC_MTC0:
5947 TCGv t0 = tcg_temp_new();
5949 gen_load_gpr(t0, rt);
5950 gen_mtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5951 tcg_temp_free(t0);
5953 opn = "mtc0";
5954 break;
5955 #if defined(TARGET_MIPS64)
5956 case OPC_DMFC0:
5957 check_insn(env, ctx, ISA_MIPS3);
5958 if (rt == 0) {
5959 /* Treat as NOP. */
5960 return;
5962 gen_dmfc0(env, ctx, cpu_gpr[rt], rd, ctx->opcode & 0x7);
5963 opn = "dmfc0";
5964 break;
5965 case OPC_DMTC0:
5966 check_insn(env, ctx, ISA_MIPS3);
5968 TCGv t0 = tcg_temp_new();
5970 gen_load_gpr(t0, rt);
5971 gen_dmtc0(env, ctx, t0, rd, ctx->opcode & 0x7);
5972 tcg_temp_free(t0);
5974 opn = "dmtc0";
5975 break;
5976 #endif
5977 case OPC_MFTR:
5978 check_insn(env, ctx, ASE_MT);
5979 if (rd == 0) {
5980 /* Treat as NOP. */
5981 return;
5983 gen_mftr(env, ctx, rt, rd, (ctx->opcode >> 5) & 1,
5984 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5985 opn = "mftr";
5986 break;
5987 case OPC_MTTR:
5988 check_insn(env, ctx, ASE_MT);
5989 gen_mttr(env, ctx, rd, rt, (ctx->opcode >> 5) & 1,
5990 ctx->opcode & 0x7, (ctx->opcode >> 4) & 1);
5991 opn = "mttr";
5992 break;
5993 case OPC_TLBWI:
5994 opn = "tlbwi";
5995 if (!env->tlb->helper_tlbwi)
5996 goto die;
5997 gen_helper_tlbwi();
5998 break;
5999 case OPC_TLBWR:
6000 opn = "tlbwr";
6001 if (!env->tlb->helper_tlbwr)
6002 goto die;
6003 gen_helper_tlbwr();
6004 break;
6005 case OPC_TLBP:
6006 opn = "tlbp";
6007 if (!env->tlb->helper_tlbp)
6008 goto die;
6009 gen_helper_tlbp();
6010 break;
6011 case OPC_TLBR:
6012 opn = "tlbr";
6013 if (!env->tlb->helper_tlbr)
6014 goto die;
6015 gen_helper_tlbr();
6016 break;
6017 case OPC_ERET:
6018 opn = "eret";
6019 check_insn(env, ctx, ISA_MIPS2);
6020 gen_helper_eret();
6021 ctx->bstate = BS_EXCP;
6022 break;
6023 case OPC_DERET:
6024 opn = "deret";
6025 check_insn(env, ctx, ISA_MIPS32);
6026 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
6027 MIPS_INVAL(opn);
6028 generate_exception(ctx, EXCP_RI);
6029 } else {
6030 gen_helper_deret();
6031 ctx->bstate = BS_EXCP;
6033 break;
6034 case OPC_WAIT:
6035 opn = "wait";
6036 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
6037 /* If we get an exception, we want to restart at next instruction */
6038 ctx->pc += 4;
6039 save_cpu_state(ctx, 1);
6040 ctx->pc -= 4;
6041 gen_helper_wait();
6042 ctx->bstate = BS_EXCP;
6043 break;
6044 default:
6045 die:
6046 MIPS_INVAL(opn);
6047 generate_exception(ctx, EXCP_RI);
6048 return;
6050 (void)opn; /* avoid a compiler warning */
6051 MIPS_DEBUG("%s %s %d", opn, regnames[rt], rd);
6053 #endif /* !CONFIG_USER_ONLY */
6055 /* CP1 Branches (before delay slot) */
6056 static void gen_compute_branch1 (CPUMIPSState *env, DisasContext *ctx, uint32_t op,
6057 int32_t cc, int32_t offset)
6059 target_ulong btarget;
6060 const char *opn = "cp1 cond branch";
6061 TCGv_i32 t0 = tcg_temp_new_i32();
6063 if (cc != 0)
6064 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
6066 btarget = ctx->pc + 4 + offset;
6068 switch (op) {
6069 case OPC_BC1F:
6070 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6071 tcg_gen_not_i32(t0, t0);
6072 tcg_gen_andi_i32(t0, t0, 1);
6073 tcg_gen_extu_i32_tl(bcond, t0);
6074 opn = "bc1f";
6075 goto not_likely;
6076 case OPC_BC1FL:
6077 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6078 tcg_gen_not_i32(t0, t0);
6079 tcg_gen_andi_i32(t0, t0, 1);
6080 tcg_gen_extu_i32_tl(bcond, t0);
6081 opn = "bc1fl";
6082 goto likely;
6083 case OPC_BC1T:
6084 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6085 tcg_gen_andi_i32(t0, t0, 1);
6086 tcg_gen_extu_i32_tl(bcond, t0);
6087 opn = "bc1t";
6088 goto not_likely;
6089 case OPC_BC1TL:
6090 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6091 tcg_gen_andi_i32(t0, t0, 1);
6092 tcg_gen_extu_i32_tl(bcond, t0);
6093 opn = "bc1tl";
6094 likely:
6095 ctx->hflags |= MIPS_HFLAG_BL;
6096 break;
6097 case OPC_BC1FANY2:
6099 TCGv_i32 t1 = tcg_temp_new_i32();
6100 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6101 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6102 tcg_gen_nor_i32(t0, t0, t1);
6103 tcg_temp_free_i32(t1);
6104 tcg_gen_andi_i32(t0, t0, 1);
6105 tcg_gen_extu_i32_tl(bcond, t0);
6107 opn = "bc1any2f";
6108 goto not_likely;
6109 case OPC_BC1TANY2:
6111 TCGv_i32 t1 = tcg_temp_new_i32();
6112 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6113 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6114 tcg_gen_or_i32(t0, t0, t1);
6115 tcg_temp_free_i32(t1);
6116 tcg_gen_andi_i32(t0, t0, 1);
6117 tcg_gen_extu_i32_tl(bcond, t0);
6119 opn = "bc1any2t";
6120 goto not_likely;
6121 case OPC_BC1FANY4:
6123 TCGv_i32 t1 = tcg_temp_new_i32();
6124 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6125 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6126 tcg_gen_or_i32(t0, t0, t1);
6127 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6128 tcg_gen_or_i32(t0, t0, t1);
6129 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6130 tcg_gen_nor_i32(t0, t0, t1);
6131 tcg_temp_free_i32(t1);
6132 tcg_gen_andi_i32(t0, t0, 1);
6133 tcg_gen_extu_i32_tl(bcond, t0);
6135 opn = "bc1any4f";
6136 goto not_likely;
6137 case OPC_BC1TANY4:
6139 TCGv_i32 t1 = tcg_temp_new_i32();
6140 tcg_gen_shri_i32(t0, fpu_fcr31, get_fp_bit(cc));
6141 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+1));
6142 tcg_gen_or_i32(t0, t0, t1);
6143 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+2));
6144 tcg_gen_or_i32(t0, t0, t1);
6145 tcg_gen_shri_i32(t1, fpu_fcr31, get_fp_bit(cc+3));
6146 tcg_gen_or_i32(t0, t0, t1);
6147 tcg_temp_free_i32(t1);
6148 tcg_gen_andi_i32(t0, t0, 1);
6149 tcg_gen_extu_i32_tl(bcond, t0);
6151 opn = "bc1any4t";
6152 not_likely:
6153 ctx->hflags |= MIPS_HFLAG_BC;
6154 break;
6155 default:
6156 MIPS_INVAL(opn);
6157 generate_exception (ctx, EXCP_RI);
6158 goto out;
6160 (void)opn; /* avoid a compiler warning */
6161 MIPS_DEBUG("%s: cond %02x target " TARGET_FMT_lx, opn,
6162 ctx->hflags, btarget);
6163 ctx->btarget = btarget;
6165 out:
6166 tcg_temp_free_i32(t0);
6169 /* Coprocessor 1 (FPU) */
6171 #define FOP(func, fmt) (((fmt) << 21) | (func))
6173 enum fopcode {
6174 OPC_ADD_S = FOP(0, FMT_S),
6175 OPC_SUB_S = FOP(1, FMT_S),
6176 OPC_MUL_S = FOP(2, FMT_S),
6177 OPC_DIV_S = FOP(3, FMT_S),
6178 OPC_SQRT_S = FOP(4, FMT_S),
6179 OPC_ABS_S = FOP(5, FMT_S),
6180 OPC_MOV_S = FOP(6, FMT_S),
6181 OPC_NEG_S = FOP(7, FMT_S),
6182 OPC_ROUND_L_S = FOP(8, FMT_S),
6183 OPC_TRUNC_L_S = FOP(9, FMT_S),
6184 OPC_CEIL_L_S = FOP(10, FMT_S),
6185 OPC_FLOOR_L_S = FOP(11, FMT_S),
6186 OPC_ROUND_W_S = FOP(12, FMT_S),
6187 OPC_TRUNC_W_S = FOP(13, FMT_S),
6188 OPC_CEIL_W_S = FOP(14, FMT_S),
6189 OPC_FLOOR_W_S = FOP(15, FMT_S),
6190 OPC_MOVCF_S = FOP(17, FMT_S),
6191 OPC_MOVZ_S = FOP(18, FMT_S),
6192 OPC_MOVN_S = FOP(19, FMT_S),
6193 OPC_RECIP_S = FOP(21, FMT_S),
6194 OPC_RSQRT_S = FOP(22, FMT_S),
6195 OPC_RECIP2_S = FOP(28, FMT_S),
6196 OPC_RECIP1_S = FOP(29, FMT_S),
6197 OPC_RSQRT1_S = FOP(30, FMT_S),
6198 OPC_RSQRT2_S = FOP(31, FMT_S),
6199 OPC_CVT_D_S = FOP(33, FMT_S),
6200 OPC_CVT_W_S = FOP(36, FMT_S),
6201 OPC_CVT_L_S = FOP(37, FMT_S),
6202 OPC_CVT_PS_S = FOP(38, FMT_S),
6203 OPC_CMP_F_S = FOP (48, FMT_S),
6204 OPC_CMP_UN_S = FOP (49, FMT_S),
6205 OPC_CMP_EQ_S = FOP (50, FMT_S),
6206 OPC_CMP_UEQ_S = FOP (51, FMT_S),
6207 OPC_CMP_OLT_S = FOP (52, FMT_S),
6208 OPC_CMP_ULT_S = FOP (53, FMT_S),
6209 OPC_CMP_OLE_S = FOP (54, FMT_S),
6210 OPC_CMP_ULE_S = FOP (55, FMT_S),
6211 OPC_CMP_SF_S = FOP (56, FMT_S),
6212 OPC_CMP_NGLE_S = FOP (57, FMT_S),
6213 OPC_CMP_SEQ_S = FOP (58, FMT_S),
6214 OPC_CMP_NGL_S = FOP (59, FMT_S),
6215 OPC_CMP_LT_S = FOP (60, FMT_S),
6216 OPC_CMP_NGE_S = FOP (61, FMT_S),
6217 OPC_CMP_LE_S = FOP (62, FMT_S),
6218 OPC_CMP_NGT_S = FOP (63, FMT_S),
6220 OPC_ADD_D = FOP(0, FMT_D),
6221 OPC_SUB_D = FOP(1, FMT_D),
6222 OPC_MUL_D = FOP(2, FMT_D),
6223 OPC_DIV_D = FOP(3, FMT_D),
6224 OPC_SQRT_D = FOP(4, FMT_D),
6225 OPC_ABS_D = FOP(5, FMT_D),
6226 OPC_MOV_D = FOP(6, FMT_D),
6227 OPC_NEG_D = FOP(7, FMT_D),
6228 OPC_ROUND_L_D = FOP(8, FMT_D),
6229 OPC_TRUNC_L_D = FOP(9, FMT_D),
6230 OPC_CEIL_L_D = FOP(10, FMT_D),
6231 OPC_FLOOR_L_D = FOP(11, FMT_D),
6232 OPC_ROUND_W_D = FOP(12, FMT_D),
6233 OPC_TRUNC_W_D = FOP(13, FMT_D),
6234 OPC_CEIL_W_D = FOP(14, FMT_D),
6235 OPC_FLOOR_W_D = FOP(15, FMT_D),
6236 OPC_MOVCF_D = FOP(17, FMT_D),
6237 OPC_MOVZ_D = FOP(18, FMT_D),
6238 OPC_MOVN_D = FOP(19, FMT_D),
6239 OPC_RECIP_D = FOP(21, FMT_D),
6240 OPC_RSQRT_D = FOP(22, FMT_D),
6241 OPC_RECIP2_D = FOP(28, FMT_D),
6242 OPC_RECIP1_D = FOP(29, FMT_D),
6243 OPC_RSQRT1_D = FOP(30, FMT_D),
6244 OPC_RSQRT2_D = FOP(31, FMT_D),
6245 OPC_CVT_S_D = FOP(32, FMT_D),
6246 OPC_CVT_W_D = FOP(36, FMT_D),
6247 OPC_CVT_L_D = FOP(37, FMT_D),
6248 OPC_CMP_F_D = FOP (48, FMT_D),
6249 OPC_CMP_UN_D = FOP (49, FMT_D),
6250 OPC_CMP_EQ_D = FOP (50, FMT_D),
6251 OPC_CMP_UEQ_D = FOP (51, FMT_D),
6252 OPC_CMP_OLT_D = FOP (52, FMT_D),
6253 OPC_CMP_ULT_D = FOP (53, FMT_D),
6254 OPC_CMP_OLE_D = FOP (54, FMT_D),
6255 OPC_CMP_ULE_D = FOP (55, FMT_D),
6256 OPC_CMP_SF_D = FOP (56, FMT_D),
6257 OPC_CMP_NGLE_D = FOP (57, FMT_D),
6258 OPC_CMP_SEQ_D = FOP (58, FMT_D),
6259 OPC_CMP_NGL_D = FOP (59, FMT_D),
6260 OPC_CMP_LT_D = FOP (60, FMT_D),
6261 OPC_CMP_NGE_D = FOP (61, FMT_D),
6262 OPC_CMP_LE_D = FOP (62, FMT_D),
6263 OPC_CMP_NGT_D = FOP (63, FMT_D),
6265 OPC_CVT_S_W = FOP(32, FMT_W),
6266 OPC_CVT_D_W = FOP(33, FMT_W),
6267 OPC_CVT_S_L = FOP(32, FMT_L),
6268 OPC_CVT_D_L = FOP(33, FMT_L),
6269 OPC_CVT_PS_PW = FOP(38, FMT_W),
6271 OPC_ADD_PS = FOP(0, FMT_PS),
6272 OPC_SUB_PS = FOP(1, FMT_PS),
6273 OPC_MUL_PS = FOP(2, FMT_PS),
6274 OPC_DIV_PS = FOP(3, FMT_PS),
6275 OPC_ABS_PS = FOP(5, FMT_PS),
6276 OPC_MOV_PS = FOP(6, FMT_PS),
6277 OPC_NEG_PS = FOP(7, FMT_PS),
6278 OPC_MOVCF_PS = FOP(17, FMT_PS),
6279 OPC_MOVZ_PS = FOP(18, FMT_PS),
6280 OPC_MOVN_PS = FOP(19, FMT_PS),
6281 OPC_ADDR_PS = FOP(24, FMT_PS),
6282 OPC_MULR_PS = FOP(26, FMT_PS),
6283 OPC_RECIP2_PS = FOP(28, FMT_PS),
6284 OPC_RECIP1_PS = FOP(29, FMT_PS),
6285 OPC_RSQRT1_PS = FOP(30, FMT_PS),
6286 OPC_RSQRT2_PS = FOP(31, FMT_PS),
6288 OPC_CVT_S_PU = FOP(32, FMT_PS),
6289 OPC_CVT_PW_PS = FOP(36, FMT_PS),
6290 OPC_CVT_S_PL = FOP(40, FMT_PS),
6291 OPC_PLL_PS = FOP(44, FMT_PS),
6292 OPC_PLU_PS = FOP(45, FMT_PS),
6293 OPC_PUL_PS = FOP(46, FMT_PS),
6294 OPC_PUU_PS = FOP(47, FMT_PS),
6295 OPC_CMP_F_PS = FOP (48, FMT_PS),
6296 OPC_CMP_UN_PS = FOP (49, FMT_PS),
6297 OPC_CMP_EQ_PS = FOP (50, FMT_PS),
6298 OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
6299 OPC_CMP_OLT_PS = FOP (52, FMT_PS),
6300 OPC_CMP_ULT_PS = FOP (53, FMT_PS),
6301 OPC_CMP_OLE_PS = FOP (54, FMT_PS),
6302 OPC_CMP_ULE_PS = FOP (55, FMT_PS),
6303 OPC_CMP_SF_PS = FOP (56, FMT_PS),
6304 OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
6305 OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
6306 OPC_CMP_NGL_PS = FOP (59, FMT_PS),
6307 OPC_CMP_LT_PS = FOP (60, FMT_PS),
6308 OPC_CMP_NGE_PS = FOP (61, FMT_PS),
6309 OPC_CMP_LE_PS = FOP (62, FMT_PS),
6310 OPC_CMP_NGT_PS = FOP (63, FMT_PS),
6313 static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
6315 const char *opn = "cp1 move";
6316 TCGv t0 = tcg_temp_new();
6318 switch (opc) {
6319 case OPC_MFC1:
6321 TCGv_i32 fp0 = tcg_temp_new_i32();
6323 gen_load_fpr32(fp0, fs);
6324 tcg_gen_ext_i32_tl(t0, fp0);
6325 tcg_temp_free_i32(fp0);
6327 gen_store_gpr(t0, rt);
6328 opn = "mfc1";
6329 break;
6330 case OPC_MTC1:
6331 gen_load_gpr(t0, rt);
6333 TCGv_i32 fp0 = tcg_temp_new_i32();
6335 tcg_gen_trunc_tl_i32(fp0, t0);
6336 gen_store_fpr32(fp0, fs);
6337 tcg_temp_free_i32(fp0);
6339 opn = "mtc1";
6340 break;
6341 case OPC_CFC1:
6342 gen_helper_1i(cfc1, t0, fs);
6343 gen_store_gpr(t0, rt);
6344 opn = "cfc1";
6345 break;
6346 case OPC_CTC1:
6347 gen_load_gpr(t0, rt);
6348 gen_helper_1i(ctc1, t0, fs);
6349 opn = "ctc1";
6350 break;
6351 #if defined(TARGET_MIPS64)
6352 case OPC_DMFC1:
6353 gen_load_fpr64(ctx, t0, fs);
6354 gen_store_gpr(t0, rt);
6355 opn = "dmfc1";
6356 break;
6357 case OPC_DMTC1:
6358 gen_load_gpr(t0, rt);
6359 gen_store_fpr64(ctx, t0, fs);
6360 opn = "dmtc1";
6361 break;
6362 #endif
6363 case OPC_MFHC1:
6365 TCGv_i32 fp0 = tcg_temp_new_i32();
6367 gen_load_fpr32h(fp0, fs);
6368 tcg_gen_ext_i32_tl(t0, fp0);
6369 tcg_temp_free_i32(fp0);
6371 gen_store_gpr(t0, rt);
6372 opn = "mfhc1";
6373 break;
6374 case OPC_MTHC1:
6375 gen_load_gpr(t0, rt);
6377 TCGv_i32 fp0 = tcg_temp_new_i32();
6379 tcg_gen_trunc_tl_i32(fp0, t0);
6380 gen_store_fpr32h(fp0, fs);
6381 tcg_temp_free_i32(fp0);
6383 opn = "mthc1";
6384 break;
6385 default:
6386 MIPS_INVAL(opn);
6387 generate_exception (ctx, EXCP_RI);
6388 goto out;
6390 (void)opn; /* avoid a compiler warning */
6391 MIPS_DEBUG("%s %s %s", opn, regnames[rt], fregnames[fs]);
6393 out:
6394 tcg_temp_free(t0);
6397 static void gen_movci (DisasContext *ctx, int rd, int rs, int cc, int tf)
6399 int l1;
6400 TCGCond cond;
6401 TCGv_i32 t0;
6403 if (rd == 0) {
6404 /* Treat as NOP. */
6405 return;
6408 if (tf)
6409 cond = TCG_COND_EQ;
6410 else
6411 cond = TCG_COND_NE;
6413 l1 = gen_new_label();
6414 t0 = tcg_temp_new_i32();
6415 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6416 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6417 tcg_temp_free_i32(t0);
6418 if (rs == 0) {
6419 tcg_gen_movi_tl(cpu_gpr[rd], 0);
6420 } else {
6421 tcg_gen_mov_tl(cpu_gpr[rd], cpu_gpr[rs]);
6423 gen_set_label(l1);
6426 static inline void gen_movcf_s (int fs, int fd, int cc, int tf)
6428 int cond;
6429 TCGv_i32 t0 = tcg_temp_new_i32();
6430 int l1 = gen_new_label();
6432 if (tf)
6433 cond = TCG_COND_EQ;
6434 else
6435 cond = TCG_COND_NE;
6437 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6438 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6439 gen_load_fpr32(t0, fs);
6440 gen_store_fpr32(t0, fd);
6441 gen_set_label(l1);
6442 tcg_temp_free_i32(t0);
6445 static inline void gen_movcf_d (DisasContext *ctx, int fs, int fd, int cc, int tf)
6447 int cond;
6448 TCGv_i32 t0 = tcg_temp_new_i32();
6449 TCGv_i64 fp0;
6450 int l1 = gen_new_label();
6452 if (tf)
6453 cond = TCG_COND_EQ;
6454 else
6455 cond = TCG_COND_NE;
6457 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6458 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6459 tcg_temp_free_i32(t0);
6460 fp0 = tcg_temp_new_i64();
6461 gen_load_fpr64(ctx, fp0, fs);
6462 gen_store_fpr64(ctx, fp0, fd);
6463 tcg_temp_free_i64(fp0);
6464 gen_set_label(l1);
6467 static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
6469 int cond;
6470 TCGv_i32 t0 = tcg_temp_new_i32();
6471 int l1 = gen_new_label();
6472 int l2 = gen_new_label();
6474 if (tf)
6475 cond = TCG_COND_EQ;
6476 else
6477 cond = TCG_COND_NE;
6479 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc));
6480 tcg_gen_brcondi_i32(cond, t0, 0, l1);
6481 gen_load_fpr32(t0, fs);
6482 gen_store_fpr32(t0, fd);
6483 gen_set_label(l1);
6485 tcg_gen_andi_i32(t0, fpu_fcr31, 1 << get_fp_bit(cc+1));
6486 tcg_gen_brcondi_i32(cond, t0, 0, l2);
6487 gen_load_fpr32h(t0, fs);
6488 gen_store_fpr32h(t0, fd);
6489 tcg_temp_free_i32(t0);
6490 gen_set_label(l2);
6494 static void gen_farith (DisasContext *ctx, enum fopcode op1,
6495 int ft, int fs, int fd, int cc)
6497 const char *opn = "farith";
6498 const char *condnames[] = {
6499 "c.f",
6500 "c.un",
6501 "c.eq",
6502 "c.ueq",
6503 "c.olt",
6504 "c.ult",
6505 "c.ole",
6506 "c.ule",
6507 "c.sf",
6508 "c.ngle",
6509 "c.seq",
6510 "c.ngl",
6511 "c.lt",
6512 "c.nge",
6513 "c.le",
6514 "c.ngt",
6516 const char *condnames_abs[] = {
6517 "cabs.f",
6518 "cabs.un",
6519 "cabs.eq",
6520 "cabs.ueq",
6521 "cabs.olt",
6522 "cabs.ult",
6523 "cabs.ole",
6524 "cabs.ule",
6525 "cabs.sf",
6526 "cabs.ngle",
6527 "cabs.seq",
6528 "cabs.ngl",
6529 "cabs.lt",
6530 "cabs.nge",
6531 "cabs.le",
6532 "cabs.ngt",
6534 enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
6535 uint32_t func = ctx->opcode & 0x3f;
6537 switch (op1) {
6538 case OPC_ADD_S:
6540 TCGv_i32 fp0 = tcg_temp_new_i32();
6541 TCGv_i32 fp1 = tcg_temp_new_i32();
6543 gen_load_fpr32(fp0, fs);
6544 gen_load_fpr32(fp1, ft);
6545 gen_helper_float_add_s(fp0, fp0, fp1);
6546 tcg_temp_free_i32(fp1);
6547 gen_store_fpr32(fp0, fd);
6548 tcg_temp_free_i32(fp0);
6550 opn = "add.s";
6551 optype = BINOP;
6552 break;
6553 case OPC_SUB_S:
6555 TCGv_i32 fp0 = tcg_temp_new_i32();
6556 TCGv_i32 fp1 = tcg_temp_new_i32();
6558 gen_load_fpr32(fp0, fs);
6559 gen_load_fpr32(fp1, ft);
6560 gen_helper_float_sub_s(fp0, fp0, fp1);
6561 tcg_temp_free_i32(fp1);
6562 gen_store_fpr32(fp0, fd);
6563 tcg_temp_free_i32(fp0);
6565 opn = "sub.s";
6566 optype = BINOP;
6567 break;
6568 case OPC_MUL_S:
6570 TCGv_i32 fp0 = tcg_temp_new_i32();
6571 TCGv_i32 fp1 = tcg_temp_new_i32();
6573 gen_load_fpr32(fp0, fs);
6574 gen_load_fpr32(fp1, ft);
6575 gen_helper_float_mul_s(fp0, fp0, fp1);
6576 tcg_temp_free_i32(fp1);
6577 gen_store_fpr32(fp0, fd);
6578 tcg_temp_free_i32(fp0);
6580 opn = "mul.s";
6581 optype = BINOP;
6582 break;
6583 case OPC_DIV_S:
6585 TCGv_i32 fp0 = tcg_temp_new_i32();
6586 TCGv_i32 fp1 = tcg_temp_new_i32();
6588 gen_load_fpr32(fp0, fs);
6589 gen_load_fpr32(fp1, ft);
6590 gen_helper_float_div_s(fp0, fp0, fp1);
6591 tcg_temp_free_i32(fp1);
6592 gen_store_fpr32(fp0, fd);
6593 tcg_temp_free_i32(fp0);
6595 opn = "div.s";
6596 optype = BINOP;
6597 break;
6598 case OPC_SQRT_S:
6600 TCGv_i32 fp0 = tcg_temp_new_i32();
6602 gen_load_fpr32(fp0, fs);
6603 gen_helper_float_sqrt_s(fp0, fp0);
6604 gen_store_fpr32(fp0, fd);
6605 tcg_temp_free_i32(fp0);
6607 opn = "sqrt.s";
6608 break;
6609 case OPC_ABS_S:
6611 TCGv_i32 fp0 = tcg_temp_new_i32();
6613 gen_load_fpr32(fp0, fs);
6614 gen_helper_float_abs_s(fp0, fp0);
6615 gen_store_fpr32(fp0, fd);
6616 tcg_temp_free_i32(fp0);
6618 opn = "abs.s";
6619 break;
6620 case OPC_MOV_S:
6622 TCGv_i32 fp0 = tcg_temp_new_i32();
6624 gen_load_fpr32(fp0, fs);
6625 gen_store_fpr32(fp0, fd);
6626 tcg_temp_free_i32(fp0);
6628 opn = "mov.s";
6629 break;
6630 case OPC_NEG_S:
6632 TCGv_i32 fp0 = tcg_temp_new_i32();
6634 gen_load_fpr32(fp0, fs);
6635 gen_helper_float_chs_s(fp0, fp0);
6636 gen_store_fpr32(fp0, fd);
6637 tcg_temp_free_i32(fp0);
6639 opn = "neg.s";
6640 break;
6641 case OPC_ROUND_L_S:
6642 check_cp1_64bitmode(ctx);
6644 TCGv_i32 fp32 = tcg_temp_new_i32();
6645 TCGv_i64 fp64 = tcg_temp_new_i64();
6647 gen_load_fpr32(fp32, fs);
6648 gen_helper_float_roundl_s(fp64, fp32);
6649 tcg_temp_free_i32(fp32);
6650 gen_store_fpr64(ctx, fp64, fd);
6651 tcg_temp_free_i64(fp64);
6653 opn = "round.l.s";
6654 break;
6655 case OPC_TRUNC_L_S:
6656 check_cp1_64bitmode(ctx);
6658 TCGv_i32 fp32 = tcg_temp_new_i32();
6659 TCGv_i64 fp64 = tcg_temp_new_i64();
6661 gen_load_fpr32(fp32, fs);
6662 gen_helper_float_truncl_s(fp64, fp32);
6663 tcg_temp_free_i32(fp32);
6664 gen_store_fpr64(ctx, fp64, fd);
6665 tcg_temp_free_i64(fp64);
6667 opn = "trunc.l.s";
6668 break;
6669 case OPC_CEIL_L_S:
6670 check_cp1_64bitmode(ctx);
6672 TCGv_i32 fp32 = tcg_temp_new_i32();
6673 TCGv_i64 fp64 = tcg_temp_new_i64();
6675 gen_load_fpr32(fp32, fs);
6676 gen_helper_float_ceill_s(fp64, fp32);
6677 tcg_temp_free_i32(fp32);
6678 gen_store_fpr64(ctx, fp64, fd);
6679 tcg_temp_free_i64(fp64);
6681 opn = "ceil.l.s";
6682 break;
6683 case OPC_FLOOR_L_S:
6684 check_cp1_64bitmode(ctx);
6686 TCGv_i32 fp32 = tcg_temp_new_i32();
6687 TCGv_i64 fp64 = tcg_temp_new_i64();
6689 gen_load_fpr32(fp32, fs);
6690 gen_helper_float_floorl_s(fp64, fp32);
6691 tcg_temp_free_i32(fp32);
6692 gen_store_fpr64(ctx, fp64, fd);
6693 tcg_temp_free_i64(fp64);
6695 opn = "floor.l.s";
6696 break;
6697 case OPC_ROUND_W_S:
6699 TCGv_i32 fp0 = tcg_temp_new_i32();
6701 gen_load_fpr32(fp0, fs);
6702 gen_helper_float_roundw_s(fp0, fp0);
6703 gen_store_fpr32(fp0, fd);
6704 tcg_temp_free_i32(fp0);
6706 opn = "round.w.s";
6707 break;
6708 case OPC_TRUNC_W_S:
6710 TCGv_i32 fp0 = tcg_temp_new_i32();
6712 gen_load_fpr32(fp0, fs);
6713 gen_helper_float_truncw_s(fp0, fp0);
6714 gen_store_fpr32(fp0, fd);
6715 tcg_temp_free_i32(fp0);
6717 opn = "trunc.w.s";
6718 break;
6719 case OPC_CEIL_W_S:
6721 TCGv_i32 fp0 = tcg_temp_new_i32();
6723 gen_load_fpr32(fp0, fs);
6724 gen_helper_float_ceilw_s(fp0, fp0);
6725 gen_store_fpr32(fp0, fd);
6726 tcg_temp_free_i32(fp0);
6728 opn = "ceil.w.s";
6729 break;
6730 case OPC_FLOOR_W_S:
6732 TCGv_i32 fp0 = tcg_temp_new_i32();
6734 gen_load_fpr32(fp0, fs);
6735 gen_helper_float_floorw_s(fp0, fp0);
6736 gen_store_fpr32(fp0, fd);
6737 tcg_temp_free_i32(fp0);
6739 opn = "floor.w.s";
6740 break;
6741 case OPC_MOVCF_S:
6742 gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
6743 opn = "movcf.s";
6744 break;
6745 case OPC_MOVZ_S:
6747 int l1 = gen_new_label();
6748 TCGv_i32 fp0;
6750 if (ft != 0) {
6751 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
6753 fp0 = tcg_temp_new_i32();
6754 gen_load_fpr32(fp0, fs);
6755 gen_store_fpr32(fp0, fd);
6756 tcg_temp_free_i32(fp0);
6757 gen_set_label(l1);
6759 opn = "movz.s";
6760 break;
6761 case OPC_MOVN_S:
6763 int l1 = gen_new_label();
6764 TCGv_i32 fp0;
6766 if (ft != 0) {
6767 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
6768 fp0 = tcg_temp_new_i32();
6769 gen_load_fpr32(fp0, fs);
6770 gen_store_fpr32(fp0, fd);
6771 tcg_temp_free_i32(fp0);
6772 gen_set_label(l1);
6775 opn = "movn.s";
6776 break;
6777 case OPC_RECIP_S:
6778 check_cop1x(ctx);
6780 TCGv_i32 fp0 = tcg_temp_new_i32();
6782 gen_load_fpr32(fp0, fs);
6783 gen_helper_float_recip_s(fp0, fp0);
6784 gen_store_fpr32(fp0, fd);
6785 tcg_temp_free_i32(fp0);
6787 opn = "recip.s";
6788 break;
6789 case OPC_RSQRT_S:
6790 check_cop1x(ctx);
6792 TCGv_i32 fp0 = tcg_temp_new_i32();
6794 gen_load_fpr32(fp0, fs);
6795 gen_helper_float_rsqrt_s(fp0, fp0);
6796 gen_store_fpr32(fp0, fd);
6797 tcg_temp_free_i32(fp0);
6799 opn = "rsqrt.s";
6800 break;
6801 case OPC_RECIP2_S:
6802 check_cp1_64bitmode(ctx);
6804 TCGv_i32 fp0 = tcg_temp_new_i32();
6805 TCGv_i32 fp1 = tcg_temp_new_i32();
6807 gen_load_fpr32(fp0, fs);
6808 gen_load_fpr32(fp1, fd);
6809 gen_helper_float_recip2_s(fp0, fp0, fp1);
6810 tcg_temp_free_i32(fp1);
6811 gen_store_fpr32(fp0, fd);
6812 tcg_temp_free_i32(fp0);
6814 opn = "recip2.s";
6815 break;
6816 case OPC_RECIP1_S:
6817 check_cp1_64bitmode(ctx);
6819 TCGv_i32 fp0 = tcg_temp_new_i32();
6821 gen_load_fpr32(fp0, fs);
6822 gen_helper_float_recip1_s(fp0, fp0);
6823 gen_store_fpr32(fp0, fd);
6824 tcg_temp_free_i32(fp0);
6826 opn = "recip1.s";
6827 break;
6828 case OPC_RSQRT1_S:
6829 check_cp1_64bitmode(ctx);
6831 TCGv_i32 fp0 = tcg_temp_new_i32();
6833 gen_load_fpr32(fp0, fs);
6834 gen_helper_float_rsqrt1_s(fp0, fp0);
6835 gen_store_fpr32(fp0, fd);
6836 tcg_temp_free_i32(fp0);
6838 opn = "rsqrt1.s";
6839 break;
6840 case OPC_RSQRT2_S:
6841 check_cp1_64bitmode(ctx);
6843 TCGv_i32 fp0 = tcg_temp_new_i32();
6844 TCGv_i32 fp1 = tcg_temp_new_i32();
6846 gen_load_fpr32(fp0, fs);
6847 gen_load_fpr32(fp1, ft);
6848 gen_helper_float_rsqrt2_s(fp0, fp0, fp1);
6849 tcg_temp_free_i32(fp1);
6850 gen_store_fpr32(fp0, fd);
6851 tcg_temp_free_i32(fp0);
6853 opn = "rsqrt2.s";
6854 break;
6855 case OPC_CVT_D_S:
6856 check_cp1_registers(ctx, fd);
6858 TCGv_i32 fp32 = tcg_temp_new_i32();
6859 TCGv_i64 fp64 = tcg_temp_new_i64();
6861 gen_load_fpr32(fp32, fs);
6862 gen_helper_float_cvtd_s(fp64, fp32);
6863 tcg_temp_free_i32(fp32);
6864 gen_store_fpr64(ctx, fp64, fd);
6865 tcg_temp_free_i64(fp64);
6867 opn = "cvt.d.s";
6868 break;
6869 case OPC_CVT_W_S:
6871 TCGv_i32 fp0 = tcg_temp_new_i32();
6873 gen_load_fpr32(fp0, fs);
6874 gen_helper_float_cvtw_s(fp0, fp0);
6875 gen_store_fpr32(fp0, fd);
6876 tcg_temp_free_i32(fp0);
6878 opn = "cvt.w.s";
6879 break;
6880 case OPC_CVT_L_S:
6881 check_cp1_64bitmode(ctx);
6883 TCGv_i32 fp32 = tcg_temp_new_i32();
6884 TCGv_i64 fp64 = tcg_temp_new_i64();
6886 gen_load_fpr32(fp32, fs);
6887 gen_helper_float_cvtl_s(fp64, fp32);
6888 tcg_temp_free_i32(fp32);
6889 gen_store_fpr64(ctx, fp64, fd);
6890 tcg_temp_free_i64(fp64);
6892 opn = "cvt.l.s";
6893 break;
6894 case OPC_CVT_PS_S:
6895 check_cp1_64bitmode(ctx);
6897 TCGv_i64 fp64 = tcg_temp_new_i64();
6898 TCGv_i32 fp32_0 = tcg_temp_new_i32();
6899 TCGv_i32 fp32_1 = tcg_temp_new_i32();
6901 gen_load_fpr32(fp32_0, fs);
6902 gen_load_fpr32(fp32_1, ft);
6903 tcg_gen_concat_i32_i64(fp64, fp32_0, fp32_1);
6904 tcg_temp_free_i32(fp32_1);
6905 tcg_temp_free_i32(fp32_0);
6906 gen_store_fpr64(ctx, fp64, fd);
6907 tcg_temp_free_i64(fp64);
6909 opn = "cvt.ps.s";
6910 break;
6911 case OPC_CMP_F_S:
6912 case OPC_CMP_UN_S:
6913 case OPC_CMP_EQ_S:
6914 case OPC_CMP_UEQ_S:
6915 case OPC_CMP_OLT_S:
6916 case OPC_CMP_ULT_S:
6917 case OPC_CMP_OLE_S:
6918 case OPC_CMP_ULE_S:
6919 case OPC_CMP_SF_S:
6920 case OPC_CMP_NGLE_S:
6921 case OPC_CMP_SEQ_S:
6922 case OPC_CMP_NGL_S:
6923 case OPC_CMP_LT_S:
6924 case OPC_CMP_NGE_S:
6925 case OPC_CMP_LE_S:
6926 case OPC_CMP_NGT_S:
6927 if (ctx->opcode & (1 << 6)) {
6928 gen_cmpabs_s(ctx, func-48, ft, fs, cc);
6929 opn = condnames_abs[func-48];
6930 } else {
6931 gen_cmp_s(ctx, func-48, ft, fs, cc);
6932 opn = condnames[func-48];
6934 break;
6935 case OPC_ADD_D:
6936 check_cp1_registers(ctx, fs | ft | fd);
6938 TCGv_i64 fp0 = tcg_temp_new_i64();
6939 TCGv_i64 fp1 = tcg_temp_new_i64();
6941 gen_load_fpr64(ctx, fp0, fs);
6942 gen_load_fpr64(ctx, fp1, ft);
6943 gen_helper_float_add_d(fp0, fp0, fp1);
6944 tcg_temp_free_i64(fp1);
6945 gen_store_fpr64(ctx, fp0, fd);
6946 tcg_temp_free_i64(fp0);
6948 opn = "add.d";
6949 optype = BINOP;
6950 break;
6951 case OPC_SUB_D:
6952 check_cp1_registers(ctx, fs | ft | fd);
6954 TCGv_i64 fp0 = tcg_temp_new_i64();
6955 TCGv_i64 fp1 = tcg_temp_new_i64();
6957 gen_load_fpr64(ctx, fp0, fs);
6958 gen_load_fpr64(ctx, fp1, ft);
6959 gen_helper_float_sub_d(fp0, fp0, fp1);
6960 tcg_temp_free_i64(fp1);
6961 gen_store_fpr64(ctx, fp0, fd);
6962 tcg_temp_free_i64(fp0);
6964 opn = "sub.d";
6965 optype = BINOP;
6966 break;
6967 case OPC_MUL_D:
6968 check_cp1_registers(ctx, fs | ft | fd);
6970 TCGv_i64 fp0 = tcg_temp_new_i64();
6971 TCGv_i64 fp1 = tcg_temp_new_i64();
6973 gen_load_fpr64(ctx, fp0, fs);
6974 gen_load_fpr64(ctx, fp1, ft);
6975 gen_helper_float_mul_d(fp0, fp0, fp1);
6976 tcg_temp_free_i64(fp1);
6977 gen_store_fpr64(ctx, fp0, fd);
6978 tcg_temp_free_i64(fp0);
6980 opn = "mul.d";
6981 optype = BINOP;
6982 break;
6983 case OPC_DIV_D:
6984 check_cp1_registers(ctx, fs | ft | fd);
6986 TCGv_i64 fp0 = tcg_temp_new_i64();
6987 TCGv_i64 fp1 = tcg_temp_new_i64();
6989 gen_load_fpr64(ctx, fp0, fs);
6990 gen_load_fpr64(ctx, fp1, ft);
6991 gen_helper_float_div_d(fp0, fp0, fp1);
6992 tcg_temp_free_i64(fp1);
6993 gen_store_fpr64(ctx, fp0, fd);
6994 tcg_temp_free_i64(fp0);
6996 opn = "div.d";
6997 optype = BINOP;
6998 break;
6999 case OPC_SQRT_D:
7000 check_cp1_registers(ctx, fs | fd);
7002 TCGv_i64 fp0 = tcg_temp_new_i64();
7004 gen_load_fpr64(ctx, fp0, fs);
7005 gen_helper_float_sqrt_d(fp0, fp0);
7006 gen_store_fpr64(ctx, fp0, fd);
7007 tcg_temp_free_i64(fp0);
7009 opn = "sqrt.d";
7010 break;
7011 case OPC_ABS_D:
7012 check_cp1_registers(ctx, fs | fd);
7014 TCGv_i64 fp0 = tcg_temp_new_i64();
7016 gen_load_fpr64(ctx, fp0, fs);
7017 gen_helper_float_abs_d(fp0, fp0);
7018 gen_store_fpr64(ctx, fp0, fd);
7019 tcg_temp_free_i64(fp0);
7021 opn = "abs.d";
7022 break;
7023 case OPC_MOV_D:
7024 check_cp1_registers(ctx, fs | fd);
7026 TCGv_i64 fp0 = tcg_temp_new_i64();
7028 gen_load_fpr64(ctx, fp0, fs);
7029 gen_store_fpr64(ctx, fp0, fd);
7030 tcg_temp_free_i64(fp0);
7032 opn = "mov.d";
7033 break;
7034 case OPC_NEG_D:
7035 check_cp1_registers(ctx, fs | fd);
7037 TCGv_i64 fp0 = tcg_temp_new_i64();
7039 gen_load_fpr64(ctx, fp0, fs);
7040 gen_helper_float_chs_d(fp0, fp0);
7041 gen_store_fpr64(ctx, fp0, fd);
7042 tcg_temp_free_i64(fp0);
7044 opn = "neg.d";
7045 break;
7046 case OPC_ROUND_L_D:
7047 check_cp1_64bitmode(ctx);
7049 TCGv_i64 fp0 = tcg_temp_new_i64();
7051 gen_load_fpr64(ctx, fp0, fs);
7052 gen_helper_float_roundl_d(fp0, fp0);
7053 gen_store_fpr64(ctx, fp0, fd);
7054 tcg_temp_free_i64(fp0);
7056 opn = "round.l.d";
7057 break;
7058 case OPC_TRUNC_L_D:
7059 check_cp1_64bitmode(ctx);
7061 TCGv_i64 fp0 = tcg_temp_new_i64();
7063 gen_load_fpr64(ctx, fp0, fs);
7064 gen_helper_float_truncl_d(fp0, fp0);
7065 gen_store_fpr64(ctx, fp0, fd);
7066 tcg_temp_free_i64(fp0);
7068 opn = "trunc.l.d";
7069 break;
7070 case OPC_CEIL_L_D:
7071 check_cp1_64bitmode(ctx);
7073 TCGv_i64 fp0 = tcg_temp_new_i64();
7075 gen_load_fpr64(ctx, fp0, fs);
7076 gen_helper_float_ceill_d(fp0, fp0);
7077 gen_store_fpr64(ctx, fp0, fd);
7078 tcg_temp_free_i64(fp0);
7080 opn = "ceil.l.d";
7081 break;
7082 case OPC_FLOOR_L_D:
7083 check_cp1_64bitmode(ctx);
7085 TCGv_i64 fp0 = tcg_temp_new_i64();
7087 gen_load_fpr64(ctx, fp0, fs);
7088 gen_helper_float_floorl_d(fp0, fp0);
7089 gen_store_fpr64(ctx, fp0, fd);
7090 tcg_temp_free_i64(fp0);
7092 opn = "floor.l.d";
7093 break;
7094 case OPC_ROUND_W_D:
7095 check_cp1_registers(ctx, fs);
7097 TCGv_i32 fp32 = tcg_temp_new_i32();
7098 TCGv_i64 fp64 = tcg_temp_new_i64();
7100 gen_load_fpr64(ctx, fp64, fs);
7101 gen_helper_float_roundw_d(fp32, fp64);
7102 tcg_temp_free_i64(fp64);
7103 gen_store_fpr32(fp32, fd);
7104 tcg_temp_free_i32(fp32);
7106 opn = "round.w.d";
7107 break;
7108 case OPC_TRUNC_W_D:
7109 check_cp1_registers(ctx, fs);
7111 TCGv_i32 fp32 = tcg_temp_new_i32();
7112 TCGv_i64 fp64 = tcg_temp_new_i64();
7114 gen_load_fpr64(ctx, fp64, fs);
7115 gen_helper_float_truncw_d(fp32, fp64);
7116 tcg_temp_free_i64(fp64);
7117 gen_store_fpr32(fp32, fd);
7118 tcg_temp_free_i32(fp32);
7120 opn = "trunc.w.d";
7121 break;
7122 case OPC_CEIL_W_D:
7123 check_cp1_registers(ctx, fs);
7125 TCGv_i32 fp32 = tcg_temp_new_i32();
7126 TCGv_i64 fp64 = tcg_temp_new_i64();
7128 gen_load_fpr64(ctx, fp64, fs);
7129 gen_helper_float_ceilw_d(fp32, fp64);
7130 tcg_temp_free_i64(fp64);
7131 gen_store_fpr32(fp32, fd);
7132 tcg_temp_free_i32(fp32);
7134 opn = "ceil.w.d";
7135 break;
7136 case OPC_FLOOR_W_D:
7137 check_cp1_registers(ctx, fs);
7139 TCGv_i32 fp32 = tcg_temp_new_i32();
7140 TCGv_i64 fp64 = tcg_temp_new_i64();
7142 gen_load_fpr64(ctx, fp64, fs);
7143 gen_helper_float_floorw_d(fp32, fp64);
7144 tcg_temp_free_i64(fp64);
7145 gen_store_fpr32(fp32, fd);
7146 tcg_temp_free_i32(fp32);
7148 opn = "floor.w.d";
7149 break;
7150 case OPC_MOVCF_D:
7151 gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7152 opn = "movcf.d";
7153 break;
7154 case OPC_MOVZ_D:
7156 int l1 = gen_new_label();
7157 TCGv_i64 fp0;
7159 if (ft != 0) {
7160 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7162 fp0 = tcg_temp_new_i64();
7163 gen_load_fpr64(ctx, fp0, fs);
7164 gen_store_fpr64(ctx, fp0, fd);
7165 tcg_temp_free_i64(fp0);
7166 gen_set_label(l1);
7168 opn = "movz.d";
7169 break;
7170 case OPC_MOVN_D:
7172 int l1 = gen_new_label();
7173 TCGv_i64 fp0;
7175 if (ft != 0) {
7176 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7177 fp0 = tcg_temp_new_i64();
7178 gen_load_fpr64(ctx, fp0, fs);
7179 gen_store_fpr64(ctx, fp0, fd);
7180 tcg_temp_free_i64(fp0);
7181 gen_set_label(l1);
7184 opn = "movn.d";
7185 break;
7186 case OPC_RECIP_D:
7187 check_cp1_64bitmode(ctx);
7189 TCGv_i64 fp0 = tcg_temp_new_i64();
7191 gen_load_fpr64(ctx, fp0, fs);
7192 gen_helper_float_recip_d(fp0, fp0);
7193 gen_store_fpr64(ctx, fp0, fd);
7194 tcg_temp_free_i64(fp0);
7196 opn = "recip.d";
7197 break;
7198 case OPC_RSQRT_D:
7199 check_cp1_64bitmode(ctx);
7201 TCGv_i64 fp0 = tcg_temp_new_i64();
7203 gen_load_fpr64(ctx, fp0, fs);
7204 gen_helper_float_rsqrt_d(fp0, fp0);
7205 gen_store_fpr64(ctx, fp0, fd);
7206 tcg_temp_free_i64(fp0);
7208 opn = "rsqrt.d";
7209 break;
7210 case OPC_RECIP2_D:
7211 check_cp1_64bitmode(ctx);
7213 TCGv_i64 fp0 = tcg_temp_new_i64();
7214 TCGv_i64 fp1 = tcg_temp_new_i64();
7216 gen_load_fpr64(ctx, fp0, fs);
7217 gen_load_fpr64(ctx, fp1, ft);
7218 gen_helper_float_recip2_d(fp0, fp0, fp1);
7219 tcg_temp_free_i64(fp1);
7220 gen_store_fpr64(ctx, fp0, fd);
7221 tcg_temp_free_i64(fp0);
7223 opn = "recip2.d";
7224 break;
7225 case OPC_RECIP1_D:
7226 check_cp1_64bitmode(ctx);
7228 TCGv_i64 fp0 = tcg_temp_new_i64();
7230 gen_load_fpr64(ctx, fp0, fs);
7231 gen_helper_float_recip1_d(fp0, fp0);
7232 gen_store_fpr64(ctx, fp0, fd);
7233 tcg_temp_free_i64(fp0);
7235 opn = "recip1.d";
7236 break;
7237 case OPC_RSQRT1_D:
7238 check_cp1_64bitmode(ctx);
7240 TCGv_i64 fp0 = tcg_temp_new_i64();
7242 gen_load_fpr64(ctx, fp0, fs);
7243 gen_helper_float_rsqrt1_d(fp0, fp0);
7244 gen_store_fpr64(ctx, fp0, fd);
7245 tcg_temp_free_i64(fp0);
7247 opn = "rsqrt1.d";
7248 break;
7249 case OPC_RSQRT2_D:
7250 check_cp1_64bitmode(ctx);
7252 TCGv_i64 fp0 = tcg_temp_new_i64();
7253 TCGv_i64 fp1 = tcg_temp_new_i64();
7255 gen_load_fpr64(ctx, fp0, fs);
7256 gen_load_fpr64(ctx, fp1, ft);
7257 gen_helper_float_rsqrt2_d(fp0, fp0, fp1);
7258 tcg_temp_free_i64(fp1);
7259 gen_store_fpr64(ctx, fp0, fd);
7260 tcg_temp_free_i64(fp0);
7262 opn = "rsqrt2.d";
7263 break;
7264 case OPC_CMP_F_D:
7265 case OPC_CMP_UN_D:
7266 case OPC_CMP_EQ_D:
7267 case OPC_CMP_UEQ_D:
7268 case OPC_CMP_OLT_D:
7269 case OPC_CMP_ULT_D:
7270 case OPC_CMP_OLE_D:
7271 case OPC_CMP_ULE_D:
7272 case OPC_CMP_SF_D:
7273 case OPC_CMP_NGLE_D:
7274 case OPC_CMP_SEQ_D:
7275 case OPC_CMP_NGL_D:
7276 case OPC_CMP_LT_D:
7277 case OPC_CMP_NGE_D:
7278 case OPC_CMP_LE_D:
7279 case OPC_CMP_NGT_D:
7280 if (ctx->opcode & (1 << 6)) {
7281 gen_cmpabs_d(ctx, func-48, ft, fs, cc);
7282 opn = condnames_abs[func-48];
7283 } else {
7284 gen_cmp_d(ctx, func-48, ft, fs, cc);
7285 opn = condnames[func-48];
7287 break;
7288 case OPC_CVT_S_D:
7289 check_cp1_registers(ctx, fs);
7291 TCGv_i32 fp32 = tcg_temp_new_i32();
7292 TCGv_i64 fp64 = tcg_temp_new_i64();
7294 gen_load_fpr64(ctx, fp64, fs);
7295 gen_helper_float_cvts_d(fp32, fp64);
7296 tcg_temp_free_i64(fp64);
7297 gen_store_fpr32(fp32, fd);
7298 tcg_temp_free_i32(fp32);
7300 opn = "cvt.s.d";
7301 break;
7302 case OPC_CVT_W_D:
7303 check_cp1_registers(ctx, fs);
7305 TCGv_i32 fp32 = tcg_temp_new_i32();
7306 TCGv_i64 fp64 = tcg_temp_new_i64();
7308 gen_load_fpr64(ctx, fp64, fs);
7309 gen_helper_float_cvtw_d(fp32, fp64);
7310 tcg_temp_free_i64(fp64);
7311 gen_store_fpr32(fp32, fd);
7312 tcg_temp_free_i32(fp32);
7314 opn = "cvt.w.d";
7315 break;
7316 case OPC_CVT_L_D:
7317 check_cp1_64bitmode(ctx);
7319 TCGv_i64 fp0 = tcg_temp_new_i64();
7321 gen_load_fpr64(ctx, fp0, fs);
7322 gen_helper_float_cvtl_d(fp0, fp0);
7323 gen_store_fpr64(ctx, fp0, fd);
7324 tcg_temp_free_i64(fp0);
7326 opn = "cvt.l.d";
7327 break;
7328 case OPC_CVT_S_W:
7330 TCGv_i32 fp0 = tcg_temp_new_i32();
7332 gen_load_fpr32(fp0, fs);
7333 gen_helper_float_cvts_w(fp0, fp0);
7334 gen_store_fpr32(fp0, fd);
7335 tcg_temp_free_i32(fp0);
7337 opn = "cvt.s.w";
7338 break;
7339 case OPC_CVT_D_W:
7340 check_cp1_registers(ctx, fd);
7342 TCGv_i32 fp32 = tcg_temp_new_i32();
7343 TCGv_i64 fp64 = tcg_temp_new_i64();
7345 gen_load_fpr32(fp32, fs);
7346 gen_helper_float_cvtd_w(fp64, fp32);
7347 tcg_temp_free_i32(fp32);
7348 gen_store_fpr64(ctx, fp64, fd);
7349 tcg_temp_free_i64(fp64);
7351 opn = "cvt.d.w";
7352 break;
7353 case OPC_CVT_S_L:
7354 check_cp1_64bitmode(ctx);
7356 TCGv_i32 fp32 = tcg_temp_new_i32();
7357 TCGv_i64 fp64 = tcg_temp_new_i64();
7359 gen_load_fpr64(ctx, fp64, fs);
7360 gen_helper_float_cvts_l(fp32, fp64);
7361 tcg_temp_free_i64(fp64);
7362 gen_store_fpr32(fp32, fd);
7363 tcg_temp_free_i32(fp32);
7365 opn = "cvt.s.l";
7366 break;
7367 case OPC_CVT_D_L:
7368 check_cp1_64bitmode(ctx);
7370 TCGv_i64 fp0 = tcg_temp_new_i64();
7372 gen_load_fpr64(ctx, fp0, fs);
7373 gen_helper_float_cvtd_l(fp0, fp0);
7374 gen_store_fpr64(ctx, fp0, fd);
7375 tcg_temp_free_i64(fp0);
7377 opn = "cvt.d.l";
7378 break;
7379 case OPC_CVT_PS_PW:
7380 check_cp1_64bitmode(ctx);
7382 TCGv_i64 fp0 = tcg_temp_new_i64();
7384 gen_load_fpr64(ctx, fp0, fs);
7385 gen_helper_float_cvtps_pw(fp0, fp0);
7386 gen_store_fpr64(ctx, fp0, fd);
7387 tcg_temp_free_i64(fp0);
7389 opn = "cvt.ps.pw";
7390 break;
7391 case OPC_ADD_PS:
7392 check_cp1_64bitmode(ctx);
7394 TCGv_i64 fp0 = tcg_temp_new_i64();
7395 TCGv_i64 fp1 = tcg_temp_new_i64();
7397 gen_load_fpr64(ctx, fp0, fs);
7398 gen_load_fpr64(ctx, fp1, ft);
7399 gen_helper_float_add_ps(fp0, fp0, fp1);
7400 tcg_temp_free_i64(fp1);
7401 gen_store_fpr64(ctx, fp0, fd);
7402 tcg_temp_free_i64(fp0);
7404 opn = "add.ps";
7405 break;
7406 case OPC_SUB_PS:
7407 check_cp1_64bitmode(ctx);
7409 TCGv_i64 fp0 = tcg_temp_new_i64();
7410 TCGv_i64 fp1 = tcg_temp_new_i64();
7412 gen_load_fpr64(ctx, fp0, fs);
7413 gen_load_fpr64(ctx, fp1, ft);
7414 gen_helper_float_sub_ps(fp0, fp0, fp1);
7415 tcg_temp_free_i64(fp1);
7416 gen_store_fpr64(ctx, fp0, fd);
7417 tcg_temp_free_i64(fp0);
7419 opn = "sub.ps";
7420 break;
7421 case OPC_MUL_PS:
7422 check_cp1_64bitmode(ctx);
7424 TCGv_i64 fp0 = tcg_temp_new_i64();
7425 TCGv_i64 fp1 = tcg_temp_new_i64();
7427 gen_load_fpr64(ctx, fp0, fs);
7428 gen_load_fpr64(ctx, fp1, ft);
7429 gen_helper_float_mul_ps(fp0, fp0, fp1);
7430 tcg_temp_free_i64(fp1);
7431 gen_store_fpr64(ctx, fp0, fd);
7432 tcg_temp_free_i64(fp0);
7434 opn = "mul.ps";
7435 break;
7436 case OPC_ABS_PS:
7437 check_cp1_64bitmode(ctx);
7439 TCGv_i64 fp0 = tcg_temp_new_i64();
7441 gen_load_fpr64(ctx, fp0, fs);
7442 gen_helper_float_abs_ps(fp0, fp0);
7443 gen_store_fpr64(ctx, fp0, fd);
7444 tcg_temp_free_i64(fp0);
7446 opn = "abs.ps";
7447 break;
7448 case OPC_MOV_PS:
7449 check_cp1_64bitmode(ctx);
7451 TCGv_i64 fp0 = tcg_temp_new_i64();
7453 gen_load_fpr64(ctx, fp0, fs);
7454 gen_store_fpr64(ctx, fp0, fd);
7455 tcg_temp_free_i64(fp0);
7457 opn = "mov.ps";
7458 break;
7459 case OPC_NEG_PS:
7460 check_cp1_64bitmode(ctx);
7462 TCGv_i64 fp0 = tcg_temp_new_i64();
7464 gen_load_fpr64(ctx, fp0, fs);
7465 gen_helper_float_chs_ps(fp0, fp0);
7466 gen_store_fpr64(ctx, fp0, fd);
7467 tcg_temp_free_i64(fp0);
7469 opn = "neg.ps";
7470 break;
7471 case OPC_MOVCF_PS:
7472 check_cp1_64bitmode(ctx);
7473 gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
7474 opn = "movcf.ps";
7475 break;
7476 case OPC_MOVZ_PS:
7477 check_cp1_64bitmode(ctx);
7479 int l1 = gen_new_label();
7480 TCGv_i64 fp0;
7482 if (ft != 0)
7483 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[ft], 0, l1);
7484 fp0 = tcg_temp_new_i64();
7485 gen_load_fpr64(ctx, fp0, fs);
7486 gen_store_fpr64(ctx, fp0, fd);
7487 tcg_temp_free_i64(fp0);
7488 gen_set_label(l1);
7490 opn = "movz.ps";
7491 break;
7492 case OPC_MOVN_PS:
7493 check_cp1_64bitmode(ctx);
7495 int l1 = gen_new_label();
7496 TCGv_i64 fp0;
7498 if (ft != 0) {
7499 tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[ft], 0, l1);
7500 fp0 = tcg_temp_new_i64();
7501 gen_load_fpr64(ctx, fp0, fs);
7502 gen_store_fpr64(ctx, fp0, fd);
7503 tcg_temp_free_i64(fp0);
7504 gen_set_label(l1);
7507 opn = "movn.ps";
7508 break;
7509 case OPC_ADDR_PS:
7510 check_cp1_64bitmode(ctx);
7512 TCGv_i64 fp0 = tcg_temp_new_i64();
7513 TCGv_i64 fp1 = tcg_temp_new_i64();
7515 gen_load_fpr64(ctx, fp0, ft);
7516 gen_load_fpr64(ctx, fp1, fs);
7517 gen_helper_float_addr_ps(fp0, fp0, fp1);
7518 tcg_temp_free_i64(fp1);
7519 gen_store_fpr64(ctx, fp0, fd);
7520 tcg_temp_free_i64(fp0);
7522 opn = "addr.ps";
7523 break;
7524 case OPC_MULR_PS:
7525 check_cp1_64bitmode(ctx);
7527 TCGv_i64 fp0 = tcg_temp_new_i64();
7528 TCGv_i64 fp1 = tcg_temp_new_i64();
7530 gen_load_fpr64(ctx, fp0, ft);
7531 gen_load_fpr64(ctx, fp1, fs);
7532 gen_helper_float_mulr_ps(fp0, fp0, fp1);
7533 tcg_temp_free_i64(fp1);
7534 gen_store_fpr64(ctx, fp0, fd);
7535 tcg_temp_free_i64(fp0);
7537 opn = "mulr.ps";
7538 break;
7539 case OPC_RECIP2_PS:
7540 check_cp1_64bitmode(ctx);
7542 TCGv_i64 fp0 = tcg_temp_new_i64();
7543 TCGv_i64 fp1 = tcg_temp_new_i64();
7545 gen_load_fpr64(ctx, fp0, fs);
7546 gen_load_fpr64(ctx, fp1, fd);
7547 gen_helper_float_recip2_ps(fp0, fp0, fp1);
7548 tcg_temp_free_i64(fp1);
7549 gen_store_fpr64(ctx, fp0, fd);
7550 tcg_temp_free_i64(fp0);
7552 opn = "recip2.ps";
7553 break;
7554 case OPC_RECIP1_PS:
7555 check_cp1_64bitmode(ctx);
7557 TCGv_i64 fp0 = tcg_temp_new_i64();
7559 gen_load_fpr64(ctx, fp0, fs);
7560 gen_helper_float_recip1_ps(fp0, fp0);
7561 gen_store_fpr64(ctx, fp0, fd);
7562 tcg_temp_free_i64(fp0);
7564 opn = "recip1.ps";
7565 break;
7566 case OPC_RSQRT1_PS:
7567 check_cp1_64bitmode(ctx);
7569 TCGv_i64 fp0 = tcg_temp_new_i64();
7571 gen_load_fpr64(ctx, fp0, fs);
7572 gen_helper_float_rsqrt1_ps(fp0, fp0);
7573 gen_store_fpr64(ctx, fp0, fd);
7574 tcg_temp_free_i64(fp0);
7576 opn = "rsqrt1.ps";
7577 break;
7578 case OPC_RSQRT2_PS:
7579 check_cp1_64bitmode(ctx);
7581 TCGv_i64 fp0 = tcg_temp_new_i64();
7582 TCGv_i64 fp1 = tcg_temp_new_i64();
7584 gen_load_fpr64(ctx, fp0, fs);
7585 gen_load_fpr64(ctx, fp1, ft);
7586 gen_helper_float_rsqrt2_ps(fp0, fp0, fp1);
7587 tcg_temp_free_i64(fp1);
7588 gen_store_fpr64(ctx, fp0, fd);
7589 tcg_temp_free_i64(fp0);
7591 opn = "rsqrt2.ps";
7592 break;
7593 case OPC_CVT_S_PU:
7594 check_cp1_64bitmode(ctx);
7596 TCGv_i32 fp0 = tcg_temp_new_i32();
7598 gen_load_fpr32h(fp0, fs);
7599 gen_helper_float_cvts_pu(fp0, fp0);
7600 gen_store_fpr32(fp0, fd);
7601 tcg_temp_free_i32(fp0);
7603 opn = "cvt.s.pu";
7604 break;
7605 case OPC_CVT_PW_PS:
7606 check_cp1_64bitmode(ctx);
7608 TCGv_i64 fp0 = tcg_temp_new_i64();
7610 gen_load_fpr64(ctx, fp0, fs);
7611 gen_helper_float_cvtpw_ps(fp0, fp0);
7612 gen_store_fpr64(ctx, fp0, fd);
7613 tcg_temp_free_i64(fp0);
7615 opn = "cvt.pw.ps";
7616 break;
7617 case OPC_CVT_S_PL:
7618 check_cp1_64bitmode(ctx);
7620 TCGv_i32 fp0 = tcg_temp_new_i32();
7622 gen_load_fpr32(fp0, fs);
7623 gen_helper_float_cvts_pl(fp0, fp0);
7624 gen_store_fpr32(fp0, fd);
7625 tcg_temp_free_i32(fp0);
7627 opn = "cvt.s.pl";
7628 break;
7629 case OPC_PLL_PS:
7630 check_cp1_64bitmode(ctx);
7632 TCGv_i32 fp0 = tcg_temp_new_i32();
7633 TCGv_i32 fp1 = tcg_temp_new_i32();
7635 gen_load_fpr32(fp0, fs);
7636 gen_load_fpr32(fp1, ft);
7637 gen_store_fpr32h(fp0, fd);
7638 gen_store_fpr32(fp1, fd);
7639 tcg_temp_free_i32(fp0);
7640 tcg_temp_free_i32(fp1);
7642 opn = "pll.ps";
7643 break;
7644 case OPC_PLU_PS:
7645 check_cp1_64bitmode(ctx);
7647 TCGv_i32 fp0 = tcg_temp_new_i32();
7648 TCGv_i32 fp1 = tcg_temp_new_i32();
7650 gen_load_fpr32(fp0, fs);
7651 gen_load_fpr32h(fp1, ft);
7652 gen_store_fpr32(fp1, fd);
7653 gen_store_fpr32h(fp0, fd);
7654 tcg_temp_free_i32(fp0);
7655 tcg_temp_free_i32(fp1);
7657 opn = "plu.ps";
7658 break;
7659 case OPC_PUL_PS:
7660 check_cp1_64bitmode(ctx);
7662 TCGv_i32 fp0 = tcg_temp_new_i32();
7663 TCGv_i32 fp1 = tcg_temp_new_i32();
7665 gen_load_fpr32h(fp0, fs);
7666 gen_load_fpr32(fp1, ft);
7667 gen_store_fpr32(fp1, fd);
7668 gen_store_fpr32h(fp0, fd);
7669 tcg_temp_free_i32(fp0);
7670 tcg_temp_free_i32(fp1);
7672 opn = "pul.ps";
7673 break;
7674 case OPC_PUU_PS:
7675 check_cp1_64bitmode(ctx);
7677 TCGv_i32 fp0 = tcg_temp_new_i32();
7678 TCGv_i32 fp1 = tcg_temp_new_i32();
7680 gen_load_fpr32h(fp0, fs);
7681 gen_load_fpr32h(fp1, ft);
7682 gen_store_fpr32(fp1, fd);
7683 gen_store_fpr32h(fp0, fd);
7684 tcg_temp_free_i32(fp0);
7685 tcg_temp_free_i32(fp1);
7687 opn = "puu.ps";
7688 break;
7689 case OPC_CMP_F_PS:
7690 case OPC_CMP_UN_PS:
7691 case OPC_CMP_EQ_PS:
7692 case OPC_CMP_UEQ_PS:
7693 case OPC_CMP_OLT_PS:
7694 case OPC_CMP_ULT_PS:
7695 case OPC_CMP_OLE_PS:
7696 case OPC_CMP_ULE_PS:
7697 case OPC_CMP_SF_PS:
7698 case OPC_CMP_NGLE_PS:
7699 case OPC_CMP_SEQ_PS:
7700 case OPC_CMP_NGL_PS:
7701 case OPC_CMP_LT_PS:
7702 case OPC_CMP_NGE_PS:
7703 case OPC_CMP_LE_PS:
7704 case OPC_CMP_NGT_PS:
7705 if (ctx->opcode & (1 << 6)) {
7706 gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
7707 opn = condnames_abs[func-48];
7708 } else {
7709 gen_cmp_ps(ctx, func-48, ft, fs, cc);
7710 opn = condnames[func-48];
7712 break;
7713 default:
7714 MIPS_INVAL(opn);
7715 generate_exception (ctx, EXCP_RI);
7716 return;
7718 (void)opn; /* avoid a compiler warning */
7719 switch (optype) {
7720 case BINOP:
7721 MIPS_DEBUG("%s %s, %s, %s", opn, fregnames[fd], fregnames[fs], fregnames[ft]);
7722 break;
7723 case CMPOP:
7724 MIPS_DEBUG("%s %s,%s", opn, fregnames[fs], fregnames[ft]);
7725 break;
7726 default:
7727 MIPS_DEBUG("%s %s,%s", opn, fregnames[fd], fregnames[fs]);
7728 break;
7732 /* Coprocessor 3 (FPU) */
7733 static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
7734 int fd, int fs, int base, int index)
7736 const char *opn = "extended float load/store";
7737 int store = 0;
7738 TCGv t0 = tcg_temp_new();
7740 if (base == 0) {
7741 gen_load_gpr(t0, index);
7742 } else if (index == 0) {
7743 gen_load_gpr(t0, base);
7744 } else {
7745 gen_load_gpr(t0, index);
7746 gen_op_addr_add(ctx, t0, cpu_gpr[base], t0);
7748 /* Don't do NOP if destination is zero: we must perform the actual
7749 memory access. */
7750 save_cpu_state(ctx, 0);
7751 switch (opc) {
7752 case OPC_LWXC1:
7753 check_cop1x(ctx);
7755 TCGv_i32 fp0 = tcg_temp_new_i32();
7757 tcg_gen_qemu_ld32s(t0, t0, ctx->mem_idx);
7758 tcg_gen_trunc_tl_i32(fp0, t0);
7759 gen_store_fpr32(fp0, fd);
7760 tcg_temp_free_i32(fp0);
7762 opn = "lwxc1";
7763 break;
7764 case OPC_LDXC1:
7765 check_cop1x(ctx);
7766 check_cp1_registers(ctx, fd);
7768 TCGv_i64 fp0 = tcg_temp_new_i64();
7770 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7771 gen_store_fpr64(ctx, fp0, fd);
7772 tcg_temp_free_i64(fp0);
7774 opn = "ldxc1";
7775 break;
7776 case OPC_LUXC1:
7777 check_cp1_64bitmode(ctx);
7778 tcg_gen_andi_tl(t0, t0, ~0x7);
7780 TCGv_i64 fp0 = tcg_temp_new_i64();
7782 tcg_gen_qemu_ld64(fp0, t0, ctx->mem_idx);
7783 gen_store_fpr64(ctx, fp0, fd);
7784 tcg_temp_free_i64(fp0);
7786 opn = "luxc1";
7787 break;
7788 case OPC_SWXC1:
7789 check_cop1x(ctx);
7791 TCGv_i32 fp0 = tcg_temp_new_i32();
7792 TCGv t1 = tcg_temp_new();
7794 gen_load_fpr32(fp0, fs);
7795 tcg_gen_extu_i32_tl(t1, fp0);
7796 tcg_gen_qemu_st32(t1, t0, ctx->mem_idx);
7797 tcg_temp_free_i32(fp0);
7798 tcg_temp_free(t1);
7800 opn = "swxc1";
7801 store = 1;
7802 break;
7803 case OPC_SDXC1:
7804 check_cop1x(ctx);
7805 check_cp1_registers(ctx, fs);
7807 TCGv_i64 fp0 = tcg_temp_new_i64();
7809 gen_load_fpr64(ctx, fp0, fs);
7810 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7811 tcg_temp_free_i64(fp0);
7813 opn = "sdxc1";
7814 store = 1;
7815 break;
7816 case OPC_SUXC1:
7817 check_cp1_64bitmode(ctx);
7818 tcg_gen_andi_tl(t0, t0, ~0x7);
7820 TCGv_i64 fp0 = tcg_temp_new_i64();
7822 gen_load_fpr64(ctx, fp0, fs);
7823 tcg_gen_qemu_st64(fp0, t0, ctx->mem_idx);
7824 tcg_temp_free_i64(fp0);
7826 opn = "suxc1";
7827 store = 1;
7828 break;
7830 tcg_temp_free(t0);
7831 (void)opn; (void)store; /* avoid compiler warnings */
7832 MIPS_DEBUG("%s %s, %s(%s)", opn, fregnames[store ? fs : fd],
7833 regnames[index], regnames[base]);
7836 static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
7837 int fd, int fr, int fs, int ft)
7839 const char *opn = "flt3_arith";
7841 switch (opc) {
7842 case OPC_ALNV_PS:
7843 check_cp1_64bitmode(ctx);
7845 TCGv t0 = tcg_temp_local_new();
7846 TCGv_i32 fp = tcg_temp_new_i32();
7847 TCGv_i32 fph = tcg_temp_new_i32();
7848 int l1 = gen_new_label();
7849 int l2 = gen_new_label();
7851 gen_load_gpr(t0, fr);
7852 tcg_gen_andi_tl(t0, t0, 0x7);
7854 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 0, l1);
7855 gen_load_fpr32(fp, fs);
7856 gen_load_fpr32h(fph, fs);
7857 gen_store_fpr32(fp, fd);
7858 gen_store_fpr32h(fph, fd);
7859 tcg_gen_br(l2);
7860 gen_set_label(l1);
7861 tcg_gen_brcondi_tl(TCG_COND_NE, t0, 4, l2);
7862 tcg_temp_free(t0);
7863 #ifdef TARGET_WORDS_BIGENDIAN
7864 gen_load_fpr32(fp, fs);
7865 gen_load_fpr32h(fph, ft);
7866 gen_store_fpr32h(fp, fd);
7867 gen_store_fpr32(fph, fd);
7868 #else
7869 gen_load_fpr32h(fph, fs);
7870 gen_load_fpr32(fp, ft);
7871 gen_store_fpr32(fph, fd);
7872 gen_store_fpr32h(fp, fd);
7873 #endif
7874 gen_set_label(l2);
7875 tcg_temp_free_i32(fp);
7876 tcg_temp_free_i32(fph);
7878 opn = "alnv.ps";
7879 break;
7880 case OPC_MADD_S:
7881 check_cop1x(ctx);
7883 TCGv_i32 fp0 = tcg_temp_new_i32();
7884 TCGv_i32 fp1 = tcg_temp_new_i32();
7885 TCGv_i32 fp2 = tcg_temp_new_i32();
7887 gen_load_fpr32(fp0, fs);
7888 gen_load_fpr32(fp1, ft);
7889 gen_load_fpr32(fp2, fr);
7890 gen_helper_float_muladd_s(fp2, fp0, fp1, fp2);
7891 tcg_temp_free_i32(fp0);
7892 tcg_temp_free_i32(fp1);
7893 gen_store_fpr32(fp2, fd);
7894 tcg_temp_free_i32(fp2);
7896 opn = "madd.s";
7897 break;
7898 case OPC_MADD_D:
7899 check_cop1x(ctx);
7900 check_cp1_registers(ctx, fd | fs | ft | fr);
7902 TCGv_i64 fp0 = tcg_temp_new_i64();
7903 TCGv_i64 fp1 = tcg_temp_new_i64();
7904 TCGv_i64 fp2 = tcg_temp_new_i64();
7906 gen_load_fpr64(ctx, fp0, fs);
7907 gen_load_fpr64(ctx, fp1, ft);
7908 gen_load_fpr64(ctx, fp2, fr);
7909 gen_helper_float_muladd_d(fp2, fp0, fp1, fp2);
7910 tcg_temp_free_i64(fp0);
7911 tcg_temp_free_i64(fp1);
7912 gen_store_fpr64(ctx, fp2, fd);
7913 tcg_temp_free_i64(fp2);
7915 opn = "madd.d";
7916 break;
7917 case OPC_MADD_PS:
7918 check_cp1_64bitmode(ctx);
7920 TCGv_i64 fp0 = tcg_temp_new_i64();
7921 TCGv_i64 fp1 = tcg_temp_new_i64();
7922 TCGv_i64 fp2 = tcg_temp_new_i64();
7924 gen_load_fpr64(ctx, fp0, fs);
7925 gen_load_fpr64(ctx, fp1, ft);
7926 gen_load_fpr64(ctx, fp2, fr);
7927 gen_helper_float_muladd_ps(fp2, fp0, fp1, fp2);
7928 tcg_temp_free_i64(fp0);
7929 tcg_temp_free_i64(fp1);
7930 gen_store_fpr64(ctx, fp2, fd);
7931 tcg_temp_free_i64(fp2);
7933 opn = "madd.ps";
7934 break;
7935 case OPC_MSUB_S:
7936 check_cop1x(ctx);
7938 TCGv_i32 fp0 = tcg_temp_new_i32();
7939 TCGv_i32 fp1 = tcg_temp_new_i32();
7940 TCGv_i32 fp2 = tcg_temp_new_i32();
7942 gen_load_fpr32(fp0, fs);
7943 gen_load_fpr32(fp1, ft);
7944 gen_load_fpr32(fp2, fr);
7945 gen_helper_float_mulsub_s(fp2, fp0, fp1, fp2);
7946 tcg_temp_free_i32(fp0);
7947 tcg_temp_free_i32(fp1);
7948 gen_store_fpr32(fp2, fd);
7949 tcg_temp_free_i32(fp2);
7951 opn = "msub.s";
7952 break;
7953 case OPC_MSUB_D:
7954 check_cop1x(ctx);
7955 check_cp1_registers(ctx, fd | fs | ft | fr);
7957 TCGv_i64 fp0 = tcg_temp_new_i64();
7958 TCGv_i64 fp1 = tcg_temp_new_i64();
7959 TCGv_i64 fp2 = tcg_temp_new_i64();
7961 gen_load_fpr64(ctx, fp0, fs);
7962 gen_load_fpr64(ctx, fp1, ft);
7963 gen_load_fpr64(ctx, fp2, fr);
7964 gen_helper_float_mulsub_d(fp2, fp0, fp1, fp2);
7965 tcg_temp_free_i64(fp0);
7966 tcg_temp_free_i64(fp1);
7967 gen_store_fpr64(ctx, fp2, fd);
7968 tcg_temp_free_i64(fp2);
7970 opn = "msub.d";
7971 break;
7972 case OPC_MSUB_PS:
7973 check_cp1_64bitmode(ctx);
7975 TCGv_i64 fp0 = tcg_temp_new_i64();
7976 TCGv_i64 fp1 = tcg_temp_new_i64();
7977 TCGv_i64 fp2 = tcg_temp_new_i64();
7979 gen_load_fpr64(ctx, fp0, fs);
7980 gen_load_fpr64(ctx, fp1, ft);
7981 gen_load_fpr64(ctx, fp2, fr);
7982 gen_helper_float_mulsub_ps(fp2, fp0, fp1, fp2);
7983 tcg_temp_free_i64(fp0);
7984 tcg_temp_free_i64(fp1);
7985 gen_store_fpr64(ctx, fp2, fd);
7986 tcg_temp_free_i64(fp2);
7988 opn = "msub.ps";
7989 break;
7990 case OPC_NMADD_S:
7991 check_cop1x(ctx);
7993 TCGv_i32 fp0 = tcg_temp_new_i32();
7994 TCGv_i32 fp1 = tcg_temp_new_i32();
7995 TCGv_i32 fp2 = tcg_temp_new_i32();
7997 gen_load_fpr32(fp0, fs);
7998 gen_load_fpr32(fp1, ft);
7999 gen_load_fpr32(fp2, fr);
8000 gen_helper_float_nmuladd_s(fp2, fp0, fp1, fp2);
8001 tcg_temp_free_i32(fp0);
8002 tcg_temp_free_i32(fp1);
8003 gen_store_fpr32(fp2, fd);
8004 tcg_temp_free_i32(fp2);
8006 opn = "nmadd.s";
8007 break;
8008 case OPC_NMADD_D:
8009 check_cop1x(ctx);
8010 check_cp1_registers(ctx, fd | fs | ft | fr);
8012 TCGv_i64 fp0 = tcg_temp_new_i64();
8013 TCGv_i64 fp1 = tcg_temp_new_i64();
8014 TCGv_i64 fp2 = tcg_temp_new_i64();
8016 gen_load_fpr64(ctx, fp0, fs);
8017 gen_load_fpr64(ctx, fp1, ft);
8018 gen_load_fpr64(ctx, fp2, fr);
8019 gen_helper_float_nmuladd_d(fp2, fp0, fp1, fp2);
8020 tcg_temp_free_i64(fp0);
8021 tcg_temp_free_i64(fp1);
8022 gen_store_fpr64(ctx, fp2, fd);
8023 tcg_temp_free_i64(fp2);
8025 opn = "nmadd.d";
8026 break;
8027 case OPC_NMADD_PS:
8028 check_cp1_64bitmode(ctx);
8030 TCGv_i64 fp0 = tcg_temp_new_i64();
8031 TCGv_i64 fp1 = tcg_temp_new_i64();
8032 TCGv_i64 fp2 = tcg_temp_new_i64();
8034 gen_load_fpr64(ctx, fp0, fs);
8035 gen_load_fpr64(ctx, fp1, ft);
8036 gen_load_fpr64(ctx, fp2, fr);
8037 gen_helper_float_nmuladd_ps(fp2, fp0, fp1, fp2);
8038 tcg_temp_free_i64(fp0);
8039 tcg_temp_free_i64(fp1);
8040 gen_store_fpr64(ctx, fp2, fd);
8041 tcg_temp_free_i64(fp2);
8043 opn = "nmadd.ps";
8044 break;
8045 case OPC_NMSUB_S:
8046 check_cop1x(ctx);
8048 TCGv_i32 fp0 = tcg_temp_new_i32();
8049 TCGv_i32 fp1 = tcg_temp_new_i32();
8050 TCGv_i32 fp2 = tcg_temp_new_i32();
8052 gen_load_fpr32(fp0, fs);
8053 gen_load_fpr32(fp1, ft);
8054 gen_load_fpr32(fp2, fr);
8055 gen_helper_float_nmulsub_s(fp2, fp0, fp1, fp2);
8056 tcg_temp_free_i32(fp0);
8057 tcg_temp_free_i32(fp1);
8058 gen_store_fpr32(fp2, fd);
8059 tcg_temp_free_i32(fp2);
8061 opn = "nmsub.s";
8062 break;
8063 case OPC_NMSUB_D:
8064 check_cop1x(ctx);
8065 check_cp1_registers(ctx, fd | fs | ft | fr);
8067 TCGv_i64 fp0 = tcg_temp_new_i64();
8068 TCGv_i64 fp1 = tcg_temp_new_i64();
8069 TCGv_i64 fp2 = tcg_temp_new_i64();
8071 gen_load_fpr64(ctx, fp0, fs);
8072 gen_load_fpr64(ctx, fp1, ft);
8073 gen_load_fpr64(ctx, fp2, fr);
8074 gen_helper_float_nmulsub_d(fp2, fp0, fp1, fp2);
8075 tcg_temp_free_i64(fp0);
8076 tcg_temp_free_i64(fp1);
8077 gen_store_fpr64(ctx, fp2, fd);
8078 tcg_temp_free_i64(fp2);
8080 opn = "nmsub.d";
8081 break;
8082 case OPC_NMSUB_PS:
8083 check_cp1_64bitmode(ctx);
8085 TCGv_i64 fp0 = tcg_temp_new_i64();
8086 TCGv_i64 fp1 = tcg_temp_new_i64();
8087 TCGv_i64 fp2 = tcg_temp_new_i64();
8089 gen_load_fpr64(ctx, fp0, fs);
8090 gen_load_fpr64(ctx, fp1, ft);
8091 gen_load_fpr64(ctx, fp2, fr);
8092 gen_helper_float_nmulsub_ps(fp2, fp0, fp1, fp2);
8093 tcg_temp_free_i64(fp0);
8094 tcg_temp_free_i64(fp1);
8095 gen_store_fpr64(ctx, fp2, fd);
8096 tcg_temp_free_i64(fp2);
8098 opn = "nmsub.ps";
8099 break;
8100 default:
8101 MIPS_INVAL(opn);
8102 generate_exception (ctx, EXCP_RI);
8103 return;
8105 (void)opn; /* avoid a compiler warning */
8106 MIPS_DEBUG("%s %s, %s, %s, %s", opn, fregnames[fd], fregnames[fr],
8107 fregnames[fs], fregnames[ft]);
8110 static void
8111 gen_rdhwr (CPUMIPSState *env, DisasContext *ctx, int rt, int rd)
8113 TCGv t0;
8115 check_insn(env, ctx, ISA_MIPS32R2);
8116 t0 = tcg_temp_new();
8118 switch (rd) {
8119 case 0:
8120 save_cpu_state(ctx, 1);
8121 gen_helper_rdhwr_cpunum(t0);
8122 gen_store_gpr(t0, rt);
8123 break;
8124 case 1:
8125 save_cpu_state(ctx, 1);
8126 gen_helper_rdhwr_synci_step(t0);
8127 gen_store_gpr(t0, rt);
8128 break;
8129 case 2:
8130 save_cpu_state(ctx, 1);
8131 gen_helper_rdhwr_cc(t0);
8132 gen_store_gpr(t0, rt);
8133 break;
8134 case 3:
8135 save_cpu_state(ctx, 1);
8136 gen_helper_rdhwr_ccres(t0);
8137 gen_store_gpr(t0, rt);
8138 break;
8139 case 29:
8140 #if defined(CONFIG_USER_ONLY)
8141 tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUMIPSState, tls_value));
8142 gen_store_gpr(t0, rt);
8143 break;
8144 #else
8145 /* XXX: Some CPUs implement this in hardware.
8146 Not supported yet. */
8147 #endif
8148 default: /* Invalid */
8149 MIPS_INVAL("rdhwr");
8150 generate_exception(ctx, EXCP_RI);
8151 break;
8153 tcg_temp_free(t0);
8156 static void handle_delay_slot (CPUMIPSState *env, DisasContext *ctx,
8157 int insn_bytes)
8159 if (ctx->hflags & MIPS_HFLAG_BMASK) {
8160 int proc_hflags = ctx->hflags & MIPS_HFLAG_BMASK;
8161 /* Branches completion */
8162 ctx->hflags &= ~MIPS_HFLAG_BMASK;
8163 ctx->bstate = BS_BRANCH;
8164 save_cpu_state(ctx, 0);
8165 /* FIXME: Need to clear can_do_io. */
8166 switch (proc_hflags & MIPS_HFLAG_BMASK_BASE) {
8167 case MIPS_HFLAG_B:
8168 /* unconditional branch */
8169 MIPS_DEBUG("unconditional branch");
8170 if (proc_hflags & MIPS_HFLAG_BX) {
8171 tcg_gen_xori_i32(hflags, hflags, MIPS_HFLAG_M16);
8173 gen_goto_tb(ctx, 0, ctx->btarget);
8174 break;
8175 case MIPS_HFLAG_BL:
8176 /* blikely taken case */
8177 MIPS_DEBUG("blikely branch taken");
8178 gen_goto_tb(ctx, 0, ctx->btarget);
8179 break;
8180 case MIPS_HFLAG_BC:
8181 /* Conditional branch */
8182 MIPS_DEBUG("conditional branch");
8184 int l1 = gen_new_label();
8186 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
8187 gen_goto_tb(ctx, 1, ctx->pc + insn_bytes);
8188 gen_set_label(l1);
8189 gen_goto_tb(ctx, 0, ctx->btarget);
8191 break;
8192 case MIPS_HFLAG_BR:
8193 /* unconditional branch to register */
8194 MIPS_DEBUG("branch to register");
8195 if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
8196 TCGv t0 = tcg_temp_new();
8197 TCGv_i32 t1 = tcg_temp_new_i32();
8199 tcg_gen_andi_tl(t0, btarget, 0x1);
8200 tcg_gen_trunc_tl_i32(t1, t0);
8201 tcg_temp_free(t0);
8202 tcg_gen_andi_i32(hflags, hflags, ~(uint32_t)MIPS_HFLAG_M16);
8203 tcg_gen_shli_i32(t1, t1, MIPS_HFLAG_M16_SHIFT);
8204 tcg_gen_or_i32(hflags, hflags, t1);
8205 tcg_temp_free_i32(t1);
8207 tcg_gen_andi_tl(cpu_PC, btarget, ~(target_ulong)0x1);
8208 } else {
8209 tcg_gen_mov_tl(cpu_PC, btarget);
8211 if (ctx->singlestep_enabled) {
8212 save_cpu_state(ctx, 0);
8213 gen_helper_0i(raise_exception, EXCP_DEBUG);
8215 tcg_gen_exit_tb(0);
8216 break;
8217 default:
8218 MIPS_DEBUG("unknown branch");
8219 break;
8224 /* ISA extensions (ASEs) */
8225 /* MIPS16 extension to MIPS32 */
8227 /* MIPS16 major opcodes */
8228 enum {
8229 M16_OPC_ADDIUSP = 0x00,
8230 M16_OPC_ADDIUPC = 0x01,
8231 M16_OPC_B = 0x02,
8232 M16_OPC_JAL = 0x03,
8233 M16_OPC_BEQZ = 0x04,
8234 M16_OPC_BNEQZ = 0x05,
8235 M16_OPC_SHIFT = 0x06,
8236 M16_OPC_LD = 0x07,
8237 M16_OPC_RRIA = 0x08,
8238 M16_OPC_ADDIU8 = 0x09,
8239 M16_OPC_SLTI = 0x0a,
8240 M16_OPC_SLTIU = 0x0b,
8241 M16_OPC_I8 = 0x0c,
8242 M16_OPC_LI = 0x0d,
8243 M16_OPC_CMPI = 0x0e,
8244 M16_OPC_SD = 0x0f,
8245 M16_OPC_LB = 0x10,
8246 M16_OPC_LH = 0x11,
8247 M16_OPC_LWSP = 0x12,
8248 M16_OPC_LW = 0x13,
8249 M16_OPC_LBU = 0x14,
8250 M16_OPC_LHU = 0x15,
8251 M16_OPC_LWPC = 0x16,
8252 M16_OPC_LWU = 0x17,
8253 M16_OPC_SB = 0x18,
8254 M16_OPC_SH = 0x19,
8255 M16_OPC_SWSP = 0x1a,
8256 M16_OPC_SW = 0x1b,
8257 M16_OPC_RRR = 0x1c,
8258 M16_OPC_RR = 0x1d,
8259 M16_OPC_EXTEND = 0x1e,
8260 M16_OPC_I64 = 0x1f
8263 /* I8 funct field */
8264 enum {
8265 I8_BTEQZ = 0x0,
8266 I8_BTNEZ = 0x1,
8267 I8_SWRASP = 0x2,
8268 I8_ADJSP = 0x3,
8269 I8_SVRS = 0x4,
8270 I8_MOV32R = 0x5,
8271 I8_MOVR32 = 0x7
8274 /* RRR f field */
8275 enum {
8276 RRR_DADDU = 0x0,
8277 RRR_ADDU = 0x1,
8278 RRR_DSUBU = 0x2,
8279 RRR_SUBU = 0x3
8282 /* RR funct field */
8283 enum {
8284 RR_JR = 0x00,
8285 RR_SDBBP = 0x01,
8286 RR_SLT = 0x02,
8287 RR_SLTU = 0x03,
8288 RR_SLLV = 0x04,
8289 RR_BREAK = 0x05,
8290 RR_SRLV = 0x06,
8291 RR_SRAV = 0x07,
8292 RR_DSRL = 0x08,
8293 RR_CMP = 0x0a,
8294 RR_NEG = 0x0b,
8295 RR_AND = 0x0c,
8296 RR_OR = 0x0d,
8297 RR_XOR = 0x0e,
8298 RR_NOT = 0x0f,
8299 RR_MFHI = 0x10,
8300 RR_CNVT = 0x11,
8301 RR_MFLO = 0x12,
8302 RR_DSRA = 0x13,
8303 RR_DSLLV = 0x14,
8304 RR_DSRLV = 0x16,
8305 RR_DSRAV = 0x17,
8306 RR_MULT = 0x18,
8307 RR_MULTU = 0x19,
8308 RR_DIV = 0x1a,
8309 RR_DIVU = 0x1b,
8310 RR_DMULT = 0x1c,
8311 RR_DMULTU = 0x1d,
8312 RR_DDIV = 0x1e,
8313 RR_DDIVU = 0x1f
8316 /* I64 funct field */
8317 enum {
8318 I64_LDSP = 0x0,
8319 I64_SDSP = 0x1,
8320 I64_SDRASP = 0x2,
8321 I64_DADJSP = 0x3,
8322 I64_LDPC = 0x4,
8323 I64_DADDIU5 = 0x5,
8324 I64_DADDIUPC = 0x6,
8325 I64_DADDIUSP = 0x7
8328 /* RR ry field for CNVT */
8329 enum {
8330 RR_RY_CNVT_ZEB = 0x0,
8331 RR_RY_CNVT_ZEH = 0x1,
8332 RR_RY_CNVT_ZEW = 0x2,
8333 RR_RY_CNVT_SEB = 0x4,
8334 RR_RY_CNVT_SEH = 0x5,
8335 RR_RY_CNVT_SEW = 0x6,
8338 static int xlat (int r)
8340 static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
8342 return map[r];
8345 static void gen_mips16_save (DisasContext *ctx,
8346 int xsregs, int aregs,
8347 int do_ra, int do_s0, int do_s1,
8348 int framesize)
8350 TCGv t0 = tcg_temp_new();
8351 TCGv t1 = tcg_temp_new();
8352 int args, astatic;
8354 switch (aregs) {
8355 case 0:
8356 case 1:
8357 case 2:
8358 case 3:
8359 case 11:
8360 args = 0;
8361 break;
8362 case 4:
8363 case 5:
8364 case 6:
8365 case 7:
8366 args = 1;
8367 break;
8368 case 8:
8369 case 9:
8370 case 10:
8371 args = 2;
8372 break;
8373 case 12:
8374 case 13:
8375 args = 3;
8376 break;
8377 case 14:
8378 args = 4;
8379 break;
8380 default:
8381 generate_exception(ctx, EXCP_RI);
8382 return;
8385 switch (args) {
8386 case 4:
8387 gen_base_offset_addr(ctx, t0, 29, 12);
8388 gen_load_gpr(t1, 7);
8389 op_st_sw(t1, t0, ctx);
8390 /* Fall through */
8391 case 3:
8392 gen_base_offset_addr(ctx, t0, 29, 8);
8393 gen_load_gpr(t1, 6);
8394 op_st_sw(t1, t0, ctx);
8395 /* Fall through */
8396 case 2:
8397 gen_base_offset_addr(ctx, t0, 29, 4);
8398 gen_load_gpr(t1, 5);
8399 op_st_sw(t1, t0, ctx);
8400 /* Fall through */
8401 case 1:
8402 gen_base_offset_addr(ctx, t0, 29, 0);
8403 gen_load_gpr(t1, 4);
8404 op_st_sw(t1, t0, ctx);
8407 gen_load_gpr(t0, 29);
8409 #define DECR_AND_STORE(reg) do { \
8410 tcg_gen_subi_tl(t0, t0, 4); \
8411 gen_load_gpr(t1, reg); \
8412 op_st_sw(t1, t0, ctx); \
8413 } while (0)
8415 if (do_ra) {
8416 DECR_AND_STORE(31);
8419 switch (xsregs) {
8420 case 7:
8421 DECR_AND_STORE(30);
8422 /* Fall through */
8423 case 6:
8424 DECR_AND_STORE(23);
8425 /* Fall through */
8426 case 5:
8427 DECR_AND_STORE(22);
8428 /* Fall through */
8429 case 4:
8430 DECR_AND_STORE(21);
8431 /* Fall through */
8432 case 3:
8433 DECR_AND_STORE(20);
8434 /* Fall through */
8435 case 2:
8436 DECR_AND_STORE(19);
8437 /* Fall through */
8438 case 1:
8439 DECR_AND_STORE(18);
8442 if (do_s1) {
8443 DECR_AND_STORE(17);
8445 if (do_s0) {
8446 DECR_AND_STORE(16);
8449 switch (aregs) {
8450 case 0:
8451 case 4:
8452 case 8:
8453 case 12:
8454 case 14:
8455 astatic = 0;
8456 break;
8457 case 1:
8458 case 5:
8459 case 9:
8460 case 13:
8461 astatic = 1;
8462 break;
8463 case 2:
8464 case 6:
8465 case 10:
8466 astatic = 2;
8467 break;
8468 case 3:
8469 case 7:
8470 astatic = 3;
8471 break;
8472 case 11:
8473 astatic = 4;
8474 break;
8475 default:
8476 generate_exception(ctx, EXCP_RI);
8477 return;
8480 if (astatic > 0) {
8481 DECR_AND_STORE(7);
8482 if (astatic > 1) {
8483 DECR_AND_STORE(6);
8484 if (astatic > 2) {
8485 DECR_AND_STORE(5);
8486 if (astatic > 3) {
8487 DECR_AND_STORE(4);
8492 #undef DECR_AND_STORE
8494 tcg_gen_subi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8495 tcg_temp_free(t0);
8496 tcg_temp_free(t1);
8499 static void gen_mips16_restore (DisasContext *ctx,
8500 int xsregs, int aregs,
8501 int do_ra, int do_s0, int do_s1,
8502 int framesize)
8504 int astatic;
8505 TCGv t0 = tcg_temp_new();
8506 TCGv t1 = tcg_temp_new();
8508 tcg_gen_addi_tl(t0, cpu_gpr[29], framesize);
8510 #define DECR_AND_LOAD(reg) do { \
8511 tcg_gen_subi_tl(t0, t0, 4); \
8512 op_ld_lw(t1, t0, ctx); \
8513 gen_store_gpr(t1, reg); \
8514 } while (0)
8516 if (do_ra) {
8517 DECR_AND_LOAD(31);
8520 switch (xsregs) {
8521 case 7:
8522 DECR_AND_LOAD(30);
8523 /* Fall through */
8524 case 6:
8525 DECR_AND_LOAD(23);
8526 /* Fall through */
8527 case 5:
8528 DECR_AND_LOAD(22);
8529 /* Fall through */
8530 case 4:
8531 DECR_AND_LOAD(21);
8532 /* Fall through */
8533 case 3:
8534 DECR_AND_LOAD(20);
8535 /* Fall through */
8536 case 2:
8537 DECR_AND_LOAD(19);
8538 /* Fall through */
8539 case 1:
8540 DECR_AND_LOAD(18);
8543 if (do_s1) {
8544 DECR_AND_LOAD(17);
8546 if (do_s0) {
8547 DECR_AND_LOAD(16);
8550 switch (aregs) {
8551 case 0:
8552 case 4:
8553 case 8:
8554 case 12:
8555 case 14:
8556 astatic = 0;
8557 break;
8558 case 1:
8559 case 5:
8560 case 9:
8561 case 13:
8562 astatic = 1;
8563 break;
8564 case 2:
8565 case 6:
8566 case 10:
8567 astatic = 2;
8568 break;
8569 case 3:
8570 case 7:
8571 astatic = 3;
8572 break;
8573 case 11:
8574 astatic = 4;
8575 break;
8576 default:
8577 generate_exception(ctx, EXCP_RI);
8578 return;
8581 if (astatic > 0) {
8582 DECR_AND_LOAD(7);
8583 if (astatic > 1) {
8584 DECR_AND_LOAD(6);
8585 if (astatic > 2) {
8586 DECR_AND_LOAD(5);
8587 if (astatic > 3) {
8588 DECR_AND_LOAD(4);
8593 #undef DECR_AND_LOAD
8595 tcg_gen_addi_tl(cpu_gpr[29], cpu_gpr[29], framesize);
8596 tcg_temp_free(t0);
8597 tcg_temp_free(t1);
8600 static void gen_addiupc (DisasContext *ctx, int rx, int imm,
8601 int is_64_bit, int extended)
8603 TCGv t0;
8605 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8606 generate_exception(ctx, EXCP_RI);
8607 return;
8610 t0 = tcg_temp_new();
8612 tcg_gen_movi_tl(t0, pc_relative_pc(ctx));
8613 tcg_gen_addi_tl(cpu_gpr[rx], t0, imm);
8614 if (!is_64_bit) {
8615 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
8618 tcg_temp_free(t0);
8621 #if defined(TARGET_MIPS64)
8622 static void decode_i64_mips16 (CPUMIPSState *env, DisasContext *ctx,
8623 int ry, int funct, int16_t offset,
8624 int extended)
8626 switch (funct) {
8627 case I64_LDSP:
8628 check_mips_64(ctx);
8629 offset = extended ? offset : offset << 3;
8630 gen_ld(env, ctx, OPC_LD, ry, 29, offset);
8631 break;
8632 case I64_SDSP:
8633 check_mips_64(ctx);
8634 offset = extended ? offset : offset << 3;
8635 gen_st(ctx, OPC_SD, ry, 29, offset);
8636 break;
8637 case I64_SDRASP:
8638 check_mips_64(ctx);
8639 offset = extended ? offset : (ctx->opcode & 0xff) << 3;
8640 gen_st(ctx, OPC_SD, 31, 29, offset);
8641 break;
8642 case I64_DADJSP:
8643 check_mips_64(ctx);
8644 offset = extended ? offset : ((int8_t)ctx->opcode) << 3;
8645 gen_arith_imm(env, ctx, OPC_DADDIU, 29, 29, offset);
8646 break;
8647 case I64_LDPC:
8648 if (extended && (ctx->hflags & MIPS_HFLAG_BMASK)) {
8649 generate_exception(ctx, EXCP_RI);
8650 } else {
8651 offset = extended ? offset : offset << 3;
8652 gen_ld(env, ctx, OPC_LDPC, ry, 0, offset);
8654 break;
8655 case I64_DADDIU5:
8656 check_mips_64(ctx);
8657 offset = extended ? offset : ((int8_t)(offset << 3)) >> 3;
8658 gen_arith_imm(env, ctx, OPC_DADDIU, ry, ry, offset);
8659 break;
8660 case I64_DADDIUPC:
8661 check_mips_64(ctx);
8662 offset = extended ? offset : offset << 2;
8663 gen_addiupc(ctx, ry, offset, 1, extended);
8664 break;
8665 case I64_DADDIUSP:
8666 check_mips_64(ctx);
8667 offset = extended ? offset : offset << 2;
8668 gen_arith_imm(env, ctx, OPC_DADDIU, ry, 29, offset);
8669 break;
8672 #endif
8674 static int decode_extended_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
8675 int *is_branch)
8677 int extend = lduw_code(ctx->pc + 2);
8678 int op, rx, ry, funct, sa;
8679 int16_t imm, offset;
8681 ctx->opcode = (ctx->opcode << 16) | extend;
8682 op = (ctx->opcode >> 11) & 0x1f;
8683 sa = (ctx->opcode >> 22) & 0x1f;
8684 funct = (ctx->opcode >> 8) & 0x7;
8685 rx = xlat((ctx->opcode >> 8) & 0x7);
8686 ry = xlat((ctx->opcode >> 5) & 0x7);
8687 offset = imm = (int16_t) (((ctx->opcode >> 16) & 0x1f) << 11
8688 | ((ctx->opcode >> 21) & 0x3f) << 5
8689 | (ctx->opcode & 0x1f));
8691 /* The extended opcodes cleverly reuse the opcodes from their 16-bit
8692 counterparts. */
8693 switch (op) {
8694 case M16_OPC_ADDIUSP:
8695 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8696 break;
8697 case M16_OPC_ADDIUPC:
8698 gen_addiupc(ctx, rx, imm, 0, 1);
8699 break;
8700 case M16_OPC_B:
8701 gen_compute_branch(ctx, OPC_BEQ, 4, 0, 0, offset << 1);
8702 /* No delay slot, so just process as a normal instruction */
8703 break;
8704 case M16_OPC_BEQZ:
8705 gen_compute_branch(ctx, OPC_BEQ, 4, rx, 0, offset << 1);
8706 /* No delay slot, so just process as a normal instruction */
8707 break;
8708 case M16_OPC_BNEQZ:
8709 gen_compute_branch(ctx, OPC_BNE, 4, rx, 0, offset << 1);
8710 /* No delay slot, so just process as a normal instruction */
8711 break;
8712 case M16_OPC_SHIFT:
8713 switch (ctx->opcode & 0x3) {
8714 case 0x0:
8715 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8716 break;
8717 case 0x1:
8718 #if defined(TARGET_MIPS64)
8719 check_mips_64(ctx);
8720 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8721 #else
8722 generate_exception(ctx, EXCP_RI);
8723 #endif
8724 break;
8725 case 0x2:
8726 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8727 break;
8728 case 0x3:
8729 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8730 break;
8732 break;
8733 #if defined(TARGET_MIPS64)
8734 case M16_OPC_LD:
8735 check_mips_64(ctx);
8736 gen_ld(env, ctx, OPC_LD, ry, rx, offset);
8737 break;
8738 #endif
8739 case M16_OPC_RRIA:
8740 imm = ctx->opcode & 0xf;
8741 imm = imm | ((ctx->opcode >> 20) & 0x7f) << 4;
8742 imm = imm | ((ctx->opcode >> 16) & 0xf) << 11;
8743 imm = (int16_t) (imm << 1) >> 1;
8744 if ((ctx->opcode >> 4) & 0x1) {
8745 #if defined(TARGET_MIPS64)
8746 check_mips_64(ctx);
8747 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8748 #else
8749 generate_exception(ctx, EXCP_RI);
8750 #endif
8751 } else {
8752 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8754 break;
8755 case M16_OPC_ADDIU8:
8756 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8757 break;
8758 case M16_OPC_SLTI:
8759 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8760 break;
8761 case M16_OPC_SLTIU:
8762 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8763 break;
8764 case M16_OPC_I8:
8765 switch (funct) {
8766 case I8_BTEQZ:
8767 gen_compute_branch(ctx, OPC_BEQ, 4, 24, 0, offset << 1);
8768 break;
8769 case I8_BTNEZ:
8770 gen_compute_branch(ctx, OPC_BNE, 4, 24, 0, offset << 1);
8771 break;
8772 case I8_SWRASP:
8773 gen_st(ctx, OPC_SW, 31, 29, imm);
8774 break;
8775 case I8_ADJSP:
8776 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm);
8777 break;
8778 case I8_SVRS:
8780 int xsregs = (ctx->opcode >> 24) & 0x7;
8781 int aregs = (ctx->opcode >> 16) & 0xf;
8782 int do_ra = (ctx->opcode >> 6) & 0x1;
8783 int do_s0 = (ctx->opcode >> 5) & 0x1;
8784 int do_s1 = (ctx->opcode >> 4) & 0x1;
8785 int framesize = (((ctx->opcode >> 20) & 0xf) << 4
8786 | (ctx->opcode & 0xf)) << 3;
8788 if (ctx->opcode & (1 << 7)) {
8789 gen_mips16_save(ctx, xsregs, aregs,
8790 do_ra, do_s0, do_s1,
8791 framesize);
8792 } else {
8793 gen_mips16_restore(ctx, xsregs, aregs,
8794 do_ra, do_s0, do_s1,
8795 framesize);
8798 break;
8799 default:
8800 generate_exception(ctx, EXCP_RI);
8801 break;
8803 break;
8804 case M16_OPC_LI:
8805 tcg_gen_movi_tl(cpu_gpr[rx], (uint16_t) imm);
8806 break;
8807 case M16_OPC_CMPI:
8808 tcg_gen_xori_tl(cpu_gpr[24], cpu_gpr[rx], (uint16_t) imm);
8809 break;
8810 #if defined(TARGET_MIPS64)
8811 case M16_OPC_SD:
8812 gen_st(ctx, OPC_SD, ry, rx, offset);
8813 break;
8814 #endif
8815 case M16_OPC_LB:
8816 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
8817 break;
8818 case M16_OPC_LH:
8819 gen_ld(env, ctx, OPC_LH, ry, rx, offset);
8820 break;
8821 case M16_OPC_LWSP:
8822 gen_ld(env, ctx, OPC_LW, rx, 29, offset);
8823 break;
8824 case M16_OPC_LW:
8825 gen_ld(env, ctx, OPC_LW, ry, rx, offset);
8826 break;
8827 case M16_OPC_LBU:
8828 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
8829 break;
8830 case M16_OPC_LHU:
8831 gen_ld(env, ctx, OPC_LHU, ry, rx, offset);
8832 break;
8833 case M16_OPC_LWPC:
8834 gen_ld(env, ctx, OPC_LWPC, rx, 0, offset);
8835 break;
8836 #if defined(TARGET_MIPS64)
8837 case M16_OPC_LWU:
8838 gen_ld(env, ctx, OPC_LWU, ry, rx, offset);
8839 break;
8840 #endif
8841 case M16_OPC_SB:
8842 gen_st(ctx, OPC_SB, ry, rx, offset);
8843 break;
8844 case M16_OPC_SH:
8845 gen_st(ctx, OPC_SH, ry, rx, offset);
8846 break;
8847 case M16_OPC_SWSP:
8848 gen_st(ctx, OPC_SW, rx, 29, offset);
8849 break;
8850 case M16_OPC_SW:
8851 gen_st(ctx, OPC_SW, ry, rx, offset);
8852 break;
8853 #if defined(TARGET_MIPS64)
8854 case M16_OPC_I64:
8855 decode_i64_mips16(env, ctx, ry, funct, offset, 1);
8856 break;
8857 #endif
8858 default:
8859 generate_exception(ctx, EXCP_RI);
8860 break;
8863 return 4;
8866 static int decode_mips16_opc (CPUMIPSState *env, DisasContext *ctx,
8867 int *is_branch)
8869 int rx, ry;
8870 int sa;
8871 int op, cnvt_op, op1, offset;
8872 int funct;
8873 int n_bytes;
8875 op = (ctx->opcode >> 11) & 0x1f;
8876 sa = (ctx->opcode >> 2) & 0x7;
8877 sa = sa == 0 ? 8 : sa;
8878 rx = xlat((ctx->opcode >> 8) & 0x7);
8879 cnvt_op = (ctx->opcode >> 5) & 0x7;
8880 ry = xlat((ctx->opcode >> 5) & 0x7);
8881 op1 = offset = ctx->opcode & 0x1f;
8883 n_bytes = 2;
8885 switch (op) {
8886 case M16_OPC_ADDIUSP:
8888 int16_t imm = ((uint8_t) ctx->opcode) << 2;
8890 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 29, imm);
8892 break;
8893 case M16_OPC_ADDIUPC:
8894 gen_addiupc(ctx, rx, ((uint8_t) ctx->opcode) << 2, 0, 0);
8895 break;
8896 case M16_OPC_B:
8897 offset = (ctx->opcode & 0x7ff) << 1;
8898 offset = (int16_t)(offset << 4) >> 4;
8899 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0, offset);
8900 /* No delay slot, so just process as a normal instruction */
8901 break;
8902 case M16_OPC_JAL:
8903 offset = lduw_code(ctx->pc + 2);
8904 offset = (((ctx->opcode & 0x1f) << 21)
8905 | ((ctx->opcode >> 5) & 0x1f) << 16
8906 | offset) << 2;
8907 op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
8908 gen_compute_branch(ctx, op, 4, rx, ry, offset);
8909 n_bytes = 4;
8910 *is_branch = 1;
8911 break;
8912 case M16_OPC_BEQZ:
8913 gen_compute_branch(ctx, OPC_BEQ, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8914 /* No delay slot, so just process as a normal instruction */
8915 break;
8916 case M16_OPC_BNEQZ:
8917 gen_compute_branch(ctx, OPC_BNE, 2, rx, 0, ((int8_t)ctx->opcode) << 1);
8918 /* No delay slot, so just process as a normal instruction */
8919 break;
8920 case M16_OPC_SHIFT:
8921 switch (ctx->opcode & 0x3) {
8922 case 0x0:
8923 gen_shift_imm(env, ctx, OPC_SLL, rx, ry, sa);
8924 break;
8925 case 0x1:
8926 #if defined(TARGET_MIPS64)
8927 check_mips_64(ctx);
8928 gen_shift_imm(env, ctx, OPC_DSLL, rx, ry, sa);
8929 #else
8930 generate_exception(ctx, EXCP_RI);
8931 #endif
8932 break;
8933 case 0x2:
8934 gen_shift_imm(env, ctx, OPC_SRL, rx, ry, sa);
8935 break;
8936 case 0x3:
8937 gen_shift_imm(env, ctx, OPC_SRA, rx, ry, sa);
8938 break;
8940 break;
8941 #if defined(TARGET_MIPS64)
8942 case M16_OPC_LD:
8943 check_mips_64(ctx);
8944 gen_ld(env, ctx, OPC_LD, ry, rx, offset << 3);
8945 break;
8946 #endif
8947 case M16_OPC_RRIA:
8949 int16_t imm = (int8_t)((ctx->opcode & 0xf) << 4) >> 4;
8951 if ((ctx->opcode >> 4) & 1) {
8952 #if defined(TARGET_MIPS64)
8953 check_mips_64(ctx);
8954 gen_arith_imm(env, ctx, OPC_DADDIU, ry, rx, imm);
8955 #else
8956 generate_exception(ctx, EXCP_RI);
8957 #endif
8958 } else {
8959 gen_arith_imm(env, ctx, OPC_ADDIU, ry, rx, imm);
8962 break;
8963 case M16_OPC_ADDIU8:
8965 int16_t imm = (int8_t) ctx->opcode;
8967 gen_arith_imm(env, ctx, OPC_ADDIU, rx, rx, imm);
8969 break;
8970 case M16_OPC_SLTI:
8972 int16_t imm = (uint8_t) ctx->opcode;
8974 gen_slt_imm(env, OPC_SLTI, 24, rx, imm);
8976 break;
8977 case M16_OPC_SLTIU:
8979 int16_t imm = (uint8_t) ctx->opcode;
8981 gen_slt_imm(env, OPC_SLTIU, 24, rx, imm);
8983 break;
8984 case M16_OPC_I8:
8986 int reg32;
8988 funct = (ctx->opcode >> 8) & 0x7;
8989 switch (funct) {
8990 case I8_BTEQZ:
8991 gen_compute_branch(ctx, OPC_BEQ, 2, 24, 0,
8992 ((int8_t)ctx->opcode) << 1);
8993 break;
8994 case I8_BTNEZ:
8995 gen_compute_branch(ctx, OPC_BNE, 2, 24, 0,
8996 ((int8_t)ctx->opcode) << 1);
8997 break;
8998 case I8_SWRASP:
8999 gen_st(ctx, OPC_SW, 31, 29, (ctx->opcode & 0xff) << 2);
9000 break;
9001 case I8_ADJSP:
9002 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29,
9003 ((int8_t)ctx->opcode) << 3);
9004 break;
9005 case I8_SVRS:
9007 int do_ra = ctx->opcode & (1 << 6);
9008 int do_s0 = ctx->opcode & (1 << 5);
9009 int do_s1 = ctx->opcode & (1 << 4);
9010 int framesize = ctx->opcode & 0xf;
9012 if (framesize == 0) {
9013 framesize = 128;
9014 } else {
9015 framesize = framesize << 3;
9018 if (ctx->opcode & (1 << 7)) {
9019 gen_mips16_save(ctx, 0, 0,
9020 do_ra, do_s0, do_s1, framesize);
9021 } else {
9022 gen_mips16_restore(ctx, 0, 0,
9023 do_ra, do_s0, do_s1, framesize);
9026 break;
9027 case I8_MOV32R:
9029 int rz = xlat(ctx->opcode & 0x7);
9031 reg32 = (((ctx->opcode >> 3) & 0x3) << 3) |
9032 ((ctx->opcode >> 5) & 0x7);
9033 gen_arith(env, ctx, OPC_ADDU, reg32, rz, 0);
9035 break;
9036 case I8_MOVR32:
9037 reg32 = ctx->opcode & 0x1f;
9038 gen_arith(env, ctx, OPC_ADDU, ry, reg32, 0);
9039 break;
9040 default:
9041 generate_exception(ctx, EXCP_RI);
9042 break;
9045 break;
9046 case M16_OPC_LI:
9048 int16_t imm = (uint8_t) ctx->opcode;
9050 gen_arith_imm(env, ctx, OPC_ADDIU, rx, 0, imm);
9052 break;
9053 case M16_OPC_CMPI:
9055 int16_t imm = (uint8_t) ctx->opcode;
9057 gen_logic_imm(env, OPC_XORI, 24, rx, imm);
9059 break;
9060 #if defined(TARGET_MIPS64)
9061 case M16_OPC_SD:
9062 check_mips_64(ctx);
9063 gen_st(ctx, OPC_SD, ry, rx, offset << 3);
9064 break;
9065 #endif
9066 case M16_OPC_LB:
9067 gen_ld(env, ctx, OPC_LB, ry, rx, offset);
9068 break;
9069 case M16_OPC_LH:
9070 gen_ld(env, ctx, OPC_LH, ry, rx, offset << 1);
9071 break;
9072 case M16_OPC_LWSP:
9073 gen_ld(env, ctx, OPC_LW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9074 break;
9075 case M16_OPC_LW:
9076 gen_ld(env, ctx, OPC_LW, ry, rx, offset << 2);
9077 break;
9078 case M16_OPC_LBU:
9079 gen_ld(env, ctx, OPC_LBU, ry, rx, offset);
9080 break;
9081 case M16_OPC_LHU:
9082 gen_ld(env, ctx, OPC_LHU, ry, rx, offset << 1);
9083 break;
9084 case M16_OPC_LWPC:
9085 gen_ld(env, ctx, OPC_LWPC, rx, 0, ((uint8_t)ctx->opcode) << 2);
9086 break;
9087 #if defined (TARGET_MIPS64)
9088 case M16_OPC_LWU:
9089 check_mips_64(ctx);
9090 gen_ld(env, ctx, OPC_LWU, ry, rx, offset << 2);
9091 break;
9092 #endif
9093 case M16_OPC_SB:
9094 gen_st(ctx, OPC_SB, ry, rx, offset);
9095 break;
9096 case M16_OPC_SH:
9097 gen_st(ctx, OPC_SH, ry, rx, offset << 1);
9098 break;
9099 case M16_OPC_SWSP:
9100 gen_st(ctx, OPC_SW, rx, 29, ((uint8_t)ctx->opcode) << 2);
9101 break;
9102 case M16_OPC_SW:
9103 gen_st(ctx, OPC_SW, ry, rx, offset << 2);
9104 break;
9105 case M16_OPC_RRR:
9107 int rz = xlat((ctx->opcode >> 2) & 0x7);
9108 int mips32_op;
9110 switch (ctx->opcode & 0x3) {
9111 case RRR_ADDU:
9112 mips32_op = OPC_ADDU;
9113 break;
9114 case RRR_SUBU:
9115 mips32_op = OPC_SUBU;
9116 break;
9117 #if defined(TARGET_MIPS64)
9118 case RRR_DADDU:
9119 mips32_op = OPC_DADDU;
9120 check_mips_64(ctx);
9121 break;
9122 case RRR_DSUBU:
9123 mips32_op = OPC_DSUBU;
9124 check_mips_64(ctx);
9125 break;
9126 #endif
9127 default:
9128 generate_exception(ctx, EXCP_RI);
9129 goto done;
9132 gen_arith(env, ctx, mips32_op, rz, rx, ry);
9133 done:
9136 break;
9137 case M16_OPC_RR:
9138 switch (op1) {
9139 case RR_JR:
9141 int nd = (ctx->opcode >> 7) & 0x1;
9142 int link = (ctx->opcode >> 6) & 0x1;
9143 int ra = (ctx->opcode >> 5) & 0x1;
9145 if (link) {
9146 op = nd ? OPC_JALRC : OPC_JALRS;
9147 } else {
9148 op = OPC_JR;
9151 gen_compute_branch(ctx, op, 2, ra ? 31 : rx, 31, 0);
9152 if (!nd) {
9153 *is_branch = 1;
9156 break;
9157 case RR_SDBBP:
9158 /* XXX: not clear which exception should be raised
9159 * when in debug mode...
9161 check_insn(env, ctx, ISA_MIPS32);
9162 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9163 generate_exception(ctx, EXCP_DBp);
9164 } else {
9165 generate_exception(ctx, EXCP_DBp);
9167 break;
9168 case RR_SLT:
9169 gen_slt(env, OPC_SLT, 24, rx, ry);
9170 break;
9171 case RR_SLTU:
9172 gen_slt(env, OPC_SLTU, 24, rx, ry);
9173 break;
9174 case RR_BREAK:
9175 generate_exception(ctx, EXCP_BREAK);
9176 break;
9177 case RR_SLLV:
9178 gen_shift(env, ctx, OPC_SLLV, ry, rx, ry);
9179 break;
9180 case RR_SRLV:
9181 gen_shift(env, ctx, OPC_SRLV, ry, rx, ry);
9182 break;
9183 case RR_SRAV:
9184 gen_shift(env, ctx, OPC_SRAV, ry, rx, ry);
9185 break;
9186 #if defined (TARGET_MIPS64)
9187 case RR_DSRL:
9188 check_mips_64(ctx);
9189 gen_shift_imm(env, ctx, OPC_DSRL, ry, ry, sa);
9190 break;
9191 #endif
9192 case RR_CMP:
9193 gen_logic(env, OPC_XOR, 24, rx, ry);
9194 break;
9195 case RR_NEG:
9196 gen_arith(env, ctx, OPC_SUBU, rx, 0, ry);
9197 break;
9198 case RR_AND:
9199 gen_logic(env, OPC_AND, rx, rx, ry);
9200 break;
9201 case RR_OR:
9202 gen_logic(env, OPC_OR, rx, rx, ry);
9203 break;
9204 case RR_XOR:
9205 gen_logic(env, OPC_XOR, rx, rx, ry);
9206 break;
9207 case RR_NOT:
9208 gen_logic(env, OPC_NOR, rx, ry, 0);
9209 break;
9210 case RR_MFHI:
9211 gen_HILO(ctx, OPC_MFHI, rx);
9212 break;
9213 case RR_CNVT:
9214 switch (cnvt_op) {
9215 case RR_RY_CNVT_ZEB:
9216 tcg_gen_ext8u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9217 break;
9218 case RR_RY_CNVT_ZEH:
9219 tcg_gen_ext16u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9220 break;
9221 case RR_RY_CNVT_SEB:
9222 tcg_gen_ext8s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9223 break;
9224 case RR_RY_CNVT_SEH:
9225 tcg_gen_ext16s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9226 break;
9227 #if defined (TARGET_MIPS64)
9228 case RR_RY_CNVT_ZEW:
9229 check_mips_64(ctx);
9230 tcg_gen_ext32u_tl(cpu_gpr[rx], cpu_gpr[rx]);
9231 break;
9232 case RR_RY_CNVT_SEW:
9233 check_mips_64(ctx);
9234 tcg_gen_ext32s_tl(cpu_gpr[rx], cpu_gpr[rx]);
9235 break;
9236 #endif
9237 default:
9238 generate_exception(ctx, EXCP_RI);
9239 break;
9241 break;
9242 case RR_MFLO:
9243 gen_HILO(ctx, OPC_MFLO, rx);
9244 break;
9245 #if defined (TARGET_MIPS64)
9246 case RR_DSRA:
9247 check_mips_64(ctx);
9248 gen_shift_imm(env, ctx, OPC_DSRA, ry, ry, sa);
9249 break;
9250 case RR_DSLLV:
9251 check_mips_64(ctx);
9252 gen_shift(env, ctx, OPC_DSLLV, ry, rx, ry);
9253 break;
9254 case RR_DSRLV:
9255 check_mips_64(ctx);
9256 gen_shift(env, ctx, OPC_DSRLV, ry, rx, ry);
9257 break;
9258 case RR_DSRAV:
9259 check_mips_64(ctx);
9260 gen_shift(env, ctx, OPC_DSRAV, ry, rx, ry);
9261 break;
9262 #endif
9263 case RR_MULT:
9264 gen_muldiv(ctx, OPC_MULT, rx, ry);
9265 break;
9266 case RR_MULTU:
9267 gen_muldiv(ctx, OPC_MULTU, rx, ry);
9268 break;
9269 case RR_DIV:
9270 gen_muldiv(ctx, OPC_DIV, rx, ry);
9271 break;
9272 case RR_DIVU:
9273 gen_muldiv(ctx, OPC_DIVU, rx, ry);
9274 break;
9275 #if defined (TARGET_MIPS64)
9276 case RR_DMULT:
9277 check_mips_64(ctx);
9278 gen_muldiv(ctx, OPC_DMULT, rx, ry);
9279 break;
9280 case RR_DMULTU:
9281 check_mips_64(ctx);
9282 gen_muldiv(ctx, OPC_DMULTU, rx, ry);
9283 break;
9284 case RR_DDIV:
9285 check_mips_64(ctx);
9286 gen_muldiv(ctx, OPC_DDIV, rx, ry);
9287 break;
9288 case RR_DDIVU:
9289 check_mips_64(ctx);
9290 gen_muldiv(ctx, OPC_DDIVU, rx, ry);
9291 break;
9292 #endif
9293 default:
9294 generate_exception(ctx, EXCP_RI);
9295 break;
9297 break;
9298 case M16_OPC_EXTEND:
9299 decode_extended_mips16_opc(env, ctx, is_branch);
9300 n_bytes = 4;
9301 break;
9302 #if defined(TARGET_MIPS64)
9303 case M16_OPC_I64:
9304 funct = (ctx->opcode >> 8) & 0x7;
9305 decode_i64_mips16(env, ctx, ry, funct, offset, 0);
9306 break;
9307 #endif
9308 default:
9309 generate_exception(ctx, EXCP_RI);
9310 break;
9313 return n_bytes;
9316 /* microMIPS extension to MIPS32 */
9318 /* microMIPS32 major opcodes */
9320 enum {
9321 POOL32A = 0x00,
9322 POOL16A = 0x01,
9323 LBU16 = 0x02,
9324 MOVE16 = 0x03,
9325 ADDI32 = 0x04,
9326 LBU32 = 0x05,
9327 SB32 = 0x06,
9328 LB32 = 0x07,
9330 POOL32B = 0x08,
9331 POOL16B = 0x09,
9332 LHU16 = 0x0a,
9333 ANDI16 = 0x0b,
9334 ADDIU32 = 0x0c,
9335 LHU32 = 0x0d,
9336 SH32 = 0x0e,
9337 LH32 = 0x0f,
9339 POOL32I = 0x10,
9340 POOL16C = 0x11,
9341 LWSP16 = 0x12,
9342 POOL16D = 0x13,
9343 ORI32 = 0x14,
9344 POOL32F = 0x15,
9345 POOL32S = 0x16,
9346 DADDIU32 = 0x17,
9348 POOL32C = 0x18,
9349 LWGP16 = 0x19,
9350 LW16 = 0x1a,
9351 POOL16E = 0x1b,
9352 XORI32 = 0x1c,
9353 JALS32 = 0x1d,
9354 ADDIUPC = 0x1e,
9355 POOL48A = 0x1f,
9357 /* 0x20 is reserved */
9358 RES_20 = 0x20,
9359 POOL16F = 0x21,
9360 SB16 = 0x22,
9361 BEQZ16 = 0x23,
9362 SLTI32 = 0x24,
9363 BEQ32 = 0x25,
9364 SWC132 = 0x26,
9365 LWC132 = 0x27,
9367 /* 0x28 and 0x29 are reserved */
9368 RES_28 = 0x28,
9369 RES_29 = 0x29,
9370 SH16 = 0x2a,
9371 BNEZ16 = 0x2b,
9372 SLTIU32 = 0x2c,
9373 BNE32 = 0x2d,
9374 SDC132 = 0x2e,
9375 LDC132 = 0x2f,
9377 /* 0x30 and 0x31 are reserved */
9378 RES_30 = 0x30,
9379 RES_31 = 0x31,
9380 SWSP16 = 0x32,
9381 B16 = 0x33,
9382 ANDI32 = 0x34,
9383 J32 = 0x35,
9384 SD32 = 0x36,
9385 LD32 = 0x37,
9387 /* 0x38 and 0x39 are reserved */
9388 RES_38 = 0x38,
9389 RES_39 = 0x39,
9390 SW16 = 0x3a,
9391 LI16 = 0x3b,
9392 JALX32 = 0x3c,
9393 JAL32 = 0x3d,
9394 SW32 = 0x3e,
9395 LW32 = 0x3f
9398 /* POOL32A encoding of minor opcode field */
9400 enum {
9401 /* These opcodes are distinguished only by bits 9..6; those bits are
9402 * what are recorded below. */
9403 SLL32 = 0x0,
9404 SRL32 = 0x1,
9405 SRA = 0x2,
9406 ROTR = 0x3,
9408 SLLV = 0x0,
9409 SRLV = 0x1,
9410 SRAV = 0x2,
9411 ROTRV = 0x3,
9412 ADD = 0x4,
9413 ADDU32 = 0x5,
9414 SUB = 0x6,
9415 SUBU32 = 0x7,
9416 MUL = 0x8,
9417 AND = 0x9,
9418 OR32 = 0xa,
9419 NOR = 0xb,
9420 XOR32 = 0xc,
9421 SLT = 0xd,
9422 SLTU = 0xe,
9424 MOVN = 0x0,
9425 MOVZ = 0x1,
9426 LWXS = 0x4,
9428 /* The following can be distinguished by their lower 6 bits. */
9429 INS = 0x0c,
9430 EXT = 0x2c,
9431 POOL32AXF = 0x3c
9434 /* POOL32AXF encoding of minor opcode field extension */
9436 enum {
9437 /* bits 11..6 */
9438 TEQ = 0x00,
9439 TGE = 0x08,
9440 TGEU = 0x10,
9441 TLT = 0x20,
9442 TLTU = 0x28,
9443 TNE = 0x30,
9445 MFC0 = 0x03,
9446 MTC0 = 0x0b,
9448 /* bits 13..12 for 0x01 */
9449 MFHI_ACC = 0x0,
9450 MFLO_ACC = 0x1,
9451 MTHI_ACC = 0x2,
9452 MTLO_ACC = 0x3,
9454 /* bits 13..12 for 0x2a */
9455 MADD_ACC = 0x0,
9456 MADDU_ACC = 0x1,
9457 MSUB_ACC = 0x2,
9458 MSUBU_ACC = 0x3,
9460 /* bits 13..12 for 0x32 */
9461 MULT_ACC = 0x0,
9462 MULTU_ACC = 0x0,
9464 /* bits 15..12 for 0x2c */
9465 SEB = 0x2,
9466 SEH = 0x3,
9467 CLO = 0x4,
9468 CLZ = 0x5,
9469 RDHWR = 0x6,
9470 WSBH = 0x7,
9471 MULT = 0x8,
9472 MULTU = 0x9,
9473 DIV = 0xa,
9474 DIVU = 0xb,
9475 MADD = 0xc,
9476 MADDU = 0xd,
9477 MSUB = 0xe,
9478 MSUBU = 0xf,
9480 /* bits 15..12 for 0x34 */
9481 MFC2 = 0x4,
9482 MTC2 = 0x5,
9483 MFHC2 = 0x8,
9484 MTHC2 = 0x9,
9485 CFC2 = 0xc,
9486 CTC2 = 0xd,
9488 /* bits 15..12 for 0x3c */
9489 JALR = 0x0,
9490 JR = 0x0, /* alias */
9491 JALR_HB = 0x1,
9492 JALRS = 0x4,
9493 JALRS_HB = 0x5,
9495 /* bits 15..12 for 0x05 */
9496 RDPGPR = 0xe,
9497 WRPGPR = 0xf,
9499 /* bits 15..12 for 0x0d */
9500 TLBP = 0x0,
9501 TLBR = 0x1,
9502 TLBWI = 0x2,
9503 TLBWR = 0x3,
9504 WAIT = 0x9,
9505 IRET = 0xd,
9506 DERET = 0xe,
9507 ERET = 0xf,
9509 /* bits 15..12 for 0x15 */
9510 DMT = 0x0,
9511 DVPE = 0x1,
9512 EMT = 0x2,
9513 EVPE = 0x3,
9515 /* bits 15..12 for 0x1d */
9516 DI = 0x4,
9517 EI = 0x5,
9519 /* bits 15..12 for 0x2d */
9520 SYNC = 0x6,
9521 SYSCALL = 0x8,
9522 SDBBP = 0xd,
9524 /* bits 15..12 for 0x35 */
9525 MFHI32 = 0x0,
9526 MFLO32 = 0x1,
9527 MTHI32 = 0x2,
9528 MTLO32 = 0x3,
9531 /* POOL32B encoding of minor opcode field (bits 15..12) */
9533 enum {
9534 LWC2 = 0x0,
9535 LWP = 0x1,
9536 LDP = 0x4,
9537 LWM32 = 0x5,
9538 CACHE = 0x6,
9539 LDM = 0x7,
9540 SWC2 = 0x8,
9541 SWP = 0x9,
9542 SDP = 0xc,
9543 SWM32 = 0xd,
9544 SDM = 0xf
9547 /* POOL32C encoding of minor opcode field (bits 15..12) */
9549 enum {
9550 LWL = 0x0,
9551 SWL = 0x8,
9552 LWR = 0x1,
9553 SWR = 0x9,
9554 PREF = 0x2,
9555 /* 0xa is reserved */
9556 LL = 0x3,
9557 SC = 0xb,
9558 LDL = 0x4,
9559 SDL = 0xc,
9560 LDR = 0x5,
9561 SDR = 0xd,
9562 /* 0x6 is reserved */
9563 LWU = 0xe,
9564 LLD = 0x7,
9565 SCD = 0xf
9568 /* POOL32F encoding of minor opcode field (bits 5..0) */
9570 enum {
9571 /* These are the bit 7..6 values */
9572 ADD_FMT = 0x0,
9573 MOVN_FMT = 0x0,
9575 SUB_FMT = 0x1,
9576 MOVZ_FMT = 0x1,
9578 MUL_FMT = 0x2,
9580 DIV_FMT = 0x3,
9582 /* These are the bit 8..6 values */
9583 RSQRT2_FMT = 0x0,
9584 MOVF_FMT = 0x0,
9586 LWXC1 = 0x1,
9587 MOVT_FMT = 0x1,
9589 PLL_PS = 0x2,
9590 SWXC1 = 0x2,
9592 PLU_PS = 0x3,
9593 LDXC1 = 0x3,
9595 PUL_PS = 0x4,
9596 SDXC1 = 0x4,
9597 RECIP2_FMT = 0x4,
9599 PUU_PS = 0x5,
9600 LUXC1 = 0x5,
9602 CVT_PS_S = 0x6,
9603 SUXC1 = 0x6,
9604 ADDR_PS = 0x6,
9605 PREFX = 0x6,
9607 MULR_PS = 0x7,
9609 MADD_S = 0x01,
9610 MADD_D = 0x09,
9611 MADD_PS = 0x11,
9612 ALNV_PS = 0x19,
9613 MSUB_S = 0x21,
9614 MSUB_D = 0x29,
9615 MSUB_PS = 0x31,
9617 NMADD_S = 0x02,
9618 NMADD_D = 0x0a,
9619 NMADD_PS = 0x12,
9620 NMSUB_S = 0x22,
9621 NMSUB_D = 0x2a,
9622 NMSUB_PS = 0x32,
9624 POOL32FXF = 0x3b,
9626 CABS_COND_FMT = 0x1c, /* MIPS3D */
9627 C_COND_FMT = 0x3c
9630 /* POOL32Fxf encoding of minor opcode extension field */
9632 enum {
9633 CVT_L = 0x04,
9634 RSQRT_FMT = 0x08,
9635 FLOOR_L = 0x0c,
9636 CVT_PW_PS = 0x1c,
9637 CVT_W = 0x24,
9638 SQRT_FMT = 0x28,
9639 FLOOR_W = 0x2c,
9640 CVT_PS_PW = 0x3c,
9641 CFC1 = 0x40,
9642 RECIP_FMT = 0x48,
9643 CEIL_L = 0x4c,
9644 CTC1 = 0x60,
9645 CEIL_W = 0x6c,
9646 MFC1 = 0x80,
9647 CVT_S_PL = 0x84,
9648 TRUNC_L = 0x8c,
9649 MTC1 = 0xa0,
9650 CVT_S_PU = 0xa4,
9651 TRUNC_W = 0xac,
9652 MFHC1 = 0xc0,
9653 ROUND_L = 0xcc,
9654 MTHC1 = 0xe0,
9655 ROUND_W = 0xec,
9657 MOV_FMT = 0x01,
9658 MOVF = 0x05,
9659 ABS_FMT = 0x0d,
9660 RSQRT1_FMT = 0x1d,
9661 MOVT = 0x25,
9662 NEG_FMT = 0x2d,
9663 CVT_D = 0x4d,
9664 RECIP1_FMT = 0x5d,
9665 CVT_S = 0x6d
9668 /* POOL32I encoding of minor opcode field (bits 25..21) */
9670 enum {
9671 BLTZ = 0x00,
9672 BLTZAL = 0x01,
9673 BGEZ = 0x02,
9674 BGEZAL = 0x03,
9675 BLEZ = 0x04,
9676 BNEZC = 0x05,
9677 BGTZ = 0x06,
9678 BEQZC = 0x07,
9679 TLTI = 0x08,
9680 TGEI = 0x09,
9681 TLTIU = 0x0a,
9682 TGEIU = 0x0b,
9683 TNEI = 0x0c,
9684 LUI = 0x0d,
9685 TEQI = 0x0e,
9686 SYNCI = 0x10,
9687 BLTZALS = 0x11,
9688 BGEZALS = 0x13,
9689 BC2F = 0x14,
9690 BC2T = 0x15,
9691 BPOSGE64 = 0x1a,
9692 BPOSGE32 = 0x1b,
9693 /* These overlap and are distinguished by bit16 of the instruction */
9694 BC1F = 0x1c,
9695 BC1T = 0x1d,
9696 BC1ANY2F = 0x1c,
9697 BC1ANY2T = 0x1d,
9698 BC1ANY4F = 0x1e,
9699 BC1ANY4T = 0x1f
9702 /* POOL16A encoding of minor opcode field */
9704 enum {
9705 ADDU16 = 0x0,
9706 SUBU16 = 0x1
9709 /* POOL16B encoding of minor opcode field */
9711 enum {
9712 SLL16 = 0x0,
9713 SRL16 = 0x1
9716 /* POOL16C encoding of minor opcode field */
9718 enum {
9719 NOT16 = 0x00,
9720 XOR16 = 0x04,
9721 AND16 = 0x08,
9722 OR16 = 0x0c,
9723 LWM16 = 0x10,
9724 SWM16 = 0x14,
9725 JR16 = 0x18,
9726 JRC16 = 0x1a,
9727 JALR16 = 0x1c,
9728 JALR16S = 0x1e,
9729 MFHI16 = 0x20,
9730 MFLO16 = 0x24,
9731 BREAK16 = 0x28,
9732 SDBBP16 = 0x2c,
9733 JRADDIUSP = 0x30
9736 /* POOL16D encoding of minor opcode field */
9738 enum {
9739 ADDIUS5 = 0x0,
9740 ADDIUSP = 0x1
9743 /* POOL16E encoding of minor opcode field */
9745 enum {
9746 ADDIUR2 = 0x0,
9747 ADDIUR1SP = 0x1
9750 static int mmreg (int r)
9752 static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
9754 return map[r];
9757 /* Used for 16-bit store instructions. */
9758 static int mmreg2 (int r)
9760 static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
9762 return map[r];
9765 #define uMIPS_RD(op) ((op >> 7) & 0x7)
9766 #define uMIPS_RS(op) ((op >> 4) & 0x7)
9767 #define uMIPS_RS2(op) uMIPS_RS(op)
9768 #define uMIPS_RS1(op) ((op >> 1) & 0x7)
9769 #define uMIPS_RD5(op) ((op >> 5) & 0x1f)
9770 #define uMIPS_RS5(op) (op & 0x1f)
9772 /* Signed immediate */
9773 #define SIMM(op, start, width) \
9774 ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
9775 << (32-width)) \
9776 >> (32-width))
9777 /* Zero-extended immediate */
9778 #define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
9780 static void gen_addiur1sp (CPUMIPSState *env, DisasContext *ctx)
9782 int rd = mmreg(uMIPS_RD(ctx->opcode));
9784 gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
9787 static void gen_addiur2 (CPUMIPSState *env, DisasContext *ctx)
9789 static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
9790 int rd = mmreg(uMIPS_RD(ctx->opcode));
9791 int rs = mmreg(uMIPS_RS(ctx->opcode));
9793 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
9796 static void gen_addiusp (CPUMIPSState *env, DisasContext *ctx)
9798 int encoded = ZIMM(ctx->opcode, 1, 9);
9799 int decoded;
9801 if (encoded <= 1) {
9802 decoded = 256 + encoded;
9803 } else if (encoded <= 255) {
9804 decoded = encoded;
9805 } else if (encoded <= 509) {
9806 decoded = encoded - 512;
9807 } else {
9808 decoded = encoded - 768;
9811 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
9814 static void gen_addius5 (CPUMIPSState *env, DisasContext *ctx)
9816 int imm = SIMM(ctx->opcode, 1, 4);
9817 int rd = (ctx->opcode >> 5) & 0x1f;
9819 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
9822 static void gen_andi16 (CPUMIPSState *env, DisasContext *ctx)
9824 static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
9825 31, 32, 63, 64, 255, 32768, 65535 };
9826 int rd = mmreg(uMIPS_RD(ctx->opcode));
9827 int rs = mmreg(uMIPS_RS(ctx->opcode));
9828 int encoded = ZIMM(ctx->opcode, 0, 4);
9830 gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
9833 static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
9834 int base, int16_t offset)
9836 TCGv t0, t1;
9837 TCGv_i32 t2;
9839 if (ctx->hflags & MIPS_HFLAG_BMASK) {
9840 generate_exception(ctx, EXCP_RI);
9841 return;
9844 t0 = tcg_temp_new();
9846 gen_base_offset_addr(ctx, t0, base, offset);
9848 t1 = tcg_const_tl(reglist);
9849 t2 = tcg_const_i32(ctx->mem_idx);
9851 save_cpu_state(ctx, 1);
9852 switch (opc) {
9853 case LWM32:
9854 gen_helper_lwm(t0, t1, t2);
9855 break;
9856 case SWM32:
9857 gen_helper_swm(t0, t1, t2);
9858 break;
9859 #ifdef TARGET_MIPS64
9860 case LDM:
9861 gen_helper_ldm(t0, t1, t2);
9862 break;
9863 case SDM:
9864 gen_helper_sdm(t0, t1, t2);
9865 break;
9866 #endif
9868 MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
9869 tcg_temp_free(t0);
9870 tcg_temp_free(t1);
9871 tcg_temp_free_i32(t2);
9875 static void gen_pool16c_insn (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
9877 int rd = mmreg((ctx->opcode >> 3) & 0x7);
9878 int rs = mmreg(ctx->opcode & 0x7);
9879 int opc;
9881 switch (((ctx->opcode) >> 4) & 0x3f) {
9882 case NOT16 + 0:
9883 case NOT16 + 1:
9884 case NOT16 + 2:
9885 case NOT16 + 3:
9886 gen_logic(env, OPC_NOR, rd, rs, 0);
9887 break;
9888 case XOR16 + 0:
9889 case XOR16 + 1:
9890 case XOR16 + 2:
9891 case XOR16 + 3:
9892 gen_logic(env, OPC_XOR, rd, rd, rs);
9893 break;
9894 case AND16 + 0:
9895 case AND16 + 1:
9896 case AND16 + 2:
9897 case AND16 + 3:
9898 gen_logic(env, OPC_AND, rd, rd, rs);
9899 break;
9900 case OR16 + 0:
9901 case OR16 + 1:
9902 case OR16 + 2:
9903 case OR16 + 3:
9904 gen_logic(env, OPC_OR, rd, rd, rs);
9905 break;
9906 case LWM16 + 0:
9907 case LWM16 + 1:
9908 case LWM16 + 2:
9909 case LWM16 + 3:
9911 static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9912 int offset = ZIMM(ctx->opcode, 0, 4);
9914 gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
9915 29, offset << 2);
9917 break;
9918 case SWM16 + 0:
9919 case SWM16 + 1:
9920 case SWM16 + 2:
9921 case SWM16 + 3:
9923 static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
9924 int offset = ZIMM(ctx->opcode, 0, 4);
9926 gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
9927 29, offset << 2);
9929 break;
9930 case JR16 + 0:
9931 case JR16 + 1:
9933 int reg = ctx->opcode & 0x1f;
9935 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9937 *is_branch = 1;
9938 break;
9939 case JRC16 + 0:
9940 case JRC16 + 1:
9942 int reg = ctx->opcode & 0x1f;
9944 gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
9945 /* Let normal delay slot handling in our caller take us
9946 to the branch target. */
9948 break;
9949 case JALR16 + 0:
9950 case JALR16 + 1:
9951 opc = OPC_JALR;
9952 goto do_jalr;
9953 case JALR16S + 0:
9954 case JALR16S + 1:
9955 opc = OPC_JALRS;
9956 do_jalr:
9958 int reg = ctx->opcode & 0x1f;
9960 gen_compute_branch(ctx, opc, 2, reg, 31, 0);
9962 *is_branch = 1;
9963 break;
9964 case MFHI16 + 0:
9965 case MFHI16 + 1:
9966 gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
9967 break;
9968 case MFLO16 + 0:
9969 case MFLO16 + 1:
9970 gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
9971 break;
9972 case BREAK16:
9973 generate_exception(ctx, EXCP_BREAK);
9974 break;
9975 case SDBBP16:
9976 /* XXX: not clear which exception should be raised
9977 * when in debug mode...
9979 check_insn(env, ctx, ISA_MIPS32);
9980 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
9981 generate_exception(ctx, EXCP_DBp);
9982 } else {
9983 generate_exception(ctx, EXCP_DBp);
9985 break;
9986 case JRADDIUSP + 0:
9987 case JRADDIUSP + 1:
9989 int imm = ZIMM(ctx->opcode, 0, 5);
9991 gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
9992 gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
9993 /* Let normal delay slot handling in our caller take us
9994 to the branch target. */
9996 break;
9997 default:
9998 generate_exception(ctx, EXCP_RI);
9999 break;
10003 static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
10005 TCGv t0 = tcg_temp_new();
10006 TCGv t1 = tcg_temp_new();
10008 gen_load_gpr(t0, base);
10010 if (index != 0) {
10011 gen_load_gpr(t1, index);
10012 tcg_gen_shli_tl(t1, t1, 2);
10013 gen_op_addr_add(ctx, t0, t1, t0);
10016 save_cpu_state(ctx, 0);
10017 op_ld_lw(t1, t0, ctx);
10018 gen_store_gpr(t1, rd);
10020 tcg_temp_free(t0);
10021 tcg_temp_free(t1);
10024 static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
10025 int base, int16_t offset)
10027 const char *opn = "ldst_pair";
10028 TCGv t0, t1;
10030 if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
10031 generate_exception(ctx, EXCP_RI);
10032 return;
10035 t0 = tcg_temp_new();
10036 t1 = tcg_temp_new();
10038 gen_base_offset_addr(ctx, t0, base, offset);
10040 switch (opc) {
10041 case LWP:
10042 save_cpu_state(ctx, 0);
10043 op_ld_lw(t1, t0, ctx);
10044 gen_store_gpr(t1, rd);
10045 tcg_gen_movi_tl(t1, 4);
10046 gen_op_addr_add(ctx, t0, t0, t1);
10047 op_ld_lw(t1, t0, ctx);
10048 gen_store_gpr(t1, rd+1);
10049 opn = "lwp";
10050 break;
10051 case SWP:
10052 save_cpu_state(ctx, 0);
10053 gen_load_gpr(t1, rd);
10054 op_st_sw(t1, t0, ctx);
10055 tcg_gen_movi_tl(t1, 4);
10056 gen_op_addr_add(ctx, t0, t0, t1);
10057 gen_load_gpr(t1, rd+1);
10058 op_st_sw(t1, t0, ctx);
10059 opn = "swp";
10060 break;
10061 #ifdef TARGET_MIPS64
10062 case LDP:
10063 save_cpu_state(ctx, 0);
10064 op_ld_ld(t1, t0, ctx);
10065 gen_store_gpr(t1, rd);
10066 tcg_gen_movi_tl(t1, 8);
10067 gen_op_addr_add(ctx, t0, t0, t1);
10068 op_ld_ld(t1, t0, ctx);
10069 gen_store_gpr(t1, rd+1);
10070 opn = "ldp";
10071 break;
10072 case SDP:
10073 save_cpu_state(ctx, 0);
10074 gen_load_gpr(t1, rd);
10075 op_st_sd(t1, t0, ctx);
10076 tcg_gen_movi_tl(t1, 8);
10077 gen_op_addr_add(ctx, t0, t0, t1);
10078 gen_load_gpr(t1, rd+1);
10079 op_st_sd(t1, t0, ctx);
10080 opn = "sdp";
10081 break;
10082 #endif
10084 (void)opn; /* avoid a compiler warning */
10085 MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
10086 tcg_temp_free(t0);
10087 tcg_temp_free(t1);
10090 static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs,
10091 int *is_branch)
10093 int extension = (ctx->opcode >> 6) & 0x3f;
10094 int minor = (ctx->opcode >> 12) & 0xf;
10095 uint32_t mips32_op;
10097 switch (extension) {
10098 case TEQ:
10099 mips32_op = OPC_TEQ;
10100 goto do_trap;
10101 case TGE:
10102 mips32_op = OPC_TGE;
10103 goto do_trap;
10104 case TGEU:
10105 mips32_op = OPC_TGEU;
10106 goto do_trap;
10107 case TLT:
10108 mips32_op = OPC_TLT;
10109 goto do_trap;
10110 case TLTU:
10111 mips32_op = OPC_TLTU;
10112 goto do_trap;
10113 case TNE:
10114 mips32_op = OPC_TNE;
10115 do_trap:
10116 gen_trap(ctx, mips32_op, rs, rt, -1);
10117 break;
10118 #ifndef CONFIG_USER_ONLY
10119 case MFC0:
10120 case MFC0 + 32:
10121 if (rt == 0) {
10122 /* Treat as NOP. */
10123 break;
10125 gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
10126 break;
10127 case MTC0:
10128 case MTC0 + 32:
10130 TCGv t0 = tcg_temp_new();
10132 gen_load_gpr(t0, rt);
10133 gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
10134 tcg_temp_free(t0);
10136 break;
10137 #endif
10138 case 0x2c:
10139 switch (minor) {
10140 case SEB:
10141 gen_bshfl(ctx, OPC_SEB, rs, rt);
10142 break;
10143 case SEH:
10144 gen_bshfl(ctx, OPC_SEH, rs, rt);
10145 break;
10146 case CLO:
10147 mips32_op = OPC_CLO;
10148 goto do_cl;
10149 case CLZ:
10150 mips32_op = OPC_CLZ;
10151 do_cl:
10152 check_insn(env, ctx, ISA_MIPS32);
10153 gen_cl(ctx, mips32_op, rt, rs);
10154 break;
10155 case RDHWR:
10156 gen_rdhwr(env, ctx, rt, rs);
10157 break;
10158 case WSBH:
10159 gen_bshfl(ctx, OPC_WSBH, rs, rt);
10160 break;
10161 case MULT:
10162 mips32_op = OPC_MULT;
10163 goto do_muldiv;
10164 case MULTU:
10165 mips32_op = OPC_MULTU;
10166 goto do_muldiv;
10167 case DIV:
10168 mips32_op = OPC_DIV;
10169 goto do_muldiv;
10170 case DIVU:
10171 mips32_op = OPC_DIVU;
10172 goto do_muldiv;
10173 case MADD:
10174 mips32_op = OPC_MADD;
10175 goto do_muldiv;
10176 case MADDU:
10177 mips32_op = OPC_MADDU;
10178 goto do_muldiv;
10179 case MSUB:
10180 mips32_op = OPC_MSUB;
10181 goto do_muldiv;
10182 case MSUBU:
10183 mips32_op = OPC_MSUBU;
10184 do_muldiv:
10185 check_insn(env, ctx, ISA_MIPS32);
10186 gen_muldiv(ctx, mips32_op, rs, rt);
10187 break;
10188 default:
10189 goto pool32axf_invalid;
10191 break;
10192 case 0x34:
10193 switch (minor) {
10194 case MFC2:
10195 case MTC2:
10196 case MFHC2:
10197 case MTHC2:
10198 case CFC2:
10199 case CTC2:
10200 generate_exception_err(ctx, EXCP_CpU, 2);
10201 break;
10202 default:
10203 goto pool32axf_invalid;
10205 break;
10206 case 0x3c:
10207 switch (minor) {
10208 case JALR:
10209 case JALR_HB:
10210 gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
10211 *is_branch = 1;
10212 break;
10213 case JALRS:
10214 case JALRS_HB:
10215 gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
10216 *is_branch = 1;
10217 break;
10218 default:
10219 goto pool32axf_invalid;
10221 break;
10222 case 0x05:
10223 switch (minor) {
10224 case RDPGPR:
10225 check_insn(env, ctx, ISA_MIPS32R2);
10226 gen_load_srsgpr(rt, rs);
10227 break;
10228 case WRPGPR:
10229 check_insn(env, ctx, ISA_MIPS32R2);
10230 gen_store_srsgpr(rt, rs);
10231 break;
10232 default:
10233 goto pool32axf_invalid;
10235 break;
10236 #ifndef CONFIG_USER_ONLY
10237 case 0x0d:
10238 switch (minor) {
10239 case TLBP:
10240 mips32_op = OPC_TLBP;
10241 goto do_cp0;
10242 case TLBR:
10243 mips32_op = OPC_TLBR;
10244 goto do_cp0;
10245 case TLBWI:
10246 mips32_op = OPC_TLBWI;
10247 goto do_cp0;
10248 case TLBWR:
10249 mips32_op = OPC_TLBWR;
10250 goto do_cp0;
10251 case WAIT:
10252 mips32_op = OPC_WAIT;
10253 goto do_cp0;
10254 case DERET:
10255 mips32_op = OPC_DERET;
10256 goto do_cp0;
10257 case ERET:
10258 mips32_op = OPC_ERET;
10259 do_cp0:
10260 gen_cp0(env, ctx, mips32_op, rt, rs);
10261 break;
10262 default:
10263 goto pool32axf_invalid;
10265 break;
10266 case 0x1d:
10267 switch (minor) {
10268 case DI:
10270 TCGv t0 = tcg_temp_new();
10272 save_cpu_state(ctx, 1);
10273 gen_helper_di(t0);
10274 gen_store_gpr(t0, rs);
10275 /* Stop translation as we may have switched the execution mode */
10276 ctx->bstate = BS_STOP;
10277 tcg_temp_free(t0);
10279 break;
10280 case EI:
10282 TCGv t0 = tcg_temp_new();
10284 save_cpu_state(ctx, 1);
10285 gen_helper_ei(t0);
10286 gen_store_gpr(t0, rs);
10287 /* Stop translation as we may have switched the execution mode */
10288 ctx->bstate = BS_STOP;
10289 tcg_temp_free(t0);
10291 break;
10292 default:
10293 goto pool32axf_invalid;
10295 break;
10296 #endif
10297 case 0x2d:
10298 switch (minor) {
10299 case SYNC:
10300 /* NOP */
10301 break;
10302 case SYSCALL:
10303 generate_exception(ctx, EXCP_SYSCALL);
10304 ctx->bstate = BS_STOP;
10305 break;
10306 case SDBBP:
10307 check_insn(env, ctx, ISA_MIPS32);
10308 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
10309 generate_exception(ctx, EXCP_DBp);
10310 } else {
10311 generate_exception(ctx, EXCP_DBp);
10313 break;
10314 default:
10315 goto pool32axf_invalid;
10317 break;
10318 case 0x35:
10319 switch (minor) {
10320 case MFHI32:
10321 gen_HILO(ctx, OPC_MFHI, rs);
10322 break;
10323 case MFLO32:
10324 gen_HILO(ctx, OPC_MFLO, rs);
10325 break;
10326 case MTHI32:
10327 gen_HILO(ctx, OPC_MTHI, rs);
10328 break;
10329 case MTLO32:
10330 gen_HILO(ctx, OPC_MTLO, rs);
10331 break;
10332 default:
10333 goto pool32axf_invalid;
10335 break;
10336 default:
10337 pool32axf_invalid:
10338 MIPS_INVAL("pool32axf");
10339 generate_exception(ctx, EXCP_RI);
10340 break;
10344 /* Values for microMIPS fmt field. Variable-width, depending on which
10345 formats the instruction supports. */
10347 enum {
10348 FMT_SD_S = 0,
10349 FMT_SD_D = 1,
10351 FMT_SDPS_S = 0,
10352 FMT_SDPS_D = 1,
10353 FMT_SDPS_PS = 2,
10355 FMT_SWL_S = 0,
10356 FMT_SWL_W = 1,
10357 FMT_SWL_L = 2,
10359 FMT_DWL_D = 0,
10360 FMT_DWL_W = 1,
10361 FMT_DWL_L = 2
10364 static void gen_pool32fxf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
10366 int extension = (ctx->opcode >> 6) & 0x3ff;
10367 uint32_t mips32_op;
10369 #define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
10370 #define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
10371 #define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
10373 switch (extension) {
10374 case FLOAT_1BIT_FMT(CFC1, 0):
10375 mips32_op = OPC_CFC1;
10376 goto do_cp1;
10377 case FLOAT_1BIT_FMT(CTC1, 0):
10378 mips32_op = OPC_CTC1;
10379 goto do_cp1;
10380 case FLOAT_1BIT_FMT(MFC1, 0):
10381 mips32_op = OPC_MFC1;
10382 goto do_cp1;
10383 case FLOAT_1BIT_FMT(MTC1, 0):
10384 mips32_op = OPC_MTC1;
10385 goto do_cp1;
10386 case FLOAT_1BIT_FMT(MFHC1, 0):
10387 mips32_op = OPC_MFHC1;
10388 goto do_cp1;
10389 case FLOAT_1BIT_FMT(MTHC1, 0):
10390 mips32_op = OPC_MTHC1;
10391 do_cp1:
10392 gen_cp1(ctx, mips32_op, rt, rs);
10393 break;
10395 /* Reciprocal square root */
10396 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
10397 mips32_op = OPC_RSQRT_S;
10398 goto do_unaryfp;
10399 case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
10400 mips32_op = OPC_RSQRT_D;
10401 goto do_unaryfp;
10403 /* Square root */
10404 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
10405 mips32_op = OPC_SQRT_S;
10406 goto do_unaryfp;
10407 case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
10408 mips32_op = OPC_SQRT_D;
10409 goto do_unaryfp;
10411 /* Reciprocal */
10412 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
10413 mips32_op = OPC_RECIP_S;
10414 goto do_unaryfp;
10415 case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
10416 mips32_op = OPC_RECIP_D;
10417 goto do_unaryfp;
10419 /* Floor */
10420 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
10421 mips32_op = OPC_FLOOR_L_S;
10422 goto do_unaryfp;
10423 case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
10424 mips32_op = OPC_FLOOR_L_D;
10425 goto do_unaryfp;
10426 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
10427 mips32_op = OPC_FLOOR_W_S;
10428 goto do_unaryfp;
10429 case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
10430 mips32_op = OPC_FLOOR_W_D;
10431 goto do_unaryfp;
10433 /* Ceiling */
10434 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
10435 mips32_op = OPC_CEIL_L_S;
10436 goto do_unaryfp;
10437 case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
10438 mips32_op = OPC_CEIL_L_D;
10439 goto do_unaryfp;
10440 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
10441 mips32_op = OPC_CEIL_W_S;
10442 goto do_unaryfp;
10443 case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
10444 mips32_op = OPC_CEIL_W_D;
10445 goto do_unaryfp;
10447 /* Truncation */
10448 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
10449 mips32_op = OPC_TRUNC_L_S;
10450 goto do_unaryfp;
10451 case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
10452 mips32_op = OPC_TRUNC_L_D;
10453 goto do_unaryfp;
10454 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
10455 mips32_op = OPC_TRUNC_W_S;
10456 goto do_unaryfp;
10457 case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
10458 mips32_op = OPC_TRUNC_W_D;
10459 goto do_unaryfp;
10461 /* Round */
10462 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
10463 mips32_op = OPC_ROUND_L_S;
10464 goto do_unaryfp;
10465 case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
10466 mips32_op = OPC_ROUND_L_D;
10467 goto do_unaryfp;
10468 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
10469 mips32_op = OPC_ROUND_W_S;
10470 goto do_unaryfp;
10471 case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
10472 mips32_op = OPC_ROUND_W_D;
10473 goto do_unaryfp;
10475 /* Integer to floating-point conversion */
10476 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
10477 mips32_op = OPC_CVT_L_S;
10478 goto do_unaryfp;
10479 case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
10480 mips32_op = OPC_CVT_L_D;
10481 goto do_unaryfp;
10482 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
10483 mips32_op = OPC_CVT_W_S;
10484 goto do_unaryfp;
10485 case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
10486 mips32_op = OPC_CVT_W_D;
10487 goto do_unaryfp;
10489 /* Paired-foo conversions */
10490 case FLOAT_1BIT_FMT(CVT_S_PL, 0):
10491 mips32_op = OPC_CVT_S_PL;
10492 goto do_unaryfp;
10493 case FLOAT_1BIT_FMT(CVT_S_PU, 0):
10494 mips32_op = OPC_CVT_S_PU;
10495 goto do_unaryfp;
10496 case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
10497 mips32_op = OPC_CVT_PW_PS;
10498 goto do_unaryfp;
10499 case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
10500 mips32_op = OPC_CVT_PS_PW;
10501 goto do_unaryfp;
10503 /* Floating-point moves */
10504 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
10505 mips32_op = OPC_MOV_S;
10506 goto do_unaryfp;
10507 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
10508 mips32_op = OPC_MOV_D;
10509 goto do_unaryfp;
10510 case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
10511 mips32_op = OPC_MOV_PS;
10512 goto do_unaryfp;
10514 /* Absolute value */
10515 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
10516 mips32_op = OPC_ABS_S;
10517 goto do_unaryfp;
10518 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
10519 mips32_op = OPC_ABS_D;
10520 goto do_unaryfp;
10521 case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
10522 mips32_op = OPC_ABS_PS;
10523 goto do_unaryfp;
10525 /* Negation */
10526 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
10527 mips32_op = OPC_NEG_S;
10528 goto do_unaryfp;
10529 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
10530 mips32_op = OPC_NEG_D;
10531 goto do_unaryfp;
10532 case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
10533 mips32_op = OPC_NEG_PS;
10534 goto do_unaryfp;
10536 /* Reciprocal square root step */
10537 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
10538 mips32_op = OPC_RSQRT1_S;
10539 goto do_unaryfp;
10540 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
10541 mips32_op = OPC_RSQRT1_D;
10542 goto do_unaryfp;
10543 case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
10544 mips32_op = OPC_RSQRT1_PS;
10545 goto do_unaryfp;
10547 /* Reciprocal step */
10548 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
10549 mips32_op = OPC_RECIP1_S;
10550 goto do_unaryfp;
10551 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
10552 mips32_op = OPC_RECIP1_S;
10553 goto do_unaryfp;
10554 case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
10555 mips32_op = OPC_RECIP1_PS;
10556 goto do_unaryfp;
10558 /* Conversions from double */
10559 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
10560 mips32_op = OPC_CVT_D_S;
10561 goto do_unaryfp;
10562 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
10563 mips32_op = OPC_CVT_D_W;
10564 goto do_unaryfp;
10565 case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
10566 mips32_op = OPC_CVT_D_L;
10567 goto do_unaryfp;
10569 /* Conversions from single */
10570 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
10571 mips32_op = OPC_CVT_S_D;
10572 goto do_unaryfp;
10573 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
10574 mips32_op = OPC_CVT_S_W;
10575 goto do_unaryfp;
10576 case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
10577 mips32_op = OPC_CVT_S_L;
10578 do_unaryfp:
10579 gen_farith(ctx, mips32_op, -1, rs, rt, 0);
10580 break;
10582 /* Conditional moves on floating-point codes */
10583 case COND_FLOAT_MOV(MOVT, 0):
10584 case COND_FLOAT_MOV(MOVT, 1):
10585 case COND_FLOAT_MOV(MOVT, 2):
10586 case COND_FLOAT_MOV(MOVT, 3):
10587 case COND_FLOAT_MOV(MOVT, 4):
10588 case COND_FLOAT_MOV(MOVT, 5):
10589 case COND_FLOAT_MOV(MOVT, 6):
10590 case COND_FLOAT_MOV(MOVT, 7):
10591 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
10592 break;
10593 case COND_FLOAT_MOV(MOVF, 0):
10594 case COND_FLOAT_MOV(MOVF, 1):
10595 case COND_FLOAT_MOV(MOVF, 2):
10596 case COND_FLOAT_MOV(MOVF, 3):
10597 case COND_FLOAT_MOV(MOVF, 4):
10598 case COND_FLOAT_MOV(MOVF, 5):
10599 case COND_FLOAT_MOV(MOVF, 6):
10600 case COND_FLOAT_MOV(MOVF, 7):
10601 gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
10602 break;
10603 default:
10604 MIPS_INVAL("pool32fxf");
10605 generate_exception(ctx, EXCP_RI);
10606 break;
10610 static void decode_micromips32_opc (CPUMIPSState *env, DisasContext *ctx,
10611 uint16_t insn_hw1, int *is_branch)
10613 int32_t offset;
10614 uint16_t insn;
10615 int rt, rs, rd, rr;
10616 int16_t imm;
10617 uint32_t op, minor, mips32_op;
10618 uint32_t cond, fmt, cc;
10620 insn = lduw_code(ctx->pc + 2);
10621 ctx->opcode = (ctx->opcode << 16) | insn;
10623 rt = (ctx->opcode >> 21) & 0x1f;
10624 rs = (ctx->opcode >> 16) & 0x1f;
10625 rd = (ctx->opcode >> 11) & 0x1f;
10626 rr = (ctx->opcode >> 6) & 0x1f;
10627 imm = (int16_t) ctx->opcode;
10629 op = (ctx->opcode >> 26) & 0x3f;
10630 switch (op) {
10631 case POOL32A:
10632 minor = ctx->opcode & 0x3f;
10633 switch (minor) {
10634 case 0x00:
10635 minor = (ctx->opcode >> 6) & 0xf;
10636 switch (minor) {
10637 case SLL32:
10638 mips32_op = OPC_SLL;
10639 goto do_shifti;
10640 case SRA:
10641 mips32_op = OPC_SRA;
10642 goto do_shifti;
10643 case SRL32:
10644 mips32_op = OPC_SRL;
10645 goto do_shifti;
10646 case ROTR:
10647 mips32_op = OPC_ROTR;
10648 do_shifti:
10649 gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
10650 break;
10651 default:
10652 goto pool32a_invalid;
10654 break;
10655 case 0x10:
10656 minor = (ctx->opcode >> 6) & 0xf;
10657 switch (minor) {
10658 /* Arithmetic */
10659 case ADD:
10660 mips32_op = OPC_ADD;
10661 goto do_arith;
10662 case ADDU32:
10663 mips32_op = OPC_ADDU;
10664 goto do_arith;
10665 case SUB:
10666 mips32_op = OPC_SUB;
10667 goto do_arith;
10668 case SUBU32:
10669 mips32_op = OPC_SUBU;
10670 goto do_arith;
10671 case MUL:
10672 mips32_op = OPC_MUL;
10673 do_arith:
10674 gen_arith(env, ctx, mips32_op, rd, rs, rt);
10675 break;
10676 /* Shifts */
10677 case SLLV:
10678 mips32_op = OPC_SLLV;
10679 goto do_shift;
10680 case SRLV:
10681 mips32_op = OPC_SRLV;
10682 goto do_shift;
10683 case SRAV:
10684 mips32_op = OPC_SRAV;
10685 goto do_shift;
10686 case ROTRV:
10687 mips32_op = OPC_ROTRV;
10688 do_shift:
10689 gen_shift(env, ctx, mips32_op, rd, rs, rt);
10690 break;
10691 /* Logical operations */
10692 case AND:
10693 mips32_op = OPC_AND;
10694 goto do_logic;
10695 case OR32:
10696 mips32_op = OPC_OR;
10697 goto do_logic;
10698 case NOR:
10699 mips32_op = OPC_NOR;
10700 goto do_logic;
10701 case XOR32:
10702 mips32_op = OPC_XOR;
10703 do_logic:
10704 gen_logic(env, mips32_op, rd, rs, rt);
10705 break;
10706 /* Set less than */
10707 case SLT:
10708 mips32_op = OPC_SLT;
10709 goto do_slt;
10710 case SLTU:
10711 mips32_op = OPC_SLTU;
10712 do_slt:
10713 gen_slt(env, mips32_op, rd, rs, rt);
10714 break;
10715 default:
10716 goto pool32a_invalid;
10718 break;
10719 case 0x18:
10720 minor = (ctx->opcode >> 6) & 0xf;
10721 switch (minor) {
10722 /* Conditional moves */
10723 case MOVN:
10724 mips32_op = OPC_MOVN;
10725 goto do_cmov;
10726 case MOVZ:
10727 mips32_op = OPC_MOVZ;
10728 do_cmov:
10729 gen_cond_move(env, mips32_op, rd, rs, rt);
10730 break;
10731 case LWXS:
10732 gen_ldxs(ctx, rs, rt, rd);
10733 break;
10734 default:
10735 goto pool32a_invalid;
10737 break;
10738 case INS:
10739 gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
10740 return;
10741 case EXT:
10742 gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
10743 return;
10744 case POOL32AXF:
10745 gen_pool32axf(env, ctx, rt, rs, is_branch);
10746 break;
10747 case 0x07:
10748 generate_exception(ctx, EXCP_BREAK);
10749 break;
10750 default:
10751 pool32a_invalid:
10752 MIPS_INVAL("pool32a");
10753 generate_exception(ctx, EXCP_RI);
10754 break;
10756 break;
10757 case POOL32B:
10758 minor = (ctx->opcode >> 12) & 0xf;
10759 switch (minor) {
10760 case CACHE:
10761 /* Treat as no-op. */
10762 break;
10763 case LWC2:
10764 case SWC2:
10765 /* COP2: Not implemented. */
10766 generate_exception_err(ctx, EXCP_CpU, 2);
10767 break;
10768 case LWP:
10769 case SWP:
10770 #ifdef TARGET_MIPS64
10771 case LDP:
10772 case SDP:
10773 #endif
10774 gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10775 break;
10776 case LWM32:
10777 case SWM32:
10778 #ifdef TARGET_MIPS64
10779 case LDM:
10780 case SDM:
10781 #endif
10782 gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
10783 break;
10784 default:
10785 MIPS_INVAL("pool32b");
10786 generate_exception(ctx, EXCP_RI);
10787 break;
10789 break;
10790 case POOL32F:
10791 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
10792 minor = ctx->opcode & 0x3f;
10793 check_cp1_enabled(ctx);
10794 switch (minor) {
10795 case ALNV_PS:
10796 mips32_op = OPC_ALNV_PS;
10797 goto do_madd;
10798 case MADD_S:
10799 mips32_op = OPC_MADD_S;
10800 goto do_madd;
10801 case MADD_D:
10802 mips32_op = OPC_MADD_D;
10803 goto do_madd;
10804 case MADD_PS:
10805 mips32_op = OPC_MADD_PS;
10806 goto do_madd;
10807 case MSUB_S:
10808 mips32_op = OPC_MSUB_S;
10809 goto do_madd;
10810 case MSUB_D:
10811 mips32_op = OPC_MSUB_D;
10812 goto do_madd;
10813 case MSUB_PS:
10814 mips32_op = OPC_MSUB_PS;
10815 goto do_madd;
10816 case NMADD_S:
10817 mips32_op = OPC_NMADD_S;
10818 goto do_madd;
10819 case NMADD_D:
10820 mips32_op = OPC_NMADD_D;
10821 goto do_madd;
10822 case NMADD_PS:
10823 mips32_op = OPC_NMADD_PS;
10824 goto do_madd;
10825 case NMSUB_S:
10826 mips32_op = OPC_NMSUB_S;
10827 goto do_madd;
10828 case NMSUB_D:
10829 mips32_op = OPC_NMSUB_D;
10830 goto do_madd;
10831 case NMSUB_PS:
10832 mips32_op = OPC_NMSUB_PS;
10833 do_madd:
10834 gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
10835 break;
10836 case CABS_COND_FMT:
10837 cond = (ctx->opcode >> 6) & 0xf;
10838 cc = (ctx->opcode >> 13) & 0x7;
10839 fmt = (ctx->opcode >> 10) & 0x3;
10840 switch (fmt) {
10841 case 0x0:
10842 gen_cmpabs_s(ctx, cond, rt, rs, cc);
10843 break;
10844 case 0x1:
10845 gen_cmpabs_d(ctx, cond, rt, rs, cc);
10846 break;
10847 case 0x2:
10848 gen_cmpabs_ps(ctx, cond, rt, rs, cc);
10849 break;
10850 default:
10851 goto pool32f_invalid;
10853 break;
10854 case C_COND_FMT:
10855 cond = (ctx->opcode >> 6) & 0xf;
10856 cc = (ctx->opcode >> 13) & 0x7;
10857 fmt = (ctx->opcode >> 10) & 0x3;
10858 switch (fmt) {
10859 case 0x0:
10860 gen_cmp_s(ctx, cond, rt, rs, cc);
10861 break;
10862 case 0x1:
10863 gen_cmp_d(ctx, cond, rt, rs, cc);
10864 break;
10865 case 0x2:
10866 gen_cmp_ps(ctx, cond, rt, rs, cc);
10867 break;
10868 default:
10869 goto pool32f_invalid;
10871 break;
10872 case POOL32FXF:
10873 gen_pool32fxf(env, ctx, rt, rs);
10874 break;
10875 case 0x00:
10876 /* PLL foo */
10877 switch ((ctx->opcode >> 6) & 0x7) {
10878 case PLL_PS:
10879 mips32_op = OPC_PLL_PS;
10880 goto do_ps;
10881 case PLU_PS:
10882 mips32_op = OPC_PLU_PS;
10883 goto do_ps;
10884 case PUL_PS:
10885 mips32_op = OPC_PUL_PS;
10886 goto do_ps;
10887 case PUU_PS:
10888 mips32_op = OPC_PUU_PS;
10889 goto do_ps;
10890 case CVT_PS_S:
10891 mips32_op = OPC_CVT_PS_S;
10892 do_ps:
10893 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10894 break;
10895 default:
10896 goto pool32f_invalid;
10898 break;
10899 case 0x08:
10900 /* [LS][WDU]XC1 */
10901 switch ((ctx->opcode >> 6) & 0x7) {
10902 case LWXC1:
10903 mips32_op = OPC_LWXC1;
10904 goto do_ldst_cp1;
10905 case SWXC1:
10906 mips32_op = OPC_SWXC1;
10907 goto do_ldst_cp1;
10908 case LDXC1:
10909 mips32_op = OPC_LDXC1;
10910 goto do_ldst_cp1;
10911 case SDXC1:
10912 mips32_op = OPC_SDXC1;
10913 goto do_ldst_cp1;
10914 case LUXC1:
10915 mips32_op = OPC_LUXC1;
10916 goto do_ldst_cp1;
10917 case SUXC1:
10918 mips32_op = OPC_SUXC1;
10919 do_ldst_cp1:
10920 gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
10921 break;
10922 default:
10923 goto pool32f_invalid;
10925 break;
10926 case 0x18:
10927 /* 3D insns */
10928 fmt = (ctx->opcode >> 9) & 0x3;
10929 switch ((ctx->opcode >> 6) & 0x7) {
10930 case RSQRT2_FMT:
10931 switch (fmt) {
10932 case FMT_SDPS_S:
10933 mips32_op = OPC_RSQRT2_S;
10934 goto do_3d;
10935 case FMT_SDPS_D:
10936 mips32_op = OPC_RSQRT2_D;
10937 goto do_3d;
10938 case FMT_SDPS_PS:
10939 mips32_op = OPC_RSQRT2_PS;
10940 goto do_3d;
10941 default:
10942 goto pool32f_invalid;
10944 break;
10945 case RECIP2_FMT:
10946 switch (fmt) {
10947 case FMT_SDPS_S:
10948 mips32_op = OPC_RECIP2_S;
10949 goto do_3d;
10950 case FMT_SDPS_D:
10951 mips32_op = OPC_RECIP2_D;
10952 goto do_3d;
10953 case FMT_SDPS_PS:
10954 mips32_op = OPC_RECIP2_PS;
10955 goto do_3d;
10956 default:
10957 goto pool32f_invalid;
10959 break;
10960 case ADDR_PS:
10961 mips32_op = OPC_ADDR_PS;
10962 goto do_3d;
10963 case MULR_PS:
10964 mips32_op = OPC_MULR_PS;
10965 do_3d:
10966 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
10967 break;
10968 default:
10969 goto pool32f_invalid;
10971 break;
10972 case 0x20:
10973 /* MOV[FT].fmt and PREFX */
10974 cc = (ctx->opcode >> 13) & 0x7;
10975 fmt = (ctx->opcode >> 9) & 0x3;
10976 switch ((ctx->opcode >> 6) & 0x7) {
10977 case MOVF_FMT:
10978 switch (fmt) {
10979 case FMT_SDPS_S:
10980 gen_movcf_s(rs, rt, cc, 0);
10981 break;
10982 case FMT_SDPS_D:
10983 gen_movcf_d(ctx, rs, rt, cc, 0);
10984 break;
10985 case FMT_SDPS_PS:
10986 gen_movcf_ps(rs, rt, cc, 0);
10987 break;
10988 default:
10989 goto pool32f_invalid;
10991 break;
10992 case MOVT_FMT:
10993 switch (fmt) {
10994 case FMT_SDPS_S:
10995 gen_movcf_s(rs, rt, cc, 1);
10996 break;
10997 case FMT_SDPS_D:
10998 gen_movcf_d(ctx, rs, rt, cc, 1);
10999 break;
11000 case FMT_SDPS_PS:
11001 gen_movcf_ps(rs, rt, cc, 1);
11002 break;
11003 default:
11004 goto pool32f_invalid;
11006 break;
11007 case PREFX:
11008 break;
11009 default:
11010 goto pool32f_invalid;
11012 break;
11013 #define FINSN_3ARG_SDPS(prfx) \
11014 switch ((ctx->opcode >> 8) & 0x3) { \
11015 case FMT_SDPS_S: \
11016 mips32_op = OPC_##prfx##_S; \
11017 goto do_fpop; \
11018 case FMT_SDPS_D: \
11019 mips32_op = OPC_##prfx##_D; \
11020 goto do_fpop; \
11021 case FMT_SDPS_PS: \
11022 mips32_op = OPC_##prfx##_PS; \
11023 goto do_fpop; \
11024 default: \
11025 goto pool32f_invalid; \
11027 case 0x30:
11028 /* regular FP ops */
11029 switch ((ctx->opcode >> 6) & 0x3) {
11030 case ADD_FMT:
11031 FINSN_3ARG_SDPS(ADD);
11032 break;
11033 case SUB_FMT:
11034 FINSN_3ARG_SDPS(SUB);
11035 break;
11036 case MUL_FMT:
11037 FINSN_3ARG_SDPS(MUL);
11038 break;
11039 case DIV_FMT:
11040 fmt = (ctx->opcode >> 8) & 0x3;
11041 if (fmt == 1) {
11042 mips32_op = OPC_DIV_D;
11043 } else if (fmt == 0) {
11044 mips32_op = OPC_DIV_S;
11045 } else {
11046 goto pool32f_invalid;
11048 goto do_fpop;
11049 default:
11050 goto pool32f_invalid;
11052 break;
11053 case 0x38:
11054 /* cmovs */
11055 switch ((ctx->opcode >> 6) & 0x3) {
11056 case MOVN_FMT:
11057 FINSN_3ARG_SDPS(MOVN);
11058 break;
11059 case MOVZ_FMT:
11060 FINSN_3ARG_SDPS(MOVZ);
11061 break;
11062 default:
11063 goto pool32f_invalid;
11065 break;
11066 do_fpop:
11067 gen_farith(ctx, mips32_op, rt, rs, rd, 0);
11068 break;
11069 default:
11070 pool32f_invalid:
11071 MIPS_INVAL("pool32f");
11072 generate_exception(ctx, EXCP_RI);
11073 break;
11075 } else {
11076 generate_exception_err(ctx, EXCP_CpU, 1);
11078 break;
11079 case POOL32I:
11080 minor = (ctx->opcode >> 21) & 0x1f;
11081 switch (minor) {
11082 case BLTZ:
11083 mips32_op = OPC_BLTZ;
11084 goto do_branch;
11085 case BLTZAL:
11086 mips32_op = OPC_BLTZAL;
11087 goto do_branch;
11088 case BLTZALS:
11089 mips32_op = OPC_BLTZALS;
11090 goto do_branch;
11091 case BGEZ:
11092 mips32_op = OPC_BGEZ;
11093 goto do_branch;
11094 case BGEZAL:
11095 mips32_op = OPC_BGEZAL;
11096 goto do_branch;
11097 case BGEZALS:
11098 mips32_op = OPC_BGEZALS;
11099 goto do_branch;
11100 case BLEZ:
11101 mips32_op = OPC_BLEZ;
11102 goto do_branch;
11103 case BGTZ:
11104 mips32_op = OPC_BGTZ;
11105 do_branch:
11106 gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
11107 *is_branch = 1;
11108 break;
11110 /* Traps */
11111 case TLTI:
11112 mips32_op = OPC_TLTI;
11113 goto do_trapi;
11114 case TGEI:
11115 mips32_op = OPC_TGEI;
11116 goto do_trapi;
11117 case TLTIU:
11118 mips32_op = OPC_TLTIU;
11119 goto do_trapi;
11120 case TGEIU:
11121 mips32_op = OPC_TGEIU;
11122 goto do_trapi;
11123 case TNEI:
11124 mips32_op = OPC_TNEI;
11125 goto do_trapi;
11126 case TEQI:
11127 mips32_op = OPC_TEQI;
11128 do_trapi:
11129 gen_trap(ctx, mips32_op, rs, -1, imm);
11130 break;
11132 case BNEZC:
11133 case BEQZC:
11134 gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
11135 4, rs, 0, imm << 1);
11136 /* Compact branches don't have a delay slot, so just let
11137 the normal delay slot handling take us to the branch
11138 target. */
11139 break;
11140 case LUI:
11141 gen_logic_imm(env, OPC_LUI, rs, -1, imm);
11142 break;
11143 case SYNCI:
11144 break;
11145 case BC2F:
11146 case BC2T:
11147 /* COP2: Not implemented. */
11148 generate_exception_err(ctx, EXCP_CpU, 2);
11149 break;
11150 case BC1F:
11151 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
11152 goto do_cp1branch;
11153 case BC1T:
11154 mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
11155 goto do_cp1branch;
11156 case BC1ANY4F:
11157 mips32_op = OPC_BC1FANY4;
11158 goto do_cp1mips3d;
11159 case BC1ANY4T:
11160 mips32_op = OPC_BC1TANY4;
11161 do_cp1mips3d:
11162 check_cop1x(ctx);
11163 check_insn(env, ctx, ASE_MIPS3D);
11164 /* Fall through */
11165 do_cp1branch:
11166 gen_compute_branch1(env, ctx, mips32_op,
11167 (ctx->opcode >> 18) & 0x7, imm << 1);
11168 *is_branch = 1;
11169 break;
11170 case BPOSGE64:
11171 case BPOSGE32:
11172 /* MIPS DSP: not implemented */
11173 /* Fall through */
11174 default:
11175 MIPS_INVAL("pool32i");
11176 generate_exception(ctx, EXCP_RI);
11177 break;
11179 break;
11180 case POOL32C:
11181 minor = (ctx->opcode >> 12) & 0xf;
11182 switch (minor) {
11183 case LWL:
11184 mips32_op = OPC_LWL;
11185 goto do_ld_lr;
11186 case SWL:
11187 mips32_op = OPC_SWL;
11188 goto do_st_lr;
11189 case LWR:
11190 mips32_op = OPC_LWR;
11191 goto do_ld_lr;
11192 case SWR:
11193 mips32_op = OPC_SWR;
11194 goto do_st_lr;
11195 #if defined(TARGET_MIPS64)
11196 case LDL:
11197 mips32_op = OPC_LDL;
11198 goto do_ld_lr;
11199 case SDL:
11200 mips32_op = OPC_SDL;
11201 goto do_st_lr;
11202 case LDR:
11203 mips32_op = OPC_LDR;
11204 goto do_ld_lr;
11205 case SDR:
11206 mips32_op = OPC_SDR;
11207 goto do_st_lr;
11208 case LWU:
11209 mips32_op = OPC_LWU;
11210 goto do_ld_lr;
11211 case LLD:
11212 mips32_op = OPC_LLD;
11213 goto do_ld_lr;
11214 #endif
11215 case LL:
11216 mips32_op = OPC_LL;
11217 goto do_ld_lr;
11218 do_ld_lr:
11219 gen_ld(env, ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11220 break;
11221 do_st_lr:
11222 gen_st(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
11223 break;
11224 case SC:
11225 gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
11226 break;
11227 #if defined(TARGET_MIPS64)
11228 case SCD:
11229 gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
11230 break;
11231 #endif
11232 case PREF:
11233 /* Treat as no-op */
11234 break;
11235 default:
11236 MIPS_INVAL("pool32c");
11237 generate_exception(ctx, EXCP_RI);
11238 break;
11240 break;
11241 case ADDI32:
11242 mips32_op = OPC_ADDI;
11243 goto do_addi;
11244 case ADDIU32:
11245 mips32_op = OPC_ADDIU;
11246 do_addi:
11247 gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
11248 break;
11250 /* Logical operations */
11251 case ORI32:
11252 mips32_op = OPC_ORI;
11253 goto do_logici;
11254 case XORI32:
11255 mips32_op = OPC_XORI;
11256 goto do_logici;
11257 case ANDI32:
11258 mips32_op = OPC_ANDI;
11259 do_logici:
11260 gen_logic_imm(env, mips32_op, rt, rs, imm);
11261 break;
11263 /* Set less than immediate */
11264 case SLTI32:
11265 mips32_op = OPC_SLTI;
11266 goto do_slti;
11267 case SLTIU32:
11268 mips32_op = OPC_SLTIU;
11269 do_slti:
11270 gen_slt_imm(env, mips32_op, rt, rs, imm);
11271 break;
11272 case JALX32:
11273 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
11274 gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
11275 *is_branch = 1;
11276 break;
11277 case JALS32:
11278 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
11279 gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
11280 *is_branch = 1;
11281 break;
11282 case BEQ32:
11283 gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
11284 *is_branch = 1;
11285 break;
11286 case BNE32:
11287 gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
11288 *is_branch = 1;
11289 break;
11290 case J32:
11291 gen_compute_branch(ctx, OPC_J, 4, rt, rs,
11292 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11293 *is_branch = 1;
11294 break;
11295 case JAL32:
11296 gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
11297 (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
11298 *is_branch = 1;
11299 break;
11300 /* Floating point (COP1) */
11301 case LWC132:
11302 mips32_op = OPC_LWC1;
11303 goto do_cop1;
11304 case LDC132:
11305 mips32_op = OPC_LDC1;
11306 goto do_cop1;
11307 case SWC132:
11308 mips32_op = OPC_SWC1;
11309 goto do_cop1;
11310 case SDC132:
11311 mips32_op = OPC_SDC1;
11312 do_cop1:
11313 gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
11314 break;
11315 case ADDIUPC:
11317 int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
11318 int offset = SIMM(ctx->opcode, 0, 23) << 2;
11320 gen_addiupc(ctx, reg, offset, 0, 0);
11322 break;
11323 /* Loads and stores */
11324 case LB32:
11325 mips32_op = OPC_LB;
11326 goto do_ld;
11327 case LBU32:
11328 mips32_op = OPC_LBU;
11329 goto do_ld;
11330 case LH32:
11331 mips32_op = OPC_LH;
11332 goto do_ld;
11333 case LHU32:
11334 mips32_op = OPC_LHU;
11335 goto do_ld;
11336 case LW32:
11337 mips32_op = OPC_LW;
11338 goto do_ld;
11339 #ifdef TARGET_MIPS64
11340 case LD32:
11341 mips32_op = OPC_LD;
11342 goto do_ld;
11343 case SD32:
11344 mips32_op = OPC_SD;
11345 goto do_st;
11346 #endif
11347 case SB32:
11348 mips32_op = OPC_SB;
11349 goto do_st;
11350 case SH32:
11351 mips32_op = OPC_SH;
11352 goto do_st;
11353 case SW32:
11354 mips32_op = OPC_SW;
11355 goto do_st;
11356 do_ld:
11357 gen_ld(env, ctx, mips32_op, rt, rs, imm);
11358 break;
11359 do_st:
11360 gen_st(ctx, mips32_op, rt, rs, imm);
11361 break;
11362 default:
11363 generate_exception(ctx, EXCP_RI);
11364 break;
11368 static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
11370 uint32_t op;
11372 /* make sure instructions are on a halfword boundary */
11373 if (ctx->pc & 0x1) {
11374 env->CP0_BadVAddr = ctx->pc;
11375 generate_exception(ctx, EXCP_AdEL);
11376 ctx->bstate = BS_STOP;
11377 return 2;
11380 op = (ctx->opcode >> 10) & 0x3f;
11381 /* Enforce properly-sized instructions in a delay slot */
11382 if (ctx->hflags & MIPS_HFLAG_BMASK) {
11383 int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
11385 switch (op) {
11386 case POOL32A:
11387 case POOL32B:
11388 case POOL32I:
11389 case POOL32C:
11390 case ADDI32:
11391 case ADDIU32:
11392 case ORI32:
11393 case XORI32:
11394 case SLTI32:
11395 case SLTIU32:
11396 case ANDI32:
11397 case JALX32:
11398 case LBU32:
11399 case LHU32:
11400 case POOL32F:
11401 case JALS32:
11402 case BEQ32:
11403 case BNE32:
11404 case J32:
11405 case JAL32:
11406 case SB32:
11407 case SH32:
11408 case POOL32S:
11409 case ADDIUPC:
11410 case SWC132:
11411 case SDC132:
11412 case SD32:
11413 case SW32:
11414 case LB32:
11415 case LH32:
11416 case DADDIU32:
11417 case POOL48A: /* ??? */
11418 case LWC132:
11419 case LDC132:
11420 case LD32:
11421 case LW32:
11422 if (bits & MIPS_HFLAG_BDS16) {
11423 generate_exception(ctx, EXCP_RI);
11424 /* Just stop translation; the user is confused. */
11425 ctx->bstate = BS_STOP;
11426 return 2;
11428 break;
11429 case POOL16A:
11430 case POOL16B:
11431 case POOL16C:
11432 case LWGP16:
11433 case POOL16F:
11434 case LBU16:
11435 case LHU16:
11436 case LWSP16:
11437 case LW16:
11438 case SB16:
11439 case SH16:
11440 case SWSP16:
11441 case SW16:
11442 case MOVE16:
11443 case ANDI16:
11444 case POOL16D:
11445 case POOL16E:
11446 case BEQZ16:
11447 case BNEZ16:
11448 case B16:
11449 case LI16:
11450 if (bits & MIPS_HFLAG_BDS32) {
11451 generate_exception(ctx, EXCP_RI);
11452 /* Just stop translation; the user is confused. */
11453 ctx->bstate = BS_STOP;
11454 return 2;
11456 break;
11457 default:
11458 break;
11461 switch (op) {
11462 case POOL16A:
11464 int rd = mmreg(uMIPS_RD(ctx->opcode));
11465 int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
11466 int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
11467 uint32_t opc = 0;
11469 switch (ctx->opcode & 0x1) {
11470 case ADDU16:
11471 opc = OPC_ADDU;
11472 break;
11473 case SUBU16:
11474 opc = OPC_SUBU;
11475 break;
11478 gen_arith(env, ctx, opc, rd, rs1, rs2);
11480 break;
11481 case POOL16B:
11483 int rd = mmreg(uMIPS_RD(ctx->opcode));
11484 int rs = mmreg(uMIPS_RS(ctx->opcode));
11485 int amount = (ctx->opcode >> 1) & 0x7;
11486 uint32_t opc = 0;
11487 amount = amount == 0 ? 8 : amount;
11489 switch (ctx->opcode & 0x1) {
11490 case SLL16:
11491 opc = OPC_SLL;
11492 break;
11493 case SRL16:
11494 opc = OPC_SRL;
11495 break;
11498 gen_shift_imm(env, ctx, opc, rd, rs, amount);
11500 break;
11501 case POOL16C:
11502 gen_pool16c_insn(env, ctx, is_branch);
11503 break;
11504 case LWGP16:
11506 int rd = mmreg(uMIPS_RD(ctx->opcode));
11507 int rb = 28; /* GP */
11508 int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
11510 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11512 break;
11513 case POOL16F:
11514 if (ctx->opcode & 1) {
11515 generate_exception(ctx, EXCP_RI);
11516 } else {
11517 /* MOVEP */
11518 int enc_dest = uMIPS_RD(ctx->opcode);
11519 int enc_rt = uMIPS_RS2(ctx->opcode);
11520 int enc_rs = uMIPS_RS1(ctx->opcode);
11521 int rd, rs, re, rt;
11522 static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
11523 static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
11524 static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
11526 rd = rd_enc[enc_dest];
11527 re = re_enc[enc_dest];
11528 rs = rs_rt_enc[enc_rs];
11529 rt = rs_rt_enc[enc_rt];
11531 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11532 gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
11534 break;
11535 case LBU16:
11537 int rd = mmreg(uMIPS_RD(ctx->opcode));
11538 int rb = mmreg(uMIPS_RS(ctx->opcode));
11539 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11540 offset = (offset == 0xf ? -1 : offset);
11542 gen_ld(env, ctx, OPC_LBU, rd, rb, offset);
11544 break;
11545 case LHU16:
11547 int rd = mmreg(uMIPS_RD(ctx->opcode));
11548 int rb = mmreg(uMIPS_RS(ctx->opcode));
11549 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11551 gen_ld(env, ctx, OPC_LHU, rd, rb, offset);
11553 break;
11554 case LWSP16:
11556 int rd = (ctx->opcode >> 5) & 0x1f;
11557 int rb = 29; /* SP */
11558 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11560 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11562 break;
11563 case LW16:
11565 int rd = mmreg(uMIPS_RD(ctx->opcode));
11566 int rb = mmreg(uMIPS_RS(ctx->opcode));
11567 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11569 gen_ld(env, ctx, OPC_LW, rd, rb, offset);
11571 break;
11572 case SB16:
11574 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11575 int rb = mmreg(uMIPS_RS(ctx->opcode));
11576 int16_t offset = ZIMM(ctx->opcode, 0, 4);
11578 gen_st(ctx, OPC_SB, rd, rb, offset);
11580 break;
11581 case SH16:
11583 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11584 int rb = mmreg(uMIPS_RS(ctx->opcode));
11585 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
11587 gen_st(ctx, OPC_SH, rd, rb, offset);
11589 break;
11590 case SWSP16:
11592 int rd = (ctx->opcode >> 5) & 0x1f;
11593 int rb = 29; /* SP */
11594 int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
11596 gen_st(ctx, OPC_SW, rd, rb, offset);
11598 break;
11599 case SW16:
11601 int rd = mmreg2(uMIPS_RD(ctx->opcode));
11602 int rb = mmreg(uMIPS_RS(ctx->opcode));
11603 int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
11605 gen_st(ctx, OPC_SW, rd, rb, offset);
11607 break;
11608 case MOVE16:
11610 int rd = uMIPS_RD5(ctx->opcode);
11611 int rs = uMIPS_RS5(ctx->opcode);
11613 gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
11615 break;
11616 case ANDI16:
11617 gen_andi16(env, ctx);
11618 break;
11619 case POOL16D:
11620 switch (ctx->opcode & 0x1) {
11621 case ADDIUS5:
11622 gen_addius5(env, ctx);
11623 break;
11624 case ADDIUSP:
11625 gen_addiusp(env, ctx);
11626 break;
11628 break;
11629 case POOL16E:
11630 switch (ctx->opcode & 0x1) {
11631 case ADDIUR2:
11632 gen_addiur2(env, ctx);
11633 break;
11634 case ADDIUR1SP:
11635 gen_addiur1sp(env, ctx);
11636 break;
11638 break;
11639 case B16:
11640 gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
11641 SIMM(ctx->opcode, 0, 10) << 1);
11642 *is_branch = 1;
11643 break;
11644 case BNEZ16:
11645 case BEQZ16:
11646 gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
11647 mmreg(uMIPS_RD(ctx->opcode)),
11648 0, SIMM(ctx->opcode, 0, 7) << 1);
11649 *is_branch = 1;
11650 break;
11651 case LI16:
11653 int reg = mmreg(uMIPS_RD(ctx->opcode));
11654 int imm = ZIMM(ctx->opcode, 0, 7);
11656 imm = (imm == 0x7f ? -1 : imm);
11657 tcg_gen_movi_tl(cpu_gpr[reg], imm);
11659 break;
11660 case RES_20:
11661 case RES_28:
11662 case RES_29:
11663 case RES_30:
11664 case RES_31:
11665 case RES_38:
11666 case RES_39:
11667 generate_exception(ctx, EXCP_RI);
11668 break;
11669 default:
11670 decode_micromips32_opc (env, ctx, op, is_branch);
11671 return 4;
11674 return 2;
11677 /* SmartMIPS extension to MIPS32 */
11679 #if defined(TARGET_MIPS64)
11681 /* MDMX extension to MIPS64 */
11683 #endif
11685 static void decode_opc (CPUMIPSState *env, DisasContext *ctx, int *is_branch)
11687 int32_t offset;
11688 int rs, rt, rd, sa;
11689 uint32_t op, op1, op2;
11690 int16_t imm;
11692 /* make sure instructions are on a word boundary */
11693 if (ctx->pc & 0x3) {
11694 env->CP0_BadVAddr = ctx->pc;
11695 generate_exception(ctx, EXCP_AdEL);
11696 return;
11699 /* Handle blikely not taken case */
11700 if ((ctx->hflags & MIPS_HFLAG_BMASK_BASE) == MIPS_HFLAG_BL) {
11701 int l1 = gen_new_label();
11703 MIPS_DEBUG("blikely condition (" TARGET_FMT_lx ")", ctx->pc + 4);
11704 tcg_gen_brcondi_tl(TCG_COND_NE, bcond, 0, l1);
11705 tcg_gen_movi_i32(hflags, ctx->hflags & ~MIPS_HFLAG_BMASK);
11706 gen_goto_tb(ctx, 1, ctx->pc + 4);
11707 gen_set_label(l1);
11710 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)))
11711 tcg_gen_debug_insn_start(ctx->pc);
11713 op = MASK_OP_MAJOR(ctx->opcode);
11714 rs = (ctx->opcode >> 21) & 0x1f;
11715 rt = (ctx->opcode >> 16) & 0x1f;
11716 rd = (ctx->opcode >> 11) & 0x1f;
11717 sa = (ctx->opcode >> 6) & 0x1f;
11718 imm = (int16_t)ctx->opcode;
11719 switch (op) {
11720 case OPC_SPECIAL:
11721 op1 = MASK_SPECIAL(ctx->opcode);
11722 switch (op1) {
11723 case OPC_SLL: /* Shift with immediate */
11724 case OPC_SRA:
11725 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11726 break;
11727 case OPC_SRL:
11728 switch ((ctx->opcode >> 21) & 0x1f) {
11729 case 1:
11730 /* rotr is decoded as srl on non-R2 CPUs */
11731 if (env->insn_flags & ISA_MIPS32R2) {
11732 op1 = OPC_ROTR;
11734 /* Fallthrough */
11735 case 0:
11736 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11737 break;
11738 default:
11739 generate_exception(ctx, EXCP_RI);
11740 break;
11742 break;
11743 case OPC_MOVN: /* Conditional move */
11744 case OPC_MOVZ:
11745 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32 |
11746 INSN_LOONGSON2E | INSN_LOONGSON2F);
11747 gen_cond_move(env, op1, rd, rs, rt);
11748 break;
11749 case OPC_ADD ... OPC_SUBU:
11750 gen_arith(env, ctx, op1, rd, rs, rt);
11751 break;
11752 case OPC_SLLV: /* Shifts */
11753 case OPC_SRAV:
11754 gen_shift(env, ctx, op1, rd, rs, rt);
11755 break;
11756 case OPC_SRLV:
11757 switch ((ctx->opcode >> 6) & 0x1f) {
11758 case 1:
11759 /* rotrv is decoded as srlv on non-R2 CPUs */
11760 if (env->insn_flags & ISA_MIPS32R2) {
11761 op1 = OPC_ROTRV;
11763 /* Fallthrough */
11764 case 0:
11765 gen_shift(env, ctx, op1, rd, rs, rt);
11766 break;
11767 default:
11768 generate_exception(ctx, EXCP_RI);
11769 break;
11771 break;
11772 case OPC_SLT: /* Set on less than */
11773 case OPC_SLTU:
11774 gen_slt(env, op1, rd, rs, rt);
11775 break;
11776 case OPC_AND: /* Logic*/
11777 case OPC_OR:
11778 case OPC_NOR:
11779 case OPC_XOR:
11780 gen_logic(env, op1, rd, rs, rt);
11781 break;
11782 case OPC_MULT ... OPC_DIVU:
11783 if (sa) {
11784 check_insn(env, ctx, INSN_VR54XX);
11785 op1 = MASK_MUL_VR54XX(ctx->opcode);
11786 gen_mul_vr54xx(ctx, op1, rd, rs, rt);
11787 } else
11788 gen_muldiv(ctx, op1, rs, rt);
11789 break;
11790 case OPC_JR ... OPC_JALR:
11791 gen_compute_branch(ctx, op1, 4, rs, rd, sa);
11792 *is_branch = 1;
11793 break;
11794 case OPC_TGE ... OPC_TEQ: /* Traps */
11795 case OPC_TNE:
11796 gen_trap(ctx, op1, rs, rt, -1);
11797 break;
11798 case OPC_MFHI: /* Move from HI/LO */
11799 case OPC_MFLO:
11800 gen_HILO(ctx, op1, rd);
11801 break;
11802 case OPC_MTHI:
11803 case OPC_MTLO: /* Move to HI/LO */
11804 gen_HILO(ctx, op1, rs);
11805 break;
11806 case OPC_PMON: /* Pmon entry point, also R4010 selsl */
11807 #ifdef MIPS_STRICT_STANDARD
11808 MIPS_INVAL("PMON / selsl");
11809 generate_exception(ctx, EXCP_RI);
11810 #else
11811 gen_helper_0i(pmon, sa);
11812 #endif
11813 break;
11814 case OPC_SYSCALL:
11815 generate_exception(ctx, EXCP_SYSCALL);
11816 ctx->bstate = BS_STOP;
11817 break;
11818 case OPC_BREAK:
11819 generate_exception(ctx, EXCP_BREAK);
11820 break;
11821 case OPC_SPIM:
11822 #ifdef MIPS_STRICT_STANDARD
11823 MIPS_INVAL("SPIM");
11824 generate_exception(ctx, EXCP_RI);
11825 #else
11826 /* Implemented as RI exception for now. */
11827 MIPS_INVAL("spim (unofficial)");
11828 generate_exception(ctx, EXCP_RI);
11829 #endif
11830 break;
11831 case OPC_SYNC:
11832 /* Treat as NOP. */
11833 break;
11835 case OPC_MOVCI:
11836 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
11837 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
11838 check_cp1_enabled(ctx);
11839 gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
11840 (ctx->opcode >> 16) & 1);
11841 } else {
11842 generate_exception_err(ctx, EXCP_CpU, 1);
11844 break;
11846 #if defined(TARGET_MIPS64)
11847 /* MIPS64 specific opcodes */
11848 case OPC_DSLL:
11849 case OPC_DSRA:
11850 case OPC_DSLL32:
11851 case OPC_DSRA32:
11852 check_insn(env, ctx, ISA_MIPS3);
11853 check_mips_64(ctx);
11854 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11855 break;
11856 case OPC_DSRL:
11857 switch ((ctx->opcode >> 21) & 0x1f) {
11858 case 1:
11859 /* drotr is decoded as dsrl on non-R2 CPUs */
11860 if (env->insn_flags & ISA_MIPS32R2) {
11861 op1 = OPC_DROTR;
11863 /* Fallthrough */
11864 case 0:
11865 check_insn(env, ctx, ISA_MIPS3);
11866 check_mips_64(ctx);
11867 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11868 break;
11869 default:
11870 generate_exception(ctx, EXCP_RI);
11871 break;
11873 break;
11874 case OPC_DSRL32:
11875 switch ((ctx->opcode >> 21) & 0x1f) {
11876 case 1:
11877 /* drotr32 is decoded as dsrl32 on non-R2 CPUs */
11878 if (env->insn_flags & ISA_MIPS32R2) {
11879 op1 = OPC_DROTR32;
11881 /* Fallthrough */
11882 case 0:
11883 check_insn(env, ctx, ISA_MIPS3);
11884 check_mips_64(ctx);
11885 gen_shift_imm(env, ctx, op1, rd, rt, sa);
11886 break;
11887 default:
11888 generate_exception(ctx, EXCP_RI);
11889 break;
11891 break;
11892 case OPC_DADD ... OPC_DSUBU:
11893 check_insn(env, ctx, ISA_MIPS3);
11894 check_mips_64(ctx);
11895 gen_arith(env, ctx, op1, rd, rs, rt);
11896 break;
11897 case OPC_DSLLV:
11898 case OPC_DSRAV:
11899 check_insn(env, ctx, ISA_MIPS3);
11900 check_mips_64(ctx);
11901 gen_shift(env, ctx, op1, rd, rs, rt);
11902 break;
11903 case OPC_DSRLV:
11904 switch ((ctx->opcode >> 6) & 0x1f) {
11905 case 1:
11906 /* drotrv is decoded as dsrlv on non-R2 CPUs */
11907 if (env->insn_flags & ISA_MIPS32R2) {
11908 op1 = OPC_DROTRV;
11910 /* Fallthrough */
11911 case 0:
11912 check_insn(env, ctx, ISA_MIPS3);
11913 check_mips_64(ctx);
11914 gen_shift(env, ctx, op1, rd, rs, rt);
11915 break;
11916 default:
11917 generate_exception(ctx, EXCP_RI);
11918 break;
11920 break;
11921 case OPC_DMULT ... OPC_DDIVU:
11922 check_insn(env, ctx, ISA_MIPS3);
11923 check_mips_64(ctx);
11924 gen_muldiv(ctx, op1, rs, rt);
11925 break;
11926 #endif
11927 default: /* Invalid */
11928 MIPS_INVAL("special");
11929 generate_exception(ctx, EXCP_RI);
11930 break;
11932 break;
11933 case OPC_SPECIAL2:
11934 op1 = MASK_SPECIAL2(ctx->opcode);
11935 switch (op1) {
11936 case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
11937 case OPC_MSUB ... OPC_MSUBU:
11938 check_insn(env, ctx, ISA_MIPS32);
11939 gen_muldiv(ctx, op1, rs, rt);
11940 break;
11941 case OPC_MUL:
11942 gen_arith(env, ctx, op1, rd, rs, rt);
11943 break;
11944 case OPC_CLO:
11945 case OPC_CLZ:
11946 check_insn(env, ctx, ISA_MIPS32);
11947 gen_cl(ctx, op1, rd, rs);
11948 break;
11949 case OPC_SDBBP:
11950 /* XXX: not clear which exception should be raised
11951 * when in debug mode...
11953 check_insn(env, ctx, ISA_MIPS32);
11954 if (!(ctx->hflags & MIPS_HFLAG_DM)) {
11955 generate_exception(ctx, EXCP_DBp);
11956 } else {
11957 generate_exception(ctx, EXCP_DBp);
11959 /* Treat as NOP. */
11960 break;
11961 case OPC_DIV_G_2F:
11962 case OPC_DIVU_G_2F:
11963 case OPC_MULT_G_2F:
11964 case OPC_MULTU_G_2F:
11965 case OPC_MOD_G_2F:
11966 case OPC_MODU_G_2F:
11967 check_insn(env, ctx, INSN_LOONGSON2F);
11968 gen_loongson_integer(ctx, op1, rd, rs, rt);
11969 break;
11970 #if defined(TARGET_MIPS64)
11971 case OPC_DCLO:
11972 case OPC_DCLZ:
11973 check_insn(env, ctx, ISA_MIPS64);
11974 check_mips_64(ctx);
11975 gen_cl(ctx, op1, rd, rs);
11976 break;
11977 case OPC_DMULT_G_2F:
11978 case OPC_DMULTU_G_2F:
11979 case OPC_DDIV_G_2F:
11980 case OPC_DDIVU_G_2F:
11981 case OPC_DMOD_G_2F:
11982 case OPC_DMODU_G_2F:
11983 check_insn(env, ctx, INSN_LOONGSON2F);
11984 gen_loongson_integer(ctx, op1, rd, rs, rt);
11985 break;
11986 #endif
11987 default: /* Invalid */
11988 MIPS_INVAL("special2");
11989 generate_exception(ctx, EXCP_RI);
11990 break;
11992 break;
11993 case OPC_SPECIAL3:
11994 op1 = MASK_SPECIAL3(ctx->opcode);
11995 switch (op1) {
11996 case OPC_EXT:
11997 case OPC_INS:
11998 check_insn(env, ctx, ISA_MIPS32R2);
11999 gen_bitops(ctx, op1, rt, rs, sa, rd);
12000 break;
12001 case OPC_BSHFL:
12002 check_insn(env, ctx, ISA_MIPS32R2);
12003 op2 = MASK_BSHFL(ctx->opcode);
12004 gen_bshfl(ctx, op2, rt, rd);
12005 break;
12006 case OPC_RDHWR:
12007 gen_rdhwr(env, ctx, rt, rd);
12008 break;
12009 case OPC_FORK:
12010 check_insn(env, ctx, ASE_MT);
12012 TCGv t0 = tcg_temp_new();
12013 TCGv t1 = tcg_temp_new();
12015 gen_load_gpr(t0, rt);
12016 gen_load_gpr(t1, rs);
12017 gen_helper_fork(t0, t1);
12018 tcg_temp_free(t0);
12019 tcg_temp_free(t1);
12021 break;
12022 case OPC_YIELD:
12023 check_insn(env, ctx, ASE_MT);
12025 TCGv t0 = tcg_temp_new();
12027 save_cpu_state(ctx, 1);
12028 gen_load_gpr(t0, rs);
12029 gen_helper_yield(t0, t0);
12030 gen_store_gpr(t0, rd);
12031 tcg_temp_free(t0);
12033 break;
12034 case OPC_DIV_G_2E ... OPC_DIVU_G_2E:
12035 case OPC_MULT_G_2E ... OPC_MULTU_G_2E:
12036 case OPC_MOD_G_2E ... OPC_MODU_G_2E:
12037 check_insn(env, ctx, INSN_LOONGSON2E);
12038 gen_loongson_integer(ctx, op1, rd, rs, rt);
12039 break;
12040 #if defined(TARGET_MIPS64)
12041 case OPC_DEXTM ... OPC_DEXT:
12042 case OPC_DINSM ... OPC_DINS:
12043 check_insn(env, ctx, ISA_MIPS64R2);
12044 check_mips_64(ctx);
12045 gen_bitops(ctx, op1, rt, rs, sa, rd);
12046 break;
12047 case OPC_DBSHFL:
12048 check_insn(env, ctx, ISA_MIPS64R2);
12049 check_mips_64(ctx);
12050 op2 = MASK_DBSHFL(ctx->opcode);
12051 gen_bshfl(ctx, op2, rt, rd);
12052 break;
12053 case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
12054 case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
12055 case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
12056 check_insn(env, ctx, INSN_LOONGSON2E);
12057 gen_loongson_integer(ctx, op1, rd, rs, rt);
12058 break;
12059 #endif
12060 default: /* Invalid */
12061 MIPS_INVAL("special3");
12062 generate_exception(ctx, EXCP_RI);
12063 break;
12065 break;
12066 case OPC_REGIMM:
12067 op1 = MASK_REGIMM(ctx->opcode);
12068 switch (op1) {
12069 case OPC_BLTZ ... OPC_BGEZL: /* REGIMM branches */
12070 case OPC_BLTZAL ... OPC_BGEZALL:
12071 gen_compute_branch(ctx, op1, 4, rs, -1, imm << 2);
12072 *is_branch = 1;
12073 break;
12074 case OPC_TGEI ... OPC_TEQI: /* REGIMM traps */
12075 case OPC_TNEI:
12076 gen_trap(ctx, op1, rs, -1, imm);
12077 break;
12078 case OPC_SYNCI:
12079 check_insn(env, ctx, ISA_MIPS32R2);
12080 /* Treat as NOP. */
12081 break;
12082 default: /* Invalid */
12083 MIPS_INVAL("regimm");
12084 generate_exception(ctx, EXCP_RI);
12085 break;
12087 break;
12088 case OPC_CP0:
12089 check_cp0_enabled(ctx);
12090 op1 = MASK_CP0(ctx->opcode);
12091 switch (op1) {
12092 case OPC_MFC0:
12093 case OPC_MTC0:
12094 case OPC_MFTR:
12095 case OPC_MTTR:
12096 #if defined(TARGET_MIPS64)
12097 case OPC_DMFC0:
12098 case OPC_DMTC0:
12099 #endif
12100 #ifndef CONFIG_USER_ONLY
12101 gen_cp0(env, ctx, op1, rt, rd);
12102 #endif /* !CONFIG_USER_ONLY */
12103 break;
12104 case OPC_C0_FIRST ... OPC_C0_LAST:
12105 #ifndef CONFIG_USER_ONLY
12106 gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
12107 #endif /* !CONFIG_USER_ONLY */
12108 break;
12109 case OPC_MFMC0:
12110 #ifndef CONFIG_USER_ONLY
12112 TCGv t0 = tcg_temp_new();
12114 op2 = MASK_MFMC0(ctx->opcode);
12115 switch (op2) {
12116 case OPC_DMT:
12117 check_insn(env, ctx, ASE_MT);
12118 gen_helper_dmt(t0);
12119 gen_store_gpr(t0, rt);
12120 break;
12121 case OPC_EMT:
12122 check_insn(env, ctx, ASE_MT);
12123 gen_helper_emt(t0);
12124 gen_store_gpr(t0, rt);
12125 break;
12126 case OPC_DVPE:
12127 check_insn(env, ctx, ASE_MT);
12128 gen_helper_dvpe(t0);
12129 gen_store_gpr(t0, rt);
12130 break;
12131 case OPC_EVPE:
12132 check_insn(env, ctx, ASE_MT);
12133 gen_helper_evpe(t0);
12134 gen_store_gpr(t0, rt);
12135 break;
12136 case OPC_DI:
12137 check_insn(env, ctx, ISA_MIPS32R2);
12138 save_cpu_state(ctx, 1);
12139 gen_helper_di(t0);
12140 gen_store_gpr(t0, rt);
12141 /* Stop translation as we may have switched the execution mode */
12142 ctx->bstate = BS_STOP;
12143 break;
12144 case OPC_EI:
12145 check_insn(env, ctx, ISA_MIPS32R2);
12146 save_cpu_state(ctx, 1);
12147 gen_helper_ei(t0);
12148 gen_store_gpr(t0, rt);
12149 /* Stop translation as we may have switched the execution mode */
12150 ctx->bstate = BS_STOP;
12151 break;
12152 default: /* Invalid */
12153 MIPS_INVAL("mfmc0");
12154 generate_exception(ctx, EXCP_RI);
12155 break;
12157 tcg_temp_free(t0);
12159 #endif /* !CONFIG_USER_ONLY */
12160 break;
12161 case OPC_RDPGPR:
12162 check_insn(env, ctx, ISA_MIPS32R2);
12163 gen_load_srsgpr(rt, rd);
12164 break;
12165 case OPC_WRPGPR:
12166 check_insn(env, ctx, ISA_MIPS32R2);
12167 gen_store_srsgpr(rt, rd);
12168 break;
12169 default:
12170 MIPS_INVAL("cp0");
12171 generate_exception(ctx, EXCP_RI);
12172 break;
12174 break;
12175 case OPC_ADDI: /* Arithmetic with immediate opcode */
12176 case OPC_ADDIU:
12177 gen_arith_imm(env, ctx, op, rt, rs, imm);
12178 break;
12179 case OPC_SLTI: /* Set on less than with immediate opcode */
12180 case OPC_SLTIU:
12181 gen_slt_imm(env, op, rt, rs, imm);
12182 break;
12183 case OPC_ANDI: /* Arithmetic with immediate opcode */
12184 case OPC_LUI:
12185 case OPC_ORI:
12186 case OPC_XORI:
12187 gen_logic_imm(env, op, rt, rs, imm);
12188 break;
12189 case OPC_J ... OPC_JAL: /* Jump */
12190 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12191 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12192 *is_branch = 1;
12193 break;
12194 case OPC_BEQ ... OPC_BGTZ: /* Branch */
12195 case OPC_BEQL ... OPC_BGTZL:
12196 gen_compute_branch(ctx, op, 4, rs, rt, imm << 2);
12197 *is_branch = 1;
12198 break;
12199 case OPC_LB ... OPC_LWR: /* Load and stores */
12200 case OPC_LL:
12201 gen_ld(env, ctx, op, rt, rs, imm);
12202 break;
12203 case OPC_SB ... OPC_SW:
12204 case OPC_SWR:
12205 gen_st(ctx, op, rt, rs, imm);
12206 break;
12207 case OPC_SC:
12208 gen_st_cond(ctx, op, rt, rs, imm);
12209 break;
12210 case OPC_CACHE:
12211 check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
12212 /* Treat as NOP. */
12213 break;
12214 case OPC_PREF:
12215 check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
12216 /* Treat as NOP. */
12217 break;
12219 /* Floating point (COP1). */
12220 case OPC_LWC1:
12221 case OPC_LDC1:
12222 case OPC_SWC1:
12223 case OPC_SDC1:
12224 gen_cop1_ldst(env, ctx, op, rt, rs, imm);
12225 break;
12227 case OPC_CP1:
12228 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12229 check_cp1_enabled(ctx);
12230 op1 = MASK_CP1(ctx->opcode);
12231 switch (op1) {
12232 case OPC_MFHC1:
12233 case OPC_MTHC1:
12234 check_insn(env, ctx, ISA_MIPS32R2);
12235 case OPC_MFC1:
12236 case OPC_CFC1:
12237 case OPC_MTC1:
12238 case OPC_CTC1:
12239 gen_cp1(ctx, op1, rt, rd);
12240 break;
12241 #if defined(TARGET_MIPS64)
12242 case OPC_DMFC1:
12243 case OPC_DMTC1:
12244 check_insn(env, ctx, ISA_MIPS3);
12245 gen_cp1(ctx, op1, rt, rd);
12246 break;
12247 #endif
12248 case OPC_BC1ANY2:
12249 case OPC_BC1ANY4:
12250 check_cop1x(ctx);
12251 check_insn(env, ctx, ASE_MIPS3D);
12252 /* fall through */
12253 case OPC_BC1:
12254 gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
12255 (rt >> 2) & 0x7, imm << 2);
12256 *is_branch = 1;
12257 break;
12258 case OPC_S_FMT:
12259 case OPC_D_FMT:
12260 case OPC_W_FMT:
12261 case OPC_L_FMT:
12262 case OPC_PS_FMT:
12263 gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
12264 (imm >> 8) & 0x7);
12265 break;
12266 default:
12267 MIPS_INVAL("cp1");
12268 generate_exception (ctx, EXCP_RI);
12269 break;
12271 } else {
12272 generate_exception_err(ctx, EXCP_CpU, 1);
12274 break;
12276 /* COP2. */
12277 case OPC_LWC2:
12278 case OPC_LDC2:
12279 case OPC_SWC2:
12280 case OPC_SDC2:
12281 case OPC_CP2:
12282 /* COP2: Not implemented. */
12283 generate_exception_err(ctx, EXCP_CpU, 2);
12284 break;
12286 case OPC_CP3:
12287 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12288 check_cp1_enabled(ctx);
12289 op1 = MASK_CP3(ctx->opcode);
12290 switch (op1) {
12291 case OPC_LWXC1:
12292 case OPC_LDXC1:
12293 case OPC_LUXC1:
12294 case OPC_SWXC1:
12295 case OPC_SDXC1:
12296 case OPC_SUXC1:
12297 gen_flt3_ldst(ctx, op1, sa, rd, rs, rt);
12298 break;
12299 case OPC_PREFX:
12300 /* Treat as NOP. */
12301 break;
12302 case OPC_ALNV_PS:
12303 case OPC_MADD_S:
12304 case OPC_MADD_D:
12305 case OPC_MADD_PS:
12306 case OPC_MSUB_S:
12307 case OPC_MSUB_D:
12308 case OPC_MSUB_PS:
12309 case OPC_NMADD_S:
12310 case OPC_NMADD_D:
12311 case OPC_NMADD_PS:
12312 case OPC_NMSUB_S:
12313 case OPC_NMSUB_D:
12314 case OPC_NMSUB_PS:
12315 gen_flt3_arith(ctx, op1, sa, rs, rd, rt);
12316 break;
12317 default:
12318 MIPS_INVAL("cp3");
12319 generate_exception (ctx, EXCP_RI);
12320 break;
12322 } else {
12323 generate_exception_err(ctx, EXCP_CpU, 1);
12325 break;
12327 #if defined(TARGET_MIPS64)
12328 /* MIPS64 opcodes */
12329 case OPC_LWU:
12330 case OPC_LDL ... OPC_LDR:
12331 case OPC_LLD:
12332 case OPC_LD:
12333 check_insn(env, ctx, ISA_MIPS3);
12334 check_mips_64(ctx);
12335 gen_ld(env, ctx, op, rt, rs, imm);
12336 break;
12337 case OPC_SDL ... OPC_SDR:
12338 case OPC_SD:
12339 check_insn(env, ctx, ISA_MIPS3);
12340 check_mips_64(ctx);
12341 gen_st(ctx, op, rt, rs, imm);
12342 break;
12343 case OPC_SCD:
12344 check_insn(env, ctx, ISA_MIPS3);
12345 check_mips_64(ctx);
12346 gen_st_cond(ctx, op, rt, rs, imm);
12347 break;
12348 case OPC_DADDI:
12349 case OPC_DADDIU:
12350 check_insn(env, ctx, ISA_MIPS3);
12351 check_mips_64(ctx);
12352 gen_arith_imm(env, ctx, op, rt, rs, imm);
12353 break;
12354 #endif
12355 case OPC_JALX:
12356 check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
12357 offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
12358 gen_compute_branch(ctx, op, 4, rs, rt, offset);
12359 *is_branch = 1;
12360 break;
12361 case OPC_MDMX:
12362 check_insn(env, ctx, ASE_MDMX);
12363 /* MDMX: Not implemented. */
12364 default: /* Invalid */
12365 MIPS_INVAL("major opcode");
12366 generate_exception(ctx, EXCP_RI);
12367 break;
12371 static inline void
12372 gen_intermediate_code_internal (CPUMIPSState *env, TranslationBlock *tb,
12373 int search_pc)
12375 DisasContext ctx;
12376 target_ulong pc_start;
12377 uint16_t *gen_opc_end;
12378 CPUBreakpoint *bp;
12379 int j, lj = -1;
12380 int num_insns;
12381 int max_insns;
12382 int insn_bytes;
12383 int is_branch;
12385 if (search_pc)
12386 qemu_log("search pc %d\n", search_pc);
12388 pc_start = tb->pc;
12389 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
12390 ctx.pc = pc_start;
12391 ctx.saved_pc = -1;
12392 ctx.singlestep_enabled = env->singlestep_enabled;
12393 ctx.tb = tb;
12394 ctx.bstate = BS_NONE;
12395 /* Restore delay slot state from the tb context. */
12396 ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
12397 restore_cpu_state(env, &ctx);
12398 #ifdef CONFIG_USER_ONLY
12399 ctx.mem_idx = MIPS_HFLAG_UM;
12400 #else
12401 ctx.mem_idx = ctx.hflags & MIPS_HFLAG_KSU;
12402 #endif
12403 num_insns = 0;
12404 max_insns = tb->cflags & CF_COUNT_MASK;
12405 if (max_insns == 0)
12406 max_insns = CF_COUNT_MASK;
12407 LOG_DISAS("\ntb %p idx %d hflags %04x\n", tb, ctx.mem_idx, ctx.hflags);
12408 gen_icount_start();
12409 while (ctx.bstate == BS_NONE) {
12410 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
12411 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
12412 if (bp->pc == ctx.pc) {
12413 save_cpu_state(&ctx, 1);
12414 ctx.bstate = BS_BRANCH;
12415 gen_helper_0i(raise_exception, EXCP_DEBUG);
12416 /* Include the breakpoint location or the tb won't
12417 * be flushed when it must be. */
12418 ctx.pc += 4;
12419 goto done_generating;
12424 if (search_pc) {
12425 j = gen_opc_ptr - gen_opc_buf;
12426 if (lj < j) {
12427 lj++;
12428 while (lj < j)
12429 gen_opc_instr_start[lj++] = 0;
12431 gen_opc_pc[lj] = ctx.pc;
12432 gen_opc_hflags[lj] = ctx.hflags & MIPS_HFLAG_BMASK;
12433 gen_opc_instr_start[lj] = 1;
12434 gen_opc_icount[lj] = num_insns;
12436 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
12437 gen_io_start();
12439 is_branch = 0;
12440 if (!(ctx.hflags & MIPS_HFLAG_M16)) {
12441 ctx.opcode = ldl_code(ctx.pc);
12442 insn_bytes = 4;
12443 decode_opc(env, &ctx, &is_branch);
12444 } else if (env->insn_flags & ASE_MICROMIPS) {
12445 ctx.opcode = lduw_code(ctx.pc);
12446 insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
12447 } else if (env->insn_flags & ASE_MIPS16) {
12448 ctx.opcode = lduw_code(ctx.pc);
12449 insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
12450 } else {
12451 generate_exception(&ctx, EXCP_RI);
12452 ctx.bstate = BS_STOP;
12453 break;
12455 if (!is_branch) {
12456 handle_delay_slot(env, &ctx, insn_bytes);
12458 ctx.pc += insn_bytes;
12460 num_insns++;
12462 /* Execute a branch and its delay slot as a single instruction.
12463 This is what GDB expects and is consistent with what the
12464 hardware does (e.g. if a delay slot instruction faults, the
12465 reported PC is the PC of the branch). */
12466 if (env->singlestep_enabled && (ctx.hflags & MIPS_HFLAG_BMASK) == 0)
12467 break;
12469 if ((ctx.pc & (TARGET_PAGE_SIZE - 1)) == 0)
12470 break;
12472 if (gen_opc_ptr >= gen_opc_end)
12473 break;
12475 if (num_insns >= max_insns)
12476 break;
12478 if (singlestep)
12479 break;
12481 if (tb->cflags & CF_LAST_IO)
12482 gen_io_end();
12483 if (env->singlestep_enabled && ctx.bstate != BS_BRANCH) {
12484 save_cpu_state(&ctx, ctx.bstate == BS_NONE);
12485 gen_helper_0i(raise_exception, EXCP_DEBUG);
12486 } else {
12487 switch (ctx.bstate) {
12488 case BS_STOP:
12489 gen_goto_tb(&ctx, 0, ctx.pc);
12490 break;
12491 case BS_NONE:
12492 save_cpu_state(&ctx, 0);
12493 gen_goto_tb(&ctx, 0, ctx.pc);
12494 break;
12495 case BS_EXCP:
12496 tcg_gen_exit_tb(0);
12497 break;
12498 case BS_BRANCH:
12499 default:
12500 break;
12503 done_generating:
12504 gen_icount_end(tb, num_insns);
12505 *gen_opc_ptr = INDEX_op_end;
12506 if (search_pc) {
12507 j = gen_opc_ptr - gen_opc_buf;
12508 lj++;
12509 while (lj <= j)
12510 gen_opc_instr_start[lj++] = 0;
12511 } else {
12512 tb->size = ctx.pc - pc_start;
12513 tb->icount = num_insns;
12515 #ifdef DEBUG_DISAS
12516 LOG_DISAS("\n");
12517 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
12518 qemu_log("IN: %s\n", lookup_symbol(pc_start));
12519 log_target_disas(pc_start, ctx.pc - pc_start, 0);
12520 qemu_log("\n");
12522 #endif
12525 void gen_intermediate_code (CPUMIPSState *env, struct TranslationBlock *tb)
12527 gen_intermediate_code_internal(env, tb, 0);
12530 void gen_intermediate_code_pc (CPUMIPSState *env, struct TranslationBlock *tb)
12532 gen_intermediate_code_internal(env, tb, 1);
12535 static void fpu_dump_state(CPUMIPSState *env, FILE *f, fprintf_function fpu_fprintf,
12536 int flags)
12538 int i;
12539 int is_fpu64 = !!(env->hflags & MIPS_HFLAG_F64);
12541 #define printfpr(fp) \
12542 do { \
12543 if (is_fpu64) \
12544 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12545 " fd:%13g fs:%13g psu: %13g\n", \
12546 (fp)->w[FP_ENDIAN_IDX], (fp)->d, \
12547 (double)(fp)->fd, \
12548 (double)(fp)->fs[FP_ENDIAN_IDX], \
12549 (double)(fp)->fs[!FP_ENDIAN_IDX]); \
12550 else { \
12551 fpr_t tmp; \
12552 tmp.w[FP_ENDIAN_IDX] = (fp)->w[FP_ENDIAN_IDX]; \
12553 tmp.w[!FP_ENDIAN_IDX] = ((fp) + 1)->w[FP_ENDIAN_IDX]; \
12554 fpu_fprintf(f, "w:%08x d:%016" PRIx64 \
12555 " fd:%13g fs:%13g psu:%13g\n", \
12556 tmp.w[FP_ENDIAN_IDX], tmp.d, \
12557 (double)tmp.fd, \
12558 (double)tmp.fs[FP_ENDIAN_IDX], \
12559 (double)tmp.fs[!FP_ENDIAN_IDX]); \
12561 } while(0)
12564 fpu_fprintf(f, "CP1 FCR0 0x%08x FCR31 0x%08x SR.FR %d fp_status 0x%02x\n",
12565 env->active_fpu.fcr0, env->active_fpu.fcr31, is_fpu64,
12566 get_float_exception_flags(&env->active_fpu.fp_status));
12567 for (i = 0; i < 32; (is_fpu64) ? i++ : (i += 2)) {
12568 fpu_fprintf(f, "%3s: ", fregnames[i]);
12569 printfpr(&env->active_fpu.fpr[i]);
12572 #undef printfpr
12575 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12576 /* Debug help: The architecture requires 32bit code to maintain proper
12577 sign-extended values on 64bit machines. */
12579 #define SIGN_EXT_P(val) ((((val) & ~0x7fffffff) == 0) || (((val) & ~0x7fffffff) == ~0x7fffffff))
12581 static void
12582 cpu_mips_check_sign_extensions (CPUMIPSState *env, FILE *f,
12583 fprintf_function cpu_fprintf,
12584 int flags)
12586 int i;
12588 if (!SIGN_EXT_P(env->active_tc.PC))
12589 cpu_fprintf(f, "BROKEN: pc=0x" TARGET_FMT_lx "\n", env->active_tc.PC);
12590 if (!SIGN_EXT_P(env->active_tc.HI[0]))
12591 cpu_fprintf(f, "BROKEN: HI=0x" TARGET_FMT_lx "\n", env->active_tc.HI[0]);
12592 if (!SIGN_EXT_P(env->active_tc.LO[0]))
12593 cpu_fprintf(f, "BROKEN: LO=0x" TARGET_FMT_lx "\n", env->active_tc.LO[0]);
12594 if (!SIGN_EXT_P(env->btarget))
12595 cpu_fprintf(f, "BROKEN: btarget=0x" TARGET_FMT_lx "\n", env->btarget);
12597 for (i = 0; i < 32; i++) {
12598 if (!SIGN_EXT_P(env->active_tc.gpr[i]))
12599 cpu_fprintf(f, "BROKEN: %s=0x" TARGET_FMT_lx "\n", regnames[i], env->active_tc.gpr[i]);
12602 if (!SIGN_EXT_P(env->CP0_EPC))
12603 cpu_fprintf(f, "BROKEN: EPC=0x" TARGET_FMT_lx "\n", env->CP0_EPC);
12604 if (!SIGN_EXT_P(env->lladdr))
12605 cpu_fprintf(f, "BROKEN: LLAddr=0x" TARGET_FMT_lx "\n", env->lladdr);
12607 #endif
12609 void cpu_dump_state (CPUMIPSState *env, FILE *f, fprintf_function cpu_fprintf,
12610 int flags)
12612 int i;
12614 cpu_fprintf(f, "pc=0x" TARGET_FMT_lx " HI=0x" TARGET_FMT_lx
12615 " LO=0x" TARGET_FMT_lx " ds %04x "
12616 TARGET_FMT_lx " " TARGET_FMT_ld "\n",
12617 env->active_tc.PC, env->active_tc.HI[0], env->active_tc.LO[0],
12618 env->hflags, env->btarget, env->bcond);
12619 for (i = 0; i < 32; i++) {
12620 if ((i & 3) == 0)
12621 cpu_fprintf(f, "GPR%02d:", i);
12622 cpu_fprintf(f, " %s " TARGET_FMT_lx, regnames[i], env->active_tc.gpr[i]);
12623 if ((i & 3) == 3)
12624 cpu_fprintf(f, "\n");
12627 cpu_fprintf(f, "CP0 Status 0x%08x Cause 0x%08x EPC 0x" TARGET_FMT_lx "\n",
12628 env->CP0_Status, env->CP0_Cause, env->CP0_EPC);
12629 cpu_fprintf(f, " Config0 0x%08x Config1 0x%08x LLAddr 0x" TARGET_FMT_lx "\n",
12630 env->CP0_Config0, env->CP0_Config1, env->lladdr);
12631 if (env->hflags & MIPS_HFLAG_FPU)
12632 fpu_dump_state(env, f, cpu_fprintf, flags);
12633 #if defined(TARGET_MIPS64) && defined(MIPS_DEBUG_SIGN_EXTENSIONS)
12634 cpu_mips_check_sign_extensions(env, f, cpu_fprintf, flags);
12635 #endif
12638 static void mips_tcg_init(void)
12640 int i;
12641 static int inited;
12643 /* Initialize various static tables. */
12644 if (inited)
12645 return;
12647 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
12648 TCGV_UNUSED(cpu_gpr[0]);
12649 for (i = 1; i < 32; i++)
12650 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
12651 offsetof(CPUMIPSState, active_tc.gpr[i]),
12652 regnames[i]);
12653 cpu_PC = tcg_global_mem_new(TCG_AREG0,
12654 offsetof(CPUMIPSState, active_tc.PC), "PC");
12655 for (i = 0; i < MIPS_DSP_ACC; i++) {
12656 cpu_HI[i] = tcg_global_mem_new(TCG_AREG0,
12657 offsetof(CPUMIPSState, active_tc.HI[i]),
12658 regnames_HI[i]);
12659 cpu_LO[i] = tcg_global_mem_new(TCG_AREG0,
12660 offsetof(CPUMIPSState, active_tc.LO[i]),
12661 regnames_LO[i]);
12662 cpu_ACX[i] = tcg_global_mem_new(TCG_AREG0,
12663 offsetof(CPUMIPSState, active_tc.ACX[i]),
12664 regnames_ACX[i]);
12666 cpu_dspctrl = tcg_global_mem_new(TCG_AREG0,
12667 offsetof(CPUMIPSState, active_tc.DSPControl),
12668 "DSPControl");
12669 bcond = tcg_global_mem_new(TCG_AREG0,
12670 offsetof(CPUMIPSState, bcond), "bcond");
12671 btarget = tcg_global_mem_new(TCG_AREG0,
12672 offsetof(CPUMIPSState, btarget), "btarget");
12673 hflags = tcg_global_mem_new_i32(TCG_AREG0,
12674 offsetof(CPUMIPSState, hflags), "hflags");
12676 fpu_fcr0 = tcg_global_mem_new_i32(TCG_AREG0,
12677 offsetof(CPUMIPSState, active_fpu.fcr0),
12678 "fcr0");
12679 fpu_fcr31 = tcg_global_mem_new_i32(TCG_AREG0,
12680 offsetof(CPUMIPSState, active_fpu.fcr31),
12681 "fcr31");
12683 /* register helpers */
12684 #define GEN_HELPER 2
12685 #include "helper.h"
12687 inited = 1;
12690 #include "translate_init.c"
12692 CPUMIPSState *cpu_mips_init (const char *cpu_model)
12694 CPUMIPSState *env;
12695 const mips_def_t *def;
12697 def = cpu_mips_find_by_name(cpu_model);
12698 if (!def)
12699 return NULL;
12700 env = g_malloc0(sizeof(CPUMIPSState));
12701 env->cpu_model = def;
12702 env->cpu_model_str = cpu_model;
12704 cpu_exec_init(env);
12705 #ifndef CONFIG_USER_ONLY
12706 mmu_init(env, def);
12707 #endif
12708 fpu_init(env, def);
12709 mvp_init(env, def);
12710 mips_tcg_init();
12711 cpu_state_reset(env);
12712 qemu_init_vcpu(env);
12713 return env;
12716 void cpu_state_reset(CPUMIPSState *env)
12718 if (qemu_loglevel_mask(CPU_LOG_RESET)) {
12719 qemu_log("CPU Reset (CPU %d)\n", env->cpu_index);
12720 log_cpu_state(env, 0);
12723 memset(env, 0, offsetof(CPUMIPSState, breakpoints));
12724 tlb_flush(env, 1);
12726 /* Reset registers to their default values */
12727 env->CP0_PRid = env->cpu_model->CP0_PRid;
12728 env->CP0_Config0 = env->cpu_model->CP0_Config0;
12729 #ifdef TARGET_WORDS_BIGENDIAN
12730 env->CP0_Config0 |= (1 << CP0C0_BE);
12731 #endif
12732 env->CP0_Config1 = env->cpu_model->CP0_Config1;
12733 env->CP0_Config2 = env->cpu_model->CP0_Config2;
12734 env->CP0_Config3 = env->cpu_model->CP0_Config3;
12735 env->CP0_Config6 = env->cpu_model->CP0_Config6;
12736 env->CP0_Config7 = env->cpu_model->CP0_Config7;
12737 env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
12738 << env->cpu_model->CP0_LLAddr_shift;
12739 env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
12740 env->SYNCI_Step = env->cpu_model->SYNCI_Step;
12741 env->CCRes = env->cpu_model->CCRes;
12742 env->CP0_Status_rw_bitmask = env->cpu_model->CP0_Status_rw_bitmask;
12743 env->CP0_TCStatus_rw_bitmask = env->cpu_model->CP0_TCStatus_rw_bitmask;
12744 env->CP0_SRSCtl = env->cpu_model->CP0_SRSCtl;
12745 env->current_tc = 0;
12746 env->SEGBITS = env->cpu_model->SEGBITS;
12747 env->SEGMask = (target_ulong)((1ULL << env->cpu_model->SEGBITS) - 1);
12748 #if defined(TARGET_MIPS64)
12749 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12750 env->SEGMask |= 3ULL << 62;
12752 #endif
12753 env->PABITS = env->cpu_model->PABITS;
12754 env->PAMask = (target_ulong)((1ULL << env->cpu_model->PABITS) - 1);
12755 env->CP0_SRSConf0_rw_bitmask = env->cpu_model->CP0_SRSConf0_rw_bitmask;
12756 env->CP0_SRSConf0 = env->cpu_model->CP0_SRSConf0;
12757 env->CP0_SRSConf1_rw_bitmask = env->cpu_model->CP0_SRSConf1_rw_bitmask;
12758 env->CP0_SRSConf1 = env->cpu_model->CP0_SRSConf1;
12759 env->CP0_SRSConf2_rw_bitmask = env->cpu_model->CP0_SRSConf2_rw_bitmask;
12760 env->CP0_SRSConf2 = env->cpu_model->CP0_SRSConf2;
12761 env->CP0_SRSConf3_rw_bitmask = env->cpu_model->CP0_SRSConf3_rw_bitmask;
12762 env->CP0_SRSConf3 = env->cpu_model->CP0_SRSConf3;
12763 env->CP0_SRSConf4_rw_bitmask = env->cpu_model->CP0_SRSConf4_rw_bitmask;
12764 env->CP0_SRSConf4 = env->cpu_model->CP0_SRSConf4;
12765 env->insn_flags = env->cpu_model->insn_flags;
12767 #if defined(CONFIG_USER_ONLY)
12768 env->hflags = MIPS_HFLAG_UM;
12769 /* Enable access to the SYNCI_Step register. */
12770 env->CP0_HWREna |= (1 << 1);
12771 if (env->CP0_Config1 & (1 << CP0C1_FP)) {
12772 env->hflags |= MIPS_HFLAG_FPU;
12774 #ifdef TARGET_MIPS64
12775 if (env->active_fpu.fcr0 & (1 << FCR0_F64)) {
12776 env->hflags |= MIPS_HFLAG_F64;
12778 #endif
12779 #else
12780 if (env->hflags & MIPS_HFLAG_BMASK) {
12781 /* If the exception was raised from a delay slot,
12782 come back to the jump. */
12783 env->CP0_ErrorEPC = env->active_tc.PC - 4;
12784 } else {
12785 env->CP0_ErrorEPC = env->active_tc.PC;
12787 env->active_tc.PC = (int32_t)0xBFC00000;
12788 env->CP0_Random = env->tlb->nb_tlb - 1;
12789 env->tlb->tlb_in_use = env->tlb->nb_tlb;
12790 env->CP0_Wired = 0;
12791 env->CP0_EBase = 0x80000000 | (env->cpu_index & 0x3FF);
12792 env->CP0_Status = (1 << CP0St_BEV) | (1 << CP0St_ERL);
12793 /* vectored interrupts not implemented, timer on int 7,
12794 no performance counters. */
12795 env->CP0_IntCtl = 0xe0000000;
12797 int i;
12799 for (i = 0; i < 7; i++) {
12800 env->CP0_WatchLo[i] = 0;
12801 env->CP0_WatchHi[i] = 0x80000000;
12803 env->CP0_WatchLo[7] = 0;
12804 env->CP0_WatchHi[7] = 0;
12806 /* Count register increments in debug mode, EJTAG version 1 */
12807 env->CP0_Debug = (1 << CP0DB_CNT) | (0x1 << CP0DB_VER);
12808 env->hflags = MIPS_HFLAG_CP0;
12810 if (env->CP0_Config3 & (1 << CP0C3_MT)) {
12811 int i;
12813 /* Only TC0 on VPE 0 starts as active. */
12814 for (i = 0; i < ARRAY_SIZE(env->tcs); i++) {
12815 env->tcs[i].CP0_TCBind = env->cpu_index << CP0TCBd_CurVPE;
12816 env->tcs[i].CP0_TCHalt = 1;
12818 env->active_tc.CP0_TCHalt = 1;
12819 env->halted = 1;
12821 if (!env->cpu_index) {
12822 /* VPE0 starts up enabled. */
12823 env->mvp->CP0_MVPControl |= (1 << CP0MVPCo_EVP);
12824 env->CP0_VPEConf0 |= (1 << CP0VPEC0_MVP) | (1 << CP0VPEC0_VPA);
12826 /* TC0 starts up unhalted. */
12827 env->halted = 0;
12828 env->active_tc.CP0_TCHalt = 0;
12829 env->tcs[0].CP0_TCHalt = 0;
12830 /* With thread 0 active. */
12831 env->active_tc.CP0_TCStatus = (1 << CP0TCSt_A);
12832 env->tcs[0].CP0_TCStatus = (1 << CP0TCSt_A);
12835 #endif
12836 #if defined(TARGET_MIPS64)
12837 if (env->cpu_model->insn_flags & ISA_MIPS3) {
12838 env->hflags |= MIPS_HFLAG_64;
12840 #endif
12841 env->exception_index = EXCP_NONE;
12844 void restore_state_to_opc(CPUMIPSState *env, TranslationBlock *tb, int pc_pos)
12846 env->active_tc.PC = gen_opc_pc[pc_pos];
12847 env->hflags &= ~MIPS_HFLAG_BMASK;
12848 env->hflags |= gen_opc_hflags[pc_pos];